Added support for Control characters and the characters <escape> and "<>{}[]^&%=\"

This commit is contained in:
Bruce Barnett 2022-07-10 10:36:49 -04:00
parent c44f9546e3
commit f27d75ea35
5 changed files with 170 additions and 19 deletions

67
LINUX.md Normal file
View File

@ -0,0 +1,67 @@
# I2C Puppet mods for Linux systems
The original version lacked certain characters, such as <ESCAPE>, and the characters "<>{}[]^&%=\"
which made it difficult to use on Linux systems
This version of the firmware has been modified to support Linux systems.
The following changes have been made
1) The backspace key works during the GUI login
2) The Sym key not acts as a Control key, so SYM+C is Control-C
3) The four top button keys are now used to provide the missing characters.
The original definiton of the keys were this
L1 L2 R1 R2 SPKR Mic BS NL SPACE
$ ~ \b \n
Shift
Alt 0
Sym | TAB
The current definition of the keys are
L1 L2 R1 R2 SPKR Mic BS NL Spacebar
<none> <esc> % = \ $ ~ BS \n <space>
Alt > ] } & ` ~ x <tab>
Shift < [ { ^ $ ` BS <space>
Sym x x x x $ ~ BS | <space>
#Linux Debug tips
The keyboard was two "outputs" - one is the USB HID interface, the other is the serial port.
Any printf() command goes to the serial port.
When the keyboard is plugged into a Linux system, a new TTY interface will appear. I usually use "ls -lt /dev/tty* | head"
to learn the name, as the newest port will appear first. On my system, it's /dev/ttyACM0
So on one terminal, I type
cat -v </dev/ttyACM0
while on a second terminal window, I type
cat -v
The first one will print all of the printf output, and the second will show you how the keyboard works normally.
#Compiling on Linux
I edit the files in <GIT>/ic2_puppet/all/ using my preferred editor. In my case, I use emacs. I have the keystroke combination "Control-C M" bound to compile, using
(global-set-key "\C-cm" 'compile)
And when I press these keys, emacs saves all files, and recompiles the
code. I have a small hub with switchable on/off ports, and restart the
keyboard into boot mode, and then do a "make install" to load the new
firmware
#TODO
Currently - the SYM+Button keys are defined as the character "x" to indicate it's not been specified.
I'l like to make these keys to the 4 arrow keys.
Also - it might be possible to create key combinations by combining the modified keys, like SYM+Alt+key

6
app/Makefile Normal file
View File

@ -0,0 +1,6 @@
# Make it useful for Linux
all: keyboard.c keyboard.h usb.c
cd ../build;make
install: ../build/app/i2c_puppet.uf2
cp ../build/app/i2c_puppet.uf2 /media/${USER}/RPI-RP2

View File

@ -2,6 +2,7 @@
#include "fifo.h" #include "fifo.h"
#include "keyboard.h" #include "keyboard.h"
#include "reg.h" #include "reg.h"
#include <stdio.h> // BGB
#include <pico/stdlib.h> #include <pico/stdlib.h>
@ -114,12 +115,76 @@ static void transition_to(struct list_item * const p_item, const enum key_state
if (reg_is_bit_set(REG_ID_CFG, CFG_USE_MODS)) { if (reg_is_bit_set(REG_ID_CFG, CFG_USE_MODS)) {
const bool shift = (self.mods[KEY_MOD_ID_SHL] || self.mods[KEY_MOD_ID_SHR]) | self.capslock; const bool shift = (self.mods[KEY_MOD_ID_SHL] || self.mods[KEY_MOD_ID_SHR]) | self.capslock;
const bool alt = self.mods[KEY_MOD_ID_ALT] | self.numlock; const bool alt = self.mods[KEY_MOD_ID_ALT] | self.numlock;
const bool is_button = (key <= KEY_BTN_RIGHT1) || ((key >= KEY_BTN_LEFT2) && (key <= KEY_BTN_RIGHT2)); // const bool is_button = (key <= KEY_BTN_RIGHT1) || ((key >= KEY_BTN_LEFT2) && (key <= KEY_BTN_RIGHT2));
const bool is_button = ((key == KEY_BTN_RIGHT1)
|| (key == KEY_BTN_RIGHT2)
|| (key == KEY_BTN_LEFT1)
|| (key == KEY_BTN_LEFT2));
const bool control = self.mods[KEY_MOD_ID_SYM];
if (alt && !is_button) { if (is_button) {
switch (key) {
case KEY_BTN_LEFT1:
if (alt) {
key = '>';
} else if (shift) {
key = '<';
} else if (control) {
key = 'x';
} else {
key =0x1B; // ESC
}
break;
case KEY_BTN_LEFT2:
if (alt) {
key = ']';
} else if (shift) {
key = '[';
} else if (control) {
key ='x';
} else {
key = '%';
}
break;
case KEY_BTN_RIGHT1:
if (alt) {
key = '}';
} else if (shift) {
key = '{';
} else if (control) {
key = 'x';
} else {
key = '=';
}
break;
case KEY_BTN_RIGHT2:
if (alt) {
key = '&';
} else if (shift) {
key = '^';
} else if (control) {
key = 'x'; // TODO
} else {
key = '\\';
}
break;
default:
// printf(" ERROR: Illegal key: %d\n", key);
;
}
} else if (alt) {
printf(" alt \n");
key = p_entry->alt; key = p_entry->alt;
} else if (!shift && (key >= 'A' && key <= 'Z')) { } else if (key >= 'A' && key <= 'Z') {
printf(" letter\n");
if (control) { // If the SYM key is held down, it's a control key
key = key - 0x40;
} else if (!shift) { // lower case letter
key = (key + ' '); key = (key + ' ');
} else {
// it's an uppercase letter - do nothing
}
} }
} }

View File

@ -22,24 +22,24 @@ enum key_mod
KEY_MOD_ID_LAST, KEY_MOD_ID_LAST,
}; };
#define KEY_JOY_UP 0x01 #define KEY_JOY_UP 0x81
#define KEY_JOY_DOWN 0x02 #define KEY_JOY_DOWN 0x82
#define KEY_JOY_LEFT 0x03 #define KEY_JOY_LEFT 0x83
#define KEY_JOY_RIGHT 0x04 #define KEY_JOY_RIGHT 0x84
#define KEY_JOY_CENTER 0x05 #define KEY_JOY_CENTER 0x85
#define KEY_BTN_LEFT1 0x06 #define KEY_BTN_LEFT1 0x86
#define KEY_BTN_RIGHT1 0x07 #define KEY_BTN_RIGHT1 0x87
// 0x08 - BACKSPACE // 0x08 - BACKSPACE
// 0x09 - TAB // 0x09 - TAB
// 0x0A - NEW LINE // 0x0A - NEW LINE
// 0x0D - CARRIAGE RETURN // 0x0D - CARRIAGE RETURN
#define KEY_BTN_LEFT2 0x11 #define KEY_BTN_LEFT2 0x91
#define KEY_BTN_RIGHT2 0x12 #define KEY_BTN_RIGHT2 0x92
#define KEY_MOD_ALT 0x1A #define KEY_MOD_ALT 0x9A
#define KEY_MOD_SHL 0x1B // Left Shift #define KEY_MOD_SHL 0x9B // Left Shift
#define KEY_MOD_SHR 0x1C // Right Shift #define KEY_MOD_SHR 0x9C // Right Shift
#define KEY_MOD_SYM 0x1D #define KEY_MOD_SYM 0x9D
struct key_callback struct key_callback
{ {

View File

@ -55,8 +55,10 @@ static void key_cb(char key, enum key_state state)
return; return;
if (tud_hid_n_ready(USB_ITF_KEYBOARD) && reg_is_bit_set(REG_ID_CF2, CF2_USB_KEYB_ON)) { if (tud_hid_n_ready(USB_ITF_KEYBOARD) && reg_is_bit_set(REG_ID_CF2, CF2_USB_KEYB_ON)) {
uint8_t conv_table[128][2] = { HID_ASCII_TO_KEYCODE }; // conv_table needs to be 256 entries long because the special keys are in range 128-256 (0x80 - 0xFF)
uint8_t conv_table[256][2] = { HID_ASCII_TO_KEYCODE };
conv_table['\n'][1] = HID_KEY_ENTER; // Fixup: Enter instead of Return conv_table['\n'][1] = HID_KEY_ENTER; // Fixup: Enter instead of Return
conv_table['\b'][1] = HID_KEY_BACKSPACE; // Fixup: HID backspace (0x2A) instead of \b (0x08)
conv_table[KEY_JOY_UP][1] = HID_KEY_ARROW_UP; conv_table[KEY_JOY_UP][1] = HID_KEY_ARROW_UP;
conv_table[KEY_JOY_DOWN][1] = HID_KEY_ARROW_DOWN; conv_table[KEY_JOY_DOWN][1] = HID_KEY_ARROW_DOWN;
conv_table[KEY_JOY_LEFT][1] = HID_KEY_ARROW_LEFT; conv_table[KEY_JOY_LEFT][1] = HID_KEY_ARROW_LEFT;
@ -66,10 +68,21 @@ static void key_cb(char key, enum key_state state)
uint8_t modifier = 0; uint8_t modifier = 0;
if (state == KEY_STATE_PRESSED) { if (state == KEY_STATE_PRESSED) {
if (conv_table[(int)key][0]) printf(" conv_table[%d][0,1]=%d,%d ",key, conv_table[(int)key][0], conv_table[(int)key][1]); // bgb
if (conv_table[(int)key][0]) {
modifier = KEYBOARD_MODIFIER_LEFTSHIFT; modifier = KEYBOARD_MODIFIER_LEFTSHIFT;
} else if (key < 0x20) { // it's a control key
if ((key == '\n') || (key == '\b')) {
// leave alone - this is necessary because the Linux graphical login processes the HID equivalent
// which is done using conv_table[] below
} else {
// convert control key, i.e. [Control-A] converts to [modifier=control, key=A]
modifier=KEYBOARD_MODIFIER_RIGHTCTRL;
key=key + 0x40;
}
keycode[0] = conv_table[(int)key][1]; }
keycode[0] = conv_table[(int)key][1];
} }
if (state != KEY_STATE_HOLD) if (state != KEY_STATE_HOLD)