4 * Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
10 * \author Stefano Fedrigo <aleph@develer.com>
12 * \brief I2C eeprom driver
17 * Revision 1.1 2004/07/20 17:11:18 bernie
23 #include <mware/byteorder.h> /* cpu_to_be16() */
24 #include <drv/kdebug.h>
30 /* Wait for TWINT flag set: bus is ready */
31 #define WAIT_TWI_READY do {} while (!(TWCR & BV(TWINT)))
33 /*! \name EEPROM control codes */
41 * Send START condition on the bus.
43 * \return true on success, false otherwise.
45 static bool twi_start(void)
47 TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
50 if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
53 DB(kprintf("!TW_(REP)START: %x\n", TWSR);)
59 * Send START condition and select slave for write.
61 * \return true on success, false otherwise.
63 static bool twi_start_w(uint8_t slave_addr)
67 /* Do a loop on the select write sequence because if the
68 * eeprom is busy writing precedently sent data it will respond
69 * with NACK to the SLA_W control byte. In this case we have
70 * to try until the eeprom reply with an ACK.
74 TWDR = SLA_W | ((slave_addr & 0x5) << 1);
75 TWCR = BV(TWINT) | BV(TWEN);
78 if (TW_STATUS == TW_MT_SLA_ACK)
80 else if (TW_STATUS != TW_MT_SLA_NACK)
82 DB(kprintf("!TW_MT_SLA_(N)ACK: %x\n", TWSR);)
92 * Send START condition and select slave for read.
94 * \return true on success, false otherwise.
96 static bool twi_start_r(uint8_t slave_addr)
102 TWDR = SLA_R | ((slave_addr & 0x5) << 1);
103 TWCR = BV(TWINT) | BV(TWEN);
106 if (TW_STATUS == TW_MR_SLA_ACK)
109 DB(kprintf("!TW_MR_SLA_ACK: %x\n", TWSR);)
117 * Send STOP condition.
119 static void twi_stop(void)
123 TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
128 * Send a sequence of bytes in master transmitter mode
129 * to the selected slave device through the TWI bus.
131 * \return true on success, false on error.
133 static bool twi_send(const uint8_t *buf, size_t count)
140 TWCR = BV(TWINT) | BV(TWEN);
142 if (TW_STATUS != TW_MT_DATA_ACK)
144 DB(kprintf("!TW_MT_DATA_ACK: %x\n", TWSR);)
154 * Receive a sequence of one or more bytes from the
155 * selected slave device in master receive mode through
158 * Received data is placed in \c buf.
160 * \return true on success, false on error
162 static bool twi_recv(uint8_t *buf, size_t count)
167 * When reading the last byte the TWEA bit is not
168 * set, and the eeprom should answer with NACK
172 TWCR = BV(TWINT) | BV(TWEN) | (count ? BV(TWEA) : 0);
177 if (TW_STATUS != TW_MR_DATA_ACK)
179 DB(kprintf("!TW_MR_DATA_ACK: %x\n", TWSR);)
185 if (TW_STATUS != TW_MR_DATA_NACK)
187 DB(kprintf("!TW_MR_DATA_NACK: %x\n", TWSR);)
199 * Copy \c count bytes from buffer \c buf to
200 * eeprom at address \c addr.
202 * \note No check is done for data crossing page
205 bool eeprom_write(e2addr_t addr, const void *buf, size_t count)
207 // eeprom accepts address as big endian
208 addr = cpu_to_be16(addr);
212 && twi_send((uint8_t *)&addr, sizeof(addr))
213 && twi_send(buf, count);
222 * Copy \c count bytes at address \c addr
223 * from eeprom to RAM to buffer \c buf.
225 bool eeprom_read(e2addr_t addr, void *buf, size_t count)
227 // eeprom accepts address as big endian
228 addr = cpu_to_be16(addr);
232 && twi_send((uint8_t *)&addr, sizeof(addr))
234 && twi_recv(buf, count);
243 * Write a single character \a c at address \a addr.
245 bool eeprom_write_char(e2addr_t addr, char c)
247 return eeprom_write(addr, &c, 1);
252 * Read a single character at address \a addr.
254 * \return the requested character or -1 in case of failure.
256 int eeprom_read_char(e2addr_t addr)
260 if (eeprom_read(addr, &c, 1))
268 * Initialize TWI module.
270 void eeprom_init(void)
273 DISABLE_IRQSAVE(flags);
275 DDRD |= BV(PORTD0) | BV(PORTD1);
276 PORTD |= BV(PORTD0) | BV(PORTD1);
280 * F = CLOCK_FREQ / (16 + 2*TWBR * 4^TWPS)
282 # define TWI_FREQ 300000 /* 300 kHz */
283 # define TWI_PRESC 1 /* 4 ^ TWPS */
285 TWBR = (CLOCK_FREQ / (2 * TWI_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);
288 ENABLE_IRQRESTORE(flags);
294 void eeprom_test(void)
296 static const char magic[] = "Humpty Dumpty";
297 char buf[sizeof magic];
299 // Write something to EEPROM and read it back
300 eeprom_write(0, magic, sizeof magic);
301 eeprom_read(0, buf, sizeof buf);
302 kprintf("EEPROM read: %s\n", buf);