79 lines
1.7 KiB
C
79 lines
1.7 KiB
C
/***
|
|
* 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 <stdlib.h>
|
|
|
|
// 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
|