4 * Copyright 2003, 2004, 2005 Develer S.r.l. (http://www.develer.com/)
5 * This file is part of DevLib - See devlib/README 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.2 2005/01/25 08:36:56 bernie
19 *#* CONFIG_TWI_FREQ: New config param.
21 *#* Revision 1.1 2005/01/06 16:09:40 aleph
22 *#* Split twi/eeprom functions from eeprom module in separate twi module
31 #include <macros.h> // BV()
36 /* Wait for TWINT flag set: bus is ready */
37 #define WAIT_TWI_READY do {} while (!(TWCR & BV(TWINT)))
39 /*! \name EEPROM control codes */
47 * Send START condition on the bus.
49 * \return true on success, false otherwise.
51 static bool twi_start(void)
53 TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
56 if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
59 kprintf("!TW_(REP)START: %x\n", TWSR);
65 * Send START condition and select slave for write.
67 * \return true on success, false otherwise.
69 bool twi_start_w(uint8_t slave_addr)
71 ASSERT(slave_addr < 8);
74 * Loop on the select write sequence: when the eeprom is busy
75 * writing previously sent data it will reply to the SLA_W
76 * control byte with a NACK. In this case, we must
77 * keep trying until the eeprom responds with an ACK.
81 TWDR = SLA_W | (slave_addr << 1);
82 TWCR = BV(TWINT) | BV(TWEN);
85 if (TW_STATUS == TW_MT_SLA_ACK)
87 else if (TW_STATUS != TW_MT_SLA_NACK)
89 kprintf("!TW_MT_SLA_(N)ACK: %x\n", TWSR);
99 * Send START condition and select slave for read.
101 * \return true on success, false otherwise.
103 bool twi_start_r(uint8_t slave_addr)
105 ASSERT(slave_addr < 8);
109 TWDR = SLA_R | (slave_addr << 1);
110 TWCR = BV(TWINT) | BV(TWEN);
113 if (TW_STATUS == TW_MR_SLA_ACK)
116 kprintf("!TW_MR_SLA_ACK: %x\n", TWSR);
124 * Send STOP condition.
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 bool twi_send(const void *_buf, size_t count)
140 const uint8_t *buf = (const uint8_t *)_buf;
145 TWCR = BV(TWINT) | BV(TWEN);
147 if (TW_STATUS != TW_MT_DATA_ACK)
149 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 bool twi_recv(void *_buf, size_t count)
169 uint8_t *buf = (uint8_t *)_buf;
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 kprintf("!TW_MR_DATA_ACK: %x\n", TWSR);
190 if (TW_STATUS != TW_MR_DATA_NACK)
192 kprintf("!TW_MR_DATA_NACK: %x\n", TWSR);
204 * Initialize TWI module.
210 * This is pretty useless according to AVR's datasheet,
211 * but it helps us driving the TWI data lines on boards
212 * where the bus pull-up resistors are missing. This is
213 * probably due to some unwanted interaction between the
214 * port pin and the TWI lines.
216 #if defined(__AVR_ATmega64__)
217 PORTD |= BV(PD0) | BV(PD1);
218 DDRD |= BV(PD0) | BV(PD1);
219 #elif defined(__AVR_ATmega8__)
220 PORTC |= BV(PC4) | BV(PC5);
221 DDRC |= BV(PC4) | BV(PC5);
223 #error Unsupported architecture
228 * F = CLOCK_FREQ / (16 + 2*TWBR * 4^TWPS)
230 #ifndef CONFIG_TWI_FREQ
231 #warning Using default value of 300000L for CONFIG_TWI_FREQ
232 #define CONFIG_TWI_FREQ 300000L /* ~300 kHz */
234 #define TWI_PRESC 1 /* 4 ^ TWPS */
236 TWBR = (CLOCK_FREQ / (2 * CONFIG_TWI_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);