-/*************************************************************************\r
-* Title: I2C master library using hardware TWI interface\r
-* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury\r
-* File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $\r
-* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3\r
-* Target: any AVR device with hardware TWI \r
-* Usage: API compatible with I2C Software Library i2cmaster.h\r
-**************************************************************************/\r
-#include <inttypes.h>\r
-#include <compat/twi.h>\r
-\r
-#include <i2cmaster.h>\r
-\r
-\r
-/* define CPU frequency in Mhz here if not defined in Makefile */\r
-#ifndef F_CPU\r
-#define F_CPU 4000000UL\r
-#endif\r
-\r
-/* I2C clock in Hz */\r
-#define SCL_CLOCK 100000L\r
-\r
-\r
-/*************************************************************************\r
- Initialization of the I2C bus interface. Need to be called only once\r
-*************************************************************************/\r
-void i2c_init(void)\r
-{\r
- /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */\r
- \r
- TWSR = 0; /* no prescaler */\r
- TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */\r
-\r
-}/* i2c_init */\r
-\r
-\r
-/************************************************************************* \r
- Issues a start condition and sends address and transfer direction.\r
- return 0 = device accessible, 1= failed to access device\r
-*************************************************************************/\r
-unsigned char i2c_start(unsigned char address)\r
-{\r
- uint8_t twst;\r
-\r
- // send START condition\r
- TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);\r
-\r
- // wait until transmission completed\r
- while(!(TWCR & (1<<TWINT)));\r
-\r
- // check value of TWI Status Register. Mask prescaler bits.\r
- twst = TW_STATUS & 0xF8;\r
- if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;\r
-\r
- // send device address\r
- TWDR = address;\r
- TWCR = (1<<TWINT) | (1<<TWEN);\r
-\r
- // wail until transmission completed and ACK/NACK has been received\r
- while(!(TWCR & (1<<TWINT)));\r
-\r
- // check value of TWI Status Register. Mask prescaler bits.\r
- twst = TW_STATUS & 0xF8;\r
- if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;\r
-\r
- return 0;\r
-\r
-}/* i2c_start */\r
-\r
-\r
-/*************************************************************************\r
- Issues a start condition and sends address and transfer direction.\r
- If device is busy, use ack polling to wait until device is ready\r
- \r
- Input: address and transfer direction of I2C device\r
-*************************************************************************/\r
-void i2c_start_wait(unsigned char address)\r
-{\r
- uint8_t twst;\r
-\r
-\r
- while ( 1 )\r
- {\r
- // send START condition\r
- TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);\r
- \r
- // wait until transmission completed\r
- while(!(TWCR & (1<<TWINT)));\r
- \r
- // check value of TWI Status Register. Mask prescaler bits.\r
- twst = TW_STATUS & 0xF8;\r
- if ( (twst != TW_START) && (twst != TW_REP_START)) continue;\r
- \r
- // send device address\r
- TWDR = address;\r
- TWCR = (1<<TWINT) | (1<<TWEN);\r
- \r
- // wail until transmission completed\r
- while(!(TWCR & (1<<TWINT)));\r
- \r
- // check value of TWI Status Register. Mask prescaler bits.\r
- twst = TW_STATUS & 0xF8;\r
- if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) \r
- { \r
- /* device busy, send stop condition to terminate write operation */\r
- TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);\r
- \r
- // wait until stop condition is executed and bus released\r
- while(TWCR & (1<<TWSTO));\r
- \r
- continue;\r
- }\r
- //if( twst != TW_MT_SLA_ACK) return 1;\r
- break;\r
- }\r
-\r
-}/* i2c_start_wait */\r
-\r
-\r
-/*************************************************************************\r
- Issues a repeated start condition and sends address and transfer direction \r
-\r
- Input: address and transfer direction of I2C device\r
- \r
- Return: 0 device accessible\r
- 1 failed to access device\r
-*************************************************************************/\r
-unsigned char i2c_rep_start(unsigned char address)\r
-{\r
- return i2c_start( address );\r
-\r
-}/* i2c_rep_start */\r
-\r
-\r
-/*************************************************************************\r
- Terminates the data transfer and releases the I2C bus\r
-*************************************************************************/\r
-void i2c_stop(void)\r
-{\r
- /* send stop condition */\r
- TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);\r
- \r
- // wait until stop condition is executed and bus released\r
- while(TWCR & (1<<TWSTO));\r
-\r
-}/* i2c_stop */\r
-\r
-\r
-/*************************************************************************\r
- Send one byte to I2C device\r
- \r
- Input: byte to be transfered\r
- Return: 0 write successful \r
- 1 write failed\r
-*************************************************************************/\r
-unsigned char i2c_write( unsigned char data )\r
-{ \r
- uint8_t twst;\r
- \r
- // send data to the previously addressed device\r
- TWDR = data;\r
- TWCR = (1<<TWINT) | (1<<TWEN);\r
-\r
- // wait until transmission completed\r
- while(!(TWCR & (1<<TWINT)));\r
-\r
- // check value of TWI Status Register. Mask prescaler bits\r
- twst = TW_STATUS & 0xF8;\r
- if( twst != TW_MT_DATA_ACK) return 1;\r
- return 0;\r
-\r
-}/* i2c_write */\r
-\r
-\r
-/*************************************************************************\r
- Read one byte from the I2C device, request more data from device \r
- \r
- Return: byte read from I2C device\r
-*************************************************************************/\r
-unsigned char i2c_readAck(void)\r
-{\r
- TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);\r
- while(!(TWCR & (1<<TWINT))); \r
-\r
- return TWDR;\r
-\r
-}/* i2c_readAck */\r
-\r
-\r
-/*************************************************************************\r
- Read one byte from the I2C device, read is followed by a stop condition \r
- \r
- Return: byte read from I2C device\r
-*************************************************************************/\r
-unsigned char i2c_readNak(void)\r
-{\r
- TWCR = (1<<TWINT) | (1<<TWEN);\r
- while(!(TWCR & (1<<TWINT)));\r
- \r
- return TWDR;\r
-\r
-}/* i2c_readNak */\r
+/*************************************************************************
+* Title: I2C master library using hardware TWI interface
+* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
+* File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
+* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
+* Target: any AVR device with hardware TWI
+* Usage: API compatible with I2C Software Library i2cmaster.h
+**************************************************************************/
+#include <inttypes.h>
+#include <compat/twi.h>
+
+#include <i2cmaster.h>
+
+
+/* define CPU frequency in Mhz here if not defined in Makefile */
+#ifndef F_CPU
+#define F_CPU 4000000UL
+#endif
+
+/* I2C clock in Hz */
+#define SCL_CLOCK 100000L
+
+
+/*************************************************************************
+ Initialization of the I2C bus interface. Need to be called only once
+*************************************************************************/
+void i2c_init(void)
+{
+ /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
+
+ TWSR = 0; /* no prescaler */
+ TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */
+
+}/* i2c_init */
+
+
+/*************************************************************************
+ Issues a start condition and sends address and transfer direction.
+ return 0 = device accessible, 1= failed to access device
+*************************************************************************/
+unsigned char i2c_start(unsigned char address)
+{
+ uint8_t twst;
+
+ // send START condition
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
+
+ // wait until transmission completed
+ while(!(TWCR & (1<<TWINT)));
+
+ // check value of TWI Status Register. Mask prescaler bits.
+ twst = TW_STATUS & 0xF8;
+ if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
+
+ // send device address
+ TWDR = address;
+ TWCR = (1<<TWINT) | (1<<TWEN);
+
+ // wail until transmission completed and ACK/NACK has been received
+ while(!(TWCR & (1<<TWINT)));
+
+ // check value of TWI Status Register. Mask prescaler bits.
+ twst = TW_STATUS & 0xF8;
+ if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
+
+ return 0;
+
+}/* i2c_start */
+
+
+/*************************************************************************
+ Issues a start condition and sends address and transfer direction.
+ If device is busy, use ack polling to wait until device is ready
+
+ Input: address and transfer direction of I2C device
+*************************************************************************/
+void i2c_start_wait(unsigned char address)
+{
+ uint8_t twst;
+
+
+ while ( 1 )
+ {
+ // send START condition
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
+
+ // wait until transmission completed
+ while(!(TWCR & (1<<TWINT)));
+
+ // check value of TWI Status Register. Mask prescaler bits.
+ twst = TW_STATUS & 0xF8;
+ if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
+
+ // send device address
+ TWDR = address;
+ TWCR = (1<<TWINT) | (1<<TWEN);
+
+ // wail until transmission completed
+ while(!(TWCR & (1<<TWINT)));
+
+ // check value of TWI Status Register. Mask prescaler bits.
+ twst = TW_STATUS & 0xF8;
+ if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
+ {
+ /* device busy, send stop condition to terminate write operation */
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
+
+ // wait until stop condition is executed and bus released
+ while(TWCR & (1<<TWSTO));
+
+ continue;
+ }
+ //if( twst != TW_MT_SLA_ACK) return 1;
+ break;
+ }
+
+}/* i2c_start_wait */
+
+
+/*************************************************************************
+ Issues a repeated start condition and sends address and transfer direction
+
+ Input: address and transfer direction of I2C device
+
+ Return: 0 device accessible
+ 1 failed to access device
+*************************************************************************/
+unsigned char i2c_rep_start(unsigned char address)
+{
+ return i2c_start( address );
+
+}/* i2c_rep_start */
+
+
+/*************************************************************************
+ Terminates the data transfer and releases the I2C bus
+*************************************************************************/
+void i2c_stop(void)
+{
+ /* send stop condition */
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
+
+ // wait until stop condition is executed and bus released
+ while(TWCR & (1<<TWSTO));
+
+}/* i2c_stop */
+
+
+/*************************************************************************
+ Send one byte to I2C device
+
+ Input: byte to be transfered
+ Return: 0 write successful
+ 1 write failed
+*************************************************************************/
+unsigned char i2c_write( unsigned char data )
+{
+ uint8_t twst;
+
+ // send data to the previously addressed device
+ TWDR = data;
+ TWCR = (1<<TWINT) | (1<<TWEN);
+
+ // wait until transmission completed
+ while(!(TWCR & (1<<TWINT)));
+
+ // check value of TWI Status Register. Mask prescaler bits
+ twst = TW_STATUS & 0xF8;
+ if( twst != TW_MT_DATA_ACK) return 1;
+ return 0;
+
+}/* i2c_write */
+
+
+/*************************************************************************
+ Read one byte from the I2C device, request more data from device
+
+ Return: byte read from I2C device
+*************************************************************************/
+unsigned char i2c_readAck(void)
+{
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
+ while(!(TWCR & (1<<TWINT)));
+
+ return TWDR;
+
+}/* i2c_readAck */
+
+
+/*************************************************************************
+ Read one byte from the I2C device, read is followed by a stop condition
+
+ Return: byte read from I2C device
+*************************************************************************/
+unsigned char i2c_readNak(void)
+{
+ TWCR = (1<<TWINT) | (1<<TWEN);
+ while(!(TWCR & (1<<TWINT)));
+
+ return TWDR;
+
+}/* i2c_readNak */