
enum {
    KBD_STATE_IDLE,
    KBD_STATE_WAIT_RELEASE,
};
char key_lookup[12] = {
    "ABC1",
    "DEF2",
    ...
};
unsigned char kbd_state = KBD_STATE_IDLE;
unsigned char kbd_rotate_state = 0;   // which of multiple alternatives to lookup and return for current key
unsigned char kbd_timeout = 0;        // tick down in interrupt handler - timeout for rotating characters for same key
unsigned char kbd_was_rotate = FALSE; // if returned key should replace previously returned key
signed char kbd_prev = -1;            // remember pressed key so we can compare with next pressed key

void my_keyboard_handler(void) {
    signed char key;

    // poll keyboard, or poll queue filled from interrupt-driven keyboard scanner.
    /// note - keyboard poll required to handle debounce.
    key = poll_keyboard();
    // key < 0 => no key pressed.
    // key 0..11 => specific key pressed.
    switch (kdb_state) {
        case KBD_STATE_IDLE:
            if (key >= 0) {
                kbd_state = KBD_STATE_WAIT_RELEASE;
                if (key == kbd_prev && kbd_timeout > 0) {
                    // repetition of same key without timeout period. Rotate through accepted keys.
                    kbd_rotate_state = (kbd_rotate_state+1) % strlen(kbd_lookup[key]);
                    kbd_was_rotate = TRUE; // redraw last character on display
                ] else {
                    kbd_prev = key;
                    kbd_was_rotate = FALSE;
                    kbd_rotate_state = 0;
                }
                kbd_timeout = KEY_TIMEOUT;
                return kbd_lookup[key][kbd_rotate_state];
            }
            return 0; // no key pressed
        case KDB_STATE_WAIT_RELEASE:
            // For now - don't support keyboard repeat, so wait for key release
            // before new presses (same key or other) may be accepted.
            if (!key) {
                // finally idle keyboard. Arm for next key press.
                kbd_state = KBD_STATE_IDLE;
            }
            return 0;
        default:
            // Invalid keyboard state machine state!
            kdb_state = KDB_STATE_IDLE;
            kbd_prev = -1;
            return 0;
    } // switch
} // my_keyboard_handler()
