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