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.5 2005/11/27 23:33:40 bernie
19 *#* Use appconfig.h instead of cfg/config.h.
21 *#* Revision 1.4 2005/04/11 19:10:28 bernie
22 *#* Include top-level headers from cfg/ subdir.
24 *#* Revision 1.3 2005/03/01 23:26:00 bernie
27 *#* Revision 1.2 2005/01/25 08:36:56 bernie
28 *#* CONFIG_TWI_FREQ: New config param.
30 *#* Revision 1.1 2005/01/06 16:09:40 aleph
31 *#* Split twi/eeprom functions from eeprom module in separate twi module
37 #include <cfg/debug.h>
39 #include <cfg/macros.h> // BV()
41 #include <appconfig.h>
43 #include <compat/twi.h>
46 /* Wait for TWINT flag set: bus is ready */
47 #define WAIT_TWI_READY do {} while (!(TWCR & BV(TWINT)))
49 /*! \name EEPROM control codes */
57 * Send START condition on the bus.
59 * \return true on success, false otherwise.
61 static bool twi_start(void)
63 TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
66 if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
69 kprintf("!TW_(REP)START: %x\n", TWSR);
75 * Send START condition and select slave for write.
77 * \return true on success, false otherwise.
79 bool twi_start_w(uint8_t slave_addr)
81 ASSERT(slave_addr < 8);
84 * Loop on the select write sequence: when the eeprom is busy
85 * writing previously sent data it will reply to the SLA_W
86 * control byte with a NACK. In this case, we must
87 * keep trying until the eeprom responds with an ACK.
91 TWDR = SLA_W | (slave_addr << 1);
92 TWCR = BV(TWINT) | BV(TWEN);
95 if (TW_STATUS == TW_MT_SLA_ACK)
97 else if (TW_STATUS != TW_MT_SLA_NACK)
99 kprintf("!TW_MT_SLA_(N)ACK: %x\n", TWSR);
109 * Send START condition and select slave for read.
111 * \return true on success, false otherwise.
113 bool twi_start_r(uint8_t slave_addr)
115 ASSERT(slave_addr < 8);
119 TWDR = SLA_R | (slave_addr << 1);
120 TWCR = BV(TWINT) | BV(TWEN);
123 if (TW_STATUS == TW_MR_SLA_ACK)
126 kprintf("!TW_MR_SLA_ACK: %x\n", TWSR);
134 * Send STOP condition.
138 TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
143 * Send a sequence of bytes in master transmitter mode
144 * to the selected slave device through the TWI bus.
146 * \return true on success, false on error.
148 bool twi_send(const void *_buf, size_t count)
150 const uint8_t *buf = (const uint8_t *)_buf;
155 TWCR = BV(TWINT) | BV(TWEN);
157 if (TW_STATUS != TW_MT_DATA_ACK)
159 kprintf("!TW_MT_DATA_ACK: %x\n", TWSR);
169 * Receive a sequence of one or more bytes from the
170 * selected slave device in master receive mode through
173 * Received data is placed in \c buf.
175 * \return true on success, false on error
177 bool twi_recv(void *_buf, size_t count)
179 uint8_t *buf = (uint8_t *)_buf;
182 * When reading the last byte the TWEA bit is not
183 * set, and the eeprom should answer with NACK
187 TWCR = BV(TWINT) | BV(TWEN) | (count ? BV(TWEA) : 0);
192 if (TW_STATUS != TW_MR_DATA_ACK)
194 kprintf("!TW_MR_DATA_ACK: %x\n", TWSR);
200 if (TW_STATUS != TW_MR_DATA_NACK)
202 kprintf("!TW_MR_DATA_NACK: %x\n", TWSR);
214 * Initialize TWI module.
220 * This is pretty useless according to AVR's datasheet,
221 * but it helps us driving the TWI data lines on boards
222 * where the bus pull-up resistors are missing. This is
223 * probably due to some unwanted interaction between the
224 * port pin and the TWI lines.
226 #if defined(__AVR_ATmega64__)
227 PORTD |= BV(PD0) | BV(PD1);
228 DDRD |= BV(PD0) | BV(PD1);
229 #elif defined(__AVR_ATmega8__)
230 PORTC |= BV(PC4) | BV(PC5);
231 DDRC |= BV(PC4) | BV(PC5);
233 #error Unsupported architecture
238 * F = CLOCK_FREQ / (16 + 2*TWBR * 4^TWPS)
240 #ifndef CONFIG_TWI_FREQ
241 #warning Using default value of 300000L for CONFIG_TWI_FREQ
242 #define CONFIG_TWI_FREQ 300000L /* ~300 kHz */
244 #define TWI_PRESC 1 /* 4 ^ TWPS */
246 TWBR = (CLOCK_FREQ / (2 * CONFIG_TWI_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);