#include #include #include #include "input.h" #include "systick.h" static volatile uint8_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 PORT_SBCMON(DDR) &= ~PIN_SBCMON; PORT_SBCMON(PORT) |= PIN_SBCMON; } inline uint8_t get_rotary_delta() { return rotary_delta; } #define ROTARY_DEBOUNCE 150 static inline void input_proc_rotary() { static int8_t last_a; int8_t a; int8_t b; int8_t p; uint8_t silly_debounce = 0; if (silly_debounce == 0) { p = PORT_ROTARY(PIN); a = (p & PIN_ROTARY_A); b = (p & PIN_ROTARY_B); a = !a; b = !b; if (a == 1 && last_a == 0) { silly_debounce = ROTARY_DEBOUNCE; if (rotary_delta < 31) rotary_delta += !!(a ^ b); } if (a == 0 && last_a == 1) { silly_debounce = ROTARY_DEBOUNCE; if (rotary_delta > 0) rotary_delta -= !(a ^ b); } last_a = a; } else { silly_debounce--; } } // 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; 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; } } inline uint8_t get_switch_event() { return sw_event; } inline void input_clear_events() { rotary_delta = 16; sw_event = 0; } inline uint8_t get_sbc_state() { return (PORT_SBCMON(PIN) & PIN_SBCMON); } // Need to call timer_proc() before calling this function! void input_proc() { input_proc_rotary(); input_proc_switches(); }