Newer keypas
This commit is contained in:
parent
30c4841562
commit
cc1785dfee
8 changed files with 530 additions and 18 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -16,4 +16,6 @@ void keypad_init(void);
|
|||
#define KEY_7 10
|
||||
#define KEY_S 11
|
||||
|
||||
uint16_t keypad_get_buttons(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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
218
software/keypad/twi.c
Normal 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
75
software/keypad/twi.h
Normal 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
|
||||
|
Loading…
Add table
Reference in a new issue