matemat/main.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;
}