Polished gdb support, etc
[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 uint8_t avr_spi_read(struct avr_t * avr, uint8_t addr, void * param)
26 {
27         avr_spi_t * p = (avr_spi_t *)param;
28         uint8_t v = p->input_data_register;
29         p->input_data_register = 0;
30 //      printf("** PIN%c = %02x\n", p->name, v);
31         return v;
32 }
33
34 static void avr_spi_write(struct avr_t * avr, uint8_t addr, uint8_t v, void * param)
35 {
36         avr_spi_t * p = (avr_spi_t *)param;
37
38         if (addr == p->r_spdr) {
39         //      printf("UDR%c(%02x) = %02x\n", p->name, addr, v);
40                 avr_core_watch_write(avr, addr, v);
41
42                 if (avr_regbit_get(avr, p->spe)) {
43                         // in master mode, any byte is sent as it comes..
44                         if (avr_regbit_get(avr, p->mstr)) {
45                                 avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, v);
46                         }
47                 }
48         }
49 }
50
51 static void avr_spi_irq_input(struct avr_irq_t * irq, uint32_t value, void * param)
52 {
53         avr_spi_t * p = (avr_spi_t *)param;
54         avr_t * avr = p->io.avr;
55
56         // check to see fi receiver is enabled
57         if (!avr_regbit_get(avr, p->spe))
58                 return;
59
60         // double buffer the input.. ?
61         p->input_data_register = value;
62         avr_raise_interrupt(avr, &p->spi);
63
64         // if in slave mode, 
65         // 'output' the byte only when we received one...
66         if (!avr_regbit_get(avr, p->mstr)) {
67                 avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]);
68         }
69 }
70
71 void avr_spi_reset(struct avr_io_t *io)
72 {
73         avr_spi_t * p = (avr_spi_t *)io;
74         avr_irq_register_notify(p->io.irq + SPI_IRQ_INPUT, avr_spi_irq_input, p);
75 }
76
77 static  avr_io_t        _io = {
78         .kind = "spi",
79         .reset = avr_spi_reset,
80 };
81
82 void avr_spi_init(avr_t * avr, avr_spi_t * p)
83 {
84         p->io = _io;
85         avr_register_io(avr, &p->io);
86
87         printf("%s SPI%c init\n", __FUNCTION__, p->name);
88
89         // allocate this module's IRQ
90         p->io.irq_count = SPI_IRQ_COUNT;
91         p->io.irq = avr_alloc_irq(0, p->io.irq_count);
92         p->io.irq_ioctl_get = AVR_IOCTL_SPI_GETIRQ(p->name);
93
94         avr_register_io_write(avr, p->r_spdr, avr_spi_write, p);
95         avr_register_io_read(avr, p->r_spdr, avr_spi_read, p);
96 }
97