webradio/firmware/input.c

99 lines
2.1 KiB
C
Raw Normal View History

2020-07-27 21:39:29 +02:00
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "input.h"
#include "systick.h"
static volatile int8_t rotary_delta = 0;
static volatile uint8_t sw_event = 0;
void input_init()
{
PORT_ROTARY(DDR) &= ~(PIN_ROTARY_A | PIN_ROTARY_B); // Configure as input
PORT_ROTARY(PORT) &= ~(PIN_ROTARY_A | PIN_ROTARY_B); // Set pullups
PORT_KEYPAD(DDR) &= ~(PIN_KEYPAD_MASK); // Key inputs
PORT_KEYPAD(PORT) |= PIN_KEYPAD_MASK; // Key pullups
}
int8_t get_rotary_delta()
{
int8_t temp = rotary_delta;
//rotary_delta = 0;
return temp;
}
static inline void input_proc_rotary()
{
static int8_t last_a;
int8_t a;
int8_t b;
int8_t p;
p = PORT_ROTARY(PIN);
a = (p & PIN_ROTARY_A);
b = (p & PIN_ROTARY_B);
a = !a;
b = !b;
if (a == 1 && last_a == 0) {
_delay_ms(1); // TODO
rotary_delta += !!(a ^ b);
}
if (a == 0 && last_a == 1) {
_delay_ms(1); // TODO
rotary_delta -= !(a ^ b);
}
last_a = a;
}
// TODO: Pressing two keys at the same time can lead to unfortunate behavior.
void input_proc_switches()
{
uint8_t sw;
uint8_t ev;
uint8_t i;
static uint8_t sw_last = 0xFF;
uint8_t delta;
sw = PORT_KEYPAD(PIN) & PIN_KEYPAD_MASK;
ev = sw ^ sw_last;
if (ev) {
if (timer_expired(TIMID_SW_DEBOUNCE)) { // If we read a value, wait for the debounce time before we process any other state
for (i=0; i < 8; ++i) {
if (ev & (1 << i)) {
if (sw & (1 << i)) { // Key release
if (timer_expired(TIMID_SW_LONGPRESS))
i |= (1 << 7) | (1 << 6);
else
i |= (1 << 7);
sw_event = i;
} else { // Key push
sw_event = 0; // To be honest, I don't have a f*cking clue why I need this...
timer_set(TIMID_SW_LONGPRESS, MS_TO_TICKS(1000));
}
timer_set(TIMID_SW_DEBOUNCE, MS_TO_TICKS(250));
break; // We can only process one event at a time anyway, so let's quit it here
}
}
}
sw_last = sw;
}
}
uint8_t get_switch_event()
{
uint8_t temp = sw_event;
sw_event = 0;
return temp;
}
// Need to call timer_proc() before calling this function!
void input_proc()
{
input_proc_rotary();
input_proc_switches();
}