Merge pull request #1040 from gedankenexperimenter/plugin/unshifter
Add CharShift pluginpull/1073/head
commit
3dfb4934fb
@ -0,0 +1,43 @@
|
|||||||
|
// -*- mode: c++ -*-
|
||||||
|
|
||||||
|
#include <Kaleidoscope.h>
|
||||||
|
|
||||||
|
#include <Kaleidoscope-CharShift.h>
|
||||||
|
|
||||||
|
// *INDENT-OFF*
|
||||||
|
KEYMAPS(
|
||||||
|
[0] = KEYMAP_STACKED
|
||||||
|
(
|
||||||
|
XXX, Key_1, Key_2, Key_3, Key_4, Key_5, Key_NoKey,
|
||||||
|
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,
|
||||||
|
XXX,
|
||||||
|
|
||||||
|
XXX, Key_6, Key_7, Key_8, Key_9, Key_0, Key_skip,
|
||||||
|
Key_Enter, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_Equals,
|
||||||
|
Key_H, Key_J, Key_K, Key_L, CS(2), Key_Quote,
|
||||||
|
Key_skip, Key_N, Key_M, CS(0), CS(1), Key_Slash, Key_Minus,
|
||||||
|
|
||||||
|
Key_RightShift, Key_RightAlt, Key_Spacebar, Key_RightControl,
|
||||||
|
XXX
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// *INDENT-ON*
|
||||||
|
|
||||||
|
KALEIDOSCOPE_INIT_PLUGINS(CharShift);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
CS_KEYS(
|
||||||
|
kaleidoscope::plugin::CharShift::KeyPair(Key_Comma, Key_Semicolon), // CS(0)
|
||||||
|
kaleidoscope::plugin::CharShift::KeyPair(Key_Period, LSHIFT(Key_Semicolon)), // CS(1)
|
||||||
|
kaleidoscope::plugin::CharShift::KeyPair(LSHIFT(Key_Comma), LSHIFT(Key_Period)), // CS(2)
|
||||||
|
);
|
||||||
|
Kaleidoscope.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Kaleidoscope.loop();
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"cpu": {
|
||||||
|
"fqbn": "keyboardio:avr:model01",
|
||||||
|
"port": ""
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
# CharShift
|
||||||
|
|
||||||
|
CharShift allows you to independently assign symbols to shifted and unshifted
|
||||||
|
positions of keymap entries. Either or both symbols can be ones that normally
|
||||||
|
requires the `shift` modifier, and either or both symbols can be ones normally
|
||||||
|
produced without it.
|
||||||
|
|
||||||
|
For example you can configure your keyboard so that a single key produces `,`
|
||||||
|
when pressed unshifted, but `;` when pressed with `shift` held. Or `(`
|
||||||
|
unshifted, and `[` shifted. Or `+`/`*` — all without changing your OS keyboard
|
||||||
|
layout.
|
||||||
|
|
||||||
|
## Using the plugin
|
||||||
|
|
||||||
|
Using the plugin with its defaults is as simple as including the header, and
|
||||||
|
enabling the plugin:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
#include <Kaleidoscope.h>
|
||||||
|
#include <Kaleidoscope-CharShift.h>
|
||||||
|
|
||||||
|
KALEIDOSCOPE_INIT_PLUGINS(CharShift);
|
||||||
|
```
|
||||||
|
|
||||||
|
Further configuration is required, of course; see below.
|
||||||
|
|
||||||
|
Note: CharShift should be registered in `KALEIDOSCOPE_INIT_PLUGINS()` after any
|
||||||
|
plugin that changes the event's `Key` value to that of an CharShift key.
|
||||||
|
|
||||||
|
## Configuring CharShift keys
|
||||||
|
|
||||||
|
To use CharShift, we must first define `KeyPair` objects, which can then be
|
||||||
|
referenced by entries in the keymap. This is easiest to do by using the
|
||||||
|
`UNKEYS()` preprocessor macro in the sketch's `setup()` function, as follows:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
void setup() {
|
||||||
|
Kaleidoscope.setup();
|
||||||
|
UNKEYS(
|
||||||
|
kaleidoscope::plugin::KeyPair(Key_Comma, Key_Semicolon), // `,`/`;`
|
||||||
|
kaleidoscope::plugin::KeyPair(Key_Period, LSHIFT(Key_Semicolon)), // `.`/`:`
|
||||||
|
kaleidoscope::plugin::KeyPair(LSHIFT(Key_9), Key_LeftBracket), // `(`/`[`
|
||||||
|
kaleidoscope::plugin::KeyPair(LSHIFT(Key_Comma), LSHIFT(Key_LeftBracket)), // `<`/`{`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The first argument to the `KeyPair()` constructor is the value for when the key is
|
||||||
|
pressed without `shift` held, the second is what you'll get if a `shift`
|
||||||
|
modifier is being held when the key toggles on. If that second ("upper") value
|
||||||
|
doesn't have the `shift` modifier flag (i.e. `LSHIFT()`) applied to it, the held
|
||||||
|
`shift` modifier will be suppressed when the key is pressed, allowing the
|
||||||
|
"unshifted" symbol to be produced.
|
||||||
|
|
||||||
|
These `KeyPair`s can be referred to in the sketch's keymap by using the `UK()`
|
||||||
|
preprocessor macro, which takes an integer argument, referring to items in the
|
||||||
|
`UNKEYS()` array, starting with zero. With the example above, an entry of
|
||||||
|
`UK(2)` will output `(` when pressed without `shift`, and `[` if `shift` is
|
||||||
|
being held.
|
||||||
|
|
||||||
|
## Further reading
|
||||||
|
|
||||||
|
Starting from the [example][plugin:example] is the recommended way of getting
|
||||||
|
started with the plugin.
|
||||||
|
|
||||||
|
[plugin:example]: /examples/Keystrokes/CharShift/CharShift.ino
|
@ -0,0 +1,7 @@
|
|||||||
|
name=Kaleidoscope-CharShift
|
||||||
|
version=0.0.0
|
||||||
|
sentence=Independent assignment of symbols to keys based on shift state
|
||||||
|
maintainer=Kaleidoscope's Developers <jesse@keyboard.io>
|
||||||
|
url=https://github.com/keyboardio/Kaleidoscope
|
||||||
|
author=Michael Richters <gedankenexperimenter@gmail.com>
|
||||||
|
paragraph=
|
@ -0,0 +1,20 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* Kaleidoscope-CharShift -- Independently assign shifted and unshifted symbols
|
||||||
|
* 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/plugin/CharShift.h>
|
@ -0,0 +1,149 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* Kaleidoscope-CharShift -- Independently assign shifted and unshifted symbols
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kaleidoscope/plugin/CharShift.h"
|
||||||
|
|
||||||
|
#include <Kaleidoscope-Ranges.h>
|
||||||
|
#include <Kaleidoscope-FocusSerial.h>
|
||||||
|
|
||||||
|
#include "kaleidoscope/KeyAddr.h"
|
||||||
|
#include "kaleidoscope/key_defs.h"
|
||||||
|
#include "kaleidoscope/KeyEvent.h"
|
||||||
|
#include "kaleidoscope/keyswitch_state.h"
|
||||||
|
#include "kaleidoscope/progmem_helpers.h"
|
||||||
|
#include "kaleidoscope/Runtime.h"
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace plugin {
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// CharShift class variables
|
||||||
|
CharShift::KeyPair const * CharShift::progmem_keypairs_{nullptr};
|
||||||
|
uint8_t CharShift::num_keypairs_{0};
|
||||||
|
|
||||||
|
bool CharShift::reverse_shift_state_{false};
|
||||||
|
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Event handlers
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
EventHandlerResult CharShift::onNameQuery() {
|
||||||
|
return ::Focus.sendName(F("CharShift"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
EventHandlerResult CharShift::onKeyEvent(KeyEvent &event) {
|
||||||
|
// If the event is for anything other than an CharShift key, we ignore it.
|
||||||
|
if (!isCharShiftKey(event.key)) {
|
||||||
|
// If this event is for a Keyboard key, we need to stop
|
||||||
|
// `beforeReportingState()` from suppressing `shift` keys.
|
||||||
|
if (event.key.isKeyboardKey())
|
||||||
|
reverse_shift_state_ = false;
|
||||||
|
return EventHandlerResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default to not suppressing `shift` modifiers.
|
||||||
|
reverse_shift_state_ = false;
|
||||||
|
|
||||||
|
// It shouldn't be possible for an CharShift key to toggle off, because it
|
||||||
|
// will get replaced by on of its `KeyPair` values when it toggles on, but just
|
||||||
|
// in case, we exit early if that happens.
|
||||||
|
if (keyToggledOff(event.state))
|
||||||
|
return EventHandlerResult::OK;
|
||||||
|
|
||||||
|
// Next, we get the `KeyPair` values corresponding to the event key.
|
||||||
|
KeyPair keypair = decodeCharShiftKey(event.key);
|
||||||
|
|
||||||
|
// Determine if a shift key is being held.
|
||||||
|
bool shift_held = false;
|
||||||
|
for (Key key : live_keys.all()) {
|
||||||
|
if (key.isKeyboardShift()) {
|
||||||
|
shift_held = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shift_held) {
|
||||||
|
// No shift key is held; just use the base value of the `KeyPair`.
|
||||||
|
event.key = keypair.lower;
|
||||||
|
} else {
|
||||||
|
// At least one shift key is held; use the shifted value.
|
||||||
|
event.key = keypair.upper;
|
||||||
|
// Check for a shift modifier flag.
|
||||||
|
if (event.key.isKeyboardKey() &&
|
||||||
|
(event.key.getFlags() & SHIFT_HELD) == 0) {
|
||||||
|
// The upper key doesn't have the `shift` modifier flag; we need to
|
||||||
|
// suppress `shift` in `beforeReportingState()`.
|
||||||
|
reverse_shift_state_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EventHandlerResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
EventHandlerResult CharShift::beforeReportingState(const KeyEvent &event) {
|
||||||
|
// If `onKeyEvent()` has signalled that `shift` should be suppressed, this is
|
||||||
|
// the time to do it. We can't do it in `onKeyEvent()`, because the new
|
||||||
|
// Keyboard HID report hasn't been prepared yet there.
|
||||||
|
if (reverse_shift_state_) {
|
||||||
|
Runtime.hid().keyboard().releaseKey(Key_LeftShift);
|
||||||
|
Runtime.hid().keyboard().releaseKey(Key_RightShift);
|
||||||
|
}
|
||||||
|
return EventHandlerResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Support functions
|
||||||
|
|
||||||
|
bool CharShift::isCharShiftKey(Key key) {
|
||||||
|
return (key >= ranges::CS_FIRST && key <= ranges::CS_LAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
CharShift::KeyPair CharShift::decodeCharShiftKey(Key key) {
|
||||||
|
uint8_t i = key.getRaw() - ranges::CS_FIRST;
|
||||||
|
if (i < numKeyPairs()) {
|
||||||
|
return readKeyPair(i);
|
||||||
|
}
|
||||||
|
return {Key_NoKey, Key_NoKey};
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should be overridden if the KeyPairs array is stored in EEPROM
|
||||||
|
__attribute__((weak))
|
||||||
|
uint8_t CharShift::numKeyPairs() {
|
||||||
|
return numProgmemKeyPairs();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should be overridden if the KeyPairs array is stored in EEPROM
|
||||||
|
__attribute__((weak))
|
||||||
|
CharShift::KeyPair CharShift::readKeyPair(uint8_t n) {
|
||||||
|
return readKeyPairFromProgmem(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CharShift::numProgmemKeyPairs() {
|
||||||
|
return num_keypairs_;
|
||||||
|
}
|
||||||
|
|
||||||
|
CharShift::KeyPair CharShift::readKeyPairFromProgmem(uint8_t n) {
|
||||||
|
return cloneFromProgmem(progmem_keypairs_[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace plugin
|
||||||
|
} // namespace kaleidoscope
|
||||||
|
|
||||||
|
kaleidoscope::plugin::CharShift CharShift;
|
@ -0,0 +1,137 @@
|
|||||||
|
/* -*- mode: c++ -*-
|
||||||
|
* Kaleidoscope-CharShift -- Independently assign shifted and unshifted symbols
|
||||||
|
* 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/Runtime.h"
|
||||||
|
|
||||||
|
#include <Kaleidoscope-Ranges.h>
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace plugin {
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
/// Kaleidoscope plugin for independently assigning shifted symbols
|
||||||
|
///
|
||||||
|
/// This plugin provides a way to define keys that, when `shift` is held, will
|
||||||
|
/// produce different symbols than they normally would. Either, both, or
|
||||||
|
/// neither of the symbols assigned to a key in this way can be ones that are
|
||||||
|
/// normally produced with the `shift` modifier. Crucially, when `shift` is
|
||||||
|
/// held, and the `Key` to be output does not have the `shift` modifier flag
|
||||||
|
/// applied to it, the held `shift` modifier will be suppressed.
|
||||||
|
class CharShift : public Plugin {
|
||||||
|
|
||||||
|
public:
|
||||||
|
EventHandlerResult onNameQuery();
|
||||||
|
EventHandlerResult onKeyEvent(KeyEvent &event);
|
||||||
|
EventHandlerResult beforeReportingState(const KeyEvent &event);
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
/// A structure that stores CharShift key pair values
|
||||||
|
///
|
||||||
|
/// This structure stores two separate `Key` values: `lower` (to be used when
|
||||||
|
/// a key is pressed without `shift` held), and `upper` (to be used when
|
||||||
|
/// `shift` is held).
|
||||||
|
struct KeyPair {
|
||||||
|
Key lower;
|
||||||
|
Key upper;
|
||||||
|
|
||||||
|
/// Constructor for use in PROGMEM
|
||||||
|
///
|
||||||
|
/// This constructor is used when defining an array of `KeyPair` objects in
|
||||||
|
/// PROGMEM (though it can also be used elsewhere).
|
||||||
|
constexpr KeyPair(Key lower, Key upper) : lower(lower), upper(upper) {}
|
||||||
|
|
||||||
|
/// Constructor for reading from PROGMEM
|
||||||
|
///
|
||||||
|
/// This constructor is used by the helper function that copies values from
|
||||||
|
/// PROGMEM so that they can be used normally.
|
||||||
|
KeyPair() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Configure the KeyPairs array in PROGMEM
|
||||||
|
///
|
||||||
|
/// This function configures the PROGMEM array of `KeyPair` objects,
|
||||||
|
/// automatically setting the internal count variable from the size of the
|
||||||
|
/// `keypairs` array given, which must be a fixed-sized array, not a pointer.
|
||||||
|
/// Generally, it will be called via the `KEYPAIRS()` preprocessor macro, not
|
||||||
|
/// directly by user code.
|
||||||
|
template <uint8_t _num_keypairs>
|
||||||
|
static void setProgmemKeyPairs(KeyPair const(&keypairs)[_num_keypairs]) {
|
||||||
|
progmem_keypairs_ = keypairs;
|
||||||
|
num_keypairs_ = _num_keypairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// A pointer to an array of `KeyPair` objects in PROGMEM
|
||||||
|
static KeyPair const * progmem_keypairs_;
|
||||||
|
// The size of the PROGMEM array of `KeyPair` objects
|
||||||
|
static uint8_t num_keypairs_;
|
||||||
|
|
||||||
|
// If a `shift` key needs to be suppressed in `beforeReportingState()`
|
||||||
|
static bool reverse_shift_state_;
|
||||||
|
|
||||||
|
/// Test for keys that should be handled by CharShift
|
||||||
|
static bool isCharShiftKey(Key key);
|
||||||
|
|
||||||
|
/// Look up the `KeyPair` specified by the given keymap entry
|
||||||
|
static KeyPair decodeCharShiftKey(Key key);
|
||||||
|
|
||||||
|
/// Get the total number of KeyPairs defined
|
||||||
|
///
|
||||||
|
/// This function can be overridden in order to store the `KeyPair` array in
|
||||||
|
/// EEPROM instead of PROGMEM.
|
||||||
|
static uint8_t numKeyPairs();
|
||||||
|
|
||||||
|
/// Get the `KeyPair` at the specified index from the defined `KeyPair` array
|
||||||
|
///
|
||||||
|
/// This function can be overridden in order to store the `KeyPair` array in
|
||||||
|
/// EEPROM instead of PROGMEM.
|
||||||
|
static KeyPair readKeyPair(uint8_t n);
|
||||||
|
|
||||||
|
// Default for `keypairsCount()`: size of the PROGMEM array
|
||||||
|
static uint8_t numProgmemKeyPairs();
|
||||||
|
// Default for `readKeypair(i)`: fetch the value from PROGMEM
|
||||||
|
static KeyPair readKeyPairFromProgmem(uint8_t n);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace plugin
|
||||||
|
} // namespace kaleidoscope
|
||||||
|
|
||||||
|
extern kaleidoscope::plugin::CharShift CharShift;
|
||||||
|
|
||||||
|
/// Define an array of `KeyPair` objects in PROGMEM
|
||||||
|
///
|
||||||
|
/// This preprocessor macro takes a list of `KeyPair` objects as arguments, and
|
||||||
|
/// defines them as an array in PROGMEM, and configures `CharShift` to use that
|
||||||
|
/// array, automatically setting the count correctly to prevent out-of-bounds
|
||||||
|
/// lookups.
|
||||||
|
#define CS_KEYS(keypairs...) { \
|
||||||
|
static kaleidoscope::plugin::CharShift::KeyPair const kp_table[] PROGMEM = { \
|
||||||
|
keypairs \
|
||||||
|
}; \
|
||||||
|
CharShift.setProgmemKeyPairs(kp_table); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Define an `KeyPair` entry in a keymap
|
||||||
|
///
|
||||||
|
/// This defines a `Key` object that will be handled by the CharShift plugin.
|
||||||
|
/// The argument `n` is the index number of the `KeyPair` in the array (starting
|
||||||
|
/// at zero).
|
||||||
|
constexpr kaleidoscope::Key CS(uint8_t n) {
|
||||||
|
return kaleidoscope::Key(kaleidoscope::ranges::CS_FIRST + n);
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/* -*- 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Kaleidoscope.h>
|
||||||
|
#include <Kaleidoscope-CharShift.h>
|
||||||
|
|
||||||
|
// *INDENT-OFF*
|
||||||
|
KEYMAPS(
|
||||||
|
[0] = KEYMAP_STACKED
|
||||||
|
(
|
||||||
|
Key_LeftShift, Key_RightShift, ___, ___, ___, ___, ___,
|
||||||
|
Key_X, LSHIFT(Key_Y), ___, ___, ___, ___, ___,
|
||||||
|
CS(0), CS(1), CS(2), CS(3), ___, ___,
|
||||||
|
___, ___, ___, ___, ___, ___, ___,
|
||||||
|
___, ___, ___, ___,
|
||||||
|
___,
|
||||||
|
|
||||||
|
___, ___, ___, ___, ___, ___, ___,
|
||||||
|
___, ___, ___, ___, ___, ___, ___,
|
||||||
|
___, ___, ___, ___, ___, ___,
|
||||||
|
___, ___, ___, ___, ___, ___, ___,
|
||||||
|
___, ___, ___, ___,
|
||||||
|
___
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// *INDENT-ON*
|
||||||
|
|
||||||
|
KALEIDOSCOPE_INIT_PLUGINS(CharShift);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Kaleidoscope.setup();
|
||||||
|
CS_KEYS(
|
||||||
|
kaleidoscope::plugin::CharShift::KeyPair(Key_A, Key_B),
|
||||||
|
kaleidoscope::plugin::CharShift::KeyPair(Key_C, LSHIFT(Key_D)),
|
||||||
|
kaleidoscope::plugin::CharShift::KeyPair(LSHIFT(Key_E), Key_F),
|
||||||
|
kaleidoscope::plugin::CharShift::KeyPair(LSHIFT(Key_G), LSHIFT(Key_H)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Kaleidoscope.loop();
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"cpu": {
|
||||||
|
"fqbn": "keyboardio:virtual:model01",
|
||||||
|
"port": ""
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,212 @@
|
|||||||
|
VERSION 1
|
||||||
|
|
||||||
|
KEYSWITCH LSHIFT 0 0
|
||||||
|
KEYSWITCH RSHIFT 0 1
|
||||||
|
KEYSWITCH x 1 0
|
||||||
|
KEYSWITCH Y 1 1
|
||||||
|
KEYSWITCH CS_ab 2 0
|
||||||
|
KEYSWITCH CS_cD 2 1
|
||||||
|
KEYSWITCH CS_Ef 2 2
|
||||||
|
KEYSWITCH CS_GH 2 3
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
NAME CharShift lower lower
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS CS_ab
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_A # report: { 4 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE CS_ab
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS LSHIFT
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS CS_ab
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
EXPECT keyboard-report Key_B # report: { 5 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE CS_ab
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE LSHIFT
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
|
||||||
|
RUN 5 ms
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
NAME CharShift lower upper
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS CS_cD
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_C # report: { 6 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE CS_cD
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS LSHIFT
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS CS_cD
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift Key_D # report: { e1 7 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE CS_cD
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE LSHIFT
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
|
||||||
|
RUN 5 ms
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
NAME CharShift upper lower
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS CS_Ef
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
EXPECT keyboard-report Key_LeftShift Key_E # report: { e1 8 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE CS_Ef
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS LSHIFT
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS CS_Ef
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
EXPECT keyboard-report Key_F # report: { 9 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE CS_Ef
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE LSHIFT
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
|
||||||
|
RUN 5 ms
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
NAME CharShift upper upper
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS CS_GH
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
EXPECT keyboard-report Key_LeftShift Key_G # report: { e1 10 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE CS_GH
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS LSHIFT
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS CS_GH
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift Key_H # report: { e1 11 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE CS_GH
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE LSHIFT
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
|
||||||
|
RUN 5 ms
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
NAME Rollover from normal to CharShift upper
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS x
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_X
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS CS_GH
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_X Key_LeftShift # report: { e1 }
|
||||||
|
EXPECT keyboard-report Key_X Key_LeftShift Key_G # report: { e1 10 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE x
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift Key_G # report: { e1 10 }
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE CS_GH
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
|
||||||
|
RUN 5 ms
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
NAME Rollover from shifted to CharShift lower
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS Y
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_LeftShift # report: { e1 }
|
||||||
|
EXPECT keyboard-report Key_LeftShift Key_Y
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
PRESS CS_ab
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_Y
|
||||||
|
EXPECT keyboard-report Key_Y Key_A
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE Y
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report Key_A
|
||||||
|
|
||||||
|
RUN 4 ms
|
||||||
|
RELEASE CS_ab
|
||||||
|
RUN 1 cycle
|
||||||
|
EXPECT keyboard-report empty
|
||||||
|
|
||||||
|
RUN 5 ms
|
Loading…
Reference in new issue