#include #include #include #include #include "lcd_routines.h" #include "uart.h" #define SAVE PD2 #define SIGNAL PD3 #define FREQ_DOWN PD4 #define FREQ_UP PD5 #define AMP_DOWN PD6 #define AMP_UP PD7 #define KEY_DDR DDRD #define KEY_PORT PORTD #define KEY_PIN PIND #define KEY_ON_DDR DDRB #define KEY_ON_PORT PORTB #define KEY_ON_PIN PINB #define KEY_ON PB0 #define LED_PIN PA7 #define LED_PORT PORTA #define LED_DDR DDRA #define led_on() LED_PORT |= _BV(LED_PIN); #define led_off() LED_PORT &= ~_BV(LED_PIN); #define led_toggle() LED_PORT ^= _BV(LED_PIN) #define UART_BAUD_RATE 9600 #define ALL_KEYS (_BV(SAVE) | _BV(SIGNAL) | _BV(FREQ_DOWN) | _BV(FREQ_UP) | _BV(AMP_DOWN) | _BV(AMP_UP) ) #define REPEAT_MASK ALL_KEYS #define REPEAT_START 50 #define REPEAT_NEXT 20 volatile uint16_t key_state; volatile uint16_t key_press; /* prototypes */ void init_io(); uint16_t get_key_press(uint16_t key_mask); int main(void) { init_io(); lcd_init(); uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU)); lcd_setcursor(0, 0); unsigned int c; sei(); for (;;) { if (uart_available() > 0) { c = uart_getc(); if (c == '}') { lcd_clear(); } else if (c == '*') { lcd_setcursor(0, 2); } else if (c == '+') { lcd_setcursor(0, 1); } else if (c == '\'') { led_off(); } else if (c == '#') { led_on(); } else { lcd_data(c); } } if (get_key_press(_BV(FREQ_DOWN))) { uart_putc('f'); } if (get_key_press(_BV(FREQ_UP))) { uart_putc('F'); } if (get_key_press(_BV(SIGNAL))) { uart_putc('s'); } if (get_key_press(_BV(AMP_UP))) { uart_putc('A'); } if (get_key_press(_BV(AMP_DOWN))) { uart_putc('a'); } if (get_key_press(_BV(KEY_ON) << 8)) { uart_putc('o'); } if (get_key_press(_BV(SAVE))) { uart_putc('v'); } } } void init_io() { KEY_DDR &= ~ALL_KEYS; // configure key port for input KEY_PORT |= ALL_KEYS; KEY_ON_DDR &= ~_BV(KEY_ON); KEY_ON_PORT |= _BV(KEY_ON); LED_DDR |= _BV(LED_PIN); LED_PORT &= ~_BV(LED_PIN); TCCR0 = (1 << CS02) | (1 << CS00); // divide by 1024 TCNT0 = (uint8_t) (int16_t) -(F_CPU / 1024 * 10e-3 + 0.5); // preload for 10ms TIMSK |= 1 << TOIE0; // enable timer interrupt } ISR( TIMER0_OVF_vect ) { static uint16_t ct0, ct1; uint16_t i; TCNT0 = (uint8_t) (int16_t) -(F_CPU / 1024 * 10e-3 + 0.5); // preload for 10ms i = key_state ^ ~(KEY_PIN | (KEY_ON_PIN << 8)); // key changed ? ct0 = ~(ct0 & i); // reset or count ct0 ct1 = ct0 ^ (ct1 & i); // reset or count ct1 i &= ct0 & ct1; // count until roll over ? key_state ^= i; // then toggle debounced state key_press |= key_state & i; // 0->1: key press detect } uint16_t get_key_press(uint16_t key_mask) { cli(); // read and clear atomic ! key_mask &= key_press; // read key(s) key_press ^= key_mask; // clear key(s) sei(); return key_mask; }