4 * Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
10 * \author Stefano Fedrigo <aleph@develer.com>
12 * \brief I2C eeprom driver
14 * \note This implementation is AVR specific.
19 * Revision 1.2 2004/07/22 01:24:43 bernie
20 * Document AVR dependency.
22 * Revision 1.1 2004/07/20 17:11:18 bernie
28 #include <mware/byteorder.h> /* cpu_to_be16() */
29 #include <drv/kdebug.h>
35 /* Wait for TWINT flag set: bus is ready */
36 #define WAIT_TWI_READY do {} while (!(TWCR & BV(TWINT)))
38 /*! \name EEPROM control codes */
46 * Send START condition on the bus.
48 * \return true on success, false otherwise.
50 static bool twi_start(void)
52 TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
55 if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
58 DB(kprintf("!TW_(REP)START: %x\n", TWSR);)
64 * Send START condition and select slave for write.
66 * \return true on success, false otherwise.
68 static bool twi_start_w(uint8_t slave_addr)
72 /* Do a loop on the select write sequence because if the
73 * eeprom is busy writing precedently sent data it will respond
74 * with NACK to the SLA_W control byte. In this case we have
75 * to try until the eeprom reply with an ACK.
79 TWDR = SLA_W | ((slave_addr & 0x5) << 1);
80 TWCR = BV(TWINT) | BV(TWEN);
83 if (TW_STATUS == TW_MT_SLA_ACK)
85 else if (TW_STATUS != TW_MT_SLA_NACK)
87 DB(kprintf("!TW_MT_SLA_(N)ACK: %x\n", TWSR);)
97 * Send START condition and select slave for read.
99 * \return true on success, false otherwise.
101 static bool twi_start_r(uint8_t slave_addr)
107 TWDR = SLA_R | ((slave_addr & 0x5) << 1);
108 TWCR = BV(TWINT) | BV(TWEN);
111 if (TW_STATUS == TW_MR_SLA_ACK)
114 DB(kprintf("!TW_MR_SLA_ACK: %x\n", TWSR);)
122 * Send STOP condition.
124 static void twi_stop(void)
128 TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
133 * Send a sequence of bytes in master transmitter mode
134 * to the selected slave device through the TWI bus.
136 * \return true on success, false on error.
138 static bool twi_send(const uint8_t *buf, size_t count)
145 TWCR = BV(TWINT) | BV(TWEN);
147 if (TW_STATUS != TW_MT_DATA_ACK)
149 DB(kprintf("!TW_MT_DATA_ACK: %x\n", TWSR);)
159 * Receive a sequence of one or more bytes from the
160 * selected slave device in master receive mode through
163 * Received data is placed in \c buf.
165 * \return true on success, false on error
167 static bool twi_recv(uint8_t *buf, size_t count)
172 * When reading the last byte the TWEA bit is not
173 * set, and the eeprom should answer with NACK
177 TWCR = BV(TWINT) | BV(TWEN) | (count ? BV(TWEA) : 0);
182 if (TW_STATUS != TW_MR_DATA_ACK)
184 DB(kprintf("!TW_MR_DATA_ACK: %x\n", TWSR);)
190 if (TW_STATUS != TW_MR_DATA_NACK)
192 DB(kprintf("!TW_MR_DATA_NACK: %x\n", TWSR);)
204 * Copy \c count bytes from buffer \c buf to
205 * eeprom at address \c addr.
207 * \note No check is done for data crossing page
210 bool eeprom_write(e2addr_t addr, const void *buf, size_t count)
212 // eeprom accepts address as big endian
213 addr = cpu_to_be16(addr);
217 && twi_send((uint8_t *)&addr, sizeof(addr))
218 && twi_send(buf, count);
227 * Copy \c count bytes at address \c addr
228 * from eeprom to RAM to buffer \c buf.
230 bool eeprom_read(e2addr_t addr, void *buf, size_t count)
232 // eeprom accepts address as big endian
233 addr = cpu_to_be16(addr);
237 && twi_send((uint8_t *)&addr, sizeof(addr))
239 && twi_recv(buf, count);
248 * Write a single character \a c at address \a addr.
250 bool eeprom_write_char(e2addr_t addr, char c)
252 return eeprom_write(addr, &c, 1);
257 * Read a single character at address \a addr.
259 * \return the requested character or -1 in case of failure.
261 int eeprom_read_char(e2addr_t addr)
265 if (eeprom_read(addr, &c, 1))
273 * Initialize TWI module.
275 void eeprom_init(void)
278 DISABLE_IRQSAVE(flags);
280 DDRD |= BV(PORTD0) | BV(PORTD1);
281 PORTD |= BV(PORTD0) | BV(PORTD1);
285 * F = CLOCK_FREQ / (16 + 2*TWBR * 4^TWPS)
287 # define TWI_FREQ 300000 /* 300 kHz */
288 # define TWI_PRESC 1 /* 4 ^ TWPS */
290 TWBR = (CLOCK_FREQ / (2 * TWI_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);
293 ENABLE_IRQRESTORE(flags);
299 void eeprom_test(void)
301 static const char magic[] = "Humpty Dumpty";
302 char buf[sizeof magic];
304 // Write something to EEPROM and read it back
305 eeprom_write(0, magic, sizeof magic);
306 eeprom_read(0, buf, sizeof buf);
307 kprintf("EEPROM read: %s\n", buf);