Compare commits

...

27 Commits

Author SHA1 Message Date
Jesse Vincent 9d9b16dc93
Astyle
3 years ago
Jesse Vincent b44edf476b
Start to implement "suspend a missing device"
3 years ago
Jesse Vincent 40e40cd868
remove 'ledpowerfault', which isn't a thing on the m100
3 years ago
Jesse Vincent fedcd25d61
Set our I2C speed to 400Khz
3 years ago
Jesse Vincent 41fad82e41
add prototype for disableScannerPower for the m100
3 years ago
Jesse Vincent b2899f970b
model 100 power management init
3 years ago
Jesse Vincent 9af4e121b2
Starting to clean up Model 100 hardware enablement
3 years ago
Jesse Vincent d84918280b
Try to enable EEPROM support, but it explodes
3 years ago
Jesse Vincent c6eb7529ca
Astyle
3 years ago
Jesse Vincent ff1cacad51
Disable gamma on the Model 100 for now.
3 years ago
Jesse Vincent 968c71abc3
Todoed storage drivers
3 years ago
Jesse Vincent 80996ee9cc
untested first pass of i2c reads.
3 years ago
Jesse Vincent 059d4c9e39
Start to implement i2c support
3 years ago
Jesse Vincent f3a604dfe1
Modernized B to 0b
3 years ago
Jesse Vincent 0e3425297a
Modernise B syntax to 0b
3 years ago
Jesse Vincent 414f9d3297
Make it possible to elide HID shortname setting by pre-defining the relevant macro
3 years ago
Jesse Vincent b73f6a7eeb
Bullet-proofing against the mouse button constants not being defined
3 years ago
Jesse Vincent 608889818c
Work on the Model 100 platform definition
3 years ago
Jesse Vincent ebc230cb96
Correct our platform name
3 years ago
Jesse Vincent f827c5506e
Rename our "CRC" class to CRCCalculator, so as not to conflict with a
3 years ago
Jesse Vincent 7a2de238c4
Replace deprecated syntax for bitfield
3 years ago
Jesse Vincent a021528b04
WIP porting to the Model100 / GD32
3 years ago
Jesse Vincent 303d4b7e3f
Ongoing work to build the GD32 core
3 years ago
Jesse Vincent 71e461966f
New plan: we always use the same packager name, regardless of whether
3 years ago
Jesse Vincent c329a6dfe0
wip support for gd32 keyboards
3 years ago
Jesse Vincent 0d23db0741
Fix our sketch id in the model 100 example
3 years ago
Jesse Vincent 2514b216fa
Bring back the Model 100 default firmware sketch
3 years ago

@ -12,7 +12,7 @@ endif
DEFAULT_GOAL: smoke-sketches DEFAULT_GOAL: smoke-sketches
setup: $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/avr/boards.txt $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/virtual/boards.txt $(ARDUINO_CLI_PATH) $(ARDUINO_DIRECTORIES_DATA)/arduino-cli.yaml install-arduino-core-avr setup: $(ARDUINO_CLI_PATH) $(ARDUINO_DIRECTORIES_DATA)/arduino-cli.yaml install-arduino-core-avr install-arduino-core-kaleidoscope $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/avr/boards.txt $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/virtual/boards.txt
@: @:
@ -27,9 +27,22 @@ $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/virtual/boards.txt:
$(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/avr/boards.txt: $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/avr/boards.txt:
git clone -c core.symlinks=true --recurse-submodules=":(exclude)avr/libraries/Kaleidoscope" --recurse-submodules=build-tools --recurse-submodules=toolchain --recurse-submodules=avr/libraries/ git://github.com/keyboardio/Kaleidoscope-Bundle-Keyboardio $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio git clone -c core.symlinks=true \
rm -d $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/avr/libraries/Kaleidoscope --recurse-submodules=":(exclude)avr/libraries/Kaleidoscope" \
--recurse-submodules=":(exclude)gd32/libraries/Kaleidoscope" \
--recurse-submodules=avr/libraries/ \
--recurse-submodules=gd32/ \
--recurse-submodules=gd32/libraries/ \
git://github.com/keyboardio/Kaleidoscope-Bundle-Keyboardio \
$(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio
-rm -d $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/avr/libraries/Kaleidoscope
ln -s $(KALEIDOSCOPE_DIR) $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/avr/libraries/Kaleidoscope ln -s $(KALEIDOSCOPE_DIR) $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/avr/libraries/Kaleidoscope
git clone -c core.symlinks=true \
--recurse-submodules=":(exclude)libraries/Kaleidoscope" \
--recurse-submodules=libraries/ \
git://github.com/keyboardio/ArduinoCore-GD32-Keyboardio $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/gd32
-rm -d $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/gd32/libraries/Kaleidoscope
ln -s $(KALEIDOSCOPE_DIR) $(ARDUINO_DIRECTORIES_USER)/hardware/keyboardio/gd32/libraries/Kaleidoscope
simulator-tests: simulator-tests:
$(MAKE) -C tests all $(MAKE) -C tests all

@ -16,8 +16,7 @@ use Cwd qw/abs_path cwd/;
use JSON::PP; use JSON::PP;
use Getopt::Long; use Getopt::Long;
my $sha256 = 0; my @ARCHES = (qw(avr gd32));
my $size = 0;
my $platforms_template = { my $platforms_template = {
avr => { avr => {
@ -50,18 +49,18 @@ my $platforms_template = {
'toolsDependencies' => [ 'toolsDependencies' => [
{ {
'name' => 'xpack-arm-none-eabi-gcc', 'name' => 'xpack-arm-none-eabi-gcc',
'packager' => 'Keyboardio', 'packager' => 'keyboardio',
'version' => '9.3.1-1.3' 'version' => '9.3.1-1.3'
}, },
{ {
'packager' => 'Keyboardio', 'packager' => 'keyboardio',
'version' => '0.11.0-1', 'version' => '0.11.0-1',
'name' => 'xpack-openocd' 'name' => 'xpack-openocd'
}, },
{ {
'name' => 'dfu-util', 'name' => 'dfu-util',
'version' => '0.10.0-arduino1', 'version' => '0.10.0-arduino1',
'packager' => 'Keyboardio' 'packager' => 'keyboardio'
} }
], ],
'version' => '0.0.1', 'version' => '0.0.1',
@ -87,16 +86,17 @@ my $builds_dir = $output_dir . '/builds';
my $only_latest_platform = 0; my $only_latest_platform = 0;
my $bundle_repo = my $bundle_repo = 'https://github.com/keyboardio/Kaleidoscope-Bundle-Keyboardio';
'https://github.com/keyboardio/Kaleidoscope-Bundle-Keyboardio'; my $gd32_core_repo = 'https://github.com/keyboardio/ArduinoCore-GD32-Keyboardio';
my $boards_repo = 'https://github.com/keyboardio/boardsmanager'; my $package_repo = 'https://github.com/keyboardio/boardsmanager';
my $push_package_repo = 0; my $push_package_repo = 0;
GetOptions( GetOptions(
"bundle-tag=s" => \$tag, "bundle-tag=s" => \$tag,
"kaleidoscope-tag=s" => \$kaleidoscope_tag, "kaleidoscope-tag=s" => \$kaleidoscope_tag,
"bundle-repo=s" => \$bundle_repo, "bundle-repo=s" => \$bundle_repo,
"output-repo=s" => \$boards_repo, "output-repo=s" => \$package_repo,
"index-filename-slug=s" => \$index_filename_slug, "index-filename-slug=s" => \$index_filename_slug,
"version=s" => \$version, "version=s" => \$version,
"only-one-platform-revision" => \$only_latest_platform, "only-one-platform-revision" => \$only_latest_platform,
@ -113,19 +113,19 @@ if ( $version eq '' && $tag =~ /^v(\d.*)$/ ) {
my $checkout_dir = 'kaleidoscope-checkout'; my $checkout_dir = 'kaleidoscope-checkout';
my $build_base_url = $boards_repo . "/raw/$main_branch_name/builds"; my $build_base_url = $package_repo . "/raw/$main_branch_name/builds";
$build_base_url =~ s|^ssh://git\@github.com|https://github.com|; $build_base_url =~ s|^ssh://git\@github.com|https://github.com|;
print "Working directory: $working_dir\n"; print "Working directory: $working_dir\n";
chdir($working_dir); chdir($working_dir);
clone_repos( $tag, $bundle_repo, $checkout_dir, $boards_repo ); clone_repos( $tag, $bundle_repo, $gd32_core_repo, $checkout_dir, $package_repo );
chdir( $working_dir . "/" . $checkout_dir ); chdir( $working_dir . "/" . $checkout_dir );
if ($only_latest_platform) { if ($only_latest_platform) {
`rm -rf $builds_dir/*`; `rm -rf $builds_dir/*`;
} }
foreach my $arch (qw(avr gd32)) { foreach my $arch (@ARCHES) {
remove_unneeded_files($arch); remove_unneeded_files($arch);
@ -166,10 +166,17 @@ sub set_plugin_versions {
sub clone_repos { sub clone_repos {
my $tag = shift; my $tag = shift;
my $bundle_repo = shift; my $bundle_repo = shift;
my $gd32_repo = shift;
my $checkout_dir = shift; my $checkout_dir = shift;
my $boards_repo = shift; my $package_repo = shift;
my $gd32_tag = $tag;
if ($gd32_tag eq 'master') {
$gd32_tag = 'main';
}
`git clone --depth=1 --quiet --recurse-submodules --branch $tag $bundle_repo $checkout_dir`; `git clone --depth=1 --quiet --recurse-submodules --branch $tag $bundle_repo $checkout_dir`;
`git clone $boards_repo $output_dir`;
`git clone --depth=1 --quiet --recurse-submodules --branch $gd32_tag $gd32_repo $checkout_dir/gd32`;
`git clone $package_repo $output_dir`;
} }
sub checkout_kaleidoscope { sub checkout_kaleidoscope {
@ -200,11 +207,11 @@ sub update_index_file {
my $json_text = <$fh>; my $json_text = <$fh>;
my $data = decode_json($json_text); my $data = decode_json($json_text);
my $this_packager = $data->{'packages'}->[0]->{'name'}; #my $this_packager = $data->{'packages'}->[0]->{'name'};
foreach my $tool (@{$platforms_template->{'gd32'}->{'toolsDependencies'}}) { #foreach my $tool (@{$platforms_template->{'gd32'}->{'toolsDependencies'}}) {
# we need to set the packager of these tools to ourself, since that's what arduino expects # # we need to set the packager of these tools to ourself, since that's what arduino expects
$tool->{"packager"} = $this_packager; # $tool->{"packager"} = $this_packager;
} # }
if ($only_latest_platform) { if ($only_latest_platform) {
@{ $data->{'packages'}->[0]->{'platforms'} } = @{ $data->{'packages'}->[0]->{'platforms'} } =
@ -264,10 +271,10 @@ sub build_archive {
`find $checkout_dir/$release_dir -name .git |xargs rm -rf`; `find $checkout_dir/$release_dir -name .git |xargs rm -rf`;
`tar cjvf $filename -C $checkout_dir/ $release_dir `; `tar cjvf $filename -C $checkout_dir/ $release_dir `;
$sha256 = `sha256sum $filename | cut -d' ' -f 1 `; my $sha256 = `sha256sum $filename | cut -d' ' -f 1 `;
chomp($sha256); chomp($sha256);
die "There was a problem generating the sha256" unless ($sha256); die "There was a problem generating the sha256" unless ($sha256);
$size = -s $filename; my $size = -s $filename;
$platforms_template->{$arch}->{'archiveFileName'} = $filename; $platforms_template->{$arch}->{'archiveFileName'} = $filename;
$platforms_template->{$arch}->{'url'} = $build_base_url . '/' . $filename; $platforms_template->{$arch}->{'url'} = $build_base_url . '/' . $filename;

@ -164,6 +164,7 @@ arduino-update-cores:
install-arduino-core-kaleidoscope: arduino-update-cores install-arduino-core-kaleidoscope: arduino-update-cores
$(QUIET) $(ARDUINO_CLI) core install "keyboardio:avr" $(QUIET) $(ARDUINO_CLI) core install "keyboardio:avr"
$(QUIET) $(ARDUINO_CLI) core install "keyboardio:gd32"
install-arduino-core-avr: arduino-update-cores install-arduino-core-avr: arduino-update-cores
$(QUIET) $(ARDUINO_CLI) core install "arduino:avr" $(QUIET) $(ARDUINO_CLI) core install "arduino:avr"

@ -0,0 +1,48 @@
# This makefile for a Kaleidoscope sketch pulls in all the targets
# required to build the example
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
null-target:
$(info You should never see this message)
@:

@ -0,0 +1,571 @@
// -*- mode: c++ -*-
// Copyright 2016 Keyboardio, inc. <jesse@keyboard.io>
// See "LICENSE" for license details
#ifndef BUILD_INFORMATION
#define BUILD_INFORMATION "locally built on " __DATE__ " at " __TIME__
#endif
/**
* These #include directives pull in the Kaleidoscope firmware core,
* as well as the Kaleidoscope plugins we use in the Model 01's firmware
*/
// The Kaleidoscope core
#include "Kaleidoscope.h"
// Support for storing the keymap in EEPROM
//#include "Kaleidoscope-EEPROM-Settings.h"
//#include "Kaleidoscope-EEPROM-Keymap.h"
// Support for communicating with the host via a simple Serial protocol
//#include "Kaleidoscope-FocusSerial.h"
// Support for keys that move the mouse
#include "Kaleidoscope-MouseKeys.h"
// Support for macros
#include "Kaleidoscope-Macros.h"
// Support for controlling the keyboard's LEDs
#include "Kaleidoscope-LEDControl.h"
// Support for "Numpad" mode, which is mostly just the Numpad specific LED mode
#include "Kaleidoscope-NumPad.h"
// Support for the "Boot greeting" effect, which pulses the 'LED' button for 10s
// when the keyboard is connected to a computer (or that computer is powered on)
#include "Kaleidoscope-LEDEffect-BootGreeting.h"
// Support for LED modes that set all LEDs to a single color
#include "Kaleidoscope-LEDEffect-SolidColor.h"
// Support for an LED mode that makes all the LEDs 'breathe'
#include "Kaleidoscope-LEDEffect-Breathe.h"
// Support for an LED mode that makes a red pixel chase a blue pixel across the keyboard
#include "Kaleidoscope-LEDEffect-Chase.h"
// Support for LED modes that pulse the keyboard's LED in a rainbow pattern
#include "Kaleidoscope-LEDEffect-Rainbow.h"
// Support for an LED mode that lights up the keys as you press them
#include "Kaleidoscope-LED-Stalker.h"
// Support for an LED mode that prints the keys you press in letters 4px high
#include "Kaleidoscope-LED-AlphaSquare.h"
// Support for shared palettes for other plugins, like Colormap below
#include "Kaleidoscope-LED-Palette-Theme.h"
// Support for an LED mode that lets one configure per-layer color maps
#include "Kaleidoscope-Colormap.h"
// Support for Keyboardio's internal keyboard testing mode
#include "Kaleidoscope-HardwareTestMode.h"
// Support for host power management (suspend & wakeup)
#include "Kaleidoscope-HostPowerManagement.h"
// Support for magic combos (key chords that trigger an action)
#include "Kaleidoscope-MagicCombo.h"
// Support for USB quirks, like changing the key state report protocol
#include "Kaleidoscope-USB-Quirks.h"
/** This 'enum' is a list of all the macros 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 macros. They'll be used in two places.
* The first is in your keymap definitions. There, you'll use the syntax
* `M(MACRO_NAME)` to mark a specific keymap position as triggering `MACRO_NAME`
*
* The second usage is in the 'switch' statement in the `macroAction` function.
* That switch statement actually runs the code associated with a macro when
* a macro key is pressed.
*/
enum { MACRO_VERSION_INFO,
MACRO_ANY
};
/** The Model 01's key layouts are defined as 'keymaps'. By default, there are three
* keymaps: The standard QWERTY keymap, the "Function layer" keymap and the "Numpad"
* keymap.
*
* Each keymap is defined as a list using the 'KEYMAP_STACKED' macro, built
* of first the left hand's layout, followed by the right hand's layout.
*
* Keymaps typically consist mostly of `Key_` definitions. There are many, many keys
* defined as part of the USB HID Keyboard specification. You can find the names
* (if not yet the explanations) for all the standard `Key_` defintions offered by
* Kaleidoscope in these files:
* https://github.com/keyboardio/Kaleidoscope/blob/master/src/kaleidoscope/key_defs_keyboard.h
* https://github.com/keyboardio/Kaleidoscope/blob/master/src/kaleidoscope/key_defs_consumerctl.h
* https://github.com/keyboardio/Kaleidoscope/blob/master/src/kaleidoscope/key_defs_sysctl.h
* https://github.com/keyboardio/Kaleidoscope/blob/master/src/kaleidoscope/key_defs_keymaps.h
*
* Additional things that should be documented here include
* using ___ to let keypresses fall through to the previously active layer
* using XXX to mark a keyswitch as 'blocked' on this layer
* using ShiftToLayer() and LockLayer() keys to change the active keymap.
* keeping NUM and FN consistent and accessible on all layers
*
* The PROG key is special, since it is how you indicate to the board that you
* want to flash the firmware. However, it can be remapped to a regular key.
* When the keyboard boots, it first looks to see whether the PROG key is held
* down; if it is, it simply awaits further flashing instructions. If it is
* not, it continues loading the rest of the firmware and the keyboard
* functions normally, with whatever binding you have set to PROG. More detail
* here: https://community.keyboard.io/t/how-the-prog-key-gets-you-into-the-bootloader/506/8
*
* The "keymaps" data structure is a list of the keymaps compiled into the firmware.
* The order of keymaps in the list is important, as the ShiftToLayer(#) and LockLayer(#)
* macros switch to key layers based on this list.
*
*
* A key defined as 'ShiftToLayer(FUNCTION)' will switch to FUNCTION while held.
* Similarly, a key defined as 'LockLayer(NUMPAD)' will switch to NUMPAD when tapped.
*/
/**
* Layers are "0-indexed" -- That is the first one is layer 0. The second one is layer 1.
* The third one is layer 2.
* This 'enum' lets us use names like QWERTY, FUNCTION, and NUMPAD in place of
* the numbers 0, 1 and 2.
*
*/
enum { PRIMARY, NUMPAD, FUNCTION }; // layers
/**
* To change your keyboard's layout from QWERTY to DVORAK or COLEMAK, comment out the line
*
* #define PRIMARY_KEYMAP_QWERTY
*
* by changing it to
*
* // #define PRIMARY_KEYMAP_QWERTY
*
* Then uncomment the line corresponding to the layout you want to use.
*
*/
#define PRIMARY_KEYMAP_QWERTY
// #define PRIMARY_KEYMAP_DVORAK
// #define PRIMARY_KEYMAP_COLEMAK
// #define PRIMARY_KEYMAP_CUSTOM
/* This comment temporarily turns off astyle's indent enforcement
* so we can make the keymaps actually resemble the physical key layout better
*/
// *INDENT-OFF*
KEYMAPS(
#if defined (PRIMARY_KEYMAP_QWERTY)
[PRIMARY] = KEYMAP_STACKED
(___, Key_1, Key_2, Key_3, Key_4, Key_5, Key_LEDEffectNext,
Key_Backtick, Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Tab,
Key_PageUp, Key_A, Key_S, Key_D, Key_F, Key_G,
Key_PageDown, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Escape,
Key_LeftControl, Key_Backspace, Key_LeftGui, Key_LeftShift,
ShiftToLayer(FUNCTION),
M(MACRO_ANY), Key_6, Key_7, Key_8, Key_9, Key_0, LockLayer(NUMPAD),
Key_Enter, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_Equals,
Key_H, Key_J, Key_K, Key_L, Key_Semicolon, Key_Quote,
Key_RightAlt, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus,
Key_RightShift, Key_LeftAlt, Key_Spacebar, Key_RightControl,
ShiftToLayer(FUNCTION)),
#elif defined (PRIMARY_KEYMAP_DVORAK)
[PRIMARY] = KEYMAP_STACKED
(___, Key_1, Key_2, Key_3, Key_4, Key_5, Key_LEDEffectNext,
Key_Backtick, Key_Quote, Key_Comma, Key_Period, Key_P, Key_Y, Key_Tab,
Key_PageUp, Key_A, Key_O, Key_E, Key_U, Key_I,
Key_PageDown, Key_Semicolon, Key_Q, Key_J, Key_K, Key_X, Key_Escape,
Key_LeftControl, Key_Backspace, Key_LeftGui, Key_LeftShift,
ShiftToLayer(FUNCTION),
M(MACRO_ANY), Key_6, Key_7, Key_8, Key_9, Key_0, LockLayer(NUMPAD),
Key_Enter, Key_F, Key_G, Key_C, Key_R, Key_L, Key_Slash,
Key_D, Key_H, Key_T, Key_N, Key_S, Key_Minus,
Key_RightAlt, Key_B, Key_M, Key_W, Key_V, Key_Z, Key_Equals,
Key_RightShift, Key_LeftAlt, Key_Spacebar, Key_RightControl,
ShiftToLayer(FUNCTION)),
#elif defined (PRIMARY_KEYMAP_COLEMAK)
[PRIMARY] = KEYMAP_STACKED
(___, Key_1, Key_2, Key_3, Key_4, Key_5, Key_LEDEffectNext,
Key_Backtick, Key_Q, Key_W, Key_F, Key_P, Key_G, Key_Tab,
Key_PageUp, Key_A, Key_R, Key_S, Key_T, Key_D,
Key_PageDown, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Escape,
Key_LeftControl, Key_Backspace, Key_LeftGui, Key_LeftShift,
ShiftToLayer(FUNCTION),
M(MACRO_ANY), Key_6, Key_7, Key_8, Key_9, Key_0, LockLayer(NUMPAD),
Key_Enter, Key_J, Key_L, Key_U, Key_Y, Key_Semicolon, Key_Equals,
Key_H, Key_N, Key_E, Key_I, Key_O, Key_Quote,
Key_RightAlt, Key_K, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus,
Key_RightShift, Key_LeftAlt, Key_Spacebar, Key_RightControl,
ShiftToLayer(FUNCTION)),
#elif defined (PRIMARY_KEYMAP_CUSTOM)
// Edit this keymap to make a custom layout
[PRIMARY] = KEYMAP_STACKED
(___, Key_1, Key_2, Key_3, Key_4, Key_5, Key_LEDEffectNext,
Key_Backtick, Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Tab,
Key_PageUp, Key_A, Key_S, Key_D, Key_F, Key_G,
Key_PageDown, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Escape,
Key_LeftControl, Key_Backspace, Key_LeftGui, Key_LeftShift,
ShiftToLayer(FUNCTION),
M(MACRO_ANY), Key_6, Key_7, Key_8, Key_9, Key_0, LockLayer(NUMPAD),
Key_Enter, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_Equals,
Key_H, Key_J, Key_K, Key_L, Key_Semicolon, Key_Quote,
Key_RightAlt, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus,
Key_RightShift, Key_LeftAlt, Key_Spacebar, Key_RightControl,
ShiftToLayer(FUNCTION)),
#else
#error "No default keymap defined. You should make sure that you have a line like '#define PRIMARY_KEYMAP_QWERTY' in your sketch"
#endif
[NUMPAD] = KEYMAP_STACKED
(___, ___, ___, ___, ___, ___, ___,
___, ___, ___, ___, ___, ___, ___,
___, ___, ___, ___, ___, ___,
___, ___, ___, ___, ___, ___, ___,
___, ___, ___, ___,
___,
M(MACRO_VERSION_INFO), ___, Key_7, Key_8, Key_9, Key_KeypadSubtract, ___,
___, ___, 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,
___, ___, ___, ___,
___),
[FUNCTION] = KEYMAP_STACKED
(___, Key_F1, Key_F2, Key_F3, Key_F4, Key_F5, Key_CapsLock,
Key_Tab, ___, Key_mouseUp, ___, Key_mouseBtnR, Key_mouseWarpEnd, Key_mouseWarpNE,
Key_Home, Key_mouseL, Key_mouseDn, Key_mouseR, Key_mouseBtnL, Key_mouseWarpNW,
Key_End, Key_PrintScreen, Key_Insert, ___, Key_mouseBtnM, Key_mouseWarpSW, Key_mouseWarpSE,
___, Key_Delete, ___, ___,
___,
Consumer_ScanPreviousTrack, Key_F6, Key_F7, Key_F8, Key_F9, Key_F10, Key_F11,
Consumer_PlaySlashPause, Consumer_ScanNextTrack, Key_LeftCurlyBracket, Key_RightCurlyBracket, Key_LeftBracket, Key_RightBracket, Key_F12,
Key_LeftArrow, Key_DownArrow, Key_UpArrow, Key_RightArrow, ___, ___,
Key_PcApplication, Consumer_Mute, Consumer_VolumeDecrement, Consumer_VolumeIncrement, ___, Key_Backslash, Key_Pipe,
___, ___, Key_Enter, ___,
___)
) // KEYMAPS(
/* Re-enable astyle's indent enforcement */
// *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 key_state) {
if (keyToggledOn(key_state)) {
Macros.type(PSTR("Keyboardio Model 01 - Kaleidoscope "));
Macros.type(PSTR(BUILD_INFORMATION));
}
}
/** 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);
}
}
/** 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 macro_id, KeyEvent &event) {
switch (macro_id) {
case MACRO_VERSION_INFO:
versionInfoMacro(event.state);
break;
case MACRO_ANY:
anyKeyMacro(event);
break;
}
return MACRO_NONE;
}
// These 'solid' color effect definitions define a rainbow of
// LED color modes calibrated to draw 500mA or less on the
// Keyboardio Model 01.
static kaleidoscope::plugin::LEDSolidColor solidRed(160, 0, 0);
static kaleidoscope::plugin::LEDSolidColor solidOrange(140, 70, 0);
static kaleidoscope::plugin::LEDSolidColor solidYellow(130, 100, 0);
static kaleidoscope::plugin::LEDSolidColor solidGreen(0, 160, 0);
static kaleidoscope::plugin::LEDSolidColor solidBlue(0, 70, 130);
static kaleidoscope::plugin::LEDSolidColor solidIndigo(0, 0, 170);
static kaleidoscope::plugin::LEDSolidColor solidViolet(130, 0, 120);
/** 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 }
});
// 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(
// The EEPROMSettings & EEPROMKeymap plugins make it possible to have an
// editable keymap in EEPROM.
// EEPROMSettings,
// EEPROMKeymap,
// Focus allows bi-directional communication with the host, and is the
// interface through which the keymap in EEPROM can be edited.
//Focus,
// FocusSettingsCommand adds a few Focus commands, intended to aid in
// changing some settings of the keyboard, such as the default layer (via the
// `settings.defaultLayer` command)
//FocusSettingsCommand,
// FocusEEPROMCommand adds a set of Focus commands, which are very helpful in
// both debugging, and in backing up one's EEPROM contents.
// FocusEEPROMCommand,
// The boot greeting effect pulses the LED button for 10 seconds after the
// keyboard is first connected
BootGreetingEffect,
// The hardware test mode, which can be invoked by tapping Prog, LED and the
// left Fn button at the same time.
HardwareTestMode,
// LEDControl provides support for other LED modes
LEDControl,
// We start with the LED effect that turns off all the LEDs.
LEDOff,
// The rainbow effect changes the color of all of the keyboard's keys at the same time
// running through all the colors of the rainbow.
LEDRainbowEffect,
// The rainbow wave effect lights up your keyboard with all the colors of a rainbow
// and slowly moves the rainbow across your keyboard
LEDRainbowWaveEffect,
// The chase effect follows the adventure of a blue pixel which chases a red pixel across
// your keyboard. Spoiler: the blue pixel never catches the red pixel
LEDChaseEffect,
// These static effects turn your keyboard's LEDs a variety of colors
solidRed, solidOrange, solidYellow, solidGreen, solidBlue, solidIndigo, solidViolet,
// The breathe effect slowly pulses all of the LEDs on your keyboard
LEDBreatheEffect,
// The AlphaSquare effect prints each character you type, using your
// keyboard's LEDs as a display
AlphaSquareEffect,
// The stalker effect lights up the keys you've pressed recently
StalkerEffect,
// The LED Palette Theme plugin provides a shared palette for other plugins,
// like Colormap below
LEDPaletteTheme,
// The Colormap effect makes it possible to set up per-layer colormaps
// ColormapEffect,
// The numpad plugin is responsible for lighting up the 'numpad' mode
// with a custom LED effect
NumPad,
// The macros plugin adds support for macros
Macros,
// The MouseKeys plugin lets you add keys to your keymap which move the mouse.
MouseKeys,
// 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
);
/** The 'setup' function is one of the two standard Arduino sketch functions.
* It's called when your keyboard first powers up. This is where you set up
* Kaleidoscope and any plugins.
*/
void setup() {
// First, call Kaleidoscope's internal setup function
Kaleidoscope.setup();
// 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;
// We configure the AlphaSquare effect to use RED letters
AlphaSquare.color = CRGB(255, 0, 0);
// We set the brightness of the rainbow effects to 150 (on a scale of 0-255)
// This draws more than 500mA, but looks much nicer than a dimmer effect
LEDRainbowEffect.brightness(150);
LEDRainbowWaveEffect.brightness(150);
// Set the action key the test mode should listen for to Left Fn
HardwareTestMode.setActionKey(R3C6);
// The LED Stalker mode has a few effects. The one we like is called
// 'BlazingTrail'. For details on other options, see
// https://github.com/keyboardio/Kaleidoscope/blob/master/docs/plugins/LED-Stalker.md
StalkerEffect.variant = STALKER(BlazingTrail);
// We want to make sure that the firmware starts with LED effects off
// This avoids over-taxing devices that don't have a lot of power to share
// with USB devices
LEDOff.activate();
// To make the keymap editable without flashing new firmware, we store
// additional layers in EEPROM. For now, we reserve space for five layers. If
// one wants to use these layers, just set the default layer to one in EEPROM,
// by using the `settings.defaultLayer` Focus command, or by using the
// `keymap.onlyCustom` command to use EEPROM layers only.
//EEPROMKeymap.setup(5);
// We need to tell the Colormap plugin how many layers we want to have custom
// maps for. To make things simple, we set it to five layers, which is how
// many editable layers we have (see above).
//ColormapEffect.max_layers(5);
}
/** loop is the second of the standard Arduino sketch functions.
* As you might expect, it runs in a loop, never exiting.
*
* For Kaleidoscope-based keyboard firmware, you usually just want to
* call Kaleidoscope.loop(); and not do anything custom here.
*/
void loop() {
Kaleidoscope.loop();
}

@ -0,0 +1,6 @@
{
"cpu": {
"fqbn": "keyboardio:gd32:keyboardio_model_100",
"port": ""
}
}

@ -101,7 +101,7 @@ void EEPROMSettings::ignoreHardcodedLayers(bool value) {
void EEPROMSettings::seal(void) { void EEPROMSettings::seal(void) {
sealed_ = true; sealed_ = true;
CRC.finalize(); CRCCalculator.finalize();
if (settings_.version != VERSION_CURRENT) { if (settings_.version != VERSION_CURRENT) {
is_valid_ = false; is_valid_ = false;
@ -109,9 +109,9 @@ void EEPROMSettings::seal(void) {
} }
if (settings_.crc == 0xffff) { if (settings_.crc == 0xffff) {
settings_.crc = CRC.crc; settings_.crc = CRCCalculator.crc;
update(); update();
} else if (settings_.crc != CRC.crc) { } else if (settings_.crc != CRCCalculator.crc) {
return; return;
} }
@ -134,7 +134,7 @@ uint16_t EEPROMSettings::requestSlice(uint16_t size) {
uint16_t start = next_start_; uint16_t start = next_start_;
next_start_ += size; next_start_ += size;
CRC.update((const void *)&size, sizeof(size)); CRCCalculator.update((const void *)&size, sizeof(size));
return start; return start;
} }
@ -159,7 +159,7 @@ EventHandlerResult FocusSettingsCommand::onFocusEvent(const char *command) {
DEFAULT_LAYER, DEFAULT_LAYER,
IS_VALID, IS_VALID,
GET_VERSION, GET_VERSION,
CRC, GET_CRC,
} sub_command; } sub_command;
if (::Focus.handleHelp(command, PSTR("settings.defaultLayer\nsettings.valid?\nsettings.version\nsettings.crc"))) if (::Focus.handleHelp(command, PSTR("settings.defaultLayer\nsettings.valid?\nsettings.version\nsettings.crc")))
@ -175,7 +175,7 @@ EventHandlerResult FocusSettingsCommand::onFocusEvent(const char *command) {
else if (strcmp_P(command + 9, PSTR("version")) == 0) else if (strcmp_P(command + 9, PSTR("version")) == 0)
sub_command = GET_VERSION; sub_command = GET_VERSION;
else if (strcmp_P(command + 9, PSTR("crc")) == 0) else if (strcmp_P(command + 9, PSTR("crc")) == 0)
sub_command = CRC; sub_command = GET_CRC;
else else
return EventHandlerResult::OK; return EventHandlerResult::OK;
@ -196,8 +196,8 @@ EventHandlerResult FocusSettingsCommand::onFocusEvent(const char *command) {
case GET_VERSION: case GET_VERSION:
::Focus.send(::EEPROMSettings.version()); ::Focus.send(::EEPROMSettings.version());
break; break;
case CRC: case GET_CRC:
::Focus.sendRaw(::CRC.crc, F("/"), ::EEPROMSettings.crc()); ::Focus.sendRaw(::CRCCalculator.crc, F("/"), ::EEPROMSettings.crc());
break; break;
} }

@ -66,4 +66,4 @@ CRC_::update(const void *data, uint8_t len) {
crc &= 0xffff; crc &= 0xffff;
} }
CRC_ CRC; CRC_ CRCCalculator;

@ -43,4 +43,4 @@ class CRC_ {
void reflect(uint8_t len); void reflect(uint8_t len);
}; };
extern CRC_ CRC; extern CRC_ CRCCalculator;

@ -15,16 +15,16 @@
* this program. If not, see <http://www.gnu.org/licenses/>. * this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef ARDUINO_GD32_keyboardio_model_100 #ifdef ARDUINO_keyboardio_model_100
#include "Arduino.h" // for PROGMEM #include "Arduino.h" // for PROGMEM
#include "kaleidoscope/device/keyboardio/Model100.h" // for Model100LEDDriver... #include "kaleidoscope/device/keyboardio/Model100.h" // for Model100LEDDriver...
#include "kaleidoscope/key_events.h" #include "kaleidoscope/key_events.h"
#include "kaleidoscope/driver/keyscanner/Base_Impl.h" #include "kaleidoscope/driver/keyscanner/Base_Impl.h"
#include "Wire.h"
#ifndef KALEIDOSCOPE_VIRTUAL_BUILD #ifndef KALEIDOSCOPE_VIRTUAL_BUILD
#include <KeyboardioHID.h>
#include <avr/wdt.h>
#endif // ifndef KALEIDOSCOPE_VIRTUAL_BUILD #endif // ifndef KALEIDOSCOPE_VIRTUAL_BUILD
namespace kaleidoscope { namespace kaleidoscope {
@ -48,14 +48,13 @@ driver::keyboardio::Model100Side Model100Hands::leftHand(0);
driver::keyboardio::Model100Side Model100Hands::rightHand(3); driver::keyboardio::Model100Side Model100Hands::rightHand(3);
void Model100Hands::setup(void) { void Model100Hands::setup(void) {
// This lets the keyboard pull up to 1.6 amps from the host. delay(100);
// That violates the USB spec. But it sure is pretty looking pinMode(PB9, OUTPUT_OPEN_DRAIN);
DDRE |= _BV(6); digitalWrite(PB9, LOW);
PORTE &= ~_BV(6); delay(105); // TODO remove this when we remove it from the attiny code
Wire.begin();
Wire.setClock(400000);
// Set B4, the overcurrent check to an input with an internal pull-up
DDRB &= ~_BV(4); // set bit, input
PORTB &= ~_BV(4); // set bit, enable pull-up resistor
} }
/********* LED Driver *********/ /********* LED Driver *********/
@ -103,7 +102,6 @@ cRGB Model100LEDDriver::getCrgbAt(uint8_t i) {
void Model100LEDDriver::syncLeds() { void Model100LEDDriver::syncLeds() {
if (!isLEDChanged) if (!isLEDChanged)
return; return;
// LED Data is stored in four "banks" for each side // LED Data is stored in four "banks" for each side
// We send it all at once to make it look nicer. // We send it all at once to make it look nicer.
// We alternate left and right hands because otherwise // We alternate left and right hands because otherwise
@ -125,10 +123,6 @@ void Model100LEDDriver::syncLeds() {
isLEDChanged = false; isLEDChanged = false;
} }
boolean Model100LEDDriver::ledPowerFault() {
// TODO remove - obsolete
}
/********* Key scanner *********/ /********* Key scanner *********/
driver::keyboardio::keydata_t Model100KeyScanner::leftHandState; driver::keyboardio::keydata_t Model100KeyScanner::leftHandState;
@ -137,14 +131,25 @@ driver::keyboardio::keydata_t Model100KeyScanner::previousLeftHandState;
driver::keyboardio::keydata_t Model100KeyScanner::previousRightHandState; driver::keyboardio::keydata_t Model100KeyScanner::previousRightHandState;
void Model100KeyScanner::enableScannerPower(void) { void Model100KeyScanner::enableScannerPower(void) {
// Turn on the switched 5V network.
// make sure this happens at least 100ms after USB connect
// to satisfy inrush limits
//
pinMode(PB9, OUTPUT_OPEN_DRAIN);
digitalWrite(PB9, LOW);
}
void Model100KeyScanner::disableScannerPower(void) {
// Turn on power to the 5V net // Turn on power to the 5V net
// //
pinMode(PC13, OUTPUT_OPEN_DRAIN); pinMode(PB9, OUTPUT_OPEN_DRAIN);
digitalWrite(PC13, LOW); digitalWrite(PB9, HIGH);
} }
void Model100KeyScanner::setup() { void Model100KeyScanner::setup() {
wdt_disable(); // TODO wdt_disable();
delay(100); delay(100);
enableScannerPower(); enableScannerPower();
} }
@ -228,6 +233,7 @@ uint8_t Model100KeyScanner::previousPressedKeyswitchCount() {
/********* Hardware plugin *********/ /********* Hardware plugin *********/
void Model100::setup() { void Model100::setup() {
Model100KeyScanner::setup();
Model100Hands::setup(); Model100Hands::setup();
kaleidoscope::device::Base<Model100Props>::setup(); kaleidoscope::device::Base<Model100Props>::setup();
} }

@ -17,7 +17,13 @@
#pragma once #pragma once
#ifdef ARDUINO_GD32_keyboardio_model_100 #ifdef ARDUINO_keyboardio_model_100
#define _INIT_HID_GETSHORTNAME // warning "TODO: remove this directive once we have HID"
#ifndef EEPROM_EMULATION_SIZE
#define EEPROM_EMULATION_SIZE 4096
#endif
#include <Arduino.h> #include <Arduino.h>
@ -29,17 +35,23 @@ struct cRGB {
uint8_t r; uint8_t r;
}; };
#include "kaleidoscope/device/ATmega32U4Keyboard.h"
#include "kaleidoscope/driver/keyscanner/Base.h" #include "kaleidoscope/driver/keyscanner/Base.h"
#include "kaleidoscope/driver/storage/GD32Flash.h"
#include "kaleidoscope/driver/keyboardio/Model100Side.h" #include "kaleidoscope/driver/keyboardio/Model100Side.h"
#include "kaleidoscope/driver/led/Base.h" #include "kaleidoscope/driver/led/Base.h"
#include "kaleidoscope/device/Base.h"
#include "kaleidoscope/driver/bootloader/gd32/Base.h" #include "kaleidoscope/driver/bootloader/gd32/Base.h"
namespace kaleidoscope { namespace kaleidoscope {
namespace device { namespace device {
namespace keyboardio { namespace keyboardio {
struct Model100StorageProps: public kaleidoscope::driver::storage::GD32FlashProps {
static constexpr uint16_t length = EEPROM_EMULATION_SIZE;
};
struct Model100LEDDriverProps : public kaleidoscope::driver::led::BaseProps { struct Model100LEDDriverProps : public kaleidoscope::driver::led::BaseProps {
static constexpr uint8_t led_count = 64; static constexpr uint8_t led_count = 64;
static constexpr uint8_t key_led_map[] PROGMEM = { static constexpr uint8_t key_led_map[] PROGMEM = {
@ -60,7 +72,6 @@ class Model100LEDDriver : public kaleidoscope::driver::led::Base<Model100LEDDriv
static uint8_t getBrightness(); static uint8_t getBrightness();
static void enableHighPowerLeds(); static void enableHighPowerLeds();
static boolean ledPowerFault();
private: private:
static bool isLEDChanged; static bool isLEDChanged;
@ -101,16 +112,20 @@ class Model100KeyScanner : public kaleidoscope::driver::keyscanner::Base<Model10
static void actOnHalfRow(byte row, byte colState, byte colPrevState, byte startPos); static void actOnHalfRow(byte row, byte colState, byte colPrevState, byte startPos);
static void enableScannerPower(); static void enableScannerPower();
static void disableScannerPower();
}; };
#else // ifndef KALEIDOSCOPE_VIRTUAL_BUILD #else // ifndef KALEIDOSCOPE_VIRTUAL_BUILD
class Model100KeyScanner; class Model100KeyScanner;
#endif // ifndef KALEIDOSCOPE_VIRTUAL_BUILD #endif // ifndef KALEIDOSCOPE_VIRTUAL_BUILD
struct Model100Props : public kaleidoscope::device::BaseKeyboardProps { struct Model100Props : public kaleidoscope::device::BaseProps {
typedef Model100LEDDriverProps LEDDriverProps; typedef Model100LEDDriverProps LEDDriverProps;
typedef Model100LEDDriver LEDDriver; typedef Model100LEDDriver LEDDriver;
typedef Model100KeyScannerProps KeyScannerProps; typedef Model100KeyScannerProps KeyScannerProps;
typedef Model100KeyScanner KeyScanner; typedef Model100KeyScanner KeyScanner;
typedef Model100StorageProps StorageProps;
typedef kaleidoscope::driver::storage::GD32Flash<StorageProps> Storage;
typedef kaleidoscope::driver::bootloader::gd32::Base BootLoader; typedef kaleidoscope::driver::bootloader::gd32::Base BootLoader;
static constexpr const char *short_name = "kbio100"; static constexpr const char *short_name = "kbio100";
}; };

@ -24,10 +24,8 @@
#include <Arduino.h> #include <Arduino.h>
#include "Model100Side.h" #include "Model100Side.h"
#include <Wire.h>
extern "C" { #include <utility/twi.h>
#include "kaleidoscope/device/keyboardio/twi.h"
}
#include "kaleidoscope/driver/color/GammaCorrection.h" #include "kaleidoscope/driver/color/GammaCorrection.h"
@ -43,9 +41,6 @@ uint8_t twi_uninitialized = 1;
Model100Side::Model100Side(byte setAd01) { Model100Side::Model100Side(byte setAd01) {
ad01 = setAd01; ad01 = setAd01;
addr = SCANNER_I2C_ADDR_BASE | ad01; addr = SCANNER_I2C_ADDR_BASE | ad01;
if (twi_uninitialized--) {
twi_init();
}
} }
// Returns the relative controller addresss. The expected range is 0-3 // Returns the relative controller addresss. The expected range is 0-3
@ -72,8 +67,7 @@ uint8_t Model100Side::controllerAddress() {
// https://www.arduino.cc/en/Reference/WireEndTransmission // https://www.arduino.cc/en/Reference/WireEndTransmission
byte Model100Side::setKeyscanInterval(byte delay) { byte Model100Side::setKeyscanInterval(byte delay) {
uint8_t data[] = {TWI_CMD_KEYSCAN_INTERVAL, delay}; uint8_t data[] = {TWI_CMD_KEYSCAN_INTERVAL, delay};
uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0); uint8_t result = writeData(data, ELEMENTS(data));
return result; return result;
} }
@ -103,34 +97,88 @@ int Model100Side::readLEDSPIFrequency() {
// https://www.arduino.cc/en/Reference/WireEndTransmission // https://www.arduino.cc/en/Reference/WireEndTransmission
byte Model100Side::setLEDSPIFrequency(byte frequency) { byte Model100Side::setLEDSPIFrequency(byte frequency) {
uint8_t data[] = {TWI_CMD_LED_SPI_FREQUENCY, frequency}; uint8_t data[] = {TWI_CMD_LED_SPI_FREQUENCY, frequency};
uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0); uint8_t result = writeData(data, ELEMENTS(data));
return result; return result;
} }
// GD32 I2C implements timeouts which will cause a stall when a device does not answer.
// This method will verify that the device is around and ready to talk.
bool Model100Side::isDeviceAvailable() {
// if we dont know the device is around,
return true;
// if the counter is zero, that's the special value that means "we know it's there"
if (unavailable_device_check_countdown_ == 0) {
return true;
}
int Model100Side::readRegister(uint8_t cmd) { // if the time to check counter is 1, check for the device
byte return_value = 0; else if (--unavailable_device_check_countdown_ == 0) {
uint8_t wire_result;
Wire.beginTransmission(addr);
wire_result = Wire.endTransmission();
//if the check succeeds
if (wire_result == 0) {
unavailable_device_check_countdown_ = 0; // TODO this is already true
return true;
} else {
Wire.beginTransmission(wire_result);
wire_result = Wire.endTransmission();
uint8_t data[] = {cmd}; // set the time to check counter to max
uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0); unavailable_device_check_countdown_ = UNAVAILABLE_DEVICE_COUNTDOWN_MAX;
return false;
}
} else {
// we've decremented the counter, but it's not time to probe for the device yet.
return false;
}
}
void Model100Side::markDeviceUnavailable() {
unavailable_device_check_countdown_ = 1; // We think there was a comms problem. Check on the next cycle
}
uint8_t Model100Side::writeData(uint8_t *data, uint8_t length) {
if (isDeviceAvailable() == false) {
return 1;
}
Wire.beginTransmission(addr);
Wire.write(data, length);
uint8_t result = Wire.endTransmission();
if (result) {
markDeviceUnavailable();
}
return result;
}
int Model100Side::readRegister(uint8_t cmd) {
byte return_value = 0;
uint8_t data[] = {cmd};
uint8_t result = writeData(data, ELEMENTS(data));
delayMicroseconds(15); // We may be able to drop this in the future // If the setup failed, return. This means there was a problem asking for the register
if (result) {
return -1;
}
delayMicroseconds(15); // TODO We may be able to drop this in the future
// but will need to verify with correctly // but will need to verify with correctly
// sized pull-ups on both the left and right // sized pull-ups on both the left and right
// hands' i2c SDA and SCL lines // hands' i2c SDA and SCL lines
uint8_t rxBuffer[1]; uint8_t rxBuffer[1] = {0};
// perform blocking read into buffer // perform blocking read into buffer
uint8_t read = twi_readFrom(addr, rxBuffer, ELEMENTS(rxBuffer), true);
if (read > 0) { Wire.requestFrom(addr, 1); // request 1 byte from the keyscanner
return rxBuffer[0]; if (Wire.available()) {
return Wire.read();
} else { } else {
//markDeviceUnavailable();
return -1; return -1;
} }
@ -139,20 +187,28 @@ int Model100Side::readRegister(uint8_t cmd) {
// gives information on the key that was just pressed or released. // gives information on the key that was just pressed or released.
bool Model100Side::readKeys() { bool Model100Side::readKeys() {
if (isDeviceAvailable() == false) {
return false;
}
uint8_t rxBuffer[5]; uint8_t row_counter = 0;
// perform blocking read into buffer // perform blocking read into buffer
uint8_t read = twi_readFrom(addr, rxBuffer, ELEMENTS(rxBuffer), true); uint8_t read = 0;
if (rxBuffer[0] == TWI_REPLY_KEYDATA) { uint8_t bytes_returned = 0;
keyData.rows[0] = rxBuffer[1]; bytes_returned = Wire.requestFrom(addr, 5); // request 5 bytes from the keyscanner
keyData.rows[1] = rxBuffer[2]; if (bytes_returned < 5) {
keyData.rows[2] = rxBuffer[3];
keyData.rows[3] = rxBuffer[4];
return true;
} else {
return false; return false;
} }
if (Wire.available()) {
read = Wire.read();
if (TWI_REPLY_KEYDATA == read) {
while (Wire.available()) {
keyData.rows[row_counter++] = Wire.read();
}
return true;
}
}
return false;
} }
keydata_t Model100Side::getKeyData() { keydata_t Model100Side::getKeyData() {
@ -166,7 +222,6 @@ void Model100Side::sendLEDData() {
} }
} }
auto constexpr gamma8 = kaleidoscope::driver::color::gamma_correction;
void Model100Side::sendLEDBank(byte bank) { void Model100Side::sendLEDBank(byte bank) {
uint8_t data[LED_BYTES_PER_BANK + 1]; uint8_t data[LED_BYTES_PER_BANK + 1];
@ -182,28 +237,28 @@ void Model100Side::sendLEDBank(byte bank) {
else else
c = 0; c = 0;
data[i + 1] = pgm_read_byte(&gamma8[c]); data[i + 1] = c;
} }
uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0); uint8_t result = writeData(data, ELEMENTS(data));
} }
void Model100Side::setAllLEDsTo(cRGB color) { void Model100Side::setAllLEDsTo(cRGB color) {
uint8_t data[] = {TWI_CMD_LED_SET_ALL_TO, uint8_t data[] = {TWI_CMD_LED_SET_ALL_TO,
pgm_read_byte(&gamma8[color.b]), color.b,
pgm_read_byte(&gamma8[color.g]), color.g,
pgm_read_byte(&gamma8[color.r]) color.r
}; };
uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0); uint8_t result = writeData(data, ELEMENTS(data));
} }
void Model100Side::setOneLEDTo(byte led, cRGB color) { void Model100Side::setOneLEDTo(byte led, cRGB color) {
uint8_t data[] = {TWI_CMD_LED_SET_ONE_TO, uint8_t data[] = {TWI_CMD_LED_SET_ONE_TO,
led, led,
pgm_read_byte(&gamma8[color.b]), color.b,
pgm_read_byte(&gamma8[color.g]), color.g,
pgm_read_byte(&gamma8[color.r]) color.r
}; };
uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0); uint8_t result = writeData(data, ELEMENTS(data));
} }

@ -78,9 +78,12 @@ class Model100Side {
void setAllLEDsTo(cRGB color); void setAllLEDsTo(cRGB color);
keydata_t getKeyData(); keydata_t getKeyData();
bool readKeys(); bool readKeys();
LEDData_t ledData; LEDData_t ledData;
uint8_t controllerAddress();
uint8_t controllerAddress();
bool isDeviceAvailable();
void markDeviceUnavailable();
void setBrightness(uint8_t brightness) { void setBrightness(uint8_t brightness) {
brightness_adjustment_ = 255 - brightness; brightness_adjustment_ = 255 - brightness;
} }
@ -93,9 +96,14 @@ class Model100Side {
int addr; int addr;
int ad01; int ad01;
keydata_t keyData; keydata_t keyData;
// a value of 0 is "device seen" - anything else is how many cycles before we should
// check for the device
uint16_t unavailable_device_check_countdown_ = 1;
static const uint16_t UNAVAILABLE_DEVICE_COUNTDOWN_MAX = 0xFFFFU;
byte nextLEDBank = 0; byte nextLEDBank = 0;
void sendLEDBank(byte bank); void sendLEDBank(byte bank);
int readRegister(uint8_t cmd); int readRegister(uint8_t cmd);
uint8_t writeData(uint8_t* data, uint8_t length);
}; };
#else // ifndef KALEIDOSCOPE_VIRTUAL_BUILD #else // ifndef KALEIDOSCOPE_VIRTUAL_BUILD
class Model100Side; class Model100Side;

@ -16,24 +16,19 @@
#pragma once #pragma once
#define IS_MOUSE_KEY B00010000 #define IS_MOUSE_KEY 0b00010000
// Synthetic, not internal // Synthetic, not internal
#define KEY_MOUSE_BTN_L MOUSE_LEFT // Synthetic key
#define KEY_MOUSE_BTN_M MOUSE_MIDDLE // Synthetic key
#define KEY_MOUSE_BTN_R MOUSE_RIGHT // Synthetic key
#define KEY_MOUSE_BTN_P MOUSE_PREV
#define KEY_MOUSE_BTN_N MOUSE_NEXT
#define KEY_MOUSE_UP B0000001 #define KEY_MOUSE_UP 0b0000001
#define KEY_MOUSE_DOWN B0000010 #define KEY_MOUSE_DOWN 0b0000010
#define KEY_MOUSE_LEFT B0000100 #define KEY_MOUSE_LEFT 0b0000100
#define KEY_MOUSE_RIGHT B0001000 #define KEY_MOUSE_RIGHT 0b0001000
#define KEY_MOUSE_WHEEL B0010000 #define KEY_MOUSE_WHEEL 0b0010000
#define KEY_MOUSE_WARP B0100000 #define KEY_MOUSE_WARP 0b0100000
#define KEY_MOUSE_WARP_END B1000000 #define KEY_MOUSE_WARP_END 0b1000000
// all buttons end warp. also, we're out of bits // all buttons end warp. also, we're out of bits
#define KEY_MOUSE_BUTTON B1000000 #define KEY_MOUSE_BUTTON 0b1000000
#define Key_mouseWarpNW Key(KEY_MOUSE_WARP| KEY_MOUSE_UP | KEY_MOUSE_LEFT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY) #define Key_mouseWarpNW Key(KEY_MOUSE_WARP| KEY_MOUSE_UP | KEY_MOUSE_LEFT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY)
@ -60,8 +55,31 @@
#define Key_mouseScrollDn Key(KEY_MOUSE_WHEEL | KEY_MOUSE_DOWN, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY) #define Key_mouseScrollDn Key(KEY_MOUSE_WHEEL | KEY_MOUSE_DOWN, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY)
#define Key_mouseScrollL Key(KEY_MOUSE_WHEEL | KEY_MOUSE_LEFT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY) #define Key_mouseScrollL Key(KEY_MOUSE_WHEEL | KEY_MOUSE_LEFT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY)
#define Key_mouseScrollR Key(KEY_MOUSE_WHEEL | KEY_MOUSE_RIGHT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY) #define Key_mouseScrollR Key(KEY_MOUSE_WHEEL | KEY_MOUSE_RIGHT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY)
// The MOUSE_xxx button definitions come from our HID driver
// If the HID driver doesn't define them, don't blow up compilation
#ifdef MOUSE_LEFT
#define KEY_MOUSE_BTN_L MOUSE_LEFT // Synthetic key
#define KEY_MOUSE_BTN_M MOUSE_MIDDLE // Synthetic key
#define KEY_MOUSE_BTN_R MOUSE_RIGHT // Synthetic key
#define KEY_MOUSE_BTN_P MOUSE_PREV
#define KEY_MOUSE_BTN_N MOUSE_NEXT
#define Key_mouseBtnL Key(KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_L, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY) #define Key_mouseBtnL Key(KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_L, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY)
#define Key_mouseBtnM Key(KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_M, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY) #define Key_mouseBtnM Key(KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_M, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY)
#define Key_mouseBtnR Key(KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_R, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY) #define Key_mouseBtnR Key(KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_R, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY)
#define Key_mouseBtnP Key(KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_P, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY) #define Key_mouseBtnP Key(KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_P, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY)
#define Key_mouseBtnN Key(KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_N, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY) #define Key_mouseBtnN Key(KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_N, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY)
#else
#define Key_mouseBtnL XXX
#define Key_mouseBtnM XXX
#define Key_mouseBtnR XXX
#define Key_mouseBtnP XXX
#define Key_mouseBtnN XXX
#endif

@ -19,9 +19,9 @@
#include <Arduino.h> #include <Arduino.h>
#define INJECTED B10000000 #define INJECTED 0b10000000
#define IS_PRESSED B00000010 #define IS_PRESSED 0b00000010
#define WAS_PRESSED B00000001 #define WAS_PRESSED 0b00000001
/* keyIsPressed(): This is true if the key is pressed during this scan cycle. /* keyIsPressed(): This is true if the key is pressed during this scan cycle.
* This will be true for several consecutive cycles even for a single tap of * This will be true for several consecutive cycles even for a single tap of

@ -27,7 +27,7 @@
#endif #endif
#define LED_TOGGLE B00000001 // Synthetic, internal #define LED_TOGGLE 0b00000001 // Synthetic, internal
#define Key_LEDEffectNext Key(0, KEY_FLAGS | SYNTHETIC | IS_INTERNAL | LED_TOGGLE) #define Key_LEDEffectNext Key(0, KEY_FLAGS | SYNTHETIC | IS_INTERNAL | LED_TOGGLE)
#define Key_LEDEffectPrevious Key(1, KEY_FLAGS | SYNTHETIC | IS_INTERNAL | LED_TOGGLE) #define Key_LEDEffectPrevious Key(1, KEY_FLAGS | SYNTHETIC | IS_INTERNAL | LED_TOGGLE)

@ -26,7 +26,11 @@
* this workaround. * this workaround.
*/ */
#ifndef _INIT_HID_GETSHORTNAME
#define _INIT_HID_GETSHORTNAME __NL__ \ #define _INIT_HID_GETSHORTNAME __NL__ \
uint8_t HID_::getShortName(char *name) { __NL__ \ uint8_t HID_::getShortName(char *name) { __NL__ \
return Kaleidoscope.device().getShortName(name); __NL__ \ return Kaleidoscope.device().getShortName(name); __NL__ \
} }
#endif

Loading…
Cancel
Save