Imported Upstream version 2.9.0
[debian/cc1111] / device / lib / ds390 / i2c390.c
1 /* This implemenation is based on an example I once grabbed from
2    the Philips bbs.
3    Don't know who wrote it, but is has been hacked so heavily, he/she wouldn't
4    recogize it anyway */
5
6 //#define DEBUG_I2C ==> DON'T DO THIS, THIS IS A LIBRARY <==
7
8 #ifdef DEBUG_I2C
9 #include <stdio.h>
10 #else
11 #include <tinibios.h>
12 #endif
13
14 // we are (ab)using the CAN CTX and CRX for serial data and serial clock
15 #define SCL_HIGH (P5 |= 1)
16 #define SCL_LOW (P5 &= ~1)
17 #define SDA_HIGH (P5 |= 2)
18 #define SDA_LOW (P5 &= ~2)
19
20 #define SDA_OUT(b) (b ? SDA_HIGH : SDA_LOW)
21 #define SDA_IN ((P5>>1)&1)
22 #define SCL_IN (P5&1)
23
24 /*
25  * I2C error values
26  */
27
28 #define I2CERR_OK       0       /* No error */
29 #define I2CERR_NAK      1       /* No ACK from slave */
30 #define I2CERR_LOST     2       /* Arbitration lost */
31 #define I2CERR_BUS      3       /* Bus is stuck (not used yet) */
32 #define I2CERR_TIMEOUT  4       /* Timeout on bus */
33
34 char i2cTransmitBuffer[I2C_BUFSIZE];     /* Global transfer buffers */
35 char i2cReceiveBuffer[I2C_BUFSIZE];
36
37 static char i2cError = 0;                 /* Last error */
38
39 #define I2CDELAY 1
40
41 void I2CDelay(volatile long delay) {
42  while (delay--)
43    ;
44 }
45
46 void I2CDumpError(char error);
47
48 /*
49  * Makes sure that the bus is in a known condition. Returns 1 on success,
50  * 0 if some other device is pulling on the bus.
51  */
52
53 char I2CReset(void)
54 {
55   SDA_LOW;
56   SCL_LOW;
57   SCL_HIGH;
58   SDA_HIGH;
59   i2cError = 0;
60   return (SCL_IN && SDA_IN);
61 }
62
63
64 /*
65  * Generates a start condition on the bus. Returns 0 on success, 1 if some
66  * other device is holding the bus.
67  */
68
69 char I2CStart(void)
70 {
71   SDA_HIGH;
72   SCL_HIGH;
73   I2CDelay(I2CDELAY);
74   SDA_LOW;        /* Pull SDA down... */
75   I2CDelay(I2CDELAY);
76   SCL_LOW;        /* ...and then SCL -> start condition. */
77   I2CDelay(I2CDELAY);
78   return 0;
79 }
80
81
82 /*
83  * Generates a stop condition on the bus. Returns 0 on success, 1 if some
84  * other device is holding the bus.
85  */
86
87 char I2CStop(void)
88 {
89   SDA_LOW;
90   SCL_HIGH;        /* Let SCL go up */
91   I2CDelay(I2CDELAY);
92   SDA_HIGH;        /* ...and then SDA up -> stop condition. */
93   I2CDelay(I2CDELAY);
94
95   return (SCL_IN && SDA_IN);  /* Both will be up, if everything is fine */
96 }
97
98
99 /*
100  * Clock out one bit.
101  * Returns 0 on success, 1 if we lose arbitration.
102  */
103
104 char BitOutI2C(unsigned char bout)
105 {
106   SDA_OUT(bout);              /* Put data out on SDA */
107   I2CDelay(I2CDELAY);
108   SCL_HIGH;                   /* Let SCL go up */
109   while(!SCL_IN)              /* Wait until all other devices are ready */
110     {
111       // should do a timeout here
112     }
113
114   if (SDA_IN != bout)         /* Arbitration lost, release bus and return */
115     {
116       SDA_HIGH;               /* Should be up anyway, but make sure */
117       i2cError = I2CERR_LOST;
118       I2CDumpError(i2cError);
119       return 1;
120     }
121   I2CDelay(I2CDELAY);
122   SCL_LOW;                    /* Pull SCL back down */
123   I2CDelay(I2CDELAY);
124   return 0;                   /* OK */
125 }
126
127
128 /*
129  * Clock in one bit.
130  */
131
132 char BitInI2C(void)
133 {
134   char bin;
135
136   // SDA is opencollector, so:
137   SDA_HIGH;
138
139   SCL_HIGH;                   /* Let SCL go up */
140   while(!SCL_IN)              /* Wait for other devices */
141     {
142       // should do a timeout here
143     }
144   bin = SDA_IN;               /* Read in data */
145   I2CDelay(I2CDELAY);
146   SCL_LOW;                    /* Pull SCL back up */
147   I2CDelay(I2CDELAY);
148   return bin;                 /* Return the sampled bit */
149 }
150
151
152 /*
153  * Send one byte on the bus. No start or stop conditions are generated here,
154  * but i2cError will be set according to the result.
155  * Returns 0 on success, 1 if we lose arbitration or if the slave doesn't
156  * acknowledge the byte. Check i2cError for the actual result on error.
157  */
158
159 char ByteOutI2C(char dat)
160 {
161   char bit_count;
162
163   bit_count = 8;
164   while(bit_count) {
165     if (dat & 0x80) {
166       if (BitOutI2C(1)) {
167         I2CDumpError(i2cError);
168         return 1;
169       }
170     } else {
171       if (BitOutI2C(0)) {
172         I2CDumpError(i2cError);
173         return 1;
174       }
175     }
176     dat <<= 1;
177     bit_count--;
178   }
179
180   if (BitInI2C()) {
181     i2cError = I2CERR_NAK;
182     I2CDumpError(i2cError);
183     return 1;
184   }
185   return 0;
186 }
187
188
189 /*
190  * Reads one byte in from the slave. Ack must be 1 if this is the last byte
191  * to be read during this transfer, 0 otherwise (as per I2C bus specification,
192  * the receiving master must acknowledge all but the last byte during a
193  * transfer).
194  */
195
196 char I2CByteIn(char ack)
197 {
198   char bit_count, byte_in;
199
200   bit_count = 8;
201   byte_in = 0;
202
203   while(bit_count)
204     {
205       byte_in <<= 1;
206       if (BitInI2C()) byte_in |= 0x01;
207       bit_count--;
208     }
209
210   BitOutI2C(ack);
211   SDA_HIGH;             /* Added 18-Jul-95 - thanks to Ray Bellis */
212  return byte_in;
213 }
214
215
216 /*
217  * Send 'count' bytes to slave 'addr'.
218  * Returns 0 on success. Stop condition is sent only when send_stop is true.
219  */
220
221 char I2CSendStop(char addr, char count, char send_stop)
222 {
223   char byteptr, byte_out;
224
225   if (I2CStart()) return 1;
226   i2cError = 0;
227
228   byte_out = addr & 0xfe;     /* Ensure that it's a write address */
229   count++;                    /* Include slave address to byte count */
230   byteptr = 0;
231   while(count)
232     {
233       if (ByteOutI2C(byte_out))
234         {
235           if (i2cError == I2CERR_NAK && send_stop) I2CStop();
236           return i2cError;
237         }
238       byte_out = i2cTransmitBuffer[byteptr];
239       byteptr++;
240       count--;
241     }
242
243   if (send_stop) I2CStop();
244   return 0;
245 }
246
247
248 /*
249  * Read in 'count' bytes from slave 'addr'.
250  * Returns 0 on success.
251  */
252
253 char i2c_recv(char addr, char count)
254 {
255   char byteptr, byte_in;
256
257   if (I2CStart()) return 1;
258   i2cError = 0;
259   byteptr = 0;
260
261   byte_in = addr | 0x01;
262
263   if (ByteOutI2C(byte_in))
264     {
265       if (i2cError == I2CERR_NAK) I2CStop();
266       return i2cError;
267     }
268
269   while(count)
270     {
271       count-=1;
272       if (count) {
273         byte_in = I2CByteIn(0);
274       } else {
275         byte_in = I2CByteIn(1);   /* No ACK during last byte */
276       }
277       i2cReceiveBuffer[byteptr] = byte_in;
278       byteptr++;
279     }
280
281   I2CStop();
282
283   return (i2cError ? 1 : 0);
284 }
285
286
287 /*
288  * Write 'tx_count' bytes to slave 'addr', then use a repeated start condition
289  * to read 'rx_count' bytes from the same slave during the same transfer.
290  * Returns 0 on success, 1 otherwise. On error, check i2cError for the actual
291  * error value.
292  */
293
294 char I2CSendReceive(char addr, char tx_count, char rx_count)
295 {
296   if (I2CSendStop(addr, tx_count, 0))
297     {
298      /* If send fails, abort but don't send a stop condition if we lost
299          arbitration */
300
301       if (i2cError != I2CERR_LOST) I2CStop();
302       return 1;
303     }
304
305   SDA_HIGH; /* One of these may be low now, in which case the next */
306   SCL_HIGH; /* start condition wouldn't be detected so make */
307   I2CDelay(I2CDELAY); /*   sure that they're up and wait for one delay slot */
308
309   if (i2c_recv((char)(addr|0x01), rx_count)) return 1;
310   return (i2cError ? 1 : 0);
311 }
312
313 /*
314  * Dump an error message.
315  */
316
317 void I2CDumpError(char error)
318 {
319 #ifdef DEBUG_I2C
320   switch(error)
321     {
322     case 0:
323       puts("I2C: OK.");
324       break;
325     case I2CERR_NAK:
326       puts("I2C: Slave didn't acknowledge");
327       break;
328     case I2CERR_LOST:
329       puts("I2C: Lost arbitration with another master");
330       break;
331     case I2CERR_TIMEOUT:
332       puts("I2C: Timeout on bus");
333       break;
334     case I2CERR_BUS:
335       puts("I2C: The bus is stuck");
336       break;
337     default:
338       puts("I2C: Unknown error");
339       break;
340     }
341 #else
342   error; // hush the compiler
343 #endif
344 }