Compare commits

...

2 Commits

@ -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,125 @@
/* -*- mode: c++ -*-
* Atreus -- Chrysalis-enabled Sketch for the Keyboardio Atreus
* Copyright (C) 2018, 2019 Keyboard.io, Inc
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef BUILD_INFORMATION
#define BUILD_INFORMATION "locally built on " __DATE__ " at " __TIME__
#endif
#include "Kaleidoscope.h"
#include "Kaleidoscope-EEPROM-Settings.h"
#include "Kaleidoscope-EEPROM-Keymap.h"
#include "Kaleidoscope-FocusSerial.h"
#include "Kaleidoscope-Macros.h"
#include "Kaleidoscope-MouseKeys.h"
#include "Kaleidoscope-OneShot.h"
#include "Kaleidoscope-Qukeys.h"
#include "Kaleidoscope-SpaceCadet.h"
#include "Kaleidoscope-Hardware-Keyboardio-SpaceCadet.h"
#define MO(n) ShiftToLayer(n)
#define TG(n) LockLayer(n)
enum {
MACRO_QWERTY,
MACRO_VERSION_INFO
};
#define Key_Exclamation LSHIFT(Key_1)
#define Key_At LSHIFT(Key_2)
#define Key_Hash LSHIFT(Key_3)
#define Key_Dollar LSHIFT(Key_4)
#define Key_Percent LSHIFT(Key_5)
#define Key_Caret LSHIFT(Key_6)
#define Key_And LSHIFT(Key_7)
#define Key_Star LSHIFT(Key_8)
#define Key_Plus LSHIFT(Key_Equals)
enum {
QWERTY,
FUN,
UPPER
};
/* *INDENT-OFF* */
KEYMAPS(
[QWERTY] = KEYMAP(
Key_Q ,Key_W ,Key_E ,Key_R ,Key_T ,Key_Y ,Key_U ,Key_I ,Key_O ,Key_P
,Key_A ,Key_S ,Key_D ,Key_F ,Key_G ,Key_H ,Key_J ,Key_K ,Key_L ,Key_Semicolon
,Key_Z ,Key_X ,Key_C ,Key_V ,Key_B, Key_Backtick ,Key_Backslash,Key_N ,Key_M ,Key_Comma ,Key_Period ,Key_Slash
,Key_Esc ,Key_Tab ,Key_LeftGui ,Key_LeftShift ,Key_Backspace ,Key_LeftControl ,Key_LeftAlt ,Key_Space ,MO(FUN) ,Key_Minus ,Key_Quote ,Key_Enter, Key_Q ,Key_W ,Key_E ,Key_R ,Key_T
,Key_A ,Key_S ,Key_D ,Key_F ,Key_G
,Key_Z ,Key_X ,Key_C ,Key_V ,Key_B, Key_Backtick
,Key_Esc ,Key_Tab ,Key_LeftGui ,Key_LeftShift ,Key_Backspace ,Key_LeftControl
,Key_Y ,Key_U ,Key_I ,Key_O ,Key_P
,Key_H ,Key_J ,Key_K ,Key_L ,Key_Semicolon
,Key_Backslash,Key_N ,Key_M ,Key_Comma ,Key_Period ,Key_Slash
,Key_LeftAlt ,Key_Space ,MO(FUN) ,Key_Minus ,Key_Quote ,Key_Enter
,Key_H ,Key_J ,Key_K ,Key_L ,Key_Semicolon
,Key_Backslash,Key_N ,Key_M ,Key_Comma ,Key_Period ,Key_Slash, XXX, XXX
)
)
/* *INDENT-ON* */
KALEIDOSCOPE_INIT_PLUGINS(
EEPROMSettings,
EEPROMKeymap,
Focus,
FocusEEPROMCommand,
FocusSettingsCommand,
Qukeys,
SpaceCadet,
OneShot,
Macros,
MouseKeys
);
const macro_t *macroAction(uint8_t macro_id, KeyEvent &event) {
if (keyToggledOn(event.state)) {
switch (macro_id) {
case MACRO_QWERTY:
// This macro is currently unused, but is kept around for compatibility
// reasons. We used to use it in place of `MoveToLayer(QWERTY)`, but no
// longer do. We keep it so that if someone still has the old layout with
// the macro in EEPROM, it will keep working after a firmware update.
Layer.move(QWERTY);
break;
case MACRO_VERSION_INFO:
Macros.type(PSTR("Keyboardio Atreus - Kaleidoscope "));
Macros.type(PSTR(BUILD_INFORMATION));
break;
default:
break;
}
}
return MACRO_NONE;
}
void setup() {
Kaleidoscope.setup();
SpaceCadet.disable();
EEPROMKeymap.setup(10);
}
void loop() {
Kaleidoscope.loop();
}

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

@ -0,0 +1,7 @@
name=Kaleidoscope-Hardware-Keyboardio-Spacecadet
version=0.0.0
sentence=Keyboardio Spacecadet hardware support for Kaleidoscope
maintainer=Kaleidoscope's Developers <jesse@keyboard.io>
url=https://github.com/keyboardio/Kaleidoscope
author=Keyboardio
paragraph=

@ -0,0 +1,19 @@
/* -*- mode: c++ -*-
* Copyright (C) 2021 Keyboard.io, Inc
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "kaleidoscope/device/keyboardio/Spacecadet.h"

@ -0,0 +1,227 @@
/* -*- mode: c++ -*-
* kaleidoscope::driver::keyscanner::GD32 -- AVR GD32-based keyscanner component
* Copyright (C) 2018-2020 Keyboard.io, Inc
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <Arduino.h>
#include "kaleidoscope/macro_helpers.h"
#include "kaleidoscope/driver/keyscanner/Base.h"
#include "kaleidoscope/driver/keyscanner/None.h"
namespace kaleidoscope {
namespace driver {
namespace keyscanner {
struct GD32Props: kaleidoscope::driver::keyscanner::BaseProps {
static const uint16_t keyscan_interval = 1500;
typedef uint32_t RowState;
/*
* The following two lines declare an empty array. Both of these must be
* shadowed by the descendant keyscanner description class.
*/
static constexpr uint8_t matrix_row_pins[] = {};
static constexpr uint8_t matrix_col_pins[] = {};
};
template <typename _KeyScannerProps>
class GD32: public kaleidoscope::driver::keyscanner::Base<_KeyScannerProps> {
private:
typedef GD32<_KeyScannerProps> ThisType;
uint16_t next_scan_after_ ;
public:
void setup() {
static_assert(
sizeof(_KeyScannerProps::matrix_row_pins) > 0,
"The key scanner description has an empty array of matrix row pins."
);
static_assert(
sizeof(_KeyScannerProps::matrix_col_pins) > 0,
"The key scanner description has an empty array of matrix column pins."
);
for (uint8_t i = 0; i < _KeyScannerProps::matrix_columns; i++) {
pinMode(_KeyScannerProps::matrix_col_pins[i], INPUT_PULLUP);
}
for (uint8_t i = 0; i < _KeyScannerProps::matrix_rows; i++) {
pinMode(_KeyScannerProps::matrix_row_pins[i], OUTPUT);
digitalWrite(_KeyScannerProps::matrix_row_pins[i], HIGH);
}
setScanCycleTime(_KeyScannerProps::keyscan_interval);
next_scan_after_ = 0;
}
/* setScanCycleTime takes a value of between 0 and 8192. This corresponds (roughly) to the number of microseconds to wait between scanning the key matrix. Our debouncing algorithm does four checks before deciding that a result is valid. Most normal mechanical switches specify a 5ms debounce period. On an ATMega32U4, 1700 gets you about 5ms of debouncing.
Because keycanning is triggered by an interrupt but not run in that interrupt, the actual amount of time between scans is prone to a little bit of jitter.
*/
void setScanCycleTime(uint16_t c) {
}
__attribute__((optimize(3)))
void readMatrix(void) {
typename _KeyScannerProps::RowState any_debounced_changes = 0;
for (uint8_t current_row = 0; current_row < _KeyScannerProps::matrix_rows; current_row++) {
digitalWrite(_KeyScannerProps::matrix_row_pins[current_row], LOW);
typename _KeyScannerProps::RowState hot_pins = readCols();
digitalWrite(_KeyScannerProps::matrix_row_pins[current_row], HIGH);
any_debounced_changes |= debounce(hot_pins, &matrix_state_[current_row].debouncer);
if (any_debounced_changes) {
for (uint8_t current_row = 0; current_row < _KeyScannerProps::matrix_rows; current_row++) {
matrix_state_[current_row].current = matrix_state_[current_row].debouncer.debounced_state;
}
}
}
}
void scanMatrix() {
if (micros() > next_scan_after_ || micros() < _KeyScannerProps::keyscan_interval) {
next_scan_after_ = micros() + _KeyScannerProps::keyscan_interval;
readMatrix();
}
actOnMatrixScan();
}
void __attribute__((optimize(3))) actOnMatrixScan() {
for (byte row = 0; row < _KeyScannerProps::matrix_rows; row++) {
for (byte col = 0; col < _KeyScannerProps::matrix_columns; col++) {
uint8_t keyState = (bitRead(matrix_state_[row].previous, col) << 0) | (bitRead(matrix_state_[row].current, col) << 1);
if (keyState) {
ThisType::handleKeyswitchEvent(Key_NoKey, typename _KeyScannerProps::KeyAddr(row, col), keyState);
}
}
matrix_state_[row].previous = matrix_state_[row].current;
}
}
uint8_t pressedKeyswitchCount() {
uint8_t count = 0;
for (int8_t r = 0; r < _KeyScannerProps::matrix_rows; r++) {
count += __builtin_popcount(matrix_state_[r].current);
}
return count;
}
bool isKeyswitchPressed(typename _KeyScannerProps::KeyAddr key_addr) {
return (bitRead(matrix_state_[key_addr.row()].current, key_addr.col()) != 0);
}
uint8_t previousPressedKeyswitchCount() {
uint8_t count = 0;
for (int8_t r = 0; r < _KeyScannerProps::matrix_rows; r++) {
count += __builtin_popcount(matrix_state_[r].previous);
}
return count;
}
bool wasKeyswitchPressed(typename _KeyScannerProps::KeyAddr key_addr) {
return (bitRead(matrix_state_[key_addr.row()].previous,
key_addr.col()) != 0);
}
bool do_scan_;
protected:
/*
each of these variables are storing the state for a row of keys
so for key 0, the counter is represented by db0[0] and db1[0]
and the state in debounced_state[0].
*/
struct debounce_t {
typename _KeyScannerProps::RowState db0; // counter bit 0
typename _KeyScannerProps::RowState db1; // counter bit 1
typename _KeyScannerProps::RowState debounced_state; // debounced state
};
struct row_state_t {
typename _KeyScannerProps::RowState previous;
typename _KeyScannerProps::RowState current;
debounce_t debouncer;
};
private:
typedef _KeyScannerProps KeyScannerProps_;
static row_state_t matrix_state_[_KeyScannerProps::matrix_rows];
/*
* This function has loop unrolling disabled on purpose: we want to give the
* hardware enough time to produce stable PIN reads for us. If we unroll the
* loop, we will not have that, because even with the NOP, the codepath is too
* fast. If we don't have stable reads, then entire rows or columns will behave
* erratically.
*
* For this reason, we ask the compiler to not unroll our loop, which in turn,
* gives hardware enough time to produce stable reads, at the cost of a little
* bit of speed.
*
* Do not remove the attribute!
*/
__attribute__((optimize("no-unroll-loops")))
typename _KeyScannerProps::RowState readCols() {
typename _KeyScannerProps::RowState hot_pins = 0;
for (uint8_t i = 0; i < _KeyScannerProps::matrix_columns; i++) {
// TODO - do we need this on gd32?
asm("NOP"); // We need to pause a beat before reading or we may read before the pin is hot
hot_pins |= (!digitalRead(_KeyScannerProps::matrix_col_pins[i]) << i);
}
return hot_pins;
}
static inline typename _KeyScannerProps::RowState debounce(
typename _KeyScannerProps::RowState sample, debounce_t *debouncer
) {
typename _KeyScannerProps::RowState delta, changes;
// Use xor to detect changes from last stable state:
// if a key has changed, it's bit will be 1, otherwise 0
delta = sample ^ debouncer->debounced_state;
// Increment counters and reset any unchanged bits:
// increment bit 1 for all changed keys
debouncer->db1 = ((debouncer->db1) ^ (debouncer->db0)) & delta;
// increment bit 0 for all changed keys
debouncer->db0 = ~(debouncer->db0) & delta;
// Calculate returned change set: if delta is still true
// and the counter has wrapped back to 0, the key is changed.
changes = ~(~delta | (debouncer->db0) | (debouncer->db1));
// Update state: in this case use xor to flip any bit that is true in changes.
debouncer->debounced_state ^= changes;
return changes;
}
};
}
}
}

@ -0,0 +1,60 @@
/* -*- mode: c++ -*-
* Kaleidoscope-Hardware-Spacecadet -- Keyboardio Spacecadet hardware support for Kaleidoscope
* Copyright (C) 2021 Keyboard.io, Inc
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ARDUINO_keyboardio_spacecadet
#include "Arduino.h" // for PROGMEM
#include "kaleidoscope/device/keyboardio/Spacecadet.h"
#include "kaleidoscope/device/keyboardio/GD32Keyscanner.h"
#include "kaleidoscope/key_events.h"
#include "kaleidoscope/driver/keyscanner/Base_Impl.h"
// Here, we set up aliases to the device's KeyScanner and KeyScannerProps
// in the global namespace within the scope of this file. We'll use these
// aliases to simplify some template initialization code below.
using KeyScannerProps = typename kaleidoscope::device::keyboardio::SpacecadetProps::KeyScannerProps;
using KeyScanner = typename kaleidoscope::device::keyboardio::SpacecadetProps::KeyScanner;
namespace kaleidoscope {
namespace device {
namespace keyboardio {
// `KeyScannerProps` here refers to the alias set up above. We do not need to
// prefix the `matrix_rows` and `matrix_columns` names within the array
// declaration, because those are resolved within the context of the class, so
// the `matrix_rows` in `KeyScannerProps::matrix_row_pins[matrix_rows]` gets
// resolved as `KeyScannerProps::matrix_rows`.
const uint8_t KeyScannerProps::matrix_rows;
const uint8_t KeyScannerProps::matrix_columns;
constexpr uint8_t KeyScannerProps::matrix_row_pins[matrix_rows];
constexpr uint8_t KeyScannerProps::matrix_col_pins[matrix_columns];
// `KeyScanner` here refers to the alias set up above, just like in the
// `KeyScannerProps` case above.
template<> KeyScanner::row_state_t KeyScanner::matrix_state_[KeyScannerProps::matrix_rows] = {};
}
}
}
#endif

@ -0,0 +1,101 @@
/* -*- mode: c++ -*-
* Kaleidoscope-Hardware-Spacecadet -- Keyboardio Spacecadet hardware support for Kaleidoscope
* Copyright (C) 2017-2021 Keyboard.io, Inc
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifdef ARDUINO_keyboardio_spacecadet
#ifndef EEPROM_EMULATION_SIZE
#define EEPROM_EMULATION_SIZE 4096
#endif
#include <Arduino.h>
#include "kaleidoscope/driver/keyscanner/Base.h"
#include "kaleidoscope/driver/storage/GD32Flash.h"
#include "kaleidoscope/device/Base.h"
#include "kaleidoscope/driver/hid/Keyboardio.h"
#include "kaleidoscope/driver/bootloader/gd32/Base.h"
#include "kaleidoscope/device/keyboardio/GD32Keyscanner.h"
namespace kaleidoscope {
namespace device {
namespace keyboardio {
struct SpacecadetStorageProps: public kaleidoscope::driver::storage::GD32FlashProps {
static constexpr uint16_t length = EEPROM_EMULATION_SIZE;
};
struct SpacecadetProps : public kaleidoscope::device::BaseProps {
typedef kaleidoscope::driver::hid::KeyboardioProps HIDProps;
typedef kaleidoscope::driver::hid::Keyboardio<HIDProps> HID;
struct KeyScannerProps : public kaleidoscope::driver::keyscanner::GD32Props {
static constexpr uint8_t matrix_rows = 6;
static constexpr uint8_t matrix_columns = 21;
typedef MatrixAddr<matrix_rows, matrix_columns> KeyAddr;
static constexpr uint8_t matrix_row_pins[matrix_rows] = {PB15, PB14, PB13, PB12, PB11, PB10};
static constexpr uint8_t matrix_col_pins[matrix_columns] = {PB1, PB0,PA7,PA6,PA5,PA4,PA3,PA2,PA1,PA0,PD1,PD0,PC15,PC14,PC13, PA9,PA10, PB8, PB7, PB6,PB5};
};
typedef kaleidoscope::driver::keyscanner::GD32<KeyScannerProps> KeyScanner;
typedef SpacecadetStorageProps StorageProps;
typedef kaleidoscope::driver::storage::GD32Flash<StorageProps> Storage;
typedef kaleidoscope::driver::bootloader::gd32::Base BootLoader;
static constexpr const char *short_name = "spacecadet";
};
class Spacecadet : public kaleidoscope::device::Base<SpacecadetProps> {
public:
};
} // namespace keyboardio
} // namespace device
EXPORT_DEVICE(kaleidoscope::device::keyboardio::Spacecadet)
}
#define PER_KEY_DATA(dflt, \
r0c0, r0c2, r0c3, r0c5, r0c7, r0c9, r0c11, r0c13, r0c15, r0c17, r0c18, r0c19, \
r1c0, r1c1, r1c2, r1c3, r1c4, r1c5, r1c6, r1c7, r1c8, r1c9, r1c10, r1c11, r1c12, r1c13, r1c14, r1c15, r1c16, r1c17, r1c18, r1c19, r1c20, \
r2c0, r2c1, r2c2, r2c3, r2c4, r2c5, r2c6, r2c7, r2c8, r2c9, r2c10, r2c11, r2c12, r2c13, r2c14, r2c15, r2c16, r2c17, r2c18, r2c19, \
r3c0, r3c2, r3c3, r3c4, r3c5, r3c6, r3c7, r3c8, r3c9, r3c10, r3c11, r3c12, r3c13, r3c14, r3c15, r3c17, r3c18, r3c20, \
r4c0, r4c1, r4c2, r4c3, r4c5, r4c6, r4c7, r4c8, r4c9, r4c10, r4c11, r4c12, r4c13, r4c14, r4c15, r4c17, r4c18, r4c19, r4c20, \
r5c0, r5c1, r5c2, r5c3, r5c9, r5c15, r5c17, r5c18, r5c19, ...) \
\
\
r0c0, XXX, r0c2, r0c3, XXX, r0c5, XXX, r0c7, XXX, r0c9, XXX, r0c11, XXX, r0c13, XXX, r0c15, XXX, r0c17, r0c18, r0c19, XXX, \
r1c0, r1c1, r1c2, r1c3, r1c4, r1c5, r1c6, r1c7, r1c8, r1c9, r1c10, r1c11, r1c12, r1c13, r1c14, r1c15, r1c16, r1c17, r1c18, r1c19, r1c20, \
r2c0, r2c1, r2c2, r2c3, r2c4, r2c5, r2c6, r2c7, r2c8, r2c9, r2c10, r2c11, r2c12, r2c13, r2c14, r2c15, r2c16, r2c17, r2c18, r2c19, XXX, \
r3c0, XXX, r3c2, r3c3, r3c4, r3c5, r3c6, r3c7, r3c8, r3c9, r3c10, r3c11, r3c12, r3c13, r3c14, r3c15, XXX, r3c17, r3c18, XXX, r3c20, \
r4c0, r4c1, r4c2, r4c3, XXX, r4c5, r4c6, r4c7, r4c8, r4c9, r4c10, r4c11, r4c12, r4c13, r4c14, r4c15, XXX, r4c17, r4c18, r4c19, r4c20, \
r5c0, r5c1, r5c2, r5c3, XXX, XXX, XXX, XXX, XXX, r5c9, XXX, XXX, XXX, XXX, XXX, XXX, r5c15, XXX, r5c17, r5c18, r5c19
#endif
Loading…
Cancel
Save