/*** * impl0.h * This file is part of the PIO library. * For license information see "pio.h" in the super parent directory. */ #if !defined(PIOLIB) || PIOLIB < 100 #error This file should be included directly. Use "pio.h" instead. #endif #ifndef F_CPU #error F_CPU not defined! #endif #ifndef F_I2C #ifndef PIO_DISABLE_I2C #warning F_I2C not defined, I2C disabled. #endif #else #include // AVR TWI master transmitter status codes #define TWS_START 0x08 #define TWS_REPEATED_START 0x10 #define TWS_ADDR_ACK 0x18 #define TWS_ADDR_NOT_ACK 0x20 #define TWS_DATA_ACK 0x28 #define TWS_DATA_NOT_ACK 0x30 #define TWS_ARB_LOST 0x38 // functions void i2cInit(void); void i2cBeginTransmission(uint8_t); void i2cSend(uint8_t); void i2cEndTransmission(void); // error function pointer void (*i2cError)(void) = NULL; void i2cInit() { // i2c clock speed, see SCL frequency formula in datasheet uint16_t sp = F_CPU / F_I2C - 16; uint16_t bp = sp; while(sp > 510) { TWSR++; sp /= 4; } TWBR = bp / (1<<(2*(TWSR & 0x03)+1)); } void i2cBeginTransmission(uint8_t addr) { TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTA); while (!(TWCR & _BV(TWINT))); if((TWSR & 0xF8) != TWS_START) i2cError(); TWDR = (addr & 0xFE) << 1; TWCR = _BV(TWEN) | _BV(TWINT); while (!(TWCR & _BV(TWINT))); if((TWSR & 0xF8) != TWS_ADDR_ACK) i2cError(); } void i2cSend(uint8_t b) { TWDR = b; TWCR = _BV(TWEN) | _BV(TWINT); while (!(TWCR & _BV(TWINT))); if((TWSR & 0xF8) != TWS_DATA_ACK) i2cError(); } void i2cEndTransmission() { TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTO); while (TWCR & _BV(TWSTO)); } #endif