changing circuitry to disable RTC, update initialization to match
[fw/openalt] / i2c / i2cIntWorking.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
14 //
15 //
16 //
17 static volatile int i2cBusInUse;
18 static U8 i2cAddress;
19 static U8 *i2cDataBuffer;
20 static int i2cDataLenWrite;
21 static int i2cDataLenRead;
22 static int i2cTimeout = I2C_DEFAULT_TIMEOUT;
23 static U8 *i2cDataPtr;
24 static U8 i2cTransactions [64];
25 static int i2cTransactionsIndex;
26
27 //
28 //
29 //
30 #define i2cDebug(x) do { if (i2cTransactionsIndex < (int) sizeof (i2cTransactions)) i2cTransactions [i2cTransactionsIndex++] = x; } while (0)
31
32 static void i2cISR (void) __attribute__ ((interrupt ("IRQ")));
33 static void i2cISR (void)
34 {
35   i2cErrno = (I2C0_STAT & I2C_STAT_STATMASK);
36   i2cDebug (i2cErrno);
37
38   switch (i2cErrno)
39   {
40     //
41     //  Transmit conditions
42     //
43     case I2CERR_BUSERRORx : // 0x00
44       {
45         I2C0_CONSET = I2C_CONSET_STO | I2C_CONSET_AA;
46         i2cBusInUse = FALSE;
47       }
48       break;
49
50     case I2CERR_STARTTX : // 0x08
51       {
52         i2cDebug (i2cAddress);
53         I2C0_DAT = i2cAddress;
54       }
55       break;
56
57     case I2CERR_REPEATEDSTARTTX : // 0x10
58       {
59         i2cDebug (i2cAddress);
60         I2C0_DAT = i2cAddress;
61       }
62       break;
63
64     case I2CERR_SLAWTX_ACKRX : // 0x18
65       {
66         i2cDebug (*i2cDataPtr);
67         I2C0_DAT = *i2cDataPtr++;
68         I2C0_CONCLR = I2C_CONCLR_STAC;
69       }
70       break;
71
72     case I2CERR_SLAWTX_NACKRX : // 0x20
73       {
74         I2C0_CONSET = I2C_CONSET_STO;
75         i2cBusInUse = FALSE;
76       }
77       break;
78
79     case I2CERR_DATTX_ACKRX : // 0x28
80       {
81         if (--i2cDataLenWrite)
82         {
83           i2cDebug (*i2cDataPtr);
84           I2C0_DAT = *i2cDataPtr++;
85           I2C0_CONCLR = I2C_CONCLR_STAC;
86         }
87         else
88         {
89           if (!i2cDataLenRead)
90           {
91             i2cDebug (0xff);
92             I2C0_CONCLR = I2C_CONCLR_STAC;
93             I2C0_CONSET = I2C_CONSET_STO;
94             i2cBusInUse = FALSE;
95           }
96           else
97           {
98             i2cDebug (0xfe);
99             i2cAddress |= 0x01;
100             i2cDataPtr = i2cDataBuffer;
101             I2C0_CONSET = I2C_CONSET_STA;
102           }
103         }
104       }
105       break;
106
107     case I2CERR_DATTX_NACKRX : // 0x30
108       {
109         I2C0_CONCLR = I2C_CONCLR_STAC;
110         I2C0_CONSET = I2C_CONSET_STO;
111         i2cBusInUse = FALSE;
112       }
113       break;
114
115     case I2CERR_ARBLOST : // 0x38
116       {
117         I2C0_CONSET = I2C_CONSET_STA;
118       }
119       break;
120
121     //
122     //  Receive byte conditions
123     //
124     case I2CERR_SLARTX_ACKRX : // 0x40
125       {
126         I2C0_CONCLR = I2C_CONCLR_STAC;
127         I2C0_CONSET = I2C_CONSET_AA;
128       }
129       break;
130
131     case I2CERR_SLARTX_NACKRX : // 0x48
132       {
133         I2C0_CONCLR = I2C_CONCLR_STAC;
134         I2C0_CONSET = I2C_CONSET_STO;
135         i2cBusInUse = FALSE;
136       }
137       break;
138
139     case I2CERR_DATRX_ACKTX : // 0x50
140       {
141         *i2cDataPtr++ = I2C0_DAT;
142         i2cDebug (*(i2cDataPtr - 1));
143
144         if (--i2cDataLenRead)
145         {
146           I2C0_CONCLR = I2C_CONCLR_STAC;
147           I2C0_CONSET = I2C_CONSET_AA;
148         }
149         else
150         {
151           I2C0_CONCLR = I2C_CONCLR_STAC | I2C_CONCLR_AAC;
152           i2cBusInUse = FALSE;
153         }
154       }
155       break;
156
157     case I2CERR_DATRX_NACKTX : // 0x58
158       {
159         // *i2cDataPtr = I2C0_DAT;
160         // i2cDebug (*i2cDataPtr);
161         I2C0_CONCLR = I2C_CONCLR_STAC;
162         I2C0_CONSET = I2C_CONSET_STO;
163         i2cBusInUse = FALSE;
164       }
165       break;
166
167     case I2CERR_NOINFO :
168       break;
169
170     default:
171       {
172         I2C0_CONCLR = I2C_CONCLR_I2ENC;
173         i2cBusInUse = FALSE;
174       }
175       break;
176   }
177
178   I2C0_CONCLR = I2C_CONSET_SI;
179   VIC_VectAddr = 0;
180 }
181
182 //
183 // i2c1Init
184 //
185 void i2cInit (void)
186 {
187   i2cBusInUse = FALSE;
188
189   SCB_PCONP |= SCB_PCONP_PCI2C0;
190
191   PCB_PINSEL0 = (PCB_PINSEL0 & ~(PCB_PINSEL0_P02_MASK | PCB_PINSEL0_P03_MASK)) | (PCB_PINSEL0_P02_SCL0 | PCB_PINSEL0_P03_SDA0);
192
193   I2C0_CONCLR = I2C_CONCLR_MASK;
194   I2C0_CONSET = I2C_CONSET_I2EN;
195   I2C0_SCLL   = 240;
196   I2C0_SCLH   = 240;
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 i2cTransferBytes (U8 address, U8 *buffer, int bufferLenWrite, int bufferLenRead)
211 {
212   //
213   //  Determine if our first operation will be a write or read.  If both, the
214   //  write always occurs first.
215   //
216   if (bufferLenWrite)
217     address &= ~0x01;
218   else if (bufferLenRead)
219     address |= 0x01;
220   else
221   {
222     i2cErrno = I2CERR_OTHER;
223     return -1;
224   }
225
226   //
227   //  Wait until last I2C operation has finished.  
228   //
229   if (i2cBusInUse && i2cWaitComplete (i2cTimeout))
230   {
231     i2cErrno = I2CERR_TIMEOUT;
232     return -1;
233   }
234
235   //
236   //  Mark bus as in use, save the address, buffer and length
237   //
238   i2cBusInUse = TRUE;
239   i2cAddress = address;
240   i2cDataBuffer = buffer;
241   i2cDataLenWrite = bufferLenWrite;
242   i2cDataLenRead = bufferLenRead;
243   i2cDataPtr = buffer;
244
245   i2cTransactionsIndex = 0; // ###
246
247   I2C0_CONCLR = I2C_CONCLR_MASK;
248   I2C0_CONSET = I2C_CONSET_I2EN;
249   I2C0_CONSET = I2C_CONSET_STA;
250
251   return 0;
252 }
253
254 //
255 //
256 //
257 int i2cWaitComplete (int milliseconds)
258 {
259   if (i2cBusInUse)
260   {
261     clock_t theFuture;
262
263     if (milliseconds < 10)
264       milliseconds = 10;
265
266     for (theFuture = times (NULL) + (milliseconds / 10); i2cBusInUse; )
267     {
268       if (times (NULL) > theFuture)
269       {
270         I2C0_CONCLR = I2C_CONCLR_I2ENC;
271         i2cErrno = I2CERR_TIMEOUTWC;
272         return -1;
273       }
274     }
275   }
276
277   return 0;
278 }
279
280 //
281 //
282 //
283 static int i2cWriteBufferEx (U8 address, U8 *buffer, U32 bufferLength, int milliseconds)
284 {
285   if (i2cTransferBytes (address, buffer, bufferLength, 0))
286     return -1;
287
288   return i2cWaitComplete (milliseconds);
289 }
290
291 static int i2cReadBufferEx (U8 address, U8 *buffer, U32 bufferLength, int milliseconds)
292 {
293   if (i2cTransferBytes (address, buffer, 0, bufferLength))
294     return -1;
295
296   return i2cWaitComplete (milliseconds);
297 }
298
299 static int i2cWriteReadBufferEx (U8 address, U8 *buffer, U32 putLength, U32 getLength, int milliseconds)
300 {
301   if (i2cTransferBytes (address, buffer, putLength, getLength))
302     return -1;
303
304   return i2cWaitComplete (milliseconds);
305 }
306
307 //
308 //  DANGER, WILL ROBINSON!  The callers buffer must persist until we're done
309 //
310 int i2cWriteBuffer (U8 address, U8 *buffer, U32 bufferLength)
311 {
312   return i2cWriteBufferEx (address, buffer, bufferLength, i2cTimeout);
313 }
314
315 int i2cReadBuffer (U8 address, U8 *buffer, U32 bufferLength)
316 {
317   return i2cReadBufferEx (address, buffer, bufferLength, i2cTimeout);
318 }
319
320 int i2cWriteReadBuffer (U8 address, U8 *buffer, U32 putLength, U32 getLength)
321 {
322   return i2cWriteReadBufferEx (address, buffer, putLength, getLength, i2cTimeout);
323 }
324
325 void i2cSetTimeout (int timeoutInMilliseconds)
326 {
327   if (timeoutInMilliseconds < 10)
328     timeoutInMilliseconds = 10;
329
330   i2cTimeout = timeoutInMilliseconds;
331 }
332
333 void i2cDump (void)
334 {
335   int i;
336
337   for (i = 0; i < i2cTransactionsIndex; i++)
338     printf ("0x%02x ", i2cTransactions [i]);
339
340   printf ("\n");
341 }
342