diff options
author | Thomas Albers Raviola <thomas@thomaslabs.org> | 2024-11-21 15:55:03 +0100 |
---|---|---|
committer | Thomas Albers Raviola <thomas@thomaslabs.org> | 2024-11-21 15:55:03 +0100 |
commit | 6d4ad089c5b758ad8af4f68bf385a26ec4e9653a (patch) | |
tree | 2fd65006b57d646b53e121aef42bba5ee5852840 /src/input.c |
Initial commit
Diffstat (limited to 'src/input.c')
-rw-r--r-- | src/input.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..db306ea --- /dev/null +++ b/src/input.c @@ -0,0 +1,59 @@ +#include <hardware.h> +#include <tty.h> +#include <stdint.h> +#include <input.h> + +enum encoder_state { + START, + CW_START, + CW_NEXT, + CW_FINAL, + CCW_START, + CCW_NEXT, + CCW_FINAL, + CW = 0x10, + CCW = 0x20 +}; + +/* State machine to keep track of encoder */ +static const uint8_t encoder_table[7][4] = { + /* 00 01 10 11*/ + [START] = { START, CCW_START, CW_START, START }, + [CCW_START] = { CCW_NEXT, CCW_START, START, START }, + [CCW_NEXT] = { CCW_NEXT, CCW_START, CCW_FINAL, START }, + [CCW_FINAL] = { CCW_NEXT, START, CCW_FINAL, START | CCW }, + [CW_START] = { CW_NEXT, START, CW_START, START }, + [CW_NEXT] = { CW_NEXT, CW_FINAL, CW_START, START }, + [CW_FINAL] = { CW_NEXT, CW_FINAL, START, START | CW } +}; + +struct fifo input_fifo = {0, 0, {0}}; + +void +input_event(void) __critical __interrupt(4) +{ + if ((port_b_data & 0x03) != 0x03) { + // Encoder + uint8_t state = START; + uint8_t encoder; + uint8_t next_state; + + do { + encoder = port_b_data & 0x03; + next_state = encoder_table[state][encoder]; + state = next_state & 0x0F; + } while (state != START); + + if (next_state == CW || next_state == CCW) + fifo_push(&input_fifo, next_state); + } else if (port_b_data & 0x7C) { + // Key pressed + for (int i = 0; i < 5; i++) { + uint8_t bit = 1 << (i + 2); + uint8_t state = !(port_b_data & bit); + + if (state) + fifo_push(&input_fifo, i); + } + } +} |