From 6054e32b278d35cf89df990d9a23290d49e379f7 Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Sat, 24 Sep 2022 14:35:14 -0400 Subject: initial firmware for model 100, based on my model 01 sketch. --- .gitignore | 2 + Makefile | 64 +++++++++ Model100.ino | 424 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ flash | 8 ++ gdbinit.container | 11 ++ sketch.json | 6 + 6 files changed, 515 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 Model100.ino create mode 100755 flash create mode 100644 gdbinit.container create mode 100644 sketch.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..43f0aa8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.bin +*.elf diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9d997a4 --- /dev/null +++ b/Makefile @@ -0,0 +1,64 @@ +# This makefile for a Kaleidoscope sketch pulls in all the targets +# required to build the example + +#" /home/bjc/src/Kaleidoscope/.arduino/data/packages/keyboardio/tools/dfu-util/0.10.0-arduino1/dfu-util" --device 0x3496:0x0005 -D /tmp/kaleidoscope-bjc/output/3606415822-Model100.ino/Model100.ino.bin -R + +# arduino-cli compile --fqbn keyboardio:gd32:keyboardio_model_100 --show-properties Model100.ino + +_ARDUINO_CLI_COMPILE_CUSTOM_FLAGS=--build-property "runtime.tools.xpack-arm-none-eabi-gcc-9.3.1-1.3.path=/usr" --build-property "runtime.tools.dfu-util.path=/usr/sbin" +ARDUINO_DIRECTORIES_USER=$(HOME)/Arduino/ +# ARDUINO_DIRECTORIES_DATA= +KALEIDOSCOPE_DIR=$(HOME)/Arduino/libraries/Kaleidoscope +#KALEIDOSCOPE_DIR=/tmp/Kaleidoscope + + +ifneq ($(KALEIDOSCOPE_DIR),) +search_path += $(KALEIDOSCOPE_DIR) +endif + +ifneq ($(ARDUINO_DIRECTORIES_USER),) +search_path += $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/avr/libraries/Kaleidoscope +endif + +ifeq ($(shell uname -s),Darwin) +search_path += $(HOME)/Documents/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope +else +search_path += $(HOME)/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope +endif + +sketch_makefile := etc/makefiles/sketch.mk + +$(foreach candidate, $(search_path), $(if $(wildcard $(candidate)/$(sketch_makefile)), $(eval ks_dir ?= $(candidate)))) + +ifneq ($(ks_dir),) + +$(info Using Kaleidoscope from $(ks_dir)) + +export KALEIDOSCOPE_DIR := $(ks_dir) +include $(ks_dir)/$(sketch_makefile) + +else + +$(info I can't find your Kaleidoscope installation.) +$(info ) +$(info I tried looking in:) +$(info ) +$(foreach candidate, $(search_path), $(info $(candidate))) +$(info ) +$(info The easiest way to fix this is to set the 'KALEIDOSCOPE_DIR' environment) +$(info variable to the location of your Kaleidoscope directory.) + +endif + +gdb: ${ELF_FILE_PATH} + arm-none-eabi-gdb -x gdbinit.container ${ELF_FILE_PATH} + +cp-elf: ${ELF_FILE_PATH} + cp ${ELF_FILE_PATH} . + +cp-bin: ${BIN_FILE_PATH} + cp ${BIN_FILE_PATH} . + +null-target: + $(info You should never see this message) + @: diff --git a/Model100.ino b/Model100.ino new file mode 100644 index 0000000..0813fcb --- /dev/null +++ b/Model100.ino @@ -0,0 +1,424 @@ +// -*- mode: c++ -*- + +#ifndef BUILD_INFORMATION +#define BUILD_INFORMATION "locally built" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Macros +enum { + MACRO_VERSION_INFO, + MACRO_ANY, + WOW, + SAUCY, + LUL, + ZZZ, + GIVE_PLZ, + TAKE_NRG, + SEEMS_GOOD, + GASM +}; + +// Layers +enum { ENGRAM, FUNCTION, NUMPAD, MACROS }; + +typedef struct { + const uint8_t index; + const char *string; +} emote; + +constexpr char wow[] PROGMEM = "eeriedWow"; +constexpr char saucy[] PROGMEM = "eeriedSaucy"; +constexpr char lul[] PROGMEM = "supert25LUL"; +constexpr char zzz[] PROGMEM = "plasmoWife"; +constexpr char givePLZ[] PROGMEM = "GivePLZ"; +constexpr char takeNRG[] PROGMEM = "TakeNRG"; +constexpr char seemsGood[] PROGMEM = "SeemsGood"; +constexpr char gasm[] PROGMEM = "kdubGasm"; + +static constexpr emote emotes[] = { + { WOW, wow }, + { SAUCY, saucy }, + { LUL, lul }, + { ZZZ, zzz }, + { GIVE_PLZ, givePLZ }, + { TAKE_NRG, takeNRG }, + { SEEMS_GOOD, seemsGood }, + { GASM, gasm } +}; + +// constexpr auto mapSize = kaleidoscope_internal::device.matrix_rows * kaleidoscope_internal::device.matrix_columns; +// constexpr Key workman[mapSize] = +// KEYMAP_STACKED(Key_Escape, Key_1, Key_2, Key_3, Key_4, Key_5, Key_ScrollLock, +// Key_Backtick, Key_Q, Key_D, Key_R, Key_W, Key_B, Key_Tab, +// MoveToLayer(DVORAK), Key_A, Key_S, Key_H, Key_T, Key_G, +// Key_RightGui, Key_Z, Key_X, Key_M, Key_C, Key_V, Key_LeftGui, +// Key_LeftBracket, Key_Backspace, LSHIFT(Key_LeftBracket), LSHIFT(Key_9), +// ShiftToLayer(FUNCTION), + +// LockLayer(MACROS), Key_6, Key_7, Key_8, Key_9, Key_0, LockLayer(NUMPAD), +// Key_Enter, Key_J, Key_F, Key_U, Key_P, Key_Semicolon, Key_Minus, +// Key_Y, Key_N, Key_E, Key_O, Key_I, Key_Quote, +// Key_PcApplication, Key_K, Key_L, Key_Comma, Key_Period, Key_Slash, Key_Equals, +// LSHIFT(Key_0), LSHIFT(Key_RightBracket), Key_Spacebar, Key_RightBracket, +// ShiftToLayer(FUNCTION)); + +// *INDENT-OFF* + +/* + * Engram layout: https://engram.dev/ + * + * [{ 1| 2= 3~ 4+ 5< 6> 7^ 8& 9% 0* ]} /\ + * bB yY oO uU '( ") lL dD wW vV zZ #$ @` + * cC iI eE aA ,; .: hH tT sS nN qQ + * gG xX jJ kK -_ ?! rR mM fF pP + * + */ + +KEYMAPS([ENGRAM] = KEYMAP_STACKED + (Key_Escape, Key_1, Key_2, Key_3, Key_4, Key_5, XXX, + Key_Backtick, Key_B, Key_Y, Key_O, Key_U, TD(0), Key_Tab, + Key_Slash, Key_C, Key_I, Key_E, Key_A, TD(1), + Key_RightGui, Key_G, Key_X, Key_J, Key_K, TD(2), Key_LeftGui, + Key_LeftControl, Key_Backspace, Key_LeftAlt, Key_LeftShift, + ShiftToLayer(FUNCTION), + + XXX, Key_6, Key_7, Key_8, Key_9, Key_0, LEAD(0), + Key_Enter, TD(3), Key_L, Key_D, Key_W, Key_V, Key_Z, + TD(4), Key_H, Key_T, Key_S, Key_N, Key_Q, + Key_PcApplication, TD(5), Key_R, Key_M, Key_F, Key_P, Key_Equals, + Key_RightShift, Key_RightAlt, Key_Spacebar, Key_RightControl, + ShiftToLayer(FUNCTION)), + + [FUNCTION] = KEYMAP_STACKED + (Key_LEDEffectNext, Key_F1, Key_F2, Key_F3, Key_F4, Key_F5, XXX, + ___, ___, ___, ___, ___, ___, Key_CapsLock, + Key_Copy, ___, LSHIFT(Key_LeftBracket), LSHIFT(Key_9), Key_LeftBracket, ___, + Key_Paste, Key_PrintScreen, Key_Insert, Consumer_ScanPreviousTrack, Consumer_ScanNextTrack, Consumer_PlaySlashPause, ___, + ___, Key_Delete, ___, ___, + ___, + + XXX, Key_F6, Key_F7, Key_F8, Key_F9, Key_F10, Key_F11, + ___, Key_PageUp, LCTRL(Key_LeftArrow), Key_UpArrow, LCTRL(Key_RightArrow), Key_End, Key_F12, + Key_PageDown, Key_LeftArrow, Key_DownArrow, Key_RightArrow, Key_Home, ___, + ___, Consumer_Mute, Consumer_VolumeDecrement, Consumer_VolumeIncrement, ___, Key_Backslash, Key_Pipe, + ___, ___, ___, ___, + ___), + + [NUMPAD] = KEYMAP_STACKED + (___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, + ___, + + ___, ___, Key_7, Key_8, Key_9, Key_KeypadSubtract, UnlockLayer(NUMPAD), + ___, ___, Key_4, Key_5, Key_6, Key_KeypadAdd, ___, + ___, Key_1, Key_2, Key_3, Key_Equals, ___, + ___, ___, Key_0, Key_Period, Key_KeypadMultiply, Key_KeypadDivide, Key_Enter, + ___, ___, ___, ___, + ___), + + [MACROS] = KEYMAP_STACKED + (___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, M(SEEMS_GOOD), + ___, M(ZZZ), ___, M(GASM), ___, ___, ___, + ___, ___, ___, ___, + ___, + + M(MACRO_VERSION_INFO), ___, ___, ___, ___, ___, UnlockLayer(MACROS), + ___, ___, ___, ___, ___, M(WOW), ___, + ___, ___, ___, M(LUL), M(SAUCY), ___, + ___, ___, ___, M(GIVE_PLZ), M(TAKE_NRG), ___, ___, + ___, ___, ___, ___, + ___) + ) + +// *INDENT-ON* + +/** versionInfoMacro handles the 'firmware version info' macro + * When a key bound to the macro is pressed, this macro + * prints out the firmware build information as virtual keystrokes + */ + +static void versionInfoMacro(uint8_t keyState) { + if (keyToggledOn(keyState)) { + Macros.type(PSTR("Keyboardio Model 100 - Kaleidoscope ")); + Macros.type(PSTR(BUILD_INFORMATION)); + Unicode.type(0x2615); + } +} + +/** anyKeyMacro is used to provide the functionality of the 'Any' key. + * + * When the 'any key' macro is toggled on, a random alphanumeric key is + * selected. While the key is held, the function generates a synthetic + * keypress event repeating that randomly selected key. + * + */ +static void anyKeyMacro(KeyEvent &event) { + if (keyToggledOn(event.state)) { + event.key.setKeyCode(Key_A.getKeyCode() + (uint8_t)(millis() % 36)); + event.key.setFlags(0); + } +} + +static void emoteMacro(uint8_t macroID, KeyEvent &event) { + if (keyToggledOn(event.state)) { + for (auto e : emotes) { + if (e.index == macroID) { + Macros.type(e.string); + return; + } + } + } +} + +/** macroAction dispatches keymap events that are tied to a macro + to that macro. It takes two uint8_t parameters. + + The first is the macro being called (the entry in the 'enum' earlier in this file). + The second is the state of the keyswitch. You can use the keyswitch state to figure out + if the key has just been toggled on, is currently pressed or if it's just been released. + + The 'switch' statement should have a 'case' for each entry of the macro enum. + Each 'case' statement should call out to a function to handle the macro in question. + +*/ + +const macro_t *macroAction(uint8_t macroID, KeyEvent &event) { + switch (macroID) { + case MACRO_VERSION_INFO: + versionInfoMacro(event.state); + break; + + case MACRO_ANY: + anyKeyMacro(event); + break; + + default: + emoteMacro(macroID, event); + } + return MACRO_NONE; +} + +/** toggleLedsOnSuspendResume toggles the LEDs off when the host goes to sleep, + * and turns them back on when it wakes up. + */ +void toggleLedsOnSuspendResume(kaleidoscope::plugin::HostPowerManagement::Event event) { + switch (event) { + case kaleidoscope::plugin::HostPowerManagement::Suspend: + LEDControl.disable(); + break; + case kaleidoscope::plugin::HostPowerManagement::Resume: + LEDControl.enable(); + break; + case kaleidoscope::plugin::HostPowerManagement::Sleep: + break; + } +} + +/** hostPowerManagementEventHandler dispatches power management events (suspend, + * resume, and sleep) to other functions that perform action based on these + * events. + */ +void hostPowerManagementEventHandler(kaleidoscope::plugin::HostPowerManagement::Event event) { + toggleLedsOnSuspendResume(event); +} + +/** This 'enum' is a list of all the magic combos used by the Model 01's + * firmware The names aren't particularly important. What is important is that + * each is unique. + * + * These are the names of your magic combos. They will be used by the + * `USE_MAGIC_COMBOS` call below. + */ +enum { + // Toggle between Boot (6-key rollover; for BIOSes and early boot) and NKRO + // mode. + COMBO_TOGGLE_NKRO_MODE, + // Enter test mode + COMBO_ENTER_TEST_MODE +}; + +/** Wrappers, to be used by MagicCombo. **/ + +/** + * This simply toggles the keyboard protocol via USBQuirks, and wraps it within + * a function with an unused argument, to match what MagicCombo expects. + */ +static void toggleKeyboardProtocol(uint8_t combo_index) { + USBQuirks.toggleKeyboardProtocol(); +} + +/** + * This enters the hardware test mode + */ +static void enterHardwareTestMode(uint8_t combo_index) { + HardwareTestMode.runTests(); +} + + +/** Magic combo list, a list of key combo and action pairs the firmware should + * recognise. + */ +USE_MAGIC_COMBOS({.action = toggleKeyboardProtocol, + // Left Fn + Esc + Shift + .keys = { R3C6, R2C6, R3C7 }}, + {.action = enterHardwareTestMode, + // Left Fn + Prog + LED + .keys = { R3C6, R0C0, R0C6 }}); + +void leaderMacro(uint8_t i) { + // auto event = kaleidoscope::KeyEvent(KeyAddr::none(), IS_PRESSED, ShiftToLayer(MACROS)); + // OneShot.setPending(event); + Layer.activate(MACROS); +} + +void leaderNumpad(uint8_t i) { + Layer.activate(NUMPAD); +} + +constexpr kaleidoscope::plugin::Leader::dictionary_t leaderDictionary[] = + LEADER_DICT({LEADER_SEQ(LEAD(0), Key_M), leaderMacro}, + {LEADER_SEQ(LEAD(0), Key_N), leaderNumpad}); + +constexpr int charshiftCode(uint8_t index) { + return 53631 + index; +} + +void tapDanceAction(uint8_t i, KeyAddr addr, uint8_t count, + kaleidoscope::plugin::TapDance::ActionType action) { + switch (i) { + case 0: + return tapDanceActionKeys(count, action, charshiftCode(0), LSHIFT(Key_Comma)); + case 1: + return tapDanceActionKeys(count, action, charshiftCode(1), Key_LeftBracket); + case 2: + return tapDanceActionKeys(count, action, charshiftCode(2), LSHIFT(Key_LeftBracket)); + case 3: + return tapDanceActionKeys(count, action, charshiftCode(3), LSHIFT(Key_Period)); + case 4: + return tapDanceActionKeys(count, action, charshiftCode(4), Key_RightBracket); + case 5: + return tapDanceActionKeys(count, action, charshiftCode(5), LSHIFT(Key_RightBracket)); + } +} + +static kaleidoscope::plugin::LayerHighlighter macroHighlighter(MACROS); + +// First, tell Kaleidoscope which plugins you want to use. +// The order can be important. For example, LED effects are +// added in the order they're listed here. +KALEIDOSCOPE_INIT_PLUGINS(EEPROMSettings, + EEPROMKeymap, + Focus, + FocusSettingsCommand, + FocusEEPROMCommand, + LayerNames, + //HostOS, + Unicode, + Qukeys, + CharShift, + TapDance, + Leader, + // LEDControl provides support for other LED + // modes + LEDControl, + IdleLEDs, + BootGreetingEffect, + LEDRainbowWaveEffect, + LEDBreatheEffect, + HeatmapEffect, + + // The numpad plugin is responsible for + // lighting up the 'numpad' mode with a + // custom LED effect + NumPad, + macroHighlighter, + + // The macros plugin adds support for macros + Macros, + + // The HostPowerManagement plugin allows us + // to turn LEDs off when then host goes to + // sleep, and resume them when it wakes up. + //HostPowerManagement, + + // The MagicCombo plugin lets you use key + // combinations to trigger custom actions - + // a bit like Macros, but triggered by + // pressing multiple keys at the same time. + MagicCombo, + + // The USBQuirks plugin lets you do some + // things with USB that we aren't + // comfortable - or able - to do + // automatically, but can be useful + // nevertheless. Such as toggling the key + // report protocol between Boot (used by + // BIOSes) and Report (NKRO). + USBQuirks); + +void setup() { + Serial.begin(115200); + + // Necessary for FreeBSD, as it doesn't support NKRO. + //BootKeyboard.default_protocol = HID_BOOT_PROTOCOL; + + // First, call Kaleidoscope's internal setup function + Kaleidoscope.setup(); + + LayerNames.reserve_storage(128); + EEPROMKeymap.setup(5); + + // While we hope to improve this in the future, the NumPad plugin + // needs to be explicitly told which keymap layer is your numpad layer + NumPad.numPadLayer = NUMPAD; + + Leader.dictionary = leaderDictionary; + + // Engram modifies the standard shift key behavior on the innermost + // column. + CS_KEYS(kaleidoscope::plugin::CharShift::KeyPair(Key_Quote, LSHIFT(Key_9)), + kaleidoscope::plugin::CharShift::KeyPair(Key_Comma, Key_Semicolon), + kaleidoscope::plugin::CharShift::KeyPair(Key_Minus, LSHIFT(Key_Minus)), + kaleidoscope::plugin::CharShift::KeyPair(LSHIFT(Key_Quote), LSHIFT(Key_0)), + kaleidoscope::plugin::CharShift::KeyPair(Key_Period, LSHIFT(Key_Semicolon)), + kaleidoscope::plugin::CharShift::KeyPair(LSHIFT(Key_Slash), LSHIFT(Key_1))); + + Qukeys.setOverlapThreshold(25); +} + +void loop() { + Kaleidoscope.loop(); +} diff --git a/flash b/flash new file mode 100755 index 0000000..770e600 --- /dev/null +++ b/flash @@ -0,0 +1,8 @@ +#!/bin/sh + +if [ $# -ne 1 ]; then + echo "Usage: $0 firmware.bin" >&2 + exit 1 +fi + +dfu-util --device 0x3496:0x0005 -R -D $1 diff --git a/gdbinit.container b/gdbinit.container new file mode 100644 index 0000000..695822f --- /dev/null +++ b/gdbinit.container @@ -0,0 +1,11 @@ +define hook-quit + set confirm off +end + +# print demangled symbols by default +set print asm-demangle on + +# OpenOCD +set remote hardware-breakpoint-limit 4 +set remote hardware-watchpoint-limit 2 +target extended-remote psyduck:3333 diff --git a/sketch.json b/sketch.json new file mode 100644 index 0000000..e00344e --- /dev/null +++ b/sketch.json @@ -0,0 +1,6 @@ +{ + "cpu": { + "fqbn": "keyboardio:gd32:keyboardio_model_100", + "port": "" + } +} -- cgit v1.2.3