You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
1.8 KiB
95 lines
1.8 KiB
/* i2c.c */ |
|
|
|
#include <avr/io.h> |
|
#include <util/twi.h> |
|
#include <avr/interrupt.h> |
|
|
|
#include "common.h" |
|
#include "beep.h" |
|
|
|
//#define i2c_wait() do { uint16_t count = 0; while (!(TWCR & (1<<TWINT))) if (count++ > 1000) break; } while (0) |
|
//#define i2c_status() (TWSR & 0xF8) |
|
#define i2c_check(status) if (i2c_status() != (status)) goto ERROR |
|
|
|
static void i2c_wait(void) |
|
{ |
|
uint16_t count = 0; |
|
while (!(TWCR & (1<<TWINT))) |
|
if (count++ > 1000) |
|
break; |
|
} |
|
|
|
static __attribute__ ((noinline)) uint8_t i2c_status(void) |
|
{ |
|
return TWSR & 0xF8; |
|
} |
|
|
|
uint8_t i2c_xor; |
|
|
|
void i2c_init(void) |
|
{ |
|
TWSR = 0; /* prescaler TWPS = 0 */ |
|
TWBR = 10; /* minimum value allowed */ |
|
/* f_SCL = clk / (16+(2*TWBR*TWPS)) */ |
|
|
|
TWCR = (1<<TWEN); |
|
|
|
i2c_xor = 0; |
|
} |
|
|
|
//#define i2c_start() do { TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); } while (0) |
|
//#define i2c_stop() do { TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); } while (0) |
|
//#define i2c_txbyte(data) do { TWDR = data; TWCR = (1 << TWINT) | (1<<TWEN); } while (0) |
|
|
|
static void i2c_start(void) |
|
{ |
|
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); |
|
} |
|
|
|
static void i2c_stop(void) |
|
{ |
|
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); |
|
} |
|
|
|
static __attribute__((noinline)) void i2c_txbyte(uint8_t data) |
|
{ |
|
TWDR = data; |
|
TWCR = (1 << TWINT) | (1<<TWEN); |
|
} |
|
|
|
void i2c_set_xor(uint8_t xor) |
|
{ |
|
i2c_xor = xor; |
|
} |
|
|
|
bool i2c_write(uint8_t address, uint8_t prefix, uint8_t bytes, uint8_t *data) |
|
{ |
|
uint8 i; |
|
|
|
i2c_start(); |
|
i2c_wait(); |
|
i2c_check(TW_START); |
|
|
|
i2c_txbyte((address << 1) + 0); |
|
i2c_wait(); |
|
|
|
i2c_check(TW_MT_SLA_ACK); |
|
|
|
i2c_txbyte(prefix); |
|
i2c_wait(); |
|
i2c_check(TW_MT_DATA_ACK); |
|
|
|
for (i = 0; i < bytes; i++) { |
|
i2c_txbyte(data[i] ^ i2c_xor); |
|
i2c_wait(); |
|
i2c_check(TW_MT_DATA_ACK); |
|
} |
|
|
|
i2c_stop(); |
|
return TRUE; |
|
|
|
ERROR: |
|
i2c_stop(); |
|
return FALSE; |
|
} |
|
|
|
|