Added a real example on how to integrate simavr, etc
[simavr] / simavr / sim / sim_twi.c
1 /*
2         sim_twi.c
3
4         Internal TWI/i2c slave/master subsystem
5         
6         Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
7
8         This file is part of simavr.
9
10         simavr is free software: you can redistribute it and/or modify
11         it under the terms of the GNU General Public License as published by
12         the Free Software Foundation, either version 3 of the License, or
13         (at your option) any later version.
14
15         simavr is distributed in the hope that it will be useful,
16         but WITHOUT ANY WARRANTY; without even the implied warranty of
17         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18         GNU General Public License for more details.
19
20         You should have received a copy of the GNU General Public License
21         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
22  */
23
24 #include <stdlib.h>
25 #include "sim_twi.h"
26
27 void twi_bus_init(twi_bus_t * bus)
28 {
29 }
30
31 void twi_bus_attach(twi_bus_t * bus, twi_slave_t * slave)
32 {
33         twi_slave_detach(slave);
34         slave->bus = bus;
35         slave->next = bus->slave;
36         bus->slave = slave;
37 }
38
39 int twi_bus_start(twi_bus_t * bus, uint8_t address)
40 {
41         // if we already have a peer, check to see if it's 
42         // still matching, if so, skip the lookup
43         if (bus->peer && twi_slave_match(bus->peer, address))
44                 return bus->peer->start(bus->peer, address, 1);
45                 
46         bus->peer = NULL;
47         twi_slave_t *s = bus->slave;
48         while (s) {
49                 if (twi_slave_match(s, address)) {
50                         if (s->start(s, address, 0)) {
51                                 bus->peer = s;
52                                 s->byte_index = 0;
53                                 return 1;
54                         }
55                 }
56                 s = s->next;
57         }
58         return 0;
59 }
60
61 void twi_bus_stop(twi_bus_t * bus)
62 {
63         if (bus->peer && bus->peer->stop)
64                 bus->peer->stop(bus->peer);
65         bus->peer = NULL;
66 }
67
68 int twi_bus_write(twi_bus_t * bus, uint8_t data)
69 {
70         if (!bus->peer || !bus->peer->write)
71                 return 0;
72
73         int res = bus->peer->write(bus->peer, data);
74         if (bus->peer)
75                 bus->peer->byte_index++;
76         return res;
77 }
78
79 uint8_t twi_bus_read(twi_bus_t * bus)
80 {
81         if (!bus->peer || !bus->peer->read)
82                 return 0;
83
84         uint8_t res = bus->peer->read(bus->peer);
85         if (bus->peer)
86                 bus->peer->byte_index++;
87         return res;     
88 }
89
90 void twi_slave_init(twi_slave_t * slave, void * param)
91 {
92         slave->param = param;
93 }
94
95 void twi_slave_detach(twi_slave_t * slave)
96 {
97         if (!slave || !slave->bus)
98                 return;
99         twi_slave_t *s = slave->bus->slave;
100         while (s) {
101                 if (s->next == slave) {
102                         // clear that, too
103                         if (slave->bus->peer == slave)
104                                 slave->bus->peer = NULL;
105                                 
106                         s->next = slave->next;
107                         slave->next = NULL;
108                         slave->bus = NULL;
109                         return;
110                 }
111                 s = s->next;
112         }
113 }
114
115 int twi_slave_match(twi_slave_t * slave, uint8_t address)
116 {
117         if (slave->has_address)
118                 return slave->has_address(slave, address);
119         return (address & ~1) == (slave->address & ~1);
120 }
121