270efe45ea4497f88dbb8c21eed686322e1875a8
[bertos.git] / bertos / cpu / avr / drv / twi_avr.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2003, 2004, 2005 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \brief Driver for the AVR ATMega TWI (implementation)
34  *
35  * \version $Id$
36  *
37  * \author Stefano Fedrigo <aleph@develer.com>
38  * \author Bernie Innocenti <bernie@codewiz.org>
39  */
40
41 #include "twi_avr.h"
42
43 #include "hw/hw_cpu.h"  /* CLOCK_FREQ */
44
45 #include "cfg/cfg_twi.h"
46 #include <cfg/debug.h>
47 #include <cfg/macros.h> // BV()
48 #include <cfg/module.h>
49
50 #include <cpu/detect.h>
51 #include <cpu/irq.h>
52 #include <drv/timer.h>
53
54 #include <compat/twi.h>
55
56
57 /* Wait for TWINT flag set: bus is ready */
58 #define WAIT_TWI_READY  do {} while (!(TWCR & BV(TWINT)))
59
60 #define READ_BIT BV(0)
61
62
63 /**
64  * Send START condition on the bus.
65  *
66  * \return true on success, false otherwise.
67  */
68 static bool twi_start(void)
69 {
70         TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
71         WAIT_TWI_READY;
72
73         if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
74                 return true;
75
76         kprintf("!TW_(REP)START: %x\n", TWSR);
77         return false;
78 }
79
80
81 /**
82  * Send START condition and select slave for write.
83  * \c id is the device id comprehensive of address left shifted by 1.
84  * The LSB of \c id is ignored and reset to 0 for write operation.
85  *
86  * \return true on success, false otherwise.
87  */
88 bool twi_start_w(uint8_t id)
89 {
90         /*
91          * Loop on the select write sequence: when the eeprom is busy
92          * writing previously sent data it will reply to the SLA_W
93          * control byte with a NACK.  In this case, we must
94          * keep trying until the eeprom responds with an ACK.
95          */
96         ticks_t start = timer_clock();
97         while (twi_start())
98         {
99                 TWDR = id & ~READ_BIT;
100                 TWCR = BV(TWINT) | BV(TWEN);
101                 WAIT_TWI_READY;
102
103                 if (TW_STATUS == TW_MT_SLA_ACK)
104                         return true;
105                 else if (TW_STATUS != TW_MT_SLA_NACK)
106                 {
107                         kprintf("!TW_MT_SLA_(N)ACK: %x\n", TWSR);
108                         break;
109                 }
110                 else if (timer_clock() - start > ms_to_ticks(CONFIG_TWI_START_TIMEOUT))
111                 {
112                         kprintf("Timeout on TWI_MT_START\n");
113                         break;
114                 }
115         }
116
117         return false;
118 }
119
120
121 /**
122  * Send START condition and select slave for read.
123  * \c id is the device id comprehensive of address left shifted by 1.
124  * The LSB of \c id is ignored and set to 1 for read operation.
125  *
126  * \return true on success, false otherwise.
127  */
128 bool twi_start_r(uint8_t id)
129 {
130         if (twi_start())
131         {
132                 TWDR = id | READ_BIT;
133                 TWCR = BV(TWINT) | BV(TWEN);
134                 WAIT_TWI_READY;
135
136                 if (TW_STATUS == TW_MR_SLA_ACK)
137                         return true;
138
139                 kprintf("!TW_MR_SLA_ACK: %x\n", TWSR);
140         }
141
142         return false;
143 }
144
145
146 /**
147  * Send STOP condition.
148  */
149 void twi_stop(void)
150 {
151         TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
152 }
153
154
155 /**
156  * Put a single byte in master transmitter mode
157  * to the selected slave device through the TWI bus.
158  *
159  * \return true on success, false on error.
160  */
161 bool twi_put(const uint8_t data)
162 {
163         TWDR = data;
164         TWCR = BV(TWINT) | BV(TWEN);
165         WAIT_TWI_READY;
166         if (TW_STATUS != TW_MT_DATA_ACK)
167         {
168                 kprintf("!TW_MT_DATA_ACK: %x\n", TWSR);
169                 return false;
170         }
171         return true;
172 }
173
174 /**
175  * Get 1 byte from slave in master transmitter mode
176  * to the selected slave device through the TWI bus.
177  * If \a ack is true issue a ACK after getting the byte,
178  * otherwise a NACK is issued.
179  *
180  * \return the byte read if ok, EOF on errors.
181  */
182 int twi_get(bool ack)
183 {
184         TWCR = BV(TWINT) | BV(TWEN) | (ack ? BV(TWEA) : 0);
185         WAIT_TWI_READY;
186
187         if (ack)
188         {
189                 if (TW_STATUS != TW_MR_DATA_ACK)
190                 {
191                         kprintf("!TW_MR_DATA_ACK: %x\n", TWSR);
192                         return EOF;
193                 }
194         }
195         else
196         {
197                 if (TW_STATUS != TW_MR_DATA_NACK)
198                 {
199                         kprintf("!TW_MR_DATA_NACK: %x\n", TWSR);
200                         return EOF;
201                 }
202         }
203
204         /* avoid sign extension */
205         return (int)(uint8_t)TWDR;
206 }
207
208
209 /**
210  * Send a sequence of bytes in master transmitter mode
211  * to the selected slave device through the TWI bus.
212  *
213  * \return true on success, false on error.
214  */
215 bool twi_send(const void *_buf, size_t count)
216 {
217         const uint8_t *buf = (const uint8_t *)_buf;
218
219         while (count--)
220         {
221                 if (!twi_put(*buf++))
222                         return false;
223         }
224         return true;
225 }
226
227
228 /**
229  * Receive a sequence of one or more bytes from the
230  * selected slave device in master receive mode through
231  * the TWI bus.
232  *
233  * Received data is placed in \c buf.
234  *
235  * \note a NACK is automatically given on the last received
236  *         byte.
237  *
238  * \return true on success, false on error
239  */
240 bool twi_recv(void *_buf, size_t count)
241 {
242         uint8_t *buf = (uint8_t *)_buf;
243
244         /*
245          * When reading the last byte the TWEA bit is not
246          * set, and the eeprom should answer with NACK
247          */
248         while (count--)
249         {
250                 /*
251                  * The last byte read does not has an ACK
252                  * to stop communication.
253                  */
254                 int c = twi_get(count);
255
256                 if (c == EOF)
257                         return false;
258                 else
259                         *buf++ = c;
260         }
261
262         return true;
263 }
264
265
266 MOD_DEFINE(twi);
267
268 /**
269  * Initialize TWI module.
270  */
271 void twi_init(void)
272 {
273         ATOMIC(
274                 /*
275                  * This is pretty useless according to AVR's datasheet,
276                  * but it helps us driving the TWI data lines on boards
277                  * where the bus pull-up resistors are missing.  This is
278                  * probably due to some unwanted interaction between the
279                  * port pin and the TWI lines.
280                  */
281 #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281
282                 PORTD |= BV(PD0) | BV(PD1);
283                 DDRD  |= BV(PD0) | BV(PD1);
284 #elif CPU_AVR_ATMEGA8
285                 PORTC |= BV(PC4) | BV(PC5);
286                 DDRC  |= BV(PC4) | BV(PC5);
287 #elif CPU_AVR_ATMEGA32
288                 PORTC |= BV(PC1) | BV(PC0);
289                 DDRC  |= BV(PC1) | BV(PC0);
290 #else
291                 #error Unsupported architecture
292 #endif
293
294                 /*
295                  * Set speed:
296                  * F = CLOCK_FREQ / (16 + 2*TWBR * 4^TWPS)
297                  */
298                 #ifndef CONFIG_TWI_FREQ
299                         #warning Using default value of 300000L for CONFIG_TWI_FREQ
300                         #define CONFIG_TWI_FREQ  300000L /* ~300 kHz */
301                 #endif
302                 #define TWI_PRESC 1       /* 4 ^ TWPS */
303
304                 TWBR = (CLOCK_FREQ / (2 * CONFIG_TWI_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);
305                 TWSR = 0;
306                 TWCR = BV(TWEN);
307         );
308         MOD_INIT(twi);
309 }