]> mj.ucw.cz Git - home-hw.git/commitdiff
Waiting room: Scanning keyboard
authorMartin Mares <mj@ucw.cz>
Fri, 18 Apr 2025 21:45:38 +0000 (23:45 +0200)
committerMartin Mares <mj@ucw.cz>
Fri, 18 Apr 2025 21:45:38 +0000 (23:45 +0200)
waiting/README
waiting/firmware/main.c

index 9c47db33051cbcdd8f3f706f3e52aba20e9b4b1a..44c88a9da4f2d23a0f791c8ab1b8dcae2c8d7f0b 100644 (file)
@@ -14,14 +14,14 @@ I2C2        display 1602: HD44780U controller via PCF8574 expander, needs pull-up to 5V
 BluePill LED           | PC13           GND |
                        | PC14            5V |
                        | PC15           PB9 |
-                       | PA0            PB8 |  TIM4_CH3 - Neopixel data (needs pull-up)
-                       | PA1            PB7 |
-                       | PA2            PB6 |
-                       | PA3            PB5 |
-                       | PA4            PB4 |
-                       | PA5            PB3 |
-                       | PA6           PA15 |
-                       | PA7           PA12 |
+kbd2 - col 1           | PA0            PB8 |  TIM4_CH3 - Neopixel data (needs pull-up)
+kbd3 - col 2           | PA1            PB7 |
+kbd4 - col 3           | PA2            PB6 |
+kbd5 - col 4           | PA3            PB5 |
+kbd6 - row 1           | PA4            PB4 |
+kbd7 - row 2           | PA5            PB3 |
+kbd8 - row 3           | PA6           PA15 |
+kbd9 - row 4           | PA7           PA12 |
                        | PB0           PA11 |
                        | PB1           PA10 |  RXD1 - debugging console
 I2C2_SCL - display (pu)        | PB10           PA9 |  TXD1 - debugging console
index d1f76815ddc3b8206165d2a293c5ded238726c2b..f0c552cdc61d17ee6cf9b369603b4c70f7bac4d8 100644 (file)
@@ -58,6 +58,11 @@ static void gpio_init(void)
        gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
        gpio_clear(GPIOC, GPIO13);
 
+       // PA0-7 = keyboard
+       gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, 0xf0);
+       gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_INPUT_FLOAT, 0x0f);
+       gpio_set(GPIOA, 0xff);
+
        // PB8 = data for Neopixel
        gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, GPIO8);
 
@@ -218,6 +223,13 @@ static void display_char(byte ch)
        display_write_nibble(((ch << 4) & 0xf0) | LCD_BIT_RS);
 }
 
+static void display_hex8(uint x)
+{
+       uint h = (x >> 4) & 0x0f, l = x & 0x0f;
+       display_char('0' + h + (h >= 10 ? 7 : 0));
+       display_char('0' + l + (l >= 10 ? 7 : 0));
+}
+
 static void display_string(const char *str)
 {
        while (*str)
@@ -268,6 +280,54 @@ static void display_init(void)
        debug_puts("Display ready\n");
 }
 
+/*** Keyboard ***/
+
+static byte keyboard_step;
+static u16 keyboard_tmp;
+static u16 keyboard_debounce_mask;
+static byte keyboard_debounce_cnt;
+static u16 keyboard_mask;
+static char keyboard_char;
+
+#define KEYBOARD_DEBOUNCE_CYCLES 5
+
+static const char keyboard_map[] = "123A456B789C*0#D";
+
+static void keyboard_scan(void)
+{
+       // The first step does nothing since no row is activated.
+       uint cols = gpio_get(GPIOA, 0x0f) ^ 0x0f;
+       keyboard_tmp |= cols << 4 * keyboard_step;
+
+       if (++keyboard_step == 4) {
+               if (keyboard_tmp == keyboard_debounce_mask) {
+                       if (keyboard_debounce_cnt == KEYBOARD_DEBOUNCE_CYCLES) {
+                               keyboard_debounce_cnt++;
+                               keyboard_mask = keyboard_tmp;
+                               if (keyboard_mask && !(keyboard_mask & (keyboard_mask - 1))) {
+                                       for (uint i=0; i<16; i++)
+                                               if (keyboard_mask & (1 << i)) {
+                                                       keyboard_char = keyboard_map[i];
+                                                       break;
+                                               }
+                               } else {
+                                       keyboard_char = 0;
+                               }
+                       } else if (keyboard_debounce_cnt < KEYBOARD_DEBOUNCE_CYCLES) {
+                               keyboard_debounce_cnt++;
+                       }
+               } else {
+                       keyboard_debounce_mask = keyboard_tmp;
+                       keyboard_debounce_cnt = 0;
+               }
+               keyboard_step = 0;
+               keyboard_tmp = 0;
+       }
+
+       gpio_set(GPIOA, 0xf0);
+       gpio_clear(GPIOA, 0x10 << keyboard_step);
+}
+
 /*** Neopixels ***/
 
 #if 0
@@ -571,8 +631,26 @@ int main(void)
 
        u32 last_blink = 0;
        // u32 last_send = 0;
+       uint key_column = 0;
 
        for (;;) {
+               keyboard_scan();
+#if 0
+               if (keyboard_mask != last_key_mask) {
+                       last_key_mask = keyboard_mask;
+                       display_goto(1, 0);
+                       display_hex8((keyboard_mask >> 8) & 0xff);
+                       display_hex8(keyboard_mask & 0xff);
+               }
+#endif
+               if (keyboard_char) {
+                       if (key_column < 15) {
+                               display_goto(1, key_column++);
+                               display_char(keyboard_char);
+                       }
+                       keyboard_char = 0;
+               }
+
                if (ms_ticks - last_blink >= 300) {
                        debug_led_toggle();
                        last_blink = ms_ticks;