4 Internal TWI/i2c slave/master subsystem
6 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
8 This file is part of simavr.
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.
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.
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/>.
29 static void twi_bus_master_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param)
31 twi_bus_t * bus = (twi_bus_t *)param;
36 case TWI_MASTER_START:
53 static void twi_bus_slave_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param)
55 twi_slave_t * slave = (twi_slave_t*)param;
56 twi_bus_t * bus = slave->bus;
64 printf("twi bus: slave %x selected\n", slave->address);
66 bus->ack = 0x80 | (value & 1);
71 static void twi_slave_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param)
73 twi_slave_t * slave = (twi_slave_t*)param;
81 case TWI_MASTER_START:
82 if ((value & 0xfe) == (slave->address & 0xfe)) {
87 avr_raise_irq(slave->irq + TWI_SLAVE_ACK, 1);
99 void twi_bus_init(twi_bus_t * bus)
101 memset(bus, 0, sizeof(twi_bus_t));
102 avr_init_irq(bus->irq, 0, TWI_MASTER_STATE_COUNT);
103 for (int i = 0; i < TWI_MASTER_STATE_COUNT; i++)
104 avr_irq_register_notify(bus->irq + i, twi_bus_master_irq_notify, bus);
107 void twi_bus_attach(twi_bus_t * bus, twi_slave_t * slave)
109 twi_slave_detach(slave);
111 slave->next = bus->slave;
114 for (int i = 0; i < TWI_SLAVE_STATE_COUNT; i++)
115 avr_irq_register_notify(slave->irq + i, twi_bus_slave_irq_notify, slave);
116 for (int i = 0; i < TWI_MASTER_STATE_COUNT; i++)
117 avr_irq_register_notify(bus->irq + i, twi_slave_irq_notify, slave);
120 int twi_bus_start(twi_bus_t * bus, uint8_t address)
122 avr_raise_irq(bus->irq + TWI_MASTER_START, address);
123 return bus->peer != NULL ? 1 : 0;
126 void twi_bus_stop(twi_bus_t * bus)
128 avr_raise_irq(bus->irq + TWI_MASTER_STOP, 0);
132 void twi_slave_init(twi_slave_t * slave, uint8_t address, void * param)
134 memset(slave, 0, sizeof(twi_slave_t));
135 slave->address = address;
136 // slave->param = param;
139 void twi_slave_detach(twi_slave_t * slave)
141 if (!slave || !slave->bus)
143 twi_slave_t *s = slave->bus->slave;
145 if (s->next == slave) {
147 if (slave->bus->peer == slave)
148 slave->bus->peer = NULL;
150 s->next = slave->next;