From cc1785dfeeb87a0ac27cdfe19721884b986e3847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergiusz=20=27q3k=27=20Baza=C5=84ski?= Date: Sat, 11 Jan 2014 21:28:57 +0100 Subject: [PATCH] Newer keypas --- software/keypad/Makefile | 8 +- software/keypad/buzzer.c | 13 +++ software/keypad/buzzer.h | 2 + software/keypad/keypad.c | 23 +++-- software/keypad/keypad.h | 2 + software/keypad/main.c | 207 +++++++++++++++++++++++++++++++++++-- software/keypad/twi.c | 218 +++++++++++++++++++++++++++++++++++++++ software/keypad/twi.h | 75 ++++++++++++++ 8 files changed, 530 insertions(+), 18 deletions(-) create mode 100644 software/keypad/twi.c create mode 100644 software/keypad/twi.h diff --git a/software/keypad/Makefile b/software/keypad/Makefile index e8778b7..d992d0c 100644 --- a/software/keypad/Makefile +++ b/software/keypad/Makefile @@ -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 diff --git a/software/keypad/buzzer.c b/software/keypad/buzzer.c index 458e67a..ef576df 100644 --- a/software/keypad/buzzer.c +++ b/software/keypad/buzzer.c @@ -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) diff --git a/software/keypad/buzzer.h b/software/keypad/buzzer.h index f2e4972..fa0aebf 100644 --- a/software/keypad/buzzer.h +++ b/software/keypad/buzzer.h @@ -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 diff --git a/software/keypad/keypad.c b/software/keypad/keypad.c index 96a255e..2611608 100644 --- a/software/keypad/keypad.c +++ b/software/keypad/keypad.c @@ -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; +} + + + diff --git a/software/keypad/keypad.h b/software/keypad/keypad.h index 05bd1d4..b2fb82d 100644 --- a/software/keypad/keypad.h +++ b/software/keypad/keypad.h @@ -16,4 +16,6 @@ void keypad_init(void); #define KEY_7 10 #define KEY_S 11 +uint16_t keypad_get_buttons(void); + #endif diff --git a/software/keypad/main.c b/software/keypad/main.c index 8bc84df..fae3113 100644 --- a/software/keypad/main.c +++ b/software/keypad/main.c @@ -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; + } + } } diff --git a/software/keypad/twi.c b/software/keypad/twi.c new file mode 100644 index 0000000..1c204e4 --- /dev/null +++ b/software/keypad/twi.c @@ -0,0 +1,218 @@ +#include +#include + +#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<