misc: Point to correct simavr include dirs
[simavr] / simavr / sim / avr_spi.c
1 /*
2         avr_spi.c
3
4         Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <stdio.h>
23 #include "avr_spi.h"
24
25 static avr_cycle_count_t avr_spi_raise(struct avr_t * avr, avr_cycle_count_t when, void * param)
26 {
27         avr_spi_t * p = (avr_spi_t *)param;
28         
29         if (avr_regbit_get(avr, p->spe)) {
30                 // in master mode, any byte is sent as it comes..
31                 if (avr_regbit_get(avr, p->mstr)) {
32                         avr_raise_interrupt(avr, &p->spi);
33                         avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]);
34                 }
35         }
36         return 0;
37 }
38
39 static uint8_t avr_spi_read(struct avr_t * avr, avr_io_addr_t addr, void * param)
40 {
41         avr_spi_t * p = (avr_spi_t *)param;
42         uint8_t v = p->input_data_register;
43         p->input_data_register = 0;
44         avr_regbit_clear(avr, p->spi.raised);
45 //      printf("avr_spi_read = %02x\n", v);
46         return v;
47 }
48
49 static void avr_spi_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
50 {
51         avr_spi_t * p = (avr_spi_t *)param;
52
53         if (addr == p->r_spdr) {
54         //      printf("avr_spi_write = %02x\n", v);
55                 avr_core_watch_write(avr, addr, v);
56                 avr_cycle_timer_register_usec(avr, 100, avr_spi_raise, p); // should be speed dependent
57         }
58 }
59
60 static void avr_spi_irq_input(struct avr_irq_t * irq, uint32_t value, void * param)
61 {
62         avr_spi_t * p = (avr_spi_t *)param;
63         avr_t * avr = p->io.avr;
64
65         // check to see if receiver is enabled
66         if (!avr_regbit_get(avr, p->spe))
67                 return;
68
69         // double buffer the input.. ?
70         p->input_data_register = value;
71         avr_raise_interrupt(avr, &p->spi);
72
73         // if in slave mode, 
74         // 'output' the byte only when we received one...
75         if (!avr_regbit_get(avr, p->mstr)) {
76                 avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]);
77         }
78 }
79
80 void avr_spi_reset(struct avr_io_t *io)
81 {
82         avr_spi_t * p = (avr_spi_t *)io;
83         avr_irq_register_notify(p->io.irq + SPI_IRQ_INPUT, avr_spi_irq_input, p);
84 }
85
86 static const char * irq_names[SPI_IRQ_COUNT] = {
87         [SPI_IRQ_INPUT] = "8<in",
88         [SPI_IRQ_OUTPUT] = "8<out",
89 };
90
91 static  avr_io_t        _io = {
92         .kind = "spi",
93         .reset = avr_spi_reset,
94         .irq_names = irq_names,
95 };
96
97 void avr_spi_init(avr_t * avr, avr_spi_t * p)
98 {
99         p->io = _io;
100
101         avr_register_io(avr, &p->io);
102         avr_register_vector(avr, &p->spi);
103         // allocate this module's IRQ
104         avr_io_setirqs(&p->io, AVR_IOCTL_SPI_GETIRQ(p->name), SPI_IRQ_COUNT, NULL);
105
106         avr_register_io_write(avr, p->r_spdr, avr_spi_write, p);
107         avr_register_io_read(avr, p->r_spdr, avr_spi_read, p);
108 }
109