Community Keyboard Firmware

I found the official keyboard sources: uConsole/Code/uconsole_keyboard at master · clockworkpi/uConsole · GitHub

I am aware of: I've rewritten DevTerm keyboard & trackball firmware - #69 by arru

Wondering if anyone wants to collaborate on porting @foriequal0’s firmware to the uConsole.

I would like to take a more direct approach, however, mapping every physical key to a scan code, and then handling the key layers at the xkb level, so that users have maximum flexibility without needing to further flash keyboard firmware.

Today I compared the keyboard firmware between the DevTerm and the uConsole.

The full diff appears below. The TL; DR is that, while the two are clearly related, they are most definitely not identical. This tells me that some small changes to @foriequal0 's code might be required to work with the uConsole’s keyboard.

My thought is that I like @foriequal0’s code better than I like clockwork pi’s, having looked at both of them, and would rather start there. QMK could be another option, but I am not as familiar with it.

Of particular concern is that while row / column pinouts appear to be similar, the pullup/down resistor configuration appears to be different. In addition, it appears the trackball pins seem to be slightly different. It is very important to get this right, as getting this wrong could potentially damage hardware. Not a risk I’m willing to take without being at all certain I’d be able to get another keyboard.

Speaking of which, I do not see the keyboard schematics in the uConsole repo.

Only in DevTerm/Code/devterm_keyboard/: bin
diff -u DevTerm/Code/devterm_keyboard/devterm.h uConsole/Code/uconsole_keyboard/devterm.h
--- DevTerm/Code/devterm_keyboard/devterm.h	2024-01-29 13:56:31.806854428 -0800
+++ uConsole/Code/uconsole_keyboard/devterm.h	2024-01-29 13:54:49.958777687 -0800
@@ -12,13 +12,30 @@
   
 }KEY_DEB;
 
+typedef struct keyboard_lock{
+  
+  uint16_t lock;//
+  uint16_t time;//
+  uint16_t begin;//
+    
+}KEYBOARD_LOCK;
+
 typedef struct keyboard_state{
 
   uint8_t layer;
   uint8_t prev_layer;
   uint8_t fn_on;
-  uint8_t shift;
+  uint16_t sf_on;//shift on
+  
+  uint8_t backlight;//0 1 2 3
+  uint8_t lock;//0 1
+
   
+  KEYBOARD_LOCK ctrl;
+  KEYBOARD_LOCK shift;  
+  KEYBOARD_LOCK alt;
+  KEYBOARD_LOCK fn;
+      
 }KEYBOARD_STATE;
 
 class DEVTERM {
@@ -37,6 +54,7 @@
     uint32_t delta;
 };
 
-#define KEYBOARD_PULL 1 // 1 for PULLUP, 0 FOR PULLDOWN
+#define KEYBOARD_PULL 0 // 1 for PULLUP, 0 FOR PULLDOWN
+#define KEYBOARD_LED_PWM_PERIOD 200
 
 #endif
Only in DevTerm/Code/devterm_keyboard/: devterm_keyboard.ino
diff -u DevTerm/Code/devterm_keyboard/keyboard.h uConsole/Code/uconsole_keyboard/keyboard.h
--- DevTerm/Code/devterm_keyboard/keyboard.h	2024-01-29 13:56:31.806854428 -0800
+++ uConsole/Code/uconsole_keyboard/keyboard.h	2024-01-29 13:54:49.958777687 -0800
@@ -23,6 +23,36 @@
 #   define DEBOUNCE 20
 #endif
 
+enum SKEYS {
+  _SELECT_KEY =0xe8,  //Joystick.button(n)
+  _START_KEY,          //Joystick.button(n)
+  _JOYSTICK_UP, //B1 //Joystick.Y()
+  _JOYSTICK_DOWN,    //Joystick.Y()
+  _JOYSTICK_LEFT,    //Joystick.X()
+  _JOYSTICK_RIGHT,   //Joystick.X()  
+  _JOYSTICK_A,       //Joystick.button(1)
+  _JOYSTICK_B,       //Joystick.button(2)
+  _JOYSTICK_X,       //Joystick.button(3)
+  _JOYSTICK_Y,       //Joystick.button(4)
+  _JOYSTICK_L,
+  _JOYSTICK_R,
+  _FN_KEY,
+  _MOUSE_LEFT,    // Mouse.press(1)
+  _MOUSE_MID,     // Mouse.press(2)
+  _MOUSE_RIGHT,   // Mouse.press(3)
+
+  _FN_BRIGHTNESS_UP, //USB Consumer brightness up https://github.com/torvalds/linux/blob/7fe10096c1508c7f033d34d0741809f8eecc1ed4/drivers/hid/hid-input.c#L903
+  _FN_BRIGHTNESS_DOWN, //USB Consumer brightness down 
+
+  _VOLUME_M,
+  _VOLUME_P,
+  _VOLUME_MUTE, //https://github.com/torvalds/linux/blob/7fe10096c1508c7f033d34d0741809f8eecc1ed4/drivers/hid/hid-input.c#L956
+  _TRACKBALL_BTN,
+  _FN_LOCK_KEYBOARD,
+  _FN_LIGHT_KEYBOARD,
+  _FN_SHIFT //FN+SHIFT,ready for more function key
+};
+
 void init_rows();
 void init_cols();
 uint8_t read_io(uint8_t io);
diff -u DevTerm/Code/devterm_keyboard/keyboard.ino uConsole/Code/uconsole_keyboard/keyboard.ino
--- DevTerm/Code/devterm_keyboard/keyboard.ino	2024-01-29 13:56:31.806854428 -0800
+++ uConsole/Code/uconsole_keyboard/keyboard.ino	2024-01-29 13:54:49.958777687 -0800
@@ -115,11 +115,10 @@
       matrix[row] = 0;
       for (int col = 0; col < MATRIX_COLS; col++) {
         matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col);
-        
       }
-      
      }
     keyboard_debouncing.deing = false;
+    
   }else{
     delay(1);
   }
@@ -165,7 +164,7 @@
 
 void keyboard_task(DEVTERM*dv)
 {
-
+ char buff[128];
   uint8_t matrix_row = 0;
   uint8_t matrix_change = 0;
   uint8_t pressed = 0;
@@ -176,6 +175,8 @@
     matrix_row = matrix_get_row(r);
     matrix_change = matrix_row ^ matrix_prev[r];
     if (matrix_change) { 
+      //sprintf(buff,"matrix_row: %d %d\n",matrix_row,matrix_prev[r]);
+      //dv->_Serial->print(buff);
       uint8_t col_mask = 1;
       for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) {
         if (matrix_change & col_mask) {
@@ -191,8 +192,6 @@
       }
     }
   }
-
-
 }
 
 void keyboard_init(DEVTERM*){
diff -u DevTerm/Code/devterm_keyboard/keymaps.ino uConsole/Code/uconsole_keyboard/keymaps.ino
--- DevTerm/Code/devterm_keyboard/keymaps.ino	2024-01-29 13:56:31.806854428 -0800
+++ uConsole/Code/uconsole_keyboard/keymaps.ino	2024-01-29 13:54:49.958777687 -0800
@@ -37,29 +37,6 @@
 #define _FN_KEY_LEFT_ARROW   KEY_HOME
 #define _FN_KEY_RIGHT_ARROW  KEY_END
 
-enum SKEYS {
-  _SELECT_KEY = 0xe8, //Joystick.button(n)
-  _START_KEY,          //Joystick.button(n)
-  _JOYSTICK_UP, //B1 //Joystick.Y()
-  _JOYSTICK_DOWN,    //Joystick.Y()
-  _JOYSTICK_LEFT,    //Joystick.X()
-  _JOYSTICK_RIGHT,   //Joystick.X()
-  _JOYSTICK_A,       //Joystick.button(1)
-  _JOYSTICK_B,       //Joystick.button(2)
-  _JOYSTICK_X,       //Joystick.button(3)
-  _JOYSTICK_Y,       //Joystick.button(4)
-  _FN_KEY,
-  _MOUSE_LEFT,    // Mouse.press(1)
-  _MOUSE_MID,     // Mouse.press(2)
-  _MOUSE_RIGHT,   // Mouse.press(3)
-
-  _FN_BRIGHTNESS_UP, //USB Consumer brightness up https://github.com/torvalds/linux/blob/7fe10096c1508c7f033d34d0741809f8eecc1ed4/drivers/hid/hid-input.c#L903
-  _FN_BRIGHTNESS_DOWN, //USB Consumer brightness down
-
-  _VOLUME_M,
-  _VOLUME_P,
-  _TRACKBALL_BTN,
-};
 
 #define DEF_LAYER      0x00
 #define FN_LAYER       0x01
@@ -81,23 +58,23 @@
   [DEF_LAYER] = {
     _SELECT_KEY, _START_KEY, _VOLUME_M, '`', '[', ']', '-', '=', \
     '1', '2', '3', '4', '5', '6', '7', '8', \
-    '9', '0', KEY_ESC, KEY_TAB, KEY_UP_ARROW, KEY_DOWN_ARROW, KEY_LEFT_ARROW, KEY_RIGHT_ARROW, \
+    '9', '0', KEY_ESC, KEY_TAB, EMP, EMP, EMP, EMP, \
     'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', \
     'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', \
     'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', \
     'n', 'm', ',', '.', '/', '\\', ';', '\'', \
-    KEY_BACKSPACE, KEY_RETURN, KEY_RIGHT_ALT, KEY_RIGHT_CTRL, KEY_RIGHT_SHIFT, ' ', EMP, EMP
+    KEY_BACKSPACE, KEY_RETURN, _FN_KEY, _FN_KEY, ' ', EMP, EMP, EMP
   },
 
   [FN_LAYER] = {
-    _PRINT_KEY, _PAUSE_KEY, _VOLUME_P, '`', '[', ']', KEY_F11, KEY_F12, \
+    _PRINT_KEY, _PAUSE_KEY, _VOLUME_MUTE, '`', '[', ']', KEY_F11, KEY_F12, \
     KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, \
-    KEY_F9, KEY_F10, KEY_ESC, KEY_CAPS_LOCK, _FN_KEY_UP_ARROW, _FN_KEY_DOWN_ARROW, _FN_KEY_LEFT_ARROW, _FN_KEY_RIGHT_ARROW, \
-    'q', 'w', 'e', 'r', 't', 'y', 'u', KEY_INSERT, \
-    'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', \
-    'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', \
+    KEY_F9, KEY_F10, _FN_LOCK_KEYBOARD, KEY_CAPS_LOCK, EMP, EMP, EMP, EMP, \
+    'q', 'w', 'e', 'r', 't', 'y', KEY_PAGE_UP, KEY_INSERT, \
+    'o', 'p', 'a', 's', 'd', 'f', 'g', KEY_HOME, \
+    KEY_END, KEY_PAGE_DOWN, 'l', 'z', 'x', 'c', 'v', 'b', \
     'n', 'm', _FN_BRIGHTNESS_DOWN, _FN_BRIGHTNESS_UP, '/', '\\', ';', '\'', \
-    KEY_DELETE, KEY_RETURN, KEY_RIGHT_ALT, KEY_RIGHT_CTRL, KEY_RIGHT_SHIFT, ' ', EMP, EMP
+    KEY_DELETE, KEY_RETURN, _FN_KEY, _FN_KEY, _FN_LIGHT_KEYBOARD, EMP, EMP, EMP
   }
 
 };
@@ -106,41 +83,38 @@
 
 static uint8_t fn_actions[MATRIX_KEYS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
-const uint16_t keys_maps[KEYS_NUM] = {_JOYSTICK_UP, _JOYSTICK_DOWN, _JOYSTICK_LEFT, \
-                                      _JOYSTICK_RIGHT, _JOYSTICK_A, _JOYSTICK_B, \
-                                      _JOYSTICK_X, _JOYSTICK_Y, _LEFT_SHIFT_KEY, _FN_KEY, \
-                                      _LEFT_CTRL_KEY, _CMD_KEY , _LEFT_ALT,     \
-                                      _MOUSE_LEFT, _MOUSE_MID, _MOUSE_RIGHT, _TRACKBALL_BTN
-                                     };
+const uint16_t keys_maps[][KEYS_NUM] = {
 
+  [DEF_LAYER] = {
+    KEY_UP_ARROW, KEY_DOWN_ARROW, KEY_LEFT_ARROW, KEY_RIGHT_ARROW, \
+    _JOYSTICK_A, _JOYSTICK_B, _JOYSTICK_X, _JOYSTICK_Y, \
+    _LEFT_SHIFT_KEY, KEY_RIGHT_SHIFT, _LEFT_CTRL_KEY, KEY_RIGHT_CTRL, \
+    _LEFT_ALT,  _MOUSE_LEFT,  KEY_RIGHT_ALT, _MOUSE_RIGHT,  \
+    _TRACKBALL_BTN
+  },
 
+  [FN_LAYER] = {
+    _FN_KEY_UP_ARROW, _FN_KEY_DOWN_ARROW, _FN_KEY_LEFT_ARROW, _FN_KEY_RIGHT_ARROW, \
+    _JOYSTICK_A, _JOYSTICK_B, _JOYSTICK_X, _JOYSTICK_Y, \
+    _FN_SHIFT, _FN_SHIFT, _LEFT_CTRL_KEY, KEY_RIGHT_CTRL, \
+    _CMD_KEY,  _MOUSE_LEFT,  KEY_RIGHT_ALT, _MOUSE_RIGHT,  \
+    _TRACKBALL_BTN
+  },
 
-uint8_t check_pd2() { // if swtich 2 in back is set to on(HIGH)
+};
 
-  return digitalRead(PD2);
-}
+uint16_t keys_pick_map[KEYS_NUM] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
-void dt_kbd_set_layer(DEVTERM*dv, uint8_t new_layer) {
+const uint16_t backlight_vals[3] = {0, 500, 2000};
 
-  if ( dv->Keyboard_state.layer != new_layer) {
+uint8_t check_pd2() { // if swtich 2 in back is set to on(HIGH)
 
-    dv->Keyboard_state.prev_layer = dv->Keyboard_state.layer;
-    dv->Keyboard_state.layer = new_layer;
-  }
+  return digitalRead(PD2);
 }
 
-void dt_kbd_restore_layer(DEVTERM*dv) {
-
-  dv->Keyboard_state.layer = dv->Keyboard_state.prev_layer;
-
-}
 void keyboard_release_core(DEVTERM*dv, uint16_t k) {
 
   switch (k) {
-    case KEY_RIGHT_SHIFT:
-      dv->Keyboard->release(k);
-      break;
-
     case  KEY_CAPS_LOCK:
       dv->Keyboard->setAdjustForHostCapsLock(false);
       dv->Keyboard->release(k);
@@ -167,9 +141,14 @@
     case _FN_BRIGHTNESS_DOWN:
     case _VOLUME_P:
     case _VOLUME_M:
+    case _VOLUME_MUTE:
       dv->Consumer->release();
       break;
-
+    case  _FN_KEY:
+      dv->Keyboard_state.fn_on = 0;
+      dv->Keyboard_state.fn.begin = 0;
+      dv->Keyboard_state.fn.time = 0;
+      break;
     default:
       dv->Keyboard->release(k);
       break;
@@ -185,7 +164,7 @@
   }
 }
 
-void keyboard_action(DEVTERM * dv, uint8_t row, uint8_t col, uint8_t mode) {
+void keyboard_action(DEVTERM*dv, uint8_t row, uint8_t col, uint8_t mode) {
 
   uint16_t k;
   uint8_t addr;
@@ -201,23 +180,27 @@
     return;
   }
 
-  switch (k) {
-    case KEY_RIGHT_SHIFT: {
-        if (mode == KEY_PRESSED) {
-          dv->Keyboard->press(k);
-        } else {
-          keyboard_release(dv, addr, k);
-        }
-      } break;
+  if (k != _FN_KEY && k != _FN_LOCK_KEYBOARD && dv->Keyboard_state.lock == 1) {
+    return;
+  }
+  if (mode == KEY_PRESSED) {
+    if ( keyboard_pick_map[addr] == 0) {
+      keyboard_pick_map[addr] = k;
+    }
+  }
 
+  switch (k) {
     case  KEY_CAPS_LOCK:
       if (mode == KEY_PRESSED) {
+
         dv->Keyboard->press(k);
         dv->Keyboard->setAdjustForHostCapsLock(true);
       } else if (mode == KEY_RELEASED) {
         keyboard_release(dv, addr, k);
       }
+
       break;
+
     case _SELECT_KEY:
       if (check_pd2() == HIGH) {
         k = ' ';
@@ -227,7 +210,7 @@
           keyboard_release(dv, addr, k);
         }
       } else {
-        if ( mode == KEY_PRESSED) {
+        if (mode == KEY_PRESSED) {
           dv->Joystick->button(9, mode);
         } else {
           keyboard_release(dv, addr, k);
@@ -275,11 +258,54 @@
       } break;
     case _VOLUME_M: {
         if (mode == KEY_PRESSED) {
-          dv->Consumer->press(HIDConsumer::VOLUME_DOWN);
+          if (dv->Keyboard_state.sf_on > 0) {
+            dv->Keyboard->release(_LEFT_SHIFT_KEY);
+            dv->Keyboard->release(KEY_RIGHT_SHIFT);
+            dv->Consumer->press(HIDConsumer::VOLUME_UP);
+          } else {
+            dv->Consumer->press(HIDConsumer::VOLUME_DOWN);
+          }
         } else {
           keyboard_release(dv, addr, k);
         }
       } break;
+    case _VOLUME_MUTE: {
+        if (mode == KEY_PRESSED) {
+          dv->Consumer->press(HIDConsumer::MUTE);
+        } else {
+          keyboard_release(dv, addr, k);
+        }
+      } break;
+    case _FN_LOCK_KEYBOARD: {
+        if (mode == KEY_PRESSED) {
+          dv->Keyboard_state.lock = dv->Keyboard_state.lock ^ 1;
+        }
+      } break;
+    case _FN_LIGHT_KEYBOARD: {
+        //dv->_Serial->println("light keyboard");
+
+        if (mode == KEY_PRESSED) {
+          dv->Keyboard_state.backlight ++;
+          if (dv->Keyboard_state.backlight >= 3) {
+            dv->Keyboard_state.backlight = 0;
+          }
+          timer.resume();
+          pwmWrite(PA8, backlight_vals[ dv->Keyboard_state.backlight ] );
+        }
+      } break;
+    case  _FN_KEY:
+      if (mode == KEY_PRESSED) {
+        if (dv->Keyboard_state.fn.lock == 0) {
+          dv->Keyboard_state.fn_on = FN_LAYER;
+          dv->Keyboard_state.fn.begin = k;
+        }
+      } else if (mode == KEY_RELEASED ) {
+
+        dv->Keyboard_state.fn_on = 0;
+        dv->Keyboard_state.fn.begin = 0;
+        dv->Keyboard_state.fn.time = 0;
+      }
+      break;
 
     default:
       if (mode == KEY_PRESSED) {
@@ -291,32 +317,177 @@
   }
 }
 
-void keypad_action(DEVTERM * dv, uint8_t col, uint8_t mode) {
+void keypad_release_core(DEVTERM*dv, uint16_t k) {
+
+  switch (k) {
+    case _FN_SHIFT:
+      break;
+    case _LEFT_SHIFT_KEY:
+    case KEY_RIGHT_SHIFT:
+      if (dv->Keyboard_state.shift.lock == 0) {
+        dv->Keyboard->release(k);
+        dv->Keyboard_state.shift.begin = 0;
+        dv->Keyboard_state.shift.time = 0;
+        dv->Keyboard_state.sf_on = 0;
+      }
+      break;
+
+    case _JOYSTICK_UP:
+      if (check_pd2() == HIGH) {
+        k = KEY_UP_ARROW;
+        dv->Keyboard->release(k);
+      } else {
+        dv->Joystick->Y(511);
+      }
+      break;
+    case _JOYSTICK_DOWN:
+      if (check_pd2() == HIGH) {
+        k = KEY_DOWN_ARROW;
+        dv->Keyboard->release(k);
+      } else {
+        dv->Joystick->Y(511);
+      }
+      break;
+    case _JOYSTICK_LEFT:
+      if (check_pd2() == HIGH) {
+        k = KEY_LEFT_ARROW;
+        dv->Keyboard->release(k);
+      } else {
+        dv->Joystick->X(511);
+      }
+      break;
+    case _JOYSTICK_RIGHT:
+      if (check_pd2() == HIGH) {
+        k = KEY_RIGHT_ARROW;
+        dv->Keyboard->release(k);
+      } else {
+        dv->Joystick->X(511);
+      }
+      break;
+    case _JOYSTICK_A:
+      if (check_pd2() == HIGH) {
+        k = 'j';
+        dv->Keyboard->release(k);
+      } else {
+        dv->Joystick->button(2, KEY_RELEASED);
+      }
+      break;
+    case _JOYSTICK_B:
+      if (check_pd2() == HIGH) {
+        k = 'k';
+        dv->Keyboard->release(k);
+      } else {
+        dv->Joystick->button(3, KEY_RELEASED);
+      }
+      break;
+    case _JOYSTICK_X:
+      if (check_pd2() == HIGH) {
+        k = 'u';
+        dv->Keyboard->release(k);
+      } else {
+        dv->Joystick->button(1, KEY_RELEASED );
+      }
+      break;
+    case _JOYSTICK_Y:
+      if (check_pd2() == HIGH) {
+        k = 'i';
+        dv->Keyboard->release(k);
+
+      } else {
+        dv->Joystick->button(4, KEY_RELEASED);
+      }
+      break;
+    case _MOUSE_LEFT:
+      dv->Mouse->release(1);
+      break;
+    case _MOUSE_MID:
+      if (dv->state->getScrolled() == false) {
+        //if no scrolling happend ,do as a normal mid mouse key click
+        dv->Mouse->click(MOUSE_MIDDLE);
+      }
+      dv->state->releaseMiddleClick();
+      break;
+    case _MOUSE_RIGHT:
+      dv->Mouse->release(2);
+      break;
+    //_LEFT_CTRL_KEY,_CMD_KEY , _LEFT_ALT
+    case _LEFT_CTRL_KEY:
+    case KEY_RIGHT_CTRL:
+      if (dv->Keyboard_state.ctrl.lock == 0) {
+        dv->Keyboard->release(k);
+        dv->Keyboard_state.ctrl.begin = 0;
+        dv->Keyboard_state.ctrl.time = 0;
+
+      }
+      break;
+
+    case _LEFT_ALT:
+    case KEY_RIGHT_ALT:
+      if (dv->Keyboard_state.alt.lock == 0) {
+        dv->Keyboard->release(k);
+        dv->Keyboard_state.alt.begin = 0;
+        dv->Keyboard_state.alt.time = 0;
+      }
+      break;
+    case _CMD_KEY:
+      dv->Keyboard->release(k);
+      break;
+    case _TRACKBALL_BTN:
+      dv->Mouse->release(MOUSE_MIDDLE);
+      break;
+    default:
+      dv->Keyboard->release(k);
+      break;
+  }
+}
+
+void keypad_release(DEVTERM*dv, uint8_t addr, uint16_t k) {
+  if ( keys_pick_map[addr] == 0) {
+    keypad_release_core(dv, k);
+  } else {
+    keypad_release_core(dv, keys_pick_map[addr]);
+    keys_pick_map[addr] = 0;
+  }
+}
+
+void keypad_action(DEVTERM*dv, uint8_t col, uint8_t mode) {
 
   uint16_t k;
 
-  k = keys_maps[col];
+  if (dv->Keyboard_state.fn_on > 0) {
+    k = keys_maps[dv->Keyboard_state.fn_on][col];
+  } else {
+    k = keys_maps[dv->Keyboard_state.layer][col];
+  }
 
   if (k == EMP) {
     return;
   }
 
+  if (dv->Keyboard_state.lock == 1) {
+    return;
+  }
+
+  if (mode == KEY_PRESSED) {
+    if ( keys_pick_map[col] == 0) {
+      keys_pick_map[col] = k;
+    }
+  }
 
   switch (k) {
+    case _FN_SHIFT:
+        keypad_release(dv, col, k);
+      break;
     case _LEFT_SHIFT_KEY:
+    case KEY_RIGHT_SHIFT:
       if (mode == KEY_PRESSED) {
-        dv->Keyboard->press(k);
+        if (dv->Keyboard_state.shift.lock == 0) {
+          dv->Keyboard->press(k);
+          dv->Keyboard_state.shift.begin = k;
+          dv->Keyboard_state.sf_on = k;
+        }
       } else if (mode == KEY_RELEASED) {
-        dv->Keyboard->release(k);
-      }
-      break;
-    case  _FN_KEY:
-      if (mode == KEY_PRESSED) {
-        dv->Keyboard_state.fn_on = FN_LAYER;
-
-      } else if (mode == KEY_RELEASED ) {
-        //release all pressed fn keys if they still been pressing
-        dv->Keyboard_state.fn_on = 0;
+        keypad_release(dv, col, k);
       }
       break;
 
@@ -326,11 +497,11 @@
         if (mode == KEY_PRESSED) {
           dv->Keyboard->press(k);
         } else if (mode == KEY_RELEASED) {
-          dv->Keyboard->release(k);
+          keypad_release(dv, col, k);
         }
       } else {
         if (mode == KEY_RELEASED) {
-          dv->Joystick->Y(511);
+          keypad_release(dv, col, k);
         } else {
           dv->Joystick->Y(0);
         }
@@ -342,11 +513,11 @@
         if (mode == KEY_PRESSED) {
           dv->Keyboard->press(k);
         } else if (mode == KEY_RELEASED) {
-          dv->Keyboard->release(k);
+          keypad_release(dv, col, k);
         }
       } else {
         if (mode == KEY_RELEASED) {
-          dv->Joystick->Y(511);
+          keypad_release(dv, col, k);
         } else {
           dv->Joystick->Y(1023);
         }
@@ -358,11 +529,11 @@
         if (mode == KEY_PRESSED) {
           dv->Keyboard->press(k);
         } else if (mode == KEY_RELEASED) {
-          dv->Keyboard->release(k);
+          keypad_release(dv, col, k);
         }
       } else {
         if (mode == KEY_RELEASED) {
-          dv->Joystick->X(511);
+          keypad_release(dv, col, k);
         } else {
           dv->Joystick->X(0);
         }
@@ -374,11 +545,11 @@
         if (mode == KEY_PRESSED) {
           dv->Keyboard->press(k);
         } else if (mode == KEY_RELEASED) {
-          dv->Keyboard->release(k);
+          keypad_release(dv, col, k);
         }
       } else {
         if (mode == KEY_RELEASED) {
-          dv->Joystick->X(511);
+          keypad_release(dv, col, k);
         } else {
           dv->Joystick->X(1023);
         }
@@ -390,10 +561,14 @@
         if (mode == KEY_PRESSED) {
           dv->Keyboard->press(k);
         } else if (mode == KEY_RELEASED) {
-          dv->Keyboard->release(k);
+          keypad_release(dv, col, k);
         }
       } else {
-        dv->Joystick->button(2, mode);
+        if (mode == KEY_PRESSED) {
+          dv->Joystick->button(2, mode);
+        } else {
+          keypad_release(dv, col, k);
+        }
       }
       break;
     case _JOYSTICK_B:
@@ -402,10 +577,14 @@
         if (mode == KEY_PRESSED) {
           dv->Keyboard->press(k);
         } else if (mode == KEY_RELEASED) {
-          dv->Keyboard->release(k);
+          keypad_release(dv, col, k);
         }
       } else {
-        dv->Joystick->button(3, mode);
+        if (mode == KEY_PRESSED) {
+          dv->Joystick->button(3, mode);
+        } else {
+          keypad_release(dv, col, k);
+        }
       }
       break;
     case _JOYSTICK_X:
@@ -414,10 +593,14 @@
         if (mode == KEY_PRESSED) {
           dv->Keyboard->press(k);
         } else if (mode == KEY_RELEASED) {
-          dv->Keyboard->release(k);
+          keypad_release(dv, col, k);
         }
       } else {
-        dv->Joystick->button(1, mode);
+        if (mode == KEY_PRESSED) {
+          dv->Joystick->button(1, mode);
+        } else {
+          keypad_release(dv, col, k);
+        }
       }
       break;
     case _JOYSTICK_Y:
@@ -426,29 +609,28 @@
         if (mode == KEY_PRESSED) {
           dv->Keyboard->press(k);
         } else if (mode == KEY_RELEASED) {
-          dv->Keyboard->release(k);
+          keypad_release(dv, col, k);
         }
       } else {
-        dv->Joystick->button(4, mode);
+        if (mode == KEY_PRESSED) {
+          dv->Joystick->button(4, mode);
+        } else {
+          keypad_release(dv, col, k);
+        }
       }
       break;
     case _MOUSE_LEFT:
       if (mode == KEY_PRESSED) {
         dv->Mouse->press(1);
       } else if (mode == KEY_RELEASED) {
-        dv->Mouse->release(1);
+        keypad_release(dv, col, k);
       }
       break;
     case _MOUSE_MID:
       if (mode == KEY_PRESSED) {
         dv->state->pressMiddleClick();
       } else {
-        if (dv->state->getScrolled() == false) {
-          //if no scrolling happend ,do as a normal mid mouse key click
-          dv->Mouse->click(MOUSE_MIDDLE);
-        }
-        dv->state->releaseMiddleClick();
-
+        keypad_release(dv, col, k);
       }
       break;
 
@@ -456,30 +638,57 @@
       if (mode == KEY_PRESSED) {
         dv->Mouse->press(2);
       } else if (mode == KEY_RELEASED) {
-        dv->Mouse->release(2);
+        keypad_release(dv, col, k);
       }
       break;
 
     //_LEFT_CTRL_KEY,_CMD_KEY , _LEFT_ALT
     case _LEFT_CTRL_KEY:
-    case _CMD_KEY:
+    case KEY_RIGHT_CTRL:
+      if (mode == KEY_PRESSED) {
+        if (dv->Keyboard_state.ctrl.lock == 0) {
+          dv->Keyboard->press(k);
+          dv->Keyboard_state.ctrl.begin = k;
+        }
+      } else {
+        keypad_release(dv, col, k);
+      }
+      break;
+
     case _LEFT_ALT:
+    case KEY_RIGHT_ALT:
+      if (mode == KEY_PRESSED) {
+        if (dv->Keyboard_state.alt.lock == 0) {
+          dv->Keyboard->press(k);
+          dv->Keyboard_state.alt.begin = k;
+        }
+      } else {
+        keypad_release(dv, col, k);
+      }
+      break;
+
+    case _CMD_KEY:
       if (mode == KEY_PRESSED) {
         dv->Keyboard->press(k);
       } else {
-        dv->Keyboard->release(k);
+        keypad_release(dv, col, k);
       }
       break;
 
     case _TRACKBALL_BTN:
       if (mode == KEY_PRESSED) {
-        dv->Mouse->press(1);
+        dv->Mouse->press(MOUSE_MIDDLE);
       } else if (mode == KEY_RELEASED) {
-        dv->Mouse->release(1);
+        keypad_release(dv, col, k);
+      }
+      break;
+    default:
+      if (mode == KEY_PRESSED) {
+        dv->Keyboard->press(k);
+      } else if (mode == KEY_RELEASED) {
+        keypad_release(dv, col, k);
       }
       break;
-    default: break;
 
   }
-
 }
diff -u DevTerm/Code/devterm_keyboard/trackball.h uConsole/Code/uconsole_keyboard/trackball.h
--- DevTerm/Code/devterm_keyboard/trackball.h	2024-01-29 13:56:31.806854428 -0800
+++ uConsole/Code/uconsole_keyboard/trackball.h	2024-01-29 13:54:49.958777687 -0800
@@ -12,10 +12,10 @@
 #define EXPONENTIAL_BASE      1.2
 */
 
-#define RIGHT_PIN             HO3
-#define LEFT_PIN              HO1
-#define DOWN_PIN              HO4
-#define UP_PIN                HO2
+#define RIGHT_PIN             HO2
+#define LEFT_PIN              HO4
+#define DOWN_PIN              HO3
+#define UP_PIN                HO1
 
 
 void trackball_init(DEVTERM*);
diff -u DevTerm/Code/devterm_keyboard/trackball.ino uConsole/Code/uconsole_keyboard/trackball.ino
--- DevTerm/Code/devterm_keyboard/trackball.ino	2024-01-29 13:56:31.806854428 -0800
+++ uConsole/Code/uconsole_keyboard/trackball.ino	2024-01-29 13:54:49.958777687 -0800
@@ -67,7 +67,9 @@
 void trackball_task(DEVTERM*dv) {
   int8_t x = 0, y = 0, w = 0;
   noInterrupts();
-  const auto mode = dv->state->moveTrackball();
+  //const auto mode = dv->state->moveTrackball();
+  //https://forum.clockworkpi.com/t/uconsole-trackball-as-scrolling-wheel-temporary-solution/11032/3
+  const auto mode = dv->Keyboard_state.fn_on == 0 ? TrackballMode::Mouse : TrackballMode::Wheel;
   if (lastMode != mode) {
     rateMeter[AXIS_X].expire();
     rateMeter[AXIS_Y].expire();
Only in uConsole/Code/uconsole_keyboard/: uconsole_keyboard.ino