Newer keypas

master
q3k 2014-01-11 21:28:57 +01:00
parent 30c4841562
commit cc1785dfee
8 changed files with 530 additions and 18 deletions

View File

@ -1,7 +1,7 @@
PRG = uart_hello
OBJ = main.o buzzer.o keypad.o
PROGRAMMER = buspirate
PORT = /dev/ttyACM0
OBJ = main.o buzzer.o keypad.o twi.o
PROGRAMMER = avrisp2
PORT = usb
MCU_TARGET = atmega8
AVRDUDE_TARGET = atmega8
OPTIMIZE = -Os
@ -16,7 +16,7 @@ CC = avr-gcc
# Override is only needed by avr-lib build system.
override CFLAGS = -g -DF_CPU=$(HZ) -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
override CFLAGS = -g -DF_CPU=$(HZ) -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) -std=c99
override LDFLAGS = -Wl,-Map,$(PRG).map
OBJCOPY = avr-objcopy

View File

@ -27,6 +27,13 @@ void buzzer_start(uint16_t ticks)
sei();
}
volatile uint16_t g_BuzzerTicksLeft = 0;
void buzzer_start_timed(uint16_t freq, uint16_t ticks)
{
g_BuzzerTicksLeft = ticks * freq / 2;
buzzer_start(freq);
}
void buzzer_stop(void)
{
cli();
@ -37,6 +44,12 @@ void buzzer_stop(void)
ISR(TIMER1_COMPA_vect)
{
IO_TOGGLE(BUZZER);
/*if (g_BuzzerTicksLeft > 0)
{
g_BuzzerTicksLeft--;
if (g_BuzzerTicksLeft == 0)
TIMSK &= ~_BV(OCIE1A);
}*/
}
void buzzer_signal_boot(void)

View File

@ -2,6 +2,8 @@
#define __BUZZER_H__
void buzzer_init(void);
void buzzer_signal_boot(void);
void buzzer_start_timed(uint16_t, uint16_t);
#define TONE_LOW 128
#define TONE_MID 64

View File

@ -14,7 +14,7 @@ IMPORT_IO(KPAD_COL3);
IMPORT_IO(LED_RED);
IMPORT_IO(LED_GREEN);
void _keypad_update_column(void);
static void _keypad_update_column(void);
void keypad_init(void)
{
@ -28,9 +28,9 @@ void keypad_init(void)
IO_OUT(KPAD_ROW4, 1);
}
uint8_t g_KeypadColumn = 0;
static uint8_t g_KeypadColumn = 0;
void _keypad_update_column(void)
static void _keypad_update_column(void)
{
g_KeypadColumn++;
if (g_KeypadColumn > 2)
@ -66,10 +66,10 @@ void _keypad_update_column(void)
}
// all the buttons of the matrix in a bitfield
uint16_t g_KeypadState = 0;
uint16_t g_NewKeypadState = 0;;
static volatile uint16_t g_KeypadState = 0;
static volatile uint16_t g_NewKeypadState = 0;;
uint8_t _keypad_read_rows(void)
static uint8_t _keypad_read_rows(void)
{
uint8_t Result = 0;
Result |= (IO_IN(KPAD_ROW1) << 0);
@ -91,7 +91,14 @@ ISR(TIMER0_OVF_vect)
uint8_t State = _keypad_read_rows();
g_NewKeypadState |= (State << (4 * g_KeypadColumn));
IO_OUT(LED_GREEN, (g_KeypadState >> 0) & 1);
IO_OUT(LED_RED, (g_KeypadState >> 1) & 1);
//IO_OUT(LED_GREEN, (g_KeypadState >> 0) & 1);
//IO_OUT(LED_RED, (g_KeypadState >> 1) & 1);
}
uint16_t keypad_get_buttons(void)
{
return g_KeypadState;
}

View File

@ -16,4 +16,6 @@ void keypad_init(void);
#define KEY_7 10
#define KEY_S 11
uint16_t keypad_get_buttons(void);
#endif

View File

@ -6,6 +6,7 @@
#include "io.h"
#include "buzzer.h"
#include "keypad.h"
#include "twi.h"
/////////////////////
// I/O ports setup //
@ -13,10 +14,10 @@
// Buzzer on PC2
DECLARE_IO(BUZZER, C, 2);
// Red LED pn PC1
DECLARE_IO(LED_RED, C, 1);
// Green LED on PC0
DECLARE_IO(LED_GREEN, C, 0);
// Red LED pn PC0
DECLARE_IO(LED_RED, C, 0);
// Green LED on PC1
DECLARE_IO(LED_GREEN, C, 1);
// Keypad
DECLARE_IO(KPAD_COL3, D, 0);
@ -28,6 +29,46 @@ DECLARE_IO(KPAD_ROW2, D, 5);
DECLARE_IO(KPAD_ROW4, D, 6);
DECLARE_IO(KPAD_COL1, D, 7);
#define KEYPAD_BUFFER_SIZE 16
static volatile uint8_t KeypadBytes[KEYPAD_BUFFER_SIZE];
static volatile uint8_t KeypadIndex = 0;
static volatile uint8_t KeypadShouldRead = 0;
#define KEYPAD_STATE_IDLE 0
#define KEYPAD_STATE_GETTING_BYTES 1
#define KEYPAD_STATE_TIMEOUT 2
#define KEYPAD_STATE_BYTES_READY 3
static volatile uint8_t KeypadState = KEYPAD_STATE_IDLE;
#define KEYPAD_I2C_GET_STATE 0x00
#define KEYPAD_I2C_GET_BYTES_WAITING 0x01
#define KEYPAD_I2C_GET_BYTES 0x02
#define KEYPAD_I2C_REQUEST_BYTES 0x03
#define KEYPAD_I2C_SOUND_OK 0x04
#define KEYPAD_I2C_SOUND_DENIED 0x05
#define KEYPAD_I2C_SET_IDLE 0x06
static void fsm_idle(void)
{
KeypadState = KEYPAD_STATE_IDLE;
KeypadShouldRead = 0;
KeypadIndex = 0;
IO_OUT(LED_RED, 0);
IO_OUT(LED_GREEN, 0);
}
static void fsm_get_bytes(uint8_t required)
{
KeypadState = KEYPAD_STATE_GETTING_BYTES;
KeypadShouldRead = required;
KeypadIndex = 0;
}
static void fsm_bytes_ready(void)
{
KeypadState = KEYPAD_STATE_BYTES_READY;
KeypadShouldRead = 0;
}
int main (void)
{
@ -38,7 +79,9 @@ int main (void)
buzzer_init();
keypad_init();
TWI_Slave_Initialize((uint8_t)((0x10 << TWI_ADR_BITS) | (1 << TWI_GEN_BIT) ));
sei();
TWI_Start_Transceiver();
// Flash LEDs and buzz buzzer for debug
IO_OUT(LED_GREEN, 1);
@ -47,6 +90,158 @@ int main (void)
IO_OUT(LED_GREEN, 0);
IO_OUT(LED_RED, 0);
for (;;) {}
return 0;
// Zero out the keypad buffer
for (uint8_t i = 0; i < KEYPAD_BUFFER_SIZE; i++)
KeypadBytes[i] = 0;
KeypadShouldRead = 0;
KeypadIndex = 0;
KeypadState = KEYPAD_STATE_IDLE;
uint8_t Command[2];
uint8_t OutBuffer[16];
for (;;)
{
if (!TWI_Transceiver_Busy())
{
if (TWI_statusReg.RxDataInBuf)
{
TWI_Get_Data_From_Transceiver(Command, 2);
switch(Command[0])
{
case KEYPAD_I2C_GET_STATE:
OutBuffer[0] = KeypadState;
TWI_Start_Transceiver_With_Data(OutBuffer, 1);
break;
case KEYPAD_I2C_GET_BYTES_WAITING:
OutBuffer[0] = KeypadIndex;
TWI_Start_Transceiver_With_Data(OutBuffer, 1);
break;
case KEYPAD_I2C_GET_BYTES:
for (uint8_t i = 0; i < KeypadIndex; i++)
OutBuffer[i] = KeypadBytes[i];
TWI_Start_Transceiver_With_Data(OutBuffer, KeypadIndex);
fsm_idle();
break;
case KEYPAD_I2C_REQUEST_BYTES:
fsm_get_bytes(Command[1]);
TWI_Start_Transceiver();
buzzer_start(TONE_HIGH);
_delay_ms(100);
buzzer_stop();
fsm_logic();
break;
case KEYPAD_I2C_SOUND_OK:
TWI_Start_Transceiver();
IO_OUT(LED_GREEN, 1);
buzzer_start(TONE_HIGH);
_delay_ms(100);
buzzer_stop();
_delay_ms(50);
buzzer_start(TONE_HIGH);
_delay_ms(100);
buzzer_stop();
_delay_ms(50);
buzzer_start(TONE_HIGH);
_delay_ms(100);
buzzer_stop();
_delay_ms(50);
buzzer_start(TONE_HIGH);
_delay_ms(100);
buzzer_stop();
break;
case KEYPAD_I2C_SOUND_DENIED:
TWI_Start_Transceiver();
IO_OUT(LED_RED, 1);
buzzer_start(TONE_HIGH);
_delay_ms(100);
buzzer_stop();
_delay_ms(50);
buzzer_start(TONE_HIGH);
_delay_ms(100);
buzzer_stop();
_delay_ms(50);
buzzer_start(TONE_LOW);
_delay_ms(1000);
buzzer_stop();
break;
case KEYPAD_I2C_SET_IDLE:
TWI_Start_Transceiver();
fsm_idle();
default:
TWI_Start_Transceiver();
}
}
else
fsm_logic();
}
}
}
static volatile uint16_t ButtonsPrevious = 0;
void fsm_logic(void)
{
switch(KeypadState)
{
case KEYPAD_STATE_GETTING_BYTES:
{
uint16_t Buttons = keypad_get_buttons();
if (KeypadShouldRead > 0 && Buttons != ButtonsPrevious && Buttons != 0)
{
// Debounce...
_delay_ms(20);
Buttons = keypad_get_buttons();
if (Buttons != 0)
{
// Make sure that only one button is pressed down == one bit is present
uint16_t Buttons_ = Buttons;
while ((Buttons_ & 1) != 1)
Buttons_ = Buttons_ >> 1;
Buttons_ = Buttons_ >> 1;
if (Buttons_ == 0)
{
// Okay, only one button is pressed down
uint8_t Byte = 0;
if (Buttons & (1 << KEY_1))
Byte = '1';
else if (Buttons & (1 << KEY_2))
Byte = '2';
else if (Buttons & (1 << KEY_3))
Byte = '3';
else if (Buttons & (1 << KEY_4))
Byte = '4';
else if (Buttons & (1 << KEY_5))
Byte = '5';
else if (Buttons & (1 << KEY_6))
Byte = '6';
else if (Buttons & (1 << KEY_7))
Byte = '7';
else if (Buttons & (1 << KEY_8))
Byte = '8';
else if (Buttons & (1 << KEY_9))
Byte = '9';
else if (Buttons & (1 << KEY_0))
Byte = '0';
if (Byte != 0)
{
KeypadBytes[KeypadIndex] = Byte;
KeypadIndex++;
if (KeypadShouldRead == 1)
fsm_bytes_ready();
KeypadShouldRead--;
buzzer_start(TONE_HIGH);
_delay_ms(100);
buzzer_stop();
}
}
}
}
ButtonsPrevious = Buttons;
}
}
}

218
software/keypad/twi.c Normal file
View File

@ -0,0 +1,218 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include "twi.h"
static uint8_t TWI_buf[TWI_BUFFER_SIZE]; // Transceiver buffer. Set the size in the header file
static uint8_t TWI_msgSize = 0; // Number of bytes to be transmitted.
static uint8_t TWI_state = TWI_NO_STATE; // State byte. Default set to TWI_NO_STATE.
// This is true when the TWI is in the middle of a transfer
// and set to false when all bytes have been transmitted/received
// Also used to determine how deep we can sleep.
static volatile uint8_t TWI_busy = 0;
union TWI_statusReg_t TWI_statusReg = {0}; // TWI_statusReg is defined in twi.h
/****************************************************************************
Call this function to set up the TWI slave to its initial standby state.
Remember to enable interrupts from the main application after initializing the TWI.
Pass both the slave address and the requrements for triggering on a general call in the
same byte. Use e.g. this notation when calling this function:
TWI_Slave_Initialise((TWI_slaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_GEN_BIT));
The TWI module is configured to NACK on any requests. Use a TWI_Start_Transceiver function to
start the TWI.
****************************************************************************/
void TWI_Slave_Initialize(uint8_t TWI_ownAddress)
{
TWAR = TWI_ownAddress; // Set own TWI slave address. Accept TWI General Calls.
TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins.
(0<<TWIE)|(0<<TWINT)| // Disable TWI Interupt.
(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Do not ACK on any requests, yet.
(0<<TWWC); //
TWI_busy = 0;
}
/****************************************************************************
Call this function to test if the TWI_ISR is busy transmitting.
****************************************************************************/
uint8_t TWI_Transceiver_Busy(void)
{
return TWI_busy;
}
/****************************************************************************
Call this function to fetch the state information of the previous operation. The function will hold execution (loop)
until the TWI_ISR has completed with the previous operation. If there was an error, then the function
will return the TWI State code.
****************************************************************************/
uint8_t TWI_Get_State_Info(void)
{
while (TWI_Transceiver_Busy()) {} // Wait until TWI has completed the transmission.
return (TWI_state); // Return error state.
}
/****************************************************************************
Call this function to send a prepared message, or start the Transceiver for reception. Include
a pointer to the data to be sent if a SLA+W is received. The data will be copied to the TWI buffer.
Also include how many bytes that should be sent. Note that unlike the similar Master function, the
Address byte is not included in the message buffers.
The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,
then initialize the next operation and return.
****************************************************************************/
void TWI_Start_Transceiver_With_Data(uint8_t *msg, uint8_t msgSize)
{
uint8_t temp;
while (TWI_Transceiver_Busy()) {} // Wait until TWI is ready for next transmission.
TWI_msgSize = msgSize; // Number of data to transmit.
for (temp = 0; temp < msgSize; temp++) // Copy data that may be transmitted if the TWI Master requests data.
{
TWI_buf[ temp ] = msg[ temp ];
}
TWI_statusReg.all = 0;
TWI_state = TWI_NO_STATE ;
TWCR = (1<<TWEN)| // TWI Interface enabled.
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag.
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Prepare to ACK next time the Slave is addressed.
(0<<TWWC); //
TWI_busy = 1;
}
/****************************************************************************
Call this function to start the Transceiver without specifing new transmission data. Useful for restarting
a transmission, or just starting the transceiver for reception. The driver will reuse the data previously put
in the transceiver buffers. The function will hold execution (loop) until the TWI_ISR has completed with the
previous operation, then initialize the next operation and return.
****************************************************************************/
void TWI_Start_Transceiver(void)
{
while (TWI_Transceiver_Busy()) {} // Wait until TWI is ready for next transmission.
TWI_statusReg.all = 0;
TWI_state = TWI_NO_STATE ;
TWCR = (1<<TWEN)| // TWI Interface enabled.
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag.
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Prepare to ACK next time the Slave is addressed.
(0<<TWWC); //
TWI_busy = 0;
}
/****************************************************************************
Call this function to read out the received data from the TWI transceiver buffer. I.e. first call
TWI_Start_Transceiver to get the TWI Transceiver to fetch data. Then Run this function to collect the
data when they have arrived. Include a pointer to where to place the data and the number of bytes
to fetch in the function call. The function will hold execution (loop) until the TWI_ISR has completed
with the previous operation, before reading out the data and returning.
If there was an error in the previous transmission the function will return the TWI State code.
****************************************************************************/
uint8_t TWI_Get_Data_From_Transceiver(uint8_t *msg, uint8_t msgSize)
{
uint8_t i;
while (TWI_Transceiver_Busy()) {} // Wait until TWI is ready for next transmission.
if(TWI_statusReg.lastTransOK) // Last transmission completed successfully.
{
for (i=0; i<msgSize; i++) // Copy data from Transceiver buffer.
{
msg[ i ] = TWI_buf[ i ];
}
TWI_statusReg.RxDataInBuf = FALSE; // Slave Receive data has been read from buffer.
}
return(TWI_statusReg.lastTransOK);
}
// ********** Interrupt Handlers ********** //
/****************************************************************************
This function is the Interrupt Service Routine (ISR), and called when the TWI interrupt is triggered;
that is whenever a TWI event has occurred. This function should not be called directly from the main
application.
****************************************************************************/
ISR(TWI_vect)
{
static uint8_t TWI_bufPtr;
switch (TWSR)
{
case TWI_STX_ADR_ACK: // Own SLA+R has been received; ACK has been returned
TWI_bufPtr = 0; // Set buffer pointer to first data location
case TWI_STX_DATA_ACK: // Data byte in TWDR has been transmitted; ACK has been received
TWDR = TWI_buf[TWI_bufPtr++];
TWCR = (1<<TWEN)| // TWI Interface enabled
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| //
(0<<TWWC); //
TWI_busy = 1;
break;
case TWI_STX_DATA_NACK: // Data byte in TWDR has been transmitted; NACK has been received.
// I.e. this could be the end of the transmission.
if (TWI_bufPtr == TWI_msgSize) // Have we transceived all expected data?
TWI_statusReg.lastTransOK = TRUE; // Set status bits to completed successfully.
else // Master has sent a NACK before all data where sent.
TWI_state = TWSR; // Store TWI State as errormessage.
TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins
(1<<TWIE)|(1<<TWINT)| // Keep interrupt enabled and clear the flag
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Answer on next address match
(0<<TWWC); //
TWI_busy = 0; // Transmit is finished, we are not busy anymore
break;
case TWI_SRX_GEN_ACK: // General call address has been received; ACK has been returned
// case TWI_SRX_GEN_ACK_M_ARB_LOST: // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned
TWI_statusReg.genAddressCall = TRUE;
case TWI_SRX_ADR_ACK: // Own SLA+W has been received ACK has been returned
// case TWI_SRX_ADR_ACK_M_ARB_LOST: // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned
// Dont need to clear TWI_S_statusRegister.generalAddressCall due to that it is the default state.
TWI_statusReg.RxDataInBuf = TRUE;
TWI_bufPtr = 0; // Set buffer pointer to first data location
// Reset the TWI Interupt to wait for a new event.
TWCR = (1<<TWEN)| // TWI Interface enabled
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Expect ACK on this transmission
(0<<TWWC);
TWI_busy = 1;
break;
case TWI_SRX_ADR_DATA_ACK: // Previously addressed with own SLA+W; data has been received; ACK has been returned
case TWI_SRX_GEN_DATA_ACK: // Previously addressed with general call; data has been received; ACK has been returned
TWI_buf[TWI_bufPtr++] = TWDR;
TWI_statusReg.lastTransOK = TRUE; // Set flag transmission successfull.
// Reset the TWI Interupt to wait for a new event.
TWCR = (1<<TWEN)| // TWI Interface enabled
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send ACK after next reception
(0<<TWWC); //
TWI_busy = 1;
break;
case TWI_SRX_STOP_RESTART: // A STOP condition or repeated START condition has been received while still addressed as Slave
// Enter not addressed mode and listen to address match
TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins
(1<<TWIE)|(1<<TWINT)| // Enable interrupt and clear the flag
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Wait for new address match
(0<<TWWC); //
TWI_busy = 0; // We are waiting for a new address match, so we are not busy
break;
case TWI_SRX_ADR_DATA_NACK: // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned
case TWI_SRX_GEN_DATA_NACK: // Previously addressed with general call; data has been received; NOT ACK has been returned
case TWI_STX_DATA_ACK_LAST_BYTE: // Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
// case TWI_NO_STATE // No relevant state information available; TWINT = “0”
case TWI_BUS_ERROR: // Bus error due to an illegal START or STOP condition
TWI_state = TWSR; //Store TWI State as errormessage, operation also clears noErrors bit
TWCR = (1<<TWSTO)|(1<<TWINT); //Recover from TWI_BUS_ERROR, this will release the SDA and SCL pins thus enabling other devices to use the bus
break;
default:
TWI_state = TWSR; // Store TWI State as errormessage, operation also clears the Success bit.
TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins
(1<<TWIE)|(1<<TWINT)| // Keep interrupt enabled and clear the flag
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Acknowledge on any new requests.
(0<<TWWC); //
TWI_busy = 0; // Unknown status, so we wait for a new address match that might be something we can handle
}
}

75
software/keypad/twi.h Normal file
View File

@ -0,0 +1,75 @@
#ifndef __TWI_H__
#define __TWI_H__
#define TWI_BUFFER_SIZE 4
union TWI_statusReg_t
{
uint8_t all;
struct
{
uint8_t lastTransOK : 1;
uint8_t RxDataInBuf : 1;
uint8_t genAddressCall : 1;
uint8_t unusedBits : 5;
};
};
extern union TWI_statusReg_t TWI_statusReg;
void TWI_Slave_Initialize(unsigned char);
unsigned char TWI_Transceiver_Busy(void);
unsigned char TWI_Get_State_Info(void);
void TWI_Start_Transceiver_With_Data(unsigned char *, unsigned char);
void TWI_Start_Transceiver(void);
unsigned char TWI_Get_Data_From_Transceiver(unsigned char *, unsigned char);
#define TWI_READ_BIT 0
#define TWI_ADR_BITS 1
#define TWI_GEN_BIT 0
#define TRUE 1
#define FALSE 0
// General TWI Master staus codes
#define TWI_START 0x08 // START has been transmitted
#define TWI_REP_START 0x10 // Repeated START has been transmitted
#define TWI_ARB_LOST 0x38 // Arbitration lost
// TWI Master Transmitter staus codes
#define TWI_MTX_ADR_ACK 0x18 // SLA+W has been tramsmitted and ACK received
#define TWI_MTX_ADR_NACK 0x20 // SLA+W has been tramsmitted and NACK received
#define TWI_MTX_DATA_ACK 0x28 // Data byte has been tramsmitted and ACK received
#define TWI_MTX_DATA_NACK 0x30 // Data byte has been tramsmitted and NACK received
// TWI Master Receiver staus codes
#define TWI_MRX_ADR_ACK 0x40 // SLA+R has been tramsmitted and ACK received
#define TWI_MRX_ADR_NACK 0x48 // SLA+R has been tramsmitted and NACK received
#define TWI_MRX_DATA_ACK 0x50 // Data byte has been received and ACK tramsmitted
#define TWI_MRX_DATA_NACK 0x58 // Data byte has been received and NACK tramsmitted
// TWI Slave Transmitter staus codes
#define TWI_STX_ADR_ACK 0xA8 // Own SLA+R has been received; ACK has been returned
#define TWI_STX_ADR_ACK_M_ARB_LOST 0xB0 // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned
#define TWI_STX_DATA_ACK 0xB8 // Data byte in TWDR has been transmitted; ACK has been received
#define TWI_STX_DATA_NACK 0xC0 // Data byte in TWDR has been transmitted; NOT ACK has been received
#define TWI_STX_DATA_ACK_LAST_BYTE 0xC8 // Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
// TWI Slave Receiver staus codes
#define TWI_SRX_ADR_ACK 0x60 // Own SLA+W has been received ACK has been returned
#define TWI_SRX_ADR_ACK_M_ARB_LOST 0x68 // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned
#define TWI_SRX_GEN_ACK 0x70 // General call address has been received; ACK has been returned
#define TWI_SRX_GEN_ACK_M_ARB_LOST 0x78 // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned
#define TWI_SRX_ADR_DATA_ACK 0x80 // Previously addressed with own SLA+W; data has been received; ACK has been returned
#define TWI_SRX_ADR_DATA_NACK 0x88 // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned
#define TWI_SRX_GEN_DATA_ACK 0x90 // Previously addressed with general call; data has been received; ACK has been returned
#define TWI_SRX_GEN_DATA_NACK 0x98 // Previously addressed with general call; data has been received; NOT ACK has been returned
#define TWI_SRX_STOP_RESTART 0xA0 // A STOP condition or repeated START condition has been received while still addressed as Slave
// TWI Miscellaneous status codes
#define TWI_NO_STATE 0xF8 // No relevant state information available; TWINT = “0”
#define TWI_BUS_ERROR 0x00 // Bus error due to an illegal START or STOP condition
#endif