#include #include #include #include #include static volatile uint8_t kbd_state = 0; static volatile uint8_t kbd_input = 0; static volatile uint8_t kbd_flags = 0; static volatile uint8_t ts = 10; #define KBD_FLAG_ERROR (_BV(0)) #define KBD_FLAG_BREAK (_BV(1)) #define KBD_FLAG_EXT (_BV(2)) #define KBD_CODE_UP 0xe075 #define KBD_CODE_LEFT 0xe06b #define KBD_CODE_DOWN 0xe072 #define KBD_CODE_RIGHT 0xe074 static inline bool kbd_data() { return (PINC & (1 << 0)); } static inline bool kbd_clock() { return (PINC & (1 << 1)); } ISR(PCINT1_vect) { if (kbd_clock()) return; bool data = kbd_data(); if (kbd_state == 0) { if (!data) { /* start bit */ kbd_input = 0; kbd_state++; } return; } if (kbd_state <= 8) { kbd_input |= (data << (kbd_state-1)); kbd_state++; return; } if (kbd_state == 9) { if ((__builtin_popcount(kbd_input) & 1) == data) kbd_flags |= KBD_FLAG_ERROR; kbd_state++; return; } kbd_state = 0; if (kbd_flags & KBD_FLAG_ERROR) { /* Retry */ return; } if (kbd_input == 0xe0) { kbd_flags |= KBD_FLAG_EXT; return; } if (kbd_input == 0xf0) { kbd_flags |= KBD_FLAG_BREAK; return; } uint16_t code = kbd_input; if (kbd_flags & KBD_FLAG_EXT) code |= 0xe000; if (!(kbd_flags & KBD_FLAG_BREAK)) { switch (code) { case KBD_CODE_UP: if (ts > 0) ts--; break; case KBD_CODE_DOWN: if (ts < 31) ts++; PORTB = 0; break; } } kbd_flags = 0; } int main(void) { DDRB = 0xff; PORTB = 0; DDRC = 0x00; PORTC = 0x03; PCMSK1 = (1 << PCINT9); PCICR = (1 << PCIE1); sei(); while(true) { PORTB ^= 0x20; uint32_t i; for (i = 0; i < (1 << ts); i++) _delay_ms(1); } return 0; }