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.4 2005/04/11 19:10:28 bernie
19 *#* Include top-level headers from cfg/ subdir.
21 *#* Revision 1.3 2005/03/01 23:26:00 bernie
24 *#* Revision 1.2 2005/01/25 08:36:56 bernie
25 *#* CONFIG_TWI_FREQ: New config param.
27 *#* Revision 1.1 2005/01/06 16:09:40 aleph
28 *#* Split twi/eeprom functions from eeprom module in separate twi module
33 #include <cfg/config.h>
34 #include <cfg/debug.h>
37 #include <cfg/macros.h> // BV()
39 #include <compat/twi.h>
42 /* Wait for TWINT flag set: bus is ready */
43 #define WAIT_TWI_READY do {} while (!(TWCR & BV(TWINT)))
45 /*! \name EEPROM control codes */
53 * Send START condition on the bus.
55 * \return true on success, false otherwise.
57 static bool twi_start(void)
59 TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
62 if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
65 kprintf("!TW_(REP)START: %x\n", TWSR);
71 * Send START condition and select slave for write.
73 * \return true on success, false otherwise.
75 bool twi_start_w(uint8_t slave_addr)
77 ASSERT(slave_addr < 8);
80 * Loop on the select write sequence: when the eeprom is busy
81 * writing previously sent data it will reply to the SLA_W
82 * control byte with a NACK. In this case, we must
83 * keep trying until the eeprom responds with an ACK.
87 TWDR = SLA_W | (slave_addr << 1);
88 TWCR = BV(TWINT) | BV(TWEN);
91 if (TW_STATUS == TW_MT_SLA_ACK)
93 else if (TW_STATUS != TW_MT_SLA_NACK)
95 kprintf("!TW_MT_SLA_(N)ACK: %x\n", TWSR);
105 * Send START condition and select slave for read.
107 * \return true on success, false otherwise.
109 bool twi_start_r(uint8_t slave_addr)
111 ASSERT(slave_addr < 8);
115 TWDR = SLA_R | (slave_addr << 1);
116 TWCR = BV(TWINT) | BV(TWEN);
119 if (TW_STATUS == TW_MR_SLA_ACK)
122 kprintf("!TW_MR_SLA_ACK: %x\n", TWSR);
130 * Send STOP condition.
134 TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
139 * Send a sequence of bytes in master transmitter mode
140 * to the selected slave device through the TWI bus.
142 * \return true on success, false on error.
144 bool twi_send(const void *_buf, size_t count)
146 const uint8_t *buf = (const uint8_t *)_buf;
151 TWCR = BV(TWINT) | BV(TWEN);
153 if (TW_STATUS != TW_MT_DATA_ACK)
155 kprintf("!TW_MT_DATA_ACK: %x\n", TWSR);
165 * Receive a sequence of one or more bytes from the
166 * selected slave device in master receive mode through
169 * Received data is placed in \c buf.
171 * \return true on success, false on error
173 bool twi_recv(void *_buf, size_t count)
175 uint8_t *buf = (uint8_t *)_buf;
178 * When reading the last byte the TWEA bit is not
179 * set, and the eeprom should answer with NACK
183 TWCR = BV(TWINT) | BV(TWEN) | (count ? BV(TWEA) : 0);
188 if (TW_STATUS != TW_MR_DATA_ACK)
190 kprintf("!TW_MR_DATA_ACK: %x\n", TWSR);
196 if (TW_STATUS != TW_MR_DATA_NACK)
198 kprintf("!TW_MR_DATA_NACK: %x\n", TWSR);
210 * Initialize TWI module.
216 * This is pretty useless according to AVR's datasheet,
217 * but it helps us driving the TWI data lines on boards
218 * where the bus pull-up resistors are missing. This is
219 * probably due to some unwanted interaction between the
220 * port pin and the TWI lines.
222 #if defined(__AVR_ATmega64__)
223 PORTD |= BV(PD0) | BV(PD1);
224 DDRD |= BV(PD0) | BV(PD1);
225 #elif defined(__AVR_ATmega8__)
226 PORTC |= BV(PC4) | BV(PC5);
227 DDRC |= BV(PC4) | BV(PC5);
229 #error Unsupported architecture
234 * F = CLOCK_FREQ / (16 + 2*TWBR * 4^TWPS)
236 #ifndef CONFIG_TWI_FREQ
237 #warning Using default value of 300000L for CONFIG_TWI_FREQ
238 #define CONFIG_TWI_FREQ 300000L /* ~300 kHz */
240 #define TWI_PRESC 1 /* 4 ^ TWPS */
242 TWBR = (CLOCK_FREQ / (2 * CONFIG_TWI_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);