131 lines
2.9 KiB
C
131 lines
2.9 KiB
C
#include <stdlib.h>
|
|
#include <avr/io.h>
|
|
#include <avr/interrupt.h>
|
|
#include <avr/pgmspace.h>
|
|
|
|
#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 LED_PIN PA7
|
|
#define LED_PORT PORTA
|
|
#define LED_DDR DDRA
|
|
|
|
#define led_on() LED_PORT |= _BV(LED_PORT);
|
|
#define led_off() LED_PORT &= ~_BV(LED_PORT);
|
|
|
|
#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 uint8_t key_state; // debounced and inverted key state:
|
|
// bit = 1: key pressed
|
|
volatile uint8_t key_press; // key press detect
|
|
|
|
volatile uint8_t key_rpt; // key long press and repeat
|
|
|
|
/* prototypes */
|
|
void init_io();
|
|
uint8_t get_key_press(uint8_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 {
|
|
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(SAVE))) {
|
|
uart_putc('v');
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void init_io() {
|
|
KEY_DDR &= ~ALL_KEYS; // configure key port for input
|
|
KEY_PORT |= ALL_KEYS;
|
|
LED_DDR |= _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 uint8_t ct0, ct1, rpt;
|
|
uint8_t i;
|
|
|
|
TCNT0 = (uint8_t) (int16_t) -(F_CPU / 1024 * 10e-3 + 0.5); // preload for 10ms
|
|
|
|
i = key_state ^ ~KEY_PIN; // 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
|
|
|
|
if ((key_state & REPEAT_MASK) == 0) // check repeat function
|
|
rpt = REPEAT_START; // start delay
|
|
if (--rpt == 0) {
|
|
rpt = REPEAT_NEXT; // repeat delay
|
|
key_rpt |= key_state & REPEAT_MASK;
|
|
}
|
|
}
|
|
|
|
uint8_t get_key_press(uint8_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;
|
|
}
|
|
|