4 * Copyright 2003, 2004, 2005 Develer S.r.l. (http://www.develer.com/)
5 * This file is part of DevLib - See README.devlib for information.
8 * \brief Driver for the AVR ATMega TWI (implementation)
12 * \author Stefano Fedrigo <aleph@develer.com>
13 * \author Bernardo Innocenti <bernie@develer.com>
18 *#* Revision 1.7 2006/07/19 12:56:26 bernie
19 *#* Convert to new Doxygen style.
21 *#* Revision 1.6 2006/03/20 17:49:50 bernie
22 *#* Make the TWI driver more generic to work with devices other than EEPROMS.
24 *#* Revision 1.5 2005/11/27 23:33:40 bernie
25 *#* Use appconfig.h instead of cfg/config.h.
27 *#* Revision 1.4 2005/04/11 19:10:28 bernie
28 *#* Include top-level headers from cfg/ subdir.
30 *#* Revision 1.3 2005/03/01 23:26:00 bernie
33 *#* Revision 1.2 2005/01/25 08:36:56 bernie
34 *#* CONFIG_TWI_FREQ: New config param.
36 *#* Revision 1.1 2005/01/06 16:09:40 aleph
37 *#* Split twi/eeprom functions from eeprom module in separate twi module
43 #include <cfg/debug.h>
45 #include <cfg/macros.h> // BV()
47 #include <appconfig.h>
49 #include <compat/twi.h>
52 /* Wait for TWINT flag set: bus is ready */
53 #define WAIT_TWI_READY do {} while (!(TWCR & BV(TWINT)))
55 #define READ_BIT BV(0)
59 * Send START condition on the bus.
61 * \return true on success, false otherwise.
63 static bool twi_start(void)
65 TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
68 if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
71 kprintf("!TW_(REP)START: %x\n", TWSR);
77 * Send START condition and select slave for write.
78 * \c id is the device id comprehensive of address left shifted by 1.
79 * The LSB of \c id is ignored and reset to 0 for write operation.
81 * \return true on success, false otherwise.
83 bool twi_start_w(uint8_t id)
86 * Loop on the select write sequence: when the eeprom is busy
87 * writing previously sent data it will reply to the SLA_W
88 * control byte with a NACK. In this case, we must
89 * keep trying until the eeprom responds with an ACK.
93 TWDR = id & ~READ_BIT;
94 TWCR = BV(TWINT) | BV(TWEN);
97 if (TW_STATUS == TW_MT_SLA_ACK)
99 else if (TW_STATUS != TW_MT_SLA_NACK)
101 kprintf("!TW_MT_SLA_(N)ACK: %x\n", TWSR);
111 * Send START condition and select slave for read.
112 * \c id is the device id comprehensive of address left shifted by 1.
113 * The LSB of \c id is ignored and set to 1 for read operation.
115 * \return true on success, false otherwise.
117 bool twi_start_r(uint8_t id)
121 TWDR = id | READ_BIT;
122 TWCR = BV(TWINT) | BV(TWEN);
125 if (TW_STATUS == TW_MR_SLA_ACK)
128 kprintf("!TW_MR_SLA_ACK: %x\n", TWSR);
136 * Send STOP condition.
140 TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
145 * Put a single byte in master transmitter mode
146 * to the selected slave device through the TWI bus.
148 * \return true on success, false on error.
150 bool twi_put(const uint8_t data)
153 TWCR = BV(TWINT) | BV(TWEN);
155 if (TW_STATUS != TW_MT_DATA_ACK)
157 kprintf("!TW_MT_DATA_ACK: %x\n", TWSR);
165 * Send a sequence of bytes in master transmitter mode
166 * to the selected slave device through the TWI bus.
168 * \return true on success, false on error.
170 bool twi_send(const void *_buf, size_t count)
172 const uint8_t *buf = (const uint8_t *)_buf;
176 if (!twi_put(*buf++))
184 * Receive a sequence of one or more bytes from the
185 * selected slave device in master receive mode through
188 * Received data is placed in \c buf.
190 * \return true on success, false on error
192 bool twi_recv(void *_buf, size_t count)
194 uint8_t *buf = (uint8_t *)_buf;
197 * When reading the last byte the TWEA bit is not
198 * set, and the eeprom should answer with NACK
202 TWCR = BV(TWINT) | BV(TWEN) | (count ? BV(TWEA) : 0);
207 if (TW_STATUS != TW_MR_DATA_ACK)
209 kprintf("!TW_MR_DATA_ACK: %x\n", TWSR);
215 if (TW_STATUS != TW_MR_DATA_NACK)
217 kprintf("!TW_MR_DATA_NACK: %x\n", TWSR);
229 * Initialize TWI module.
235 * This is pretty useless according to AVR's datasheet,
236 * but it helps us driving the TWI data lines on boards
237 * where the bus pull-up resistors are missing. This is
238 * probably due to some unwanted interaction between the
239 * port pin and the TWI lines.
241 #if defined(__AVR_ATmega64__)
242 PORTD |= BV(PD0) | BV(PD1);
243 DDRD |= BV(PD0) | BV(PD1);
244 #elif defined(__AVR_ATmega8__)
245 PORTC |= BV(PC4) | BV(PC5);
246 DDRC |= BV(PC4) | BV(PC5);
248 #error Unsupported architecture
253 * F = CLOCK_FREQ / (16 + 2*TWBR * 4^TWPS)
255 #ifndef CONFIG_TWI_FREQ
256 #warning Using default value of 300000L for CONFIG_TWI_FREQ
257 #define CONFIG_TWI_FREQ 300000L /* ~300 kHz */
259 #define TWI_PRESC 1 /* 4 ^ TWPS */
261 TWBR = (CLOCK_FREQ / (2 * CONFIG_TWI_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);