4 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
6 This file is part of simavr.
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.
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.
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/>.
28 #include "i2c_eeprom.h"
31 * called when a RESET signal is sent
35 struct avr_irq_t * irq,
39 i2c_eeprom_t * p = (i2c_eeprom_t*)param;
44 * If we receive a STOP, check it was meant to us, and reset the transaction
46 if (v.u.twi.msg & TWI_COND_STOP) {
50 printf("eeprom received stop\n");
57 * if we receive a start, reset status, check if the slave address is
58 * meant to be us, and if so reply with an ACK bit
60 if (v.u.twi.msg & TWI_COND_START) {
63 if ((p->addr_base & p->addr_mask) == (v.u.twi.addr & p->addr_mask)) {
65 p->selected = v.u.twi.addr;
66 avr_raise_irq(p->irq + TWI_IRQ_MISO,
67 avr_twi_irq_msg(TWI_COND_ACK, p->selected, 1));
71 * If it's a data transaction, first check it is meant to be us (we
72 * received the correct address and are selected)
76 * This is a write transaction, first receive as many address bytes
77 * as we need, then set the address register, then start
80 if (v.u.twi.msg & TWI_COND_WRITE) {
81 // address size is how many bytes we use for address register
82 avr_raise_irq(p->irq + TWI_IRQ_MISO,
83 avr_twi_irq_msg(TWI_COND_ACK, p->selected, 1));
84 int addr_size = p->size > 256 ? 2 : 1;
85 if (p->index < addr_size) {
86 p->reg_addr |= (v.u.twi.data << (p->index * 8));
87 if (p->index == addr_size-1) {
88 // add the slave address, if relevant
89 p->reg_addr += ((p->selected & 1) - p->addr_base) << 7;
91 printf("eeprom set address to 0x%04x\n", p->reg_addr);
95 printf("eeprom WRITE data 0x%04x: %02x\n", p->reg_addr, v.u.twi.data);
96 p->ee[p->reg_addr++] = v.u.twi.data;
98 p->reg_addr &= (p->size -1);
102 * It's a read transaction, just send the next byte back to the master
104 if (v.u.twi.msg & TWI_COND_READ) {
106 printf("eeprom READ data 0x%04x: %02x\n", p->reg_addr, p->ee[p->reg_addr]);
107 uint8_t data = p->ee[p->reg_addr++];
108 avr_raise_irq(p->irq + TWI_IRQ_MISO,
109 avr_twi_irq_msg(TWI_COND_READ, p->selected, data));
110 p->reg_addr &= (p->size -1);
116 static const char * _ee_irq_names[2] = {
117 [TWI_IRQ_MISO] = "8>eeprom.out",
118 [TWI_IRQ_MOSI] = "32<eeprom.in",
130 memset(p, 0, sizeof(*p));
131 memset(p->ee, 0xff, sizeof(p->ee));
132 p->irq = avr_alloc_irq(&avr->irq_pool, 0, 2, _ee_irq_names);
133 avr_irq_register_notify(p->irq + TWI_IRQ_MOSI, i2c_eeprom_in_hook, p);
135 p->size = size > sizeof(p->ee) ? sizeof(p->ee) : size;
137 memcpy(p->ee, data, p->size);
144 uint32_t i2c_irq_base )
146 // "connect" the IRQs of the eeprom to the TWI/i2c master of the AVR
148 p->irq + TWI_IRQ_MISO,
149 avr_io_getirq(avr, i2c_irq_base, TWI_IRQ_MISO));
151 avr_io_getirq(avr, i2c_irq_base, TWI_IRQ_MOSI),
152 p->irq + TWI_IRQ_MOSI );