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.3 2005/03/01 23:26:00 bernie
21 *#* Revision 1.2 2005/01/25 08:36:56 bernie
22 *#* CONFIG_TWI_FREQ: New config param.
24 *#* Revision 1.1 2005/01/06 16:09:40 aleph
25 *#* Split twi/eeprom functions from eeprom module in separate twi module
34 #include <macros.h> // BV()
36 #include <compat/twi.h>
39 /* Wait for TWINT flag set: bus is ready */
40 #define WAIT_TWI_READY do {} while (!(TWCR & BV(TWINT)))
42 /*! \name EEPROM control codes */
50 * Send START condition on the bus.
52 * \return true on success, false otherwise.
54 static bool twi_start(void)
56 TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
59 if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
62 kprintf("!TW_(REP)START: %x\n", TWSR);
68 * Send START condition and select slave for write.
70 * \return true on success, false otherwise.
72 bool twi_start_w(uint8_t slave_addr)
74 ASSERT(slave_addr < 8);
77 * Loop on the select write sequence: when the eeprom is busy
78 * writing previously sent data it will reply to the SLA_W
79 * control byte with a NACK. In this case, we must
80 * keep trying until the eeprom responds with an ACK.
84 TWDR = SLA_W | (slave_addr << 1);
85 TWCR = BV(TWINT) | BV(TWEN);
88 if (TW_STATUS == TW_MT_SLA_ACK)
90 else if (TW_STATUS != TW_MT_SLA_NACK)
92 kprintf("!TW_MT_SLA_(N)ACK: %x\n", TWSR);
102 * Send START condition and select slave for read.
104 * \return true on success, false otherwise.
106 bool twi_start_r(uint8_t slave_addr)
108 ASSERT(slave_addr < 8);
112 TWDR = SLA_R | (slave_addr << 1);
113 TWCR = BV(TWINT) | BV(TWEN);
116 if (TW_STATUS == TW_MR_SLA_ACK)
119 kprintf("!TW_MR_SLA_ACK: %x\n", TWSR);
127 * Send STOP condition.
131 TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
136 * Send a sequence of bytes in master transmitter mode
137 * to the selected slave device through the TWI bus.
139 * \return true on success, false on error.
141 bool twi_send(const void *_buf, size_t count)
143 const uint8_t *buf = (const uint8_t *)_buf;
148 TWCR = BV(TWINT) | BV(TWEN);
150 if (TW_STATUS != TW_MT_DATA_ACK)
152 kprintf("!TW_MT_DATA_ACK: %x\n", TWSR);
162 * Receive a sequence of one or more bytes from the
163 * selected slave device in master receive mode through
166 * Received data is placed in \c buf.
168 * \return true on success, false on error
170 bool twi_recv(void *_buf, size_t count)
172 uint8_t *buf = (uint8_t *)_buf;
175 * When reading the last byte the TWEA bit is not
176 * set, and the eeprom should answer with NACK
180 TWCR = BV(TWINT) | BV(TWEN) | (count ? BV(TWEA) : 0);
185 if (TW_STATUS != TW_MR_DATA_ACK)
187 kprintf("!TW_MR_DATA_ACK: %x\n", TWSR);
193 if (TW_STATUS != TW_MR_DATA_NACK)
195 kprintf("!TW_MR_DATA_NACK: %x\n", TWSR);
207 * Initialize TWI module.
213 * This is pretty useless according to AVR's datasheet,
214 * but it helps us driving the TWI data lines on boards
215 * where the bus pull-up resistors are missing. This is
216 * probably due to some unwanted interaction between the
217 * port pin and the TWI lines.
219 #if defined(__AVR_ATmega64__)
220 PORTD |= BV(PD0) | BV(PD1);
221 DDRD |= BV(PD0) | BV(PD1);
222 #elif defined(__AVR_ATmega8__)
223 PORTC |= BV(PC4) | BV(PC5);
224 DDRC |= BV(PC4) | BV(PC5);
226 #error Unsupported architecture
231 * F = CLOCK_FREQ / (16 + 2*TWBR * 4^TWPS)
233 #ifndef CONFIG_TWI_FREQ
234 #warning Using default value of 300000L for CONFIG_TWI_FREQ
235 #define CONFIG_TWI_FREQ 300000L /* ~300 kHz */
237 #define TWI_PRESC 1 /* 4 ^ TWPS */
239 TWBR = (CLOCK_FREQ / (2 * CONFIG_TWI_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);