v0.1 board believed to be reading Vbat, Pressure, and X/Y/Z correctly now,
[fw/openalt] / i2c / i2cInt.c
1 #include "FreeRTOS.h"
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <sys/times.h>
6
7 #include "i2c.h"
8
9 //
10 //  Default timeout, in milliseconds for generic read/write
11 //
12 #define I2C_DEFAULT_TIMEOUT 100
13 #undef  I2C_DEBUG
14
15 //
16 //
17 //
18 typedef enum
19 {
20   ACKPOLL_NO = 0,
21   ACKPOLL_YES
22 }
23 ackPoll_e;
24
25 //
26 //
27 //
28 static volatile int i2cBusInUse;
29 static U8 i2cAddress;
30 static U8 *i2cDataBuffer;
31 static int i2cDataLenWrite;
32 static int i2cDataLenRead;
33 static unsigned int i2cTimeoutInTicks = I2C_DEFAULT_TIMEOUT / portTICK_RATE_MS;
34 static int i2cDataCnt;
35 static ackPoll_e i2cAckPoll = ACKPOLL_NO;
36
37 //
38 //
39 //
40 #ifdef I2C_DEBUG
41 static U8 i2cTransactions [64];
42 static int i2cTransactionsIndex;
43 #define i2cDebug(x) do { if (i2cAckPoll && (i2cTransactionsIndex < (int) sizeof (i2cTransactions))) i2cTransactions [i2cTransactionsIndex++] = x; } while (0)
44 #define i2cDebugReset() do { i2cTransactionsIndex = 0; } while (0)
45 #else
46 #define i2cDebug(x) do { } while (0)
47 #define i2cDebugReset() do { } while (0)
48 #endif
49
50 static void i2cISR (void) __attribute__ ((interrupt ("IRQ")));
51 static void i2cISR (void)
52 {
53   i2cErrno = (I2C0_STAT & I2C_STAT_STATMASK);
54   i2cDebug (i2cErrno);
55
56   switch (i2cErrno)
57   {
58     //
59     //  Transmit conditions
60     //
61     case I2CERR_BUSERRORx : // 0x00
62       {
63         I2C0_CONSET = I2C_CONSET_STO | I2C_CONSET_AA;
64         i2cAckPoll = ACKPOLL_NO;
65         i2cBusInUse = FALSE;
66       }
67       break;
68
69     case I2CERR_STARTTX : // 0x08
70     case I2CERR_REPEATEDSTARTTX : // 0x10
71       {
72         i2cDebug (i2cAddress);
73         I2C0_DAT = i2cAddress;
74       }
75       break;
76
77     case I2CERR_SLAWTX_ACKRX : // 0x18
78     case I2CERR_DATTX_ACKRX : // 0x28
79       {
80         i2cAckPoll = ACKPOLL_NO;
81
82         if (i2cDataLenWrite && (i2cDataCnt < i2cDataLenWrite))
83         {
84           i2cDebug (i2cDataBuffer [i2cDataCnt]);
85           I2C0_DAT = i2cDataBuffer [i2cDataCnt++];
86           I2C0_CONCLR = I2C_CONCLR_STAC;
87         }
88         else
89         {
90           if (!i2cDataLenRead)
91           {
92             i2cDebug (0xff);
93             I2C0_CONCLR = I2C_CONCLR_STAC;
94             I2C0_CONSET = I2C_CONSET_STO;
95             i2cErrno = I2CERR_NONE;
96             i2cBusInUse = FALSE;
97           }
98           else
99           {
100             i2cDebug (0xfe);
101             i2cAddress |= 0x01;
102             i2cDataCnt = 0;
103             I2C0_CONSET = I2C_CONSET_STA;
104           }
105         }
106       }
107       break;
108
109     case I2CERR_DATRX_NACKTX : // 0x58
110       {
111         i2cDataBuffer [i2cDataCnt++] = I2C0_DAT;
112         i2cDebug (i2cDataBuffer [i2cDataCnt - 1]);
113         i2cErrno = I2CERR_NONE;
114       }
115
116     case I2CERR_SLAWTX_NACKRX : // 0x20
117     case I2CERR_SLARTX_NACKRX : // 0x48
118       {
119         if (i2cAckPoll)
120           break;
121       }
122
123     case I2CERR_DATTX_NACKRX : // 0x30
124       {
125         I2C0_CONCLR = I2C_CONCLR_STAC;
126         I2C0_CONSET = I2C_CONSET_STO;
127         i2cBusInUse = FALSE;
128       }
129       break;
130
131     case I2CERR_ARBLOST : // 0x38
132       {
133         I2C0_CONSET = I2C_CONSET_STA;
134       }
135       break;
136
137     //
138     //  Receive byte conditions (fall through is intentional)
139     //
140     case I2CERR_DATRX_ACKTX : // 0x50
141       {
142         i2cDataBuffer [i2cDataCnt++] = I2C0_DAT;
143         i2cDebug (i2cDataBuffer [i2cDataCnt - 1]);
144       }
145
146     case I2CERR_SLARTX_ACKRX : // 0x40
147       {
148         if (i2cDataCnt < i2cDataLenRead - 1)
149         {
150           I2C0_CONCLR = I2C_CONCLR_STAC;
151           I2C0_CONSET = I2C_CONSET_AA;
152         }
153         else
154           I2C0_CONCLR = I2C_CONCLR_STAC | I2C_CONCLR_AAC;
155       }
156       break;
157
158     case I2CERR_NOINFO :
159       break;
160
161     default:
162       {
163         I2C0_CONCLR = I2C_CONCLR_I2ENC;
164         i2cAckPoll = ACKPOLL_NO;
165         i2cBusInUse = FALSE;
166       }
167       break;
168   }
169
170   I2C0_CONCLR = I2C_CONSET_SI;
171   VIC_VectAddr = 0;
172 }
173
174 //
175 // i2c1Init
176 //
177 void i2cInit (void)
178 {
179   i2cBusInUse = FALSE;
180   i2cAckPoll = ACKPOLL_NO;
181
182   SCB_PCONP |= SCB_PCONP_PCI2C0;
183
184   PCB_PINSEL0 = (PCB_PINSEL0 & ~(PCB_PINSEL0_P02_MASK | PCB_PINSEL0_P03_MASK)) | (PCB_PINSEL0_P02_SCL0 | PCB_PINSEL0_P03_SDA0);
185
186   I2C0_CONCLR = I2C_CONCLR_MASK;
187   I2C0_CONSET = I2C_CONSET_I2EN;
188 #ifdef FC1025
189   // the Microchip 24FC1025 can handle a 1 Mhz clock
190   // PCLK / (i2c_clock * 2), with 12 Mhz xtal and 48 Mhz PCLK that's 24...
191   I2C0_SCLL   = 24;
192   I2C0_SCLH   = 24;
193 #else
194   I2C0_SCLL   = 240;
195   I2C0_SCLH   = 240;
196 #endif
197
198   //
199   //  Initialize the interrupt vector
200   //
201   VIC_IntSelect &= ~VIC_IntSelect_I2C0;
202   VIC_VectCntl7 = VIC_VectCntl_ENABLE | VIC_Channel_I2C0;
203   VIC_VectAddr7 = (int) i2cISR;
204   VIC_IntEnable = VIC_IntEnable_I2C0;
205 }
206
207 //
208 //
209 //
210 static int i2cWaitComplete (int ticks)
211 {
212   if (i2cBusInUse)
213   {
214     clock_t theFuture;
215
216     for (theFuture = times (NULL) + ticks; i2cBusInUse; )
217     {
218       if (times (NULL) > theFuture)
219       {
220         I2C0_CONCLR = I2C_CONCLR_I2ENC;
221         i2cErrno = I2CERR_TIMEOUTWC;
222         return -1;
223       }
224     }
225   }
226
227   return (i2cErrno == I2CERR_NONE) ? 0 : -1;
228 }
229
230 static int i2cPoll (U8 address)
231 {
232   clock_t theFuture = times (NULL) + 10;
233
234   VIC_IntEnClr = VIC_IntEnClr_I2C0;
235
236   while (times (NULL) < theFuture)
237   {
238     I2C0_CONCLR = I2C_CONSET_SI;
239     I2C0_CONSET = I2C_CONSET_STA;
240
241     while (!(I2C0_CONSET & I2C_CONSET_SI))
242       ;
243
244     I2C0_CONCLR = I2C_CONCLR_STAC | I2C_CONCLR_SIC;
245     I2C0_DAT = address & ~0x01;
246
247     while (!(I2C0_CONSET & I2C_CONSET_SI))
248       ;
249
250     if ((i2cErrno = I2C0_STAT) == I2CERR_SLAWTX_ACKRX)
251       break;
252   }
253
254   if (i2cErrno != I2CERR_SLAWTX_ACKRX)
255     i2cErrno = I2CERR_TIMEOUTACKPOLL;
256
257   I2C0_CONCLR = I2C_CONCLR_SIC;
258   I2C0_CONSET = I2C_CONSET_STO | I2C_CONSET_AA;
259
260   while (I2C0_CONSET & I2C_CONSET_STO)
261     ;
262
263   VIC_IntEnable = VIC_IntEnable_I2C0;
264
265   return (i2cErrno == I2CERR_SLAWTX_ACKRX) ? 0 : -1;
266 }
267
268 //
269 //
270 //
271 static int i2cKickOff (U8 address, U8 *buffer, int bufferLenWrite, int bufferLenRead, ackPoll_e ackPoll)
272 {
273   //
274   //  Determine if our first operation will be a write or read.  If both, the
275   //  write always occurs first.
276   //
277   if (bufferLenWrite)
278     address &= ~0x01;
279   else if (bufferLenRead)
280     address |= 0x01;
281   else
282     address &= ~0x01;
283
284   //
285   //  Wait until last I2C operation has finished.  
286   //
287   if (i2cBusInUse && i2cWaitComplete (i2cTimeoutInTicks))
288   {
289     i2cErrno = I2CERR_TIMEOUT;
290     return -1;
291   }
292
293   //
294   //  Mark bus as in use, save the address, buffer and length
295   //
296   i2cBusInUse = TRUE;
297   i2cAddress = address;
298   i2cDataBuffer = buffer;
299   i2cDataLenWrite = bufferLenWrite;
300   i2cDataLenRead = bufferLenRead;
301   i2cDataCnt = 0;
302   i2cAckPoll = ackPoll;
303   i2cDebugReset ();
304
305   //
306   //  Clear any outstanding bits, enable the interface, and send a start bit.
307   //  Once the start bit goes out, the interrupt drive state machine begins.
308   //
309   I2C0_CONCLR = I2C_CONCLR_MASK;
310   I2C0_CONSET = I2C_CONSET_I2EN;
311   I2C0_CONSET = I2C_CONSET_STA;
312
313   return 0;
314 }
315
316 //
317 //
318 //
319 static int i2cWriteBufferEx (U8 address, U8 *buffer, U32 bufferLength, int milliseconds)
320 {
321   int r;
322
323   if (!(r = i2cKickOff (address, buffer, bufferLength, 0, ACKPOLL_NO)))
324     r = i2cWaitComplete (milliseconds / portTICK_RATE_MS);
325
326   return r;
327 }
328
329 static int i2cReadBufferEx (U8 address, U8 *buffer, U32 bufferLength, int milliseconds)
330 {
331   int r;
332
333   if (!(r = i2cKickOff (address, buffer, 0, bufferLength, ACKPOLL_NO)))
334     r = i2cWaitComplete (milliseconds / portTICK_RATE_MS);
335
336   return r;
337 }
338
339 static int i2cWriteReadBufferEx (U8 address, U8 *buffer, U32 putLength, U32 getLength, int milliseconds)
340 {
341   int r;
342
343   if (!(r = i2cKickOff (address, buffer, putLength, getLength, ACKPOLL_NO)))
344     r = i2cWaitComplete (milliseconds / portTICK_RATE_MS);
345
346   return r;
347 }
348
349 //
350 //
351 //
352 void i2cSetTimeout (unsigned int timeoutInMilliseconds)
353 {
354   if (timeoutInMilliseconds < portTICK_RATE_MS)
355     timeoutInMilliseconds = portTICK_RATE_MS;
356
357   i2cTimeoutInTicks = timeoutInMilliseconds / portTICK_RATE_MS;
358 }
359
360 void i2cDump (void)
361 {
362 #ifdef I2C_DEBUG
363   int i;
364
365   for (i = 0; i < i2cTransactionsIndex; i++)
366     printf ("0x%02x ", i2cTransactions [i]);
367
368   printf ("\n");
369 #else
370   printf ("Not compiled for i2c debugging\n");
371 #endif
372 }
373
374 //
375 //  DANGER, WILL ROBINSON!  The callers buffer must persist until we're done
376 //
377 int i2cWriteBuffer (U8 address, U8 *buffer, U32 bufferLength)
378 {
379   return i2cWriteBufferEx (address, buffer, bufferLength, i2cTimeoutInTicks);
380 }
381
382 int i2cReadBuffer (U8 address, U8 *buffer, U32 bufferLength)
383 {
384   return i2cReadBufferEx (address, buffer, bufferLength, i2cTimeoutInTicks);
385 }
386
387 int i2cWriteReadBuffer (U8 address, U8 *buffer, U32 putLength, U32 getLength)
388 {
389   return i2cWriteReadBufferEx (address, buffer, putLength, getLength, i2cTimeoutInTicks);
390 }
391
392 int i2cWriteBufferPoll (U8 address, U8 *buffer, U32 bufferLength)
393 {
394   int r;
395
396   if (!(r = i2cKickOff (address, buffer, bufferLength, 0, ACKPOLL_NO)))
397     if (!(r = i2cWaitComplete (i2cTimeoutInTicks)))
398       r = i2cPoll (address);
399
400   return r;
401 }
402
403 int i2cWriteReadBufferPoll (U8 address, U8 *buffer, U32 putLength, U32 getLength)
404 {
405   int r;
406
407   if (!(r = i2cKickOff (address, buffer, putLength, getLength, ACKPOLL_NO)))
408     if (!(r = i2cWaitComplete (i2cTimeoutInTicks)))
409       r = i2cPoll (address);
410
411   return r;
412 }