I2C: use avr-libc bus status names.

No need to reinvent the wheel.
This commit is contained in:
Markus Hitter 2016-04-03 19:59:48 +02:00
parent 619560c112
commit e4067dc235
2 changed files with 27 additions and 57 deletions

54
i2c.c
View File

@ -26,6 +26,7 @@
#include <avr/io.h> #include <avr/io.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <util/twi.h>
#if defined I2C_MASTER_MODE && defined I2C_SLAVE_MODE #if defined I2C_MASTER_MODE && defined I2C_SLAVE_MODE
@ -158,14 +159,14 @@ void i2c_do_nothing(void) {
*/ */
ISR(TWI_vect) { ISR(TWI_vect) {
switch (TWSR & 0xF8) { // Cut the prescaler bits out. switch (TWSR & TW_STATUS_MASK) {
case I2C_STATE_BUS_FAIL: case TW_BUS_ERROR:
// A hardware error was detected. // A hardware error was detected.
i2c_state |= I2C_ERROR_BUS_FAIL; i2c_state |= I2C_ERROR_BUS_FAIL;
TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE);
MACRO_I2C_ERROR; MACRO_I2C_ERROR;
break; break;
case I2C_STATE_START: case TW_START:
// Start happens, send a target address. // Start happens, send a target address.
if ((i2c_state & I2C_MODE_MASK) == I2C_MODE_SARP) { if ((i2c_state & I2C_MODE_MASK) == I2C_MODE_SARP) {
i2c_address |= 0x01; i2c_address |= 0x01;
@ -175,7 +176,7 @@ ISR(TWI_vect) {
TWDR = i2c_address; TWDR = i2c_address;
TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE);
break; break;
case I2C_STATE_RESTART: case TW_REP_START:
// Start happens, send a target address. // Start happens, send a target address.
if ((i2c_state & I2C_MODE_MASK) == I2C_MODE_ENHA) { if ((i2c_state & I2C_MODE_MASK) == I2C_MODE_ENHA) {
i2c_address |= 0x01; i2c_address |= 0x01;
@ -185,7 +186,7 @@ ISR(TWI_vect) {
TWDR = i2c_address; TWDR = i2c_address;
TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE);
break; break;
case I2C_STATE_SLAWACK: case TW_MT_SLA_ACK:
// SLA+W was sent, then ACK received. // SLA+W was sent, then ACK received.
if ((i2c_state & I2C_MODE_MASK) == I2C_MODE_SAWP) { if ((i2c_state & I2C_MODE_MASK) == I2C_MODE_SAWP) {
TWDR = i2c_buffer[i2c_index++]; TWDR = i2c_buffer[i2c_index++];
@ -198,13 +199,13 @@ ISR(TWI_vect) {
} }
#endif #endif
break; break;
case I2C_STATE_SLAWNACK: case TW_MT_SLA_NACK:
// SLA+W was sent, got NACK, so slave is busy or out of bus. // SLA+W was sent, got NACK, so slave is busy or out of bus.
i2c_state |= I2C_ERROR_NO_ANSWER; i2c_state |= I2C_ERROR_NO_ANSWER;
TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE);
MACRO_I2C_ERROR; MACRO_I2C_ERROR;
break; break;
case I2C_STATE_BYTEACK: case TW_MT_DATA_ACK:
// A byte was sent, got ACK. // A byte was sent, got ACK.
if ((i2c_state & I2C_MODE_MASK) == I2C_MODE_SAWP) { if ((i2c_state & I2C_MODE_MASK) == I2C_MODE_SAWP) {
if (i2c_index == i2c_byte_count) { if (i2c_index == i2c_byte_count) {
@ -230,7 +231,7 @@ ISR(TWI_vect) {
} }
#endif #endif
break; break;
case I2C_STATE_BYTENACK: case TW_MT_DATA_NACK:
// Byte was sent but got NACK, there are two possible reasons: // Byte was sent but got NACK, there are two possible reasons:
// - a slave stops transmission and it is ok, or // - a slave stops transmission and it is ok, or
// - a slave became crazy. // - a slave became crazy.
@ -238,7 +239,7 @@ ISR(TWI_vect) {
TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE);
MACRO_I2C_MASTER; // process exit state MACRO_I2C_MASTER; // process exit state
break; break;
case I2C_STATE_COLLISION: case TW_MT_ARB_LOST: // Collision, identical to TW_MR_ARB_LOST.
// It looks like there is another master on the bus. // It looks like there is another master on the bus.
i2c_state |= I2C_ERROR_LOW_PRIO; i2c_state |= I2C_ERROR_LOW_PRIO;
// Setup all again. // Setup all again.
@ -249,7 +250,7 @@ ISR(TWI_vect) {
// Try to resend when the bus became free. // Try to resend when the bus became free.
TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE);
break; break;
case I2C_STATE_SLARACK: case TW_MR_SLA_ACK:
// SLA+R was sent, got АСК, then received a byte. // SLA+R was sent, got АСК, then received a byte.
if (i2c_index + 1 == i2c_byte_count) { if (i2c_index + 1 == i2c_byte_count) {
// Last byte fitting into the buffer. Request a byte, then send NACK // Last byte fitting into the buffer. Request a byte, then send NACK
@ -260,13 +261,13 @@ ISR(TWI_vect) {
TWCR = (1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE);
} }
break; break;
case I2C_STATE_SLARNACK: case TW_MR_SLA_NACK:
// SLA+R was sent, got NАСК, it seems the slave is busy. // SLA+R was sent, got NАСК, it seems the slave is busy.
i2c_state |= I2C_ERROR_NO_ANSWER; i2c_state |= I2C_ERROR_NO_ANSWER;
TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE);
MACRO_I2C_ERROR; MACRO_I2C_ERROR;
break; break;
case I2C_STATE_GOT_BYTE: case TW_MR_DATA_ACK:
i2c_buffer[i2c_index++] = TWDR; i2c_buffer[i2c_index++] = TWDR;
// TODO: Add BUFFER OVERFLOW check. // TODO: Add BUFFER OVERFLOW check.
if (i2c_index + 1 == i2c_byte_count) { if (i2c_index + 1 == i2c_byte_count) {
@ -277,14 +278,14 @@ ISR(TWI_vect) {
TWCR = (1<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE);
} }
break; break;
case I2C_STATE_GOT_BYTE_NACK: case TW_MR_DATA_NACK:
// Last byte received, send NACK to make the slave to release the bus. // Last byte received, send NACK to make the slave to release the bus.
i2c_buffer[i2c_index] = TWDR; i2c_buffer[i2c_index] = TWDR;
TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(I2C_MODE<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE);
MACRO_I2C_MASTER; MACRO_I2C_MASTER;
break; break;
case I2C_STATE_SLAW_LP: case TW_SR_ARB_LOST_SLA_ACK:
case I2C_STATE_SLAW_LP_ANY: case TW_SR_ARB_LOST_GCALL_ACK:
// Another master on the bus sent some bytes, receive them. // Another master on the bus sent some bytes, receive them.
i2c_state |= I2C_ERROR_LOW_PRIO; i2c_state |= I2C_ERROR_LOW_PRIO;
// Restore the transfer. // Restore the transfer.
@ -295,8 +296,8 @@ ISR(TWI_vect) {
#ifdef I2C_SLAVE_MODE #ifdef I2C_SLAVE_MODE
case I2C_STATE_SLAW: case TW_SR_SLA_ACK:
case I2C_STATE_SLAW_ANY: case TW_SR_GCALL_ACK:
i2c_state |= I2C_MODE_BUSY; // Lock bus. i2c_state |= I2C_MODE_BUSY; // Lock bus.
i2c_index = 0; i2c_index = 0;
if (I2C_SLAVE_RX_BUFFER_SIZE == 1) { if (I2C_SLAVE_RX_BUFFER_SIZE == 1) {
@ -307,8 +308,8 @@ ISR(TWI_vect) {
TWCR = (1<<TWINT)|(1<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(1<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE);
} }
break; break;
case I2C_STATE_RCV_BYTE: case TW_SR_DATA_ACK:
case I2C_STATE_RCV_BYTE_ANY: case TW_SR_GCALL_DATA_ACK:
i2c_in_buffer[i2c_index++] = TWDR; i2c_in_buffer[i2c_index++] = TWDR;
if (i2c_index == I2C_SLAVE_RX_BUFFER_SIZE - 1) { if (i2c_index == I2C_SLAVE_RX_BUFFER_SIZE - 1) {
// Room for only one byte left, send NACK. // Room for only one byte left, send NACK.
@ -318,8 +319,8 @@ ISR(TWI_vect) {
TWCR = (1<<TWINT)|(1<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(1<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE);
} }
break; break;
case I2C_STATE_RCV_LAST_BYTE: case TW_SR_DATA_NACK:
case I2C_STATE_RCV_LAST_BYTE_ANY: case TW_SR_GCALL_DATA_NACK:
i2c_in_buffer[i2c_index] = TWDR; i2c_in_buffer[i2c_index] = TWDR;
if (i2c_state & I2C_INTERRUPTED) { if (i2c_state & I2C_INTERRUPTED) {
// Если у нас был прерываный сеанс от имени мастера // Если у нас был прерываный сеанс от имени мастера
@ -331,13 +332,13 @@ ISR(TWI_vect) {
} }
MACRO_I2C_SLAVE; MACRO_I2C_SLAVE;
break; break;
case I2C_STATE_RCV_RESTART: case TW_SR_STOP:
// We got a Restart. What we will do? // We got a Restart. What we will do?
// Here we can do additional logic but we don't need it at this time. // Here we can do additional logic but we don't need it at this time.
// Just ignore it now. // Just ignore it now.
TWCR = (1<<TWINT)|(1<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(1<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE);
break; break;
case I2C_STATE_RCV_SLAR_LP: case TW_ST_ARB_LOST_SLA_ACK:
// Got own address on read from another master. // Got own address on read from another master.
i2c_state |= I2C_ERROR_LOW_PRIO | I2C_INTERRUPTED; i2c_state |= I2C_ERROR_LOW_PRIO | I2C_INTERRUPTED;
@ -346,7 +347,7 @@ ISR(TWI_vect) {
#ifdef I2C_EEPROM_SUPPORT #ifdef I2C_EEPROM_SUPPORT
i2c_page_index = 0; i2c_page_index = 0;
#endif #endif
case I2C_STATE_RCV_SLAR: case TW_ST_SLA_ACK:
// We have got own address on read. // We have got own address on read.
i2c_index = 0; i2c_index = 0;
TWDR = i2c_out_buffer[i2c_index]; TWDR = i2c_out_buffer[i2c_index];
@ -358,7 +359,7 @@ ISR(TWI_vect) {
TWCR = (1<<TWINT)|(1<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(1<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE);
} }
break; break;
case I2C_STATE_SND_BYTE_ACK: case TW_ST_DATA_ACK:
// Send byte and got ACK, then send next byte to master. // Send byte and got ACK, then send next byte to master.
TWDR = i2c_out_buffer[++i2c_index]; TWDR = i2c_out_buffer[++i2c_index];
if (I2C_SLAVE_TX_BUFFER_SIZE - 1 == i2c_index) { if (I2C_SLAVE_TX_BUFFER_SIZE - 1 == i2c_index) {
@ -369,8 +370,7 @@ ISR(TWI_vect) {
TWCR = (1<<TWINT)|(1<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(1<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWEN)|(1<<TWIE);
} }
break; break;
case I2C_STATE_SND_LAST_BYTE_NACK: case TW_ST_DATA_NACK:
case I2C_STATE_SND_LAST_BYTE_ACK:
// We sent the last byte and received NACK or ACK (doesn't matter here). // We sent the last byte and received NACK or ACK (doesn't matter here).
if (i2c_state & I2C_INTERRUPTED) { if (i2c_state & I2C_INTERRUPTED) {
// There was interrupted master transfer. // There was interrupted master transfer.

30
i2c.h
View File

@ -54,36 +54,6 @@
#define I2C_ERROR_NO_ANSWER 0b00010000 #define I2C_ERROR_NO_ANSWER 0b00010000
#define I2C_ERROR_LOW_PRIO 0b00100000 #define I2C_ERROR_LOW_PRIO 0b00100000
#define I2C_STATE_BUS_FAIL 0x00
#define I2C_STATE_START 0x08
#define I2C_STATE_RESTART 0x10
#define I2C_STATE_SLAWACK 0x18
#define I2C_STATE_SLAWNACK 0x20
#define I2C_STATE_BYTEACK 0x28
#define I2C_STATE_BYTENACK 0x30
#define I2C_STATE_COLLISION 0x38
#define I2C_STATE_SLARACK 0x40
#define I2C_STATE_SLARNACK 0x48
#define I2C_STATE_GOT_BYTE 0x50
#define I2C_STATE_GOT_BYTE_NACK 0x58
#define I2C_STATE_SLAW_LP 0x68
#define I2C_STATE_SLAW_LP_ANY 0x78
#ifdef I2C_SLAVE_MODE
#define I2C_STATE_SLAW 0x60
#define I2C_STATE_SLAW_ANY 0x70
#define I2C_STATE_RCV_BYTE 0x80
#define I2C_STATE_RCV_BYTE_ANY 0x90
#define I2C_STATE_RCV_LAST_BYTE 0x88
#define I2C_STATE_RCV_LAST_BYTE_ANY 0x98
#define I2C_STATE_RCV_RESTART 0xA0
#define I2C_STATE_RCV_SLAR 0xA8
#define I2C_STATE_RCV_SLAR_LP 0xB0
#define I2C_STATE_SND_BYTE_ACK 0xB8
#define I2C_STATE_SND_LAST_BYTE_NACK 0xC0
#define I2C_STATE_SND_LAST_BYTE_ACK 0xC0
#endif /* I2C_SLAVE_MODE */
#define MACRO_I2C_ERROR (i2c_error_func)() #define MACRO_I2C_ERROR (i2c_error_func)()
#ifdef I2C_SLAVE_MODE #ifdef I2C_SLAVE_MODE
#define MACRO_I2C_SLAVE (i2c_slave_func)() #define MACRO_I2C_SLAVE (i2c_slave_func)()