1 /* This implemenation is based on an example I once grabbed from
3 Don't know who wrote it, but is has been hacked so heavely, he/she wouldn't
17 // we are (ab)using the CAN CTX and CRX for serial data and serial clock
18 #define SCL_HIGH (P5 |= 1)
19 #define SCL_LOW (P5 &= ~1)
20 #define SDA_HIGH (P5 |= 2)
21 #define SDA_LOW (P5 &= ~2)
23 #define SDA_OUT(b) (b ? SDA_HIGH : SDA_LOW)
24 #define SDA_IN ((P5>>1)&1)
27 char i2cTransmitBuffer[I2C_BUFSIZE]; /* Global transfer buffers */
28 char i2cReceiveBuffer[I2C_BUFSIZE];
30 char i2cError = 0; /* Last error */
34 * Makes sure that the bus is in a known condition. Returns 1 on success,
35 * 0 if some other device is pulling on the bus.
40 //puts ("<I2CReset>");
46 return (SCL_IN && SDA_IN);
51 * Generates a start condition on the bus. Returns 0 on success, 1 if some
52 * other device is holding the bus.
57 //puts ("<I2CStart>");
62 SDA_LOW; /* Pull SDA down... */
64 SCL_LOW; /* ...and then SCL -> start condition. */
71 * Generates a stop condition on the bus. Returns 0 on success, 1 if some
72 * other device is holding the bus.
80 SCL_HIGH; /* Let SCL go up */
82 SDA_HIGH; /* ...and then SDA up -> stop condition. */
85 return (SCL_IN && SDA_IN); /* Both will be up, if everything is fine */
91 * Returns 0 on success, 1 if we lose arbitration.
94 char BitOutI2C(char bout)
96 //puts("<BitOutI2C>");
98 SDA_OUT(bout); /* Put data out on SDA */
100 SCL_HIGH; /* Let SCL go up */
101 while(!SCL_IN) /* Wait until all other devices are ready */
103 // should do a timeout here
106 if (SDA_IN != bout) /* Arbitration lost, release bus and return */
108 SDA_HIGH; /* Should be up anyway, but make sure */
109 i2cError = I2CERR_LOST;
110 I2CDumpError(i2cError);
114 SCL_LOW; /* Pull SCL back down */
128 //puts ("<BitInI2C>");
130 // SDA is opencollector, so:
133 SCL_HIGH; /* Let SCL go up */
134 while(!SCL_IN) /* Wait for other devices */
136 // should do a timeout here
138 bin = SDA_IN; /* Read in data */
140 SCL_LOW; /* Pull SCL back up */
142 return bin; /* Return the sampled bit */
147 * Send one byte on the bus. No start or stop conditions are generated here,
148 * but i2cError will be set according to the result.
149 * Returns 0 on success, 1 if we lose arbitration or if the slave doesn't
150 * acknowledge the byte. Check i2cError for the actual result on error.
153 char ByteOutI2C(char dat)
157 //puts ("<ByteOutI2C>");
163 I2CDumpError(i2cError);
168 I2CDumpError(i2cError);
177 i2cError = I2CERR_NAK;
178 I2CDumpError(i2cError);
186 * Reads one byte in from the slave. Ack must be 1 if this is the last byte
187 * to be read during this transfer, 0 otherwise (as per I2C bus specification,
188 * the receiving master must acknowledge all but the last byte during a
192 char I2CByteIn(char ack)
194 char bit_count, byte_in;
196 //puts ("<I2CByteIn>");
204 if (BitInI2C()) byte_in |= 0x01;
209 SDA_HIGH; /* Added 18-Jul-95 - thanks to Ray Bellis */
215 * Send 'count' bytes to slave 'addr'.
216 * Returns 0 on success. Stop condition is sent only when send_stop is true.
219 char I2CSendStop(char addr, char count, char send_stop)
221 char byteptr, byte_out;
223 //puts ("<I2CSendStop>");
225 if (I2CStart()) return 1;
228 byte_out = addr & 0xfe; /* Ensure that it's a write address */
229 count++; /* Include slave address to byte count */
233 if (ByteOutI2C(byte_out))
235 if (i2cError == I2CERR_NAK && send_stop) I2CStop();
238 byte_out = i2cTransmitBuffer[byteptr];
243 if (send_stop) I2CStop();
249 * Read in 'count' bytes from slave 'addr'.
250 * Returns 0 on success.
253 char i2c_recv(char addr, char count)
255 char byteptr, byte_in;
257 //puts ("<i2c_rec>");
259 if (I2CStart()) return 1;
263 byte_in = addr | 0x01;
265 if (ByteOutI2C(byte_in))
267 if (i2cError == I2CERR_NAK) I2CStop();
275 byte_in = I2CByteIn(0);
277 byte_in = I2CByteIn(1); /* No ACK during last byte */
279 i2cReceiveBuffer[byteptr] = byte_in;
285 return (i2cError ? 1 : 0);
290 * Write 'tx_count' bytes to slave 'addr', then use a repeated start condition
291 * to read 'rx_count' bytes from the same slave during the same transfer.
292 * Returns 0 on success, 1 otherwise. On error, check i2cError for the actual
296 char I2CSendReceive(char addr, char tx_count, char rx_count)
298 //puts ("<i2c_send_recv>");
300 if (I2CSendStop(addr, tx_count, 0))
302 /* If send fails, abort but don't send a stop condition if we lost
305 if (i2cError != I2CERR_LOST) I2CStop();
309 SDA_HIGH; /* One of these may be low now, in which case the next */
310 SCL_HIGH; /* start condition wouldn't be detected so make */
311 I2CDelay(I2CDELAY); /* sure that they're up and wait for one delay slot */
313 if (i2c_recv((char)(addr|0x01), rx_count)) return 1;
314 return (i2cError ? 1 : 0);
318 * Dump an error message.
321 void I2CDumpError(char error)
330 puts("I2C: Slave didn't acknowledge");
333 puts("I2C: Lost arbitration with another master");
336 puts("I2C: Timeout on bus");
339 puts("I2C: The bus is stuck");
342 puts("I2C: Unknown error");
348 void I2CDelay(volatile long delay) {