madgwick: remove unused code (fixed point lib)
[protos/imu.git] / i2cm_sw.c
1 /*
2  *  Copyright Droids Corporation, Microb Technology, Eirbot (2005)
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  *  Revision : $Id$
19  *
20  */
21
22
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <aversive.h>
28
29 #include <aversive/wait.h>
30
31
32 #include <util/delay.h>
33
34
35 #include "i2cm_sw.h"
36
37
38
39
40 volatile i2cm_state g_i2cm_NUM_state = NOT_INIT;
41 volatile uint8_t g_i2cm_NUM_byte;
42
43 void (*g_i2cm_NUM_event)(i2cm_state state);
44
45 /*
46   Mini Arduino
47   I2C:
48   A4 = PC4/SDA
49   A5 = PC5/SCL
50 */
51
52 #define I2CM_NUM_SCL_PORT  PORTC
53 #define I2CM_NUM_SCL_BIT   5
54
55 #define  I2CM_NUM_SDA_PORT PORTC
56 #define  I2CM_NUM_SDA_BIT  4
57
58 #define I2CM_NUM_SCL   I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT
59 #define I2CM_NUM_SDA   I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT
60
61
62
63
64 void i2cm_NUM_init(void)
65 {
66         /*
67           - port SCL/SDA is set to 0
68           - i2c is then driven using DDR 0 (Hi-Z) or 1 (For Low)
69          */
70
71         // SCL high
72         cbi(DDR(I2CM_NUM_SCL_PORT),I2CM_NUM_SCL_BIT);
73         I2C_HIGH(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
74
75         // SDA high
76         cbi(DDR(I2CM_NUM_SDA_PORT),I2CM_NUM_SDA_BIT);
77         I2C_HIGH(I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT);
78         I2CM_NUM_DELAY();
79
80         g_i2cm_NUM_state = I2CM_READY;
81 }
82
83
84 void i2cm_NUM_manage(void)
85 {
86         if ( (g_i2cm_NUM_event  != NULL) && (g_i2cm_NUM_state  != I2CM_READY) ) {
87                 g_i2cm_NUM_event( g_i2cm_NUM_state );
88                 // reset notification
89                 if (g_i2cm_NUM_state != I2CM_BUSY)
90                         g_i2cm_NUM_state = I2CM_READY;
91         }
92 }
93
94 uint8_t i2cm_NUM_get_state(void)
95 {
96         return g_i2cm_NUM_state;
97 }
98
99
100 uint8_t i2cm_NUM_get_received_byte(void)
101 {
102         g_i2cm_NUM_state = I2CM_READY;
103         return g_i2cm_NUM_byte;
104 }
105
106 void i2cm_NUM_register_event(void (*func)(i2cm_state state))
107 {
108         uint8_t flags;
109         IRQ_LOCK(flags);
110         g_i2cm_NUM_event = func;
111         IRQ_UNLOCK(flags);
112 }
113
114
115 uint8_t i2cm_NUM_send_byte(uint8_t byte)
116 {
117         uint8_t mask;
118         uint8_t err = 0;
119
120
121         g_i2cm_NUM_state = I2CM_BUSY;
122
123         // SCL should already be low
124         //  I2C_LOW(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
125         //  I2CM_NUM_DELAY();
126
127         mask = 0x80;
128         while (mask) {
129
130
131                 // data out
132                 if (mask & byte)
133                         I2C_HIGH(I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT);
134                 else
135                         I2C_LOW(I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT);
136                 I2CM_NUM_DELAY();
137                 mask >>=1;
138
139                 // delay needed ?
140                 //I2CM_NUM_DELAY();
141
142                 // clock High
143                 I2C_HIGH(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
144                 I2CM_NUM_DELAY();
145                 while ( bit_is_clear(PIN(I2CM_NUM_SCL_PORT), I2CM_NUM_SCL_BIT) );// slave handshake
146
147                 // clock low
148                 I2C_LOW(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
149
150         }
151
152         /* receive ack */
153
154         // release SDA
155         I2C_HIGH(I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT);
156         I2CM_NUM_BIT_DELAY();
157
158         // clock HIGH
159         I2C_HIGH(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
160         I2CM_NUM_DELAY();
161         while ( bit_is_clear(PIN(I2CM_NUM_SCL_PORT), I2CM_NUM_SCL_BIT) );// slave handshake
162
163         // receive ACK
164         if (bit_is_set(I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT))
165                 err = I2CM_SENT_NO_ACK;
166
167         // clock low
168         I2C_LOW(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
169         I2CM_NUM_DELAY();
170
171         return err;
172 }
173
174
175 uint8_t i2cm_NUM_send_start(uint8_t sla_w)
176 {
177         uint8_t err;
178         uint16_t i;
179         g_i2cm_NUM_state = I2CM_BUSY;
180
181         I2C_HIGH(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
182         I2C_HIGH(I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT);
183
184         I2CM_NUM_DELAY();
185
186         /* wait for bus realese */
187         for (i=0;i<0x8000; i++){
188                 if( bit_is_set(PIN(I2CM_NUM_SCL_PORT), I2CM_NUM_SCL_BIT) && \
189                     bit_is_set(PIN(I2CM_NUM_SDA_PORT), I2CM_NUM_SDA_BIT) )
190                         break;
191         }
192
193         //      while ( bit_is_clear(PIN(I2CM_NUM_SCL_PORT), I2CM_NUM_SCL_BIT) );// slave handshake
194
195         // start condition
196         I2C_LOW(I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT);
197         I2CM_NUM_DELAY();
198         I2C_LOW(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
199         I2CM_NUM_DELAY();
200
201         err = i2cm_NUM_send_byte(sla_w);
202         return err;
203 }
204
205
206
207 uint8_t i2cm_NUM_send_stop(void)
208 {
209         g_i2cm_NUM_state = I2CM_BUSY;
210
211         // data down
212         I2C_LOW(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
213         I2C_LOW(I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT);
214         I2CM_NUM_DELAY();
215
216         // stop condition
217         I2C_HIGH(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
218         I2CM_NUM_DELAY();
219         I2C_HIGH(I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT);
220         I2CM_NUM_DELAY();
221
222         g_i2cm_NUM_state = I2CM_SENT_STOP;
223         return 0;
224 }
225
226
227 uint8_t i2cm_NUM_receive_byte(uint8_t last)
228 {
229         uint8_t mask,data;
230
231         g_i2cm_NUM_state = I2CM_BUSY;
232
233         I2C_HIGH(I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT);
234
235
236         data = 0;
237         mask = 0x80;
238         while (mask) {
239
240                 // clock High
241                 I2C_HIGH(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
242                 I2CM_NUM_DELAY();
243                 while ( bit_is_clear(PIN(I2CM_NUM_SCL_PORT), I2CM_NUM_SCL_BIT) );// slave handshake
244
245                 if (bit_is_set(PIN(I2CM_NUM_SDA_PORT),I2CM_NUM_SDA_BIT))
246                         data |= mask;
247
248                 // clock low
249                 I2C_LOW(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
250                 I2CM_NUM_DELAY();
251
252                 mask >>=1;
253         }
254
255         if (!last){
256                 /* send ack */
257                 I2C_LOW(I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT);
258                 I2CM_NUM_BIT_DELAY();
259         }
260
261         // clock HIGH
262         I2C_HIGH(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
263         I2CM_NUM_DELAY();
264         while ( bit_is_clear(PIN(I2CM_NUM_SCL_PORT), I2CM_NUM_SCL_BIT) );// slave handshake
265
266         // clock low
267         I2C_LOW(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
268         I2CM_NUM_DELAY();
269
270         if (!last) {
271                 // release DATA
272                 I2C_HIGH(I2CM_NUM_SDA_PORT, I2CM_NUM_SDA_BIT);
273                 I2CM_NUM_BIT_DELAY();
274         }
275
276         g_i2cm_NUM_byte  = data;
277         g_i2cm_NUM_state = I2CM_RECEIVED_BYTE;
278
279         I2C_HIGH(I2CM_NUM_SCL_PORT, I2CM_NUM_SCL_BIT);
280
281         return 0;
282 }
283
284
285
286 uint8_t i2c_send(uint8_t addr, uint8_t* data, uint8_t len, uint8_t dummy)
287 {
288         uint8_t i;
289         uint8_t err = 0;
290
291         err = i2cm_NUM_send_start((addr<<1) | 0);
292         if (err)
293                 return err;
294
295         for (i=0; i<len; i++) {
296                 err = i2cm_NUM_send_byte(data[i]);
297                 if (err)
298                         break;
299         }
300
301         i2cm_NUM_send_stop();
302         return err;
303 }
304
305
306 uint8_t i2c_buf[0x20];
307
308 uint8_t i2c_recv(uint8_t addr, uint8_t len, uint8_t dummy)
309 {
310         uint8_t i;
311         uint8_t err = 0;
312
313         err = i2cm_NUM_send_start((addr<<1) | 1);
314         if (err)
315                 return err;
316
317         I2CM_NUM_DELAY();
318
319         for (i=0; i<len; i++){
320                 err =i2cm_NUM_receive_byte(i == len-1);
321                 i2c_buf[i] = g_i2cm_NUM_byte;
322                 if (err)
323                         break;
324         }
325         i2cm_NUM_send_stop();
326         return err;
327 }
328
329
330 uint8_t i2c_get_recv_buffer(uint8_t* buf, uint8_t len)
331 {
332         uint8_t i;
333         for (i=0; i<len; i++)
334                 buf[i] = i2c_buf[i];
335         return len;
336 }
337
338