parts: Updated to name their IRQs
[simavr] / examples / parts / hc595.c
1 /*
2         hc595.c
3
4         This defines a sample for a very simple "peripheral" 
5         that can talk to an AVR core.
6         It is in fact a bit more involved than strictly necessary,
7         but is made to demonstrante a few useful features that are
8         easy to use.
9         
10         Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
11
12         This file is part of simavr.
13
14         simavr is free software: you can redistribute it and/or modify
15         it under the terms of the GNU General Public License as published by
16         the Free Software Foundation, either version 3 of the License, or
17         (at your option) any later version.
18
19         simavr is distributed in the hope that it will be useful,
20         but WITHOUT ANY WARRANTY; without even the implied warranty of
21         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22         GNU General Public License for more details.
23
24         You should have received a copy of the GNU General Public License
25         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
26  */
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include "sim_avr.h"
31 #include "hc595.h"
32
33 /*
34  * called when a SPI byte is sent
35  */
36 static void hc595_spi_in_hook(struct avr_irq_t * irq, uint32_t value, void * param)
37 {
38         hc595_t * p = (hc595_t*)param;
39         // send "old value" to any chained one..
40         avr_raise_irq(p->irq + IRQ_HC595_SPI_BYTE_OUT, p->value);       
41         p->value = (p->value << 8) | (value & 0xff);
42 }
43
44 /*
45  * called when a LATCH signal is sent
46  */
47 static void hc595_latch_hook(struct avr_irq_t * irq, uint32_t value, void * param)
48 {
49         hc595_t * p = (hc595_t*)param;
50         if (irq->value && !value) {     // falling edge
51                 p->latch = p->value;
52                 avr_raise_irq(p->irq + IRQ_HC595_OUT, p->latch);
53         }
54 }
55
56 /*
57  * called when a RESET signal is sent
58  */
59 static void hc595_reset_hook(struct avr_irq_t * irq, uint32_t value, void * param)
60 {
61         hc595_t * p = (hc595_t*)param;
62         if (irq->value && !value)       // falling edge
63                 p->latch = p->value = 0;
64 }
65
66 const char * irq_names[IRQ_HC595_COUNT] = {
67                 [IRQ_HC595_SPI_BYTE_IN] = "8<hc595.in",
68                 [IRQ_HC595_SPI_BYTE_OUT] = "8>hc595.chain",
69                 [IRQ_HC595_IN_LATCH] = "<hc595.latch",
70                 [IRQ_HC595_IN_RESET] = "<hc595.reset",
71                 [IRQ_HC595_OUT] = "8>hc595.out",
72 };
73
74 void
75 hc595_init(
76                 struct avr_t * avr,
77                 hc595_t *p)
78 {
79         p->irq = avr_alloc_irq(&avr->irq_pool, 0, IRQ_HC595_COUNT, irq_names);
80         avr_irq_register_notify(p->irq + IRQ_HC595_SPI_BYTE_IN, hc595_spi_in_hook, p);
81         avr_irq_register_notify(p->irq + IRQ_HC595_IN_LATCH, hc595_latch_hook, p);
82         avr_irq_register_notify(p->irq + IRQ_HC595_IN_RESET, hc595_reset_hook, p);
83         
84         p->latch = p->value = 0;
85 }
86