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.1 2005/01/06 16:09:40 aleph
19 *#* Split twi/eeprom functions from eeprom module in separate twi module
32 /* Wait for TWINT flag set: bus is ready */
33 #define WAIT_TWI_READY do {} while (!(TWCR & BV(TWINT)))
35 /*! \name EEPROM control codes */
43 * Send START condition on the bus.
45 * \return true on success, false otherwise.
47 static bool twi_start(void)
49 TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
52 if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
55 kprintf("!TW_(REP)START: %x\n", TWSR);
61 * Send START condition and select slave for write.
63 * \return true on success, false otherwise.
65 bool twi_start_w(uint8_t slave_addr)
67 ASSERT(slave_addr < 8);
70 * Loop on the select write sequence: when the eeprom is busy
71 * writing previously sent data it will reply to the SLA_W
72 * control byte with a NACK. In this case, we must
73 * keep trying until the eeprom responds with an ACK.
77 TWDR = SLA_W | (slave_addr << 1);
78 TWCR = BV(TWINT) | BV(TWEN);
81 if (TW_STATUS == TW_MT_SLA_ACK)
83 else if (TW_STATUS != TW_MT_SLA_NACK)
85 kprintf("!TW_MT_SLA_(N)ACK: %x\n", TWSR);
95 * Send START condition and select slave for read.
97 * \return true on success, false otherwise.
99 bool twi_start_r(uint8_t slave_addr)
101 ASSERT(slave_addr < 8);
105 TWDR = SLA_R | (slave_addr << 1);
106 TWCR = BV(TWINT) | BV(TWEN);
109 if (TW_STATUS == TW_MR_SLA_ACK)
112 kprintf("!TW_MR_SLA_ACK: %x\n", TWSR);
120 * Send STOP condition.
124 TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
129 * Send a sequence of bytes in master transmitter mode
130 * to the selected slave device through the TWI bus.
132 * \return true on success, false on error.
134 bool twi_send(const void *_buf, size_t count)
136 const uint8_t *buf = (const uint8_t *)_buf;
141 TWCR = BV(TWINT) | BV(TWEN);
143 if (TW_STATUS != TW_MT_DATA_ACK)
145 kprintf("!TW_MT_DATA_ACK: %x\n", TWSR);
155 * Receive a sequence of one or more bytes from the
156 * selected slave device in master receive mode through
159 * Received data is placed in \c buf.
161 * \return true on success, false on error
163 bool twi_recv(void *_buf, size_t count)
165 uint8_t *buf = (uint8_t *)_buf;
168 * When reading the last byte the TWEA bit is not
169 * set, and the eeprom should answer with NACK
173 TWCR = BV(TWINT) | BV(TWEN) | (count ? BV(TWEA) : 0);
178 if (TW_STATUS != TW_MR_DATA_ACK)
180 kprintf("!TW_MR_DATA_ACK: %x\n", TWSR);
186 if (TW_STATUS != TW_MR_DATA_NACK)
188 kprintf("!TW_MR_DATA_NACK: %x\n", TWSR);
200 * Initialize TWI module.
206 * This is pretty useless according to AVR's datasheet,
207 * but it helps us driving the TWI data lines on boards
208 * where the bus pull-up resistors are missing. This is
209 * probably due to some unwanted interaction between the
210 * port pin and the TWI lines.
212 #if defined(__AVR_ATmega64__)
213 PORTD |= BV(PD0) | BV(PD1);
214 DDRD |= BV(PD0) | BV(PD1);
215 #elif defined(__AVR_ATmega8__)
216 PORTC |= BV(PC4) | BV(PC5);
217 DDRC |= BV(PC4) | BV(PC5);
219 #error Unsupported architecture
224 * F = CLOCK_FREQ / (16 + 2*TWBR * 4^TWPS)
226 #define TWI_FREQ 300000L /* ~300 kHz */
227 #define TWI_PRESC 1 /* 4 ^ TWPS */
229 TWBR = (CLOCK_FREQ / (2 * TWI_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);