From 406be08f5ee993be508223bc3b9c81f3478209b9 Mon Sep 17 00:00:00 2001
From: Stephen D <webmaster@scd31.com>
Date: Tue, 6 Feb 2024 22:15:59 -0400
Subject: [PATCH] keyboard driver

---
 src/keyboard.rs | 165 ++++++++++++++++++++++++++++++++++++++++++++++--
 src/main.rs     |   1 -
 2 files changed, 159 insertions(+), 7 deletions(-)

diff --git a/src/keyboard.rs b/src/keyboard.rs
index e787964..2a11aef 100644
--- a/src/keyboard.rs
+++ b/src/keyboard.rs
@@ -1,11 +1,96 @@
-use core::convert::Infallible;
+use core::{convert::Infallible, fmt::Display};
 
 use embedded_hal::{
     blocking::delay::{DelayMs, DelayUs},
     digital::v2::{InputPin, OutputPin},
 };
 use rp2040_hal::Timer;
-use rtt_target::rprintln;
+use rtt_target::{rprint, rprintln};
+
+const NONE: char = '\0';
+const CALL_END: char = '\x01';
+const L_SHIFT: char = '\x02';
+const R_SHIFT: char = '\x03';
+const ALT: char = '\x04';
+const SYM: char = '\x05';
+const BACK: char = '\x06';
+const MENU: char = '\x07';
+const BACKSPACE: char = '\x08';
+const CALL_START: char = '\x09';
+const TOUCHPAD_BUTTON: char = '\x0B';
+const ENTER: char = '\n';
+const KEYMAP: [[char; 8]; 6] = [
+    [CALL_END, ENTER, 'b', 'y', 'n', 'j', 'u', 'h'],
+    [NONE, BACKSPACE, '$', 'i', 'm', 'k', 'o', 'l'],
+    [NONE, 'p', 'x', 'd', 'z', L_SHIFT, 'e', 's'],
+    [NONE, R_SHIFT, 'v', 't', 'c', 'f', 'r', 'g'],
+    [NONE, 'a', ALT, SYM, ' ', '0', 'q', 'w'],
+    [
+        NONE,
+        NONE,
+        BACK,
+        MENU,
+        NONE,
+        CALL_START,
+        NONE,
+        TOUCHPAD_BUTTON,
+    ],
+];
+
+enum KeyCode {
+    CallStart,
+    Menu,
+    Touchpad,
+    Back,
+    CallEnd,
+    Backspace,
+    Enter,
+    LeftShift,
+    RightShift,
+    Alt,
+    Sym,
+    Char(char),
+}
+
+impl KeyCode {
+    fn from_keyboard(c: char, alt: bool, shift: bool) -> Self {
+        match (alt, shift, c) {
+            (_, _, CALL_END) => KeyCode::CallEnd,
+            (_, _, L_SHIFT) => KeyCode::LeftShift,
+            (_, _, R_SHIFT) => KeyCode::RightShift,
+            (_, _, ALT) => KeyCode::Alt,
+            (_, _, SYM) => KeyCode::Sym,
+            (_, _, BACK) => KeyCode::Back,
+            (_, _, MENU) => KeyCode::Menu,
+            (_, _, BACKSPACE) => KeyCode::Backspace,
+            (_, _, CALL_START) => KeyCode::CallStart,
+            (_, _, TOUCHPAD_BUTTON) => KeyCode::Touchpad,
+            (_, _, ENTER) => KeyCode::Enter,
+            (false, false, _) => KeyCode::Char(c),
+            (true, _, _) => KeyCode::Char(altify(c)),
+            (false, true, _) => KeyCode::Char(c.to_ascii_uppercase()),
+        }
+    }
+}
+
+impl Display for KeyCode {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        match self {
+            KeyCode::CallEnd => write!(f, "<CALLEND>"),
+            KeyCode::Backspace => write!(f, "<BACKSPACE>"),
+            KeyCode::Enter => write!(f, "\n"),
+            KeyCode::CallStart => write!(f, "<CALLSTART>"),
+            KeyCode::Menu => write!(f, "<MENU>"),
+            KeyCode::Touchpad => write!(f, "<TOUCHPAD>"),
+            KeyCode::Back => write!(f, "<BACK>"),
+            KeyCode::LeftShift => write!(f, "<LEFTSHIFT>"),
+            KeyCode::RightShift => write!(f, "<RIGHTSHIFT>"),
+            KeyCode::Alt => write!(f, "<ALT>"),
+            KeyCode::Sym => write!(f, "<SYM>"),
+            KeyCode::Char(c) => write!(f, "{c}"),
+        }
+    }
+}
 
 pub struct Keyboard<
     // col
@@ -24,6 +109,7 @@ pub struct Keyboard<
     row_clk: RCLK,
     row_ser: RSER,
     row_ld: RLD,
+    last_state: u64,
 }
 
 impl<
@@ -54,11 +140,13 @@ impl<
             row_clk,
             row_ser,
             row_ld,
+
+            last_state: 0,
         }
     }
 
     pub fn read_state(&mut self) -> u64 {
-        let mut out = 0;
+        let mut state = 0;
 
         for x in 0..6 {
             // +2 gets us to QF (col 6)
@@ -66,15 +154,37 @@ impl<
 
             self.timer.delay_ms(1);
 
-            out |= u64::from(read_rows(
+            let y = read_rows(
                 &mut self.timer,
                 &mut self.row_clk,
                 &mut self.row_ser,
                 &mut self.row_ld,
-            )) << (x * 8);
+            );
+
+            state |= u64::from(y) << (x * 8);
+        }
+
+        let delta = (!self.last_state) & state;
+        for x in 0..6 {
+            for y in 0..8 {
+                if delta & (1 << (x * 8 + y)) > 0 {
+                    let key = KEYMAP[usize::try_from(x).unwrap()][usize::try_from(y).unwrap()];
+                    if key != NONE {
+                        let keycode = KeyCode::from_keyboard(
+                            key,
+                            is_alt_pressed(state),
+                            is_shift_pressed(state),
+                        );
+                        rprint!("{}", keycode);
+                    } else {
+                        rprint!("\n({}, {})", x, y);
+                    }
+                }
+            }
         }
 
-        out
+        self.last_state = state;
+        state
     }
 
     // 1s in val are low
@@ -122,3 +232,46 @@ fn read_rows<
 
     out
 }
+
+fn is_alt_pressed(state: u64) -> bool {
+    (state & (1 << (4 * 8 + 2))) > 0
+}
+
+fn is_shift_pressed(state: u64) -> bool {
+    let left = (state & (1 << (2 * 8 + 5))) > 0;
+    let right = (state & (1 << (3 * 8 + 1))) > 0;
+
+    left || right
+}
+
+fn altify(c: char) -> char {
+    match c {
+        'q' => '#',
+        'w' => '1',
+        'e' => '2',
+        'r' => '3',
+        't' => '(',
+        'y' => ')',
+        'u' => '_',
+        'i' => '-',
+        'o' => '+',
+        'p' => '@',
+        'a' => '*',
+        's' => '4',
+        'd' => '5',
+        'f' => '6',
+        'g' => '/',
+        'h' => ':',
+        'j' => ';',
+        'k' => ',',
+        'l' => '"',
+        'z' => '7',
+        'x' => '8',
+        'c' => '9',
+        'v' => '?',
+        'b' => '!',
+        'n' => ',',
+        'm' => '.',
+        _ => c,
+    }
+}
diff --git a/src/main.rs b/src/main.rs
index 868b3de..a4a5ae2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -277,7 +277,6 @@ mod app {
 
         let state = keyboard.read_state();
         if state > 0 {
-            rprintln!("{:x}", state);
             write!(&mut buf, "KB: {state:x}\r\n").unwrap();
             //serial.write(&buf.as_bytes());
             keyboard_bl.set_duty(max_duty);
-- 
GitLab