Kaleidoscope Style Guide conformance

...and an update to use the newest Ranges APIs.

Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
pull/389/head
Gergely Nagy 8 years ago
parent a6983c5c4d
commit 8be191fe9b

@ -5,9 +5,9 @@
[travis:image]: https://travis-ci.org/keyboardio/Kaleidoscope-TapDance.svg?branch=master [travis:image]: https://travis-ci.org/keyboardio/Kaleidoscope-TapDance.svg?branch=master
[travis:status]: https://travis-ci.org/keyboardio/Kaleidoscope-TapDance [travis:status]: https://travis-ci.org/keyboardio/Kaleidoscope-TapDance
[st:stable]: https://img.shields.io/badge/stable-✔-black.png?style=flat&colorA=44cc11&colorB=494e52 [st:stable]: https://img.shields.io/badge/stable-✔-black.svg?style=flat&colorA=44cc11&colorB=494e52
[st:broken]: https://img.shields.io/badge/broken-X-black.png?style=flat&colorA=e05d44&colorB=494e52 [st:broken]: https://img.shields.io/badge/broken-X-black.svg?style=flat&colorA=e05d44&colorB=494e52
[st:experimental]: https://img.shields.io/badge/experimental----black.png?style=flat&colorA=dfb317&colorB=494e52 [st:experimental]: https://img.shields.io/badge/experimental----black.svg?style=flat&colorA=dfb317&colorB=494e52
Tap-dance keys are general purpose, multi-use keys, which trigger a different Tap-dance keys are general purpose, multi-use keys, which trigger a different
action based on the number of times they were tapped in sequence. As an example action based on the number of times they were tapped in sequence. As an example
@ -44,21 +44,20 @@ This is to preserve the order of keys pressed.
In both of these cases, the [`tapDanceAction`][tdaction] will be called, with In both of these cases, the [`tapDanceAction`][tdaction] will be called, with
`tapDanceIndex` set to the index of the tap-dance action (as set in the keymap), `tapDanceIndex` set to the index of the tap-dance action (as set in the keymap),
the `tapCount`, and `tapDanceAction` set to either the `tapCount`, and `tapDanceAction` set to either
`KaleidoscopePlugins::TapDance::Interrupt`, or `kaleidoscope::TapDance::Interrupt`, or `kaleidoscope::TapDance::Timeout`. If we
`KaleidoscopePlugins::TapDance::Timeout`. If we continue holding the key, then continue holding the key, then as long as it is held, the same function will be
as long as it is held, the same function will be called with `tapDanceAction` called with `tapDanceAction` set to `kaleidoscope::TapDance::Hold`. When the key
set to `KaleidoscopePlugins::TapDance::Hold`. When the key is released, after is released, after either an `Interrupt` or `Timeout` action was triggered, the
either an `Interrupt` or `Timeout` action was triggered, the function will be function will be called with `tapDanceAction` set to
called with `tapDanceAction` set to `KaleidoscopePlugins::TapDance::Release`. `kaleidoscope::TapDance::Release`.
These actions allow us to create sophisticated tap-dance setups, where one can These actions allow us to create sophisticated tap-dance setups, where one can
tap a key twice and hold it, and have it repeat, for example. tap a key twice and hold it, and have it repeat, for example.
There is one additional value the `tapDanceAction` parameter can take: There is one additional value the `tapDanceAction` parameter can take:
`KaleidoscopePlugins::TapDance::Tap`. It is called with this argument for each `kaleidoscope::TapDance::Tap`. It is called with this argument for each and
and every tap, even if no action is to be triggered yet. This is so that we can every tap, even if no action is to be triggered yet. This is so that we can have
have a way to do some side-effects, like light up LEDs to show progress, and so a way to do some side-effects, like light up LEDs to show progress, and so on.
on.
## Using the plugin ## Using the plugin
@ -75,18 +74,19 @@ time an action is to be performed.
TD(0) TD(0)
// later in the Sketch: // later in the Sketch:
void tapDanceAction (uint8_t tapDanceIndex, uint8_t tapCount, void tapDanceAction(uint8_t tap_dance_index, uint8_t tap_count,
KaleidoscopePlugins::TapDance::ActionType tapDanceAction) { kaleidoscope::TapDance::ActionType tap_dance_action) {
switch (tapDanceIndex) { switch (tap_dance_index) {
case 0: case 0:
return tapDanceActionKeys (tapCount, tapDanceAction, return tapDanceActionKeys(tap_count, tap_dance_action,
Key_nextTrack, Key_prevTrack); Consumer_ScanNextTrack, Consumer_ScanPreviousTrack);
} }
} }
void setup (void) { void setup() {
Kaleidoscope.setup (KEYMAP_SIZE); USE_PLUGINS(&TapDance);
Kaleidoscope.use (&TapDance, NULL);
Kaleidoscope.setup ();
} }
``` ```
@ -98,8 +98,8 @@ void setup (void) {
> implementation for the `id` index within the [`tapDanceActions`][tdactions] > implementation for the `id` index within the [`tapDanceActions`][tdactions]
> function. > function.
> >
> The `id` parameter here is what will be used as `tapDanceIndex` in the handler > The `id` parameter here is what will be used as `tap_dance_index` in the
> function. > handler function.
[tdaction]: #tapdanceactiontapdanceindex-tapcount-tapdanceaction [tdaction]: #tapdanceactiontapdanceindex-tapcount-tapdanceaction
@ -109,17 +109,15 @@ The plugin provides a `TapDance` object, but to implement the actions, we need
to define a function ([`tapDanceAction`][tdaction]) outside of the object. A to define a function ([`tapDanceAction`][tdaction]) outside of the object. A
handler, of sorts. Nevertheless, the plugin provides one macro that is handler, of sorts. Nevertheless, the plugin provides one macro that is
particularly useful: `tapDanceActionKeys`. Apart from that, it provides one particularly useful: `tapDanceActionKeys`. Apart from that, it provides one
method only: property only:
### `.timeOut` ### `.time_out`
> The number of loop iterations to wait before a tap-dance sequence times out. > The number of loop iterations to wait before a tap-dance sequence times out.
> Once the sequence timed out, the action for it will trigger, even without an > Once the sequence timed out, the action for it will trigger, even without an
> interruptor. Defaults to 5, and the timer resets with every tap of the same > interruptor. Defaults to 5, and the timer resets with every tap of the same
> Not strictly a method, it is a variable one can assign a new value to. ### `tapDanceActionKeys(tap_count, tap_dance_action, keys...)`
### `tapDanceActionKeys(tapCount, tapDanceAction, keys...)`
> Sets up an action where for each subsequent tap, a different key will be > Sets up an action where for each subsequent tap, a different key will be
> chosen from the list of keys supplied in the `keys...` argument. > chosen from the list of keys supplied in the `keys...` argument.
@ -130,19 +128,19 @@ method only:
> When all our actions are just different keys, this is a very handy macro to > When all our actions are just different keys, this is a very handy macro to
> use. > use.
> >
> The `tapCount` and `tapDanceActions` parameters should be the same as the > The `tap_count` and `tap_dance_actions` parameters should be the same as the
> similarly named parameters of the `tapDanceAction` function. > similarly named parameters of the `tapDanceAction` function.
### `tapDanceAction(tapDanceIndex, row, col, tapCount, tapDanceAction)` ### `tapDanceAction(tap_dance_index, row, col, tap_count, tap_dance_action)`
> The heart of the tap-dance plugin is the handler method. This is called every > The heart of the tap-dance plugin is the handler method. This is called every
> time any kind of tap-dance action is to be performed. See the > time any kind of tap-dance action is to be performed. See the
> *[How does it work?](#how-does-it-work)* section for details about when and > *[How does it work?](#how-does-it-work)* section for details about when and
> how this function is called. > how this function is called.
> >
> The `tapDanceIndex` and `tapCount` parameters help us choose which action to > The `tap_dance_index` and `tap_count` parameters help us choose which action
> perform. The `row` and `col` parameters tell us where the tap-dance key is on > to perform. The `row` and `col` parameters tell us where the tap-dance key is
> the keyboard. > on the keyboard.
## Dependencies ## Dependencies

@ -36,26 +36,26 @@ const Key keymaps[][ROWS][COLS] PROGMEM = {
Key_skip, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus, Key_skip, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus,
Key_RightShift, Key_RightAlt, Key_Spacebar, Key_RightControl, Key_RightShift, Key_RightAlt, Key_Spacebar, Key_RightControl,
TD(1) TD(1)),
),
}; };
static void tapDanceEsc(uint8_t tapDanceIndex, uint8_t tapCount, KaleidoscopePlugins::TapDance::ActionType tapDanceAction) { static void tapDanceEsc(uint8_t tap_dance_index, uint8_t tap_count, kaleidoscope::TapDance::ActionType tap_dance_action) {
tapDanceActionKeys(tapCount, tapDanceAction, Key_Escape, Key_Tab); tap_dance_actionKeys(tap_count, tap_dance_action, Key_Escape, Key_Tab);
} }
void tapDanceAction(uint8_t tapDanceIndex, byte row, byte col, uint8_t tapCount, KaleidoscopePlugins::TapDance::ActionType tapDanceAction) { void tap_dance_action(uint8_t tap_dance_index, byte row, byte col, uint8_t tap_count, kaleidoscope::TapDance::ActionType tap_dance_action) {
switch (tapDanceIndex) { switch (tap_dance_index) {
case 0: case 0:
return tapDanceActionKeys(tapCount, tapDanceAction, Key_Tab, Key_Escape); return tap_dance_actionKeys(tap_count, tap_dance_action, Key_Tab, Key_Escape);
case 1: case 1:
return tapDanceEsc(tapDanceIndex, tapCount, tapDanceAction); return tapDanceEsc(tap_dance_index, tap_count, tap_dance_action);
} }
} }
void setup() { void setup() {
Kaleidoscope.setup(KEYMAP_SIZE); USE_PLUGINS(&TapDance);
Kaleidoscope.use(&TapDance, NULL);
Kaleidoscope.setup();
} }
void loop() { void loop() {

@ -18,76 +18,73 @@
#include <Kaleidoscope-TapDance.h> #include <Kaleidoscope-TapDance.h>
namespace KaleidoscopePlugins { namespace kaleidoscope {
// --- state --- // --- state ---
uint32_t TapDance::endTime; uint32_t TapDance::end_time_;
uint16_t TapDance::timeOut = 200; uint16_t TapDance::time_out = 200;
uint8_t TapDance::tapCount[16]; uint8_t TapDance::tap_count_[16];
uint16_t TapDance::pressedState; uint16_t TapDance::pressed_state_;
uint16_t TapDance::triggeredState; uint16_t TapDance::triggered_state_;
uint16_t TapDance::releaseNextState; uint16_t TapDance::release_next_state_;
Key TapDance::lastTapDanceKey; Key TapDance::last_tap_dance_key_;
byte TapDance::lastTapDanceRow; byte TapDance::last_tap_dance_row_;
byte TapDance::lastTapDanceCol; byte TapDance::last_tap_dance_col_;
// --- helpers --- // --- helpers ---
#define isTapDance(k) (k.raw >= Ranges::TD_FIRST && k.raw <= Ranges::TD_LAST) #define isTapDance(k) (k.raw >= ranges::TD_FIRST && k.raw <= ranges::TD_LAST)
#define isInSeq(k) (lastTapDanceKey.raw == k.raw) #define isInSeq(k) (last_tap_dance_key_.raw == k.raw)
#define stillHeld(idx) (tapCount[idx]) #define stillHeld(idx) (tap_count_[idx])
#define isActive() (lastTapDanceKey.raw != Key_NoKey.raw) #define isActive() (last_tap_dance_key_.raw != Key_NoKey.raw)
// --- actions --- // --- actions ---
void void TapDance::interrupt(void) {
TapDance::interrupt(void) { uint8_t idx = last_tap_dance_key_.raw - ranges::TD_FIRST;
uint8_t idx = lastTapDanceKey.raw - Ranges::TD_FIRST;
tapDanceAction(idx, lastTapDanceRow, lastTapDanceCol, tapCount[idx], Interrupt); tapDanceAction(idx, last_tap_dance_row_, last_tap_dance_col_, tap_count_[idx], Interrupt);
bitWrite(triggeredState, idx, 1); bitWrite(triggered_state_, idx, 1);
endTime = 0; end_time_ = 0;
if (bitRead(pressedState, idx)) if (bitRead(pressed_state_, idx))
return; return;
release(idx); release(idx);
} }
void void TapDance::timeout(void) {
TapDance::timeout(void) { uint8_t idx = last_tap_dance_key_.raw - ranges::TD_FIRST;
uint8_t idx = lastTapDanceKey.raw - Ranges::TD_FIRST;
tapDanceAction(idx, lastTapDanceRow, lastTapDanceCol, tapCount[idx], Timeout); tapDanceAction(idx, last_tap_dance_row_, last_tap_dance_col_, tap_count_[idx], Timeout);
bitWrite(triggeredState, idx, 1); bitWrite(triggered_state_, idx, 1);
if (bitRead(pressedState, idx)) if (bitRead(pressed_state_, idx))
return; return;
lastTapDanceKey.raw = Key_NoKey.raw; last_tap_dance_key_.raw = Key_NoKey.raw;
release(idx); release(idx);
} }
Key Key TapDance::release(uint8_t tap_dance_index) {
TapDance::release(uint8_t tapDanceIndex) { end_time_ = 0;
endTime = 0; last_tap_dance_key_.raw = Key_NoKey.raw;
lastTapDanceKey.raw = Key_NoKey.raw;
bitClear(pressedState, tapDanceIndex); bitClear(pressed_state_, tap_dance_index);
bitClear(triggeredState, tapDanceIndex); bitClear(triggered_state_, tap_dance_index);
bitWrite(releaseNextState, tapDanceIndex, 1); bitWrite(release_next_state_, tap_dance_index, 1);
return Key_NoKey; return Key_NoKey;
} }
Key Key TapDance::tap(void) {
TapDance::tap(void) { uint8_t idx = last_tap_dance_key_.raw - ranges::TD_FIRST;
uint8_t idx = lastTapDanceKey.raw - Ranges::TD_FIRST;
tapCount[idx]++; tap_count_[idx]++;
endTime = millis() + timeOut; end_time_ = millis() + time_out;
tapDanceAction(idx, lastTapDanceRow, lastTapDanceCol, tapCount[idx], Tap); tapDanceAction(idx, last_tap_dance_row_, last_tap_dance_col_, tap_count_[idx], Tap);
return Key_NoKey; return Key_NoKey;
} }
@ -95,86 +92,82 @@ TapDance::tap(void) {
// --- api --- // --- api ---
TapDance::TapDance(void) { TapDance::TapDance(void) {
lastTapDanceKey.raw = Key_NoKey.raw;
} }
void void TapDance::begin(void) {
TapDance::begin(void) { event_handler_hook_use(eventHandlerHook);
event_handler_hook_use(this->eventHandlerHook); loop_hook_use(loopHook);
loop_hook_use(this->loopHook);
} }
void void TapDance::actionKeys(uint8_t tap_count, ActionType tap_dance_action, uint8_t max_keys, const Key tap_keys[]) {
TapDance::actionKeys(uint8_t tapCount, ActionType tapDanceAction, uint8_t maxKeys, const Key tapKeys[]) { if (tap_count > max_keys)
if (tapCount > maxKeys) tap_count = max_keys;
tapCount = maxKeys;
Key key; Key key;
key.raw = pgm_read_word(&(tapKeys[tapCount - 1].raw)); key.raw = pgm_read_word(&(tap_keys[tap_count - 1].raw));
switch (tapDanceAction) { switch (tap_dance_action) {
case Tap: case Tap:
break; break;
case Interrupt: case Interrupt:
case Timeout: case Timeout:
handle_keyswitch_event(key, lastTapDanceRow, lastTapDanceCol, IS_PRESSED | INJECTED); handle_keyswitch_event(key, last_tap_dance_row_, last_tap_dance_col_, IS_PRESSED | INJECTED);
break; break;
case Hold: case Hold:
handle_keyswitch_event(key, lastTapDanceRow, lastTapDanceCol, IS_PRESSED | WAS_PRESSED | INJECTED); handle_keyswitch_event(key, last_tap_dance_row_, last_tap_dance_col_, IS_PRESSED | WAS_PRESSED | INJECTED);
break; break;
case Release: case Release:
Keyboard.sendReport(); Keyboard.sendReport();
handle_keyswitch_event(key, lastTapDanceRow, lastTapDanceCol, WAS_PRESSED | INJECTED); handle_keyswitch_event(key, last_tap_dance_row_, last_tap_dance_col_, WAS_PRESSED | INJECTED);
break; break;
} }
} }
// --- hooks --- // --- hooks ---
Key Key TapDance::eventHandlerHook(Key mapped_key, byte row, byte col, uint8_t key_state) {
TapDance::eventHandlerHook(Key mappedKey, byte row, byte col, uint8_t keyState) { if (key_state & INJECTED)
if (keyState & INJECTED) return mapped_key;
return mappedKey;
if (!key_is_pressed(keyState) && !key_was_pressed(keyState)) { if (!key_is_pressed(key_state) && !key_was_pressed(key_state)) {
if (isTapDance(mappedKey)) if (isTapDance(mapped_key))
return Key_NoKey; return Key_NoKey;
return mappedKey; return mapped_key;
} }
if (!isTapDance(mappedKey)) { if (!isTapDance(mapped_key)) {
if (!isActive()) if (!isActive())
return mappedKey; return mapped_key;
if (key_toggled_on(keyState)) if (key_toggled_on(key_state))
interrupt(); interrupt();
return mappedKey; return mapped_key;
} }
uint8_t tapDanceIndex = mappedKey.raw - Ranges::TD_FIRST; uint8_t tap_dance_index = mapped_key.raw - ranges::TD_FIRST;
if (key_toggled_off(keyState)) if (key_toggled_off(key_state))
bitClear(pressedState, tapDanceIndex); bitClear(pressed_state_, tap_dance_index);
if (!isInSeq(mappedKey)) { if (!isInSeq(mapped_key)) {
if (!isActive()) { if (!isActive()) {
if (bitRead(triggeredState, tapDanceIndex)) { if (bitRead(triggered_state_, tap_dance_index)) {
if (key_toggled_off(keyState)) if (key_toggled_off(key_state))
return release(tapDanceIndex); return release(tap_dance_index);
return Key_NoKey; return Key_NoKey;
} }
lastTapDanceKey.raw = mappedKey.raw; last_tap_dance_key_.raw = mapped_key.raw;
lastTapDanceRow = row; last_tap_dance_row_ = row;
lastTapDanceCol = col; last_tap_dance_col_ = col;
return tap(); return tap();
} else { } else {
if (key_toggled_off(keyState) && stillHeld(tapDanceIndex)) { if (key_toggled_off(key_state) && stillHeld(tap_dance_index)) {
return release(tapDanceIndex); return release(tap_dance_index);
} }
if (!key_toggled_on(keyState)) if (!key_toggled_on(key_state))
return Key_NoKey; return Key_NoKey;
interrupt(); interrupt();
@ -183,48 +176,48 @@ TapDance::eventHandlerHook(Key mappedKey, byte row, byte col, uint8_t keyState)
// in sequence // in sequence
if (key_toggled_off(keyState)) if (key_toggled_off(key_state))
return Key_NoKey; return Key_NoKey;
lastTapDanceKey.raw = mappedKey.raw; last_tap_dance_key_.raw = mapped_key.raw;
lastTapDanceRow = row; last_tap_dance_row_ = row;
lastTapDanceCol = col; last_tap_dance_col_ = col;
bitSet(pressedState, tapDanceIndex); bitSet(pressed_state_, tap_dance_index);
if (key_toggled_on(keyState)) if (key_toggled_on(key_state))
return tap(); return tap();
if (bitRead(triggeredState, tapDanceIndex)) if (bitRead(triggered_state_, tap_dance_index))
tapDanceAction(tapDanceIndex, row, col, tapCount[tapDanceIndex], Hold); tapDanceAction(tap_dance_index, row, col, tap_count_[tap_dance_index], Hold);
return Key_NoKey; return Key_NoKey;
} }
void void
TapDance::loopHook(bool postClear) { TapDance::loopHook(bool is_post_clear) {
if (!postClear) if (!is_post_clear)
return; return;
for (uint8_t i = 0; i < 16; i++) { for (uint8_t i = 0; i < 16; i++) {
if (!bitRead(releaseNextState, i)) if (!bitRead(release_next_state_, i))
continue; continue;
tapDanceAction(i, lastTapDanceRow, lastTapDanceCol, tapCount[i], Release); tapDanceAction(i, last_tap_dance_row_, last_tap_dance_col_, tap_count_[i], Release);
tapCount[i] = 0; tap_count_[i] = 0;
bitClear(releaseNextState, i); bitClear(release_next_state_, i);
} }
if (!isActive()) if (!isActive())
return; return;
if (endTime && millis() > endTime) if (end_time_ && millis() > end_time_)
timeout(); timeout();
} }
} // namespace KaleidoscopePlugins
__attribute__((weak))
void
tapDanceAction(uint8_t tapDanceIndex, byte row, byte col, uint8_t tapCount, KaleidoscopePlugins::TapDance::ActionType tapDanceAction) {
} }
KaleidoscopePlugins::TapDance TapDance; __attribute__((weak)) void tapDanceAction(uint8_t tap_dance_index, byte row, byte col, uint8_t tap_count,
kaleidoscope::TapDance::ActionType tap_dance_action) {
}
kaleidoscope::TapDance TapDance;

@ -21,15 +21,15 @@
#include <Kaleidoscope.h> #include <Kaleidoscope.h>
#include <Kaleidoscope-Ranges.h> #include <Kaleidoscope-Ranges.h>
#define TD(n) (Key){.raw = KaleidoscopePlugins::Ranges::TD_FIRST + n } #define TD(n) (Key) {.raw = kaleidoscope::ranges::TD_FIRST + n }
#define tapDanceActionKeys(tapCount, tapDanceAction, ...) ({ \ #define tap_dance_actionKeys(tap_count, tap_dance_action, ...) ({ \
static const Key __k[] PROGMEM = { __VA_ARGS__ }; \ static const Key __k[] PROGMEM = { __VA_ARGS__ }; \
TapDance.actionKeys (tapCount, tapDanceAction, \ TapDance.actionKeys(tap_count, tap_dance_action, \
sizeof (__k) / sizeof (Key), &__k[0]); \ sizeof (__k) / sizeof (Key), &__k[0]); \
}) })
namespace KaleidoscopePlugins { namespace kaleidoscope {
class TapDance : public KaleidoscopePlugin { class TapDance : public KaleidoscopePlugin {
public: public:
typedef enum { typedef enum {
@ -43,30 +43,32 @@ class TapDance : public KaleidoscopePlugin {
TapDance(void); TapDance(void);
void begin(void) final; void begin(void) final;
static uint16_t timeOut; static uint16_t time_out;
void actionKeys(uint8_t tapCount, ActionType tapDanceAction, uint8_t maxKeys, const Key tapKeys[]); void actionKeys(uint8_t tap_count, ActionType tap_dance_action, uint8_t max_keys, const Key tap_keys[]);
private: private:
static uint32_t endTime; static uint32_t end_time_;
static uint8_t tapCount[16]; static uint8_t tap_count_[16];
static uint16_t pressedState; static uint16_t pressed_state_;
static uint16_t triggeredState; static uint16_t triggered_state_;
static uint16_t releaseNextState; static uint16_t release_next_state_;
static Key lastTapDanceKey; static Key last_tap_dance_key_;
static byte lastTapDanceRow; static byte last_tap_dance_row_;
static byte lastTapDanceCol; static byte last_tap_dance_col_;
static Key eventHandlerHook(Key mappedKey, byte row, byte col, uint8_t keyState); static Key eventHandlerHook(Key mapped_key, byte row, byte col, uint8_t key_state);
static void loopHook(bool postClear); static void loopHook(bool is_post_clear);
static Key tap(void); static Key tap(void);
static void interrupt(void); static void interrupt(void);
static void timeout(void); static void timeout(void);
static Key release(uint8_t tapDanceIndex); static Key release(uint8_t tap_dance_index);
}; };
} // namespace KaleidoscopePlugins
void tapDanceAction(uint8_t tapDanceIndex, byte row, byte col, uint8_t tapCount, KaleidoscopePlugins::TapDance::ActionType tapDanceAction); }
extern KaleidoscopePlugins::TapDance TapDance; void tapDanceAction(uint8_t tap_dance_index, byte row, byte col, uint8_t tap_count,
kaleidoscope::TapDance::ActionType tap_dance_action);
extern kaleidoscope::TapDance TapDance;

Loading…
Cancel
Save