aboutsummaryrefslogtreecommitdiff
path: root/src/input.c
diff options
context:
space:
mode:
authorThomas Albers Raviola <thomas@thomaslabs.org>2024-11-21 15:55:03 +0100
committerThomas Albers Raviola <thomas@thomaslabs.org>2024-11-21 15:55:03 +0100
commit6d4ad089c5b758ad8af4f68bf385a26ec4e9653a (patch)
tree2fd65006b57d646b53e121aef42bba5ee5852840 /src/input.c
Initial commit
Diffstat (limited to 'src/input.c')
-rw-r--r--src/input.c59
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);
+ }
+ }
+}