Skip to content

Commit 1ac7503

Browse files
Florian FleissnerFlorian Fleissner
authored andcommitted
This PR enables logically grouping keys and apply layer switch and toggle operation to selected key groups only. Examples are provide that demonstrate grouping keys by keyboard hand sides, via condition expressions and with keymap-style color arrays.
The basic idea that led to this PR was the question: How to switch one half of the keyboard to another layer while the other half should stay at the base layer. My intention was to switch via the thumb key of the Model01 one half of the keyboard to a modifier layer where all modifiers are supposed to reside on the home row. The other half of the keyboard should stay at the base layer. By means of that I intent to make typing modifier shortcuts with combined modifiers and keys more convenient. Of coures, this could already be done with the existing Kaleidoscope, e.g. by defining two individual additional layers whose keys for one half match those of the base layer and the other half the modifier layer. The redundancy is obvious. That's how the idea emerged to modity the layer class in a way that it stores not only one pair of `layer_state_` and `top_active_layer_` but several, each pair of those variables for a separate region of the keyboard. This makes it possible to make separate regions of the keyboard behave as individual keyboards in terms of their layer state. Lacking a better name, I called those keys assigned to such a region a "key group". Keys can be arbitrarily assigned to key groups. Layer switches/toggles can be defined to affect one or more key groups (see examples). By default only two key groups are defined. One for the left and one for the right hand side of the keyboard. * added header `src/Kaleidoscope-KeyGroups.h` * hardwares implement static constexpr bool isOnLeftHalf(uint8_t row, uint8_t col) convenience methods to test for the hand a key belongs to (one-handed keybords could just unconditionally return true) * added header `key_groups.h` * layers class tracks state of up to six key groups now * all public methods that affect the layer states now can be passed a key group flags to name the affected layers * method `extern uint8_t groupOfKey(uint8_t row, uint8_t col)` introduced that can be overridden from within the sketch * fixed Colormap plugin to work with multiple key groups * fixed plugin LED-ActiveLayerColor to work with multiple key groups * fixed plugin LED-ActiveModColor to work with multiple key groups * added TODO-comments in contexts (plugins EEPROM-KeymapOProgrmmer and NumPad) where layer-methods are used but no layer group information is available * added TODO-comments about the implementation of method `isOnLeftHalf` in some keyboards * examples were added to illustrate different use cases The PR will not break any user code or plugins. Only if keygroups are assigned to layer switch operations, the firmware behavior will differ from what it does currently. Changes will probably not noticeabley affect runtime performance. Stock firmware: Groth of program size from 25192 to 26992 bytes. Data usage grows from 1414 to 1459 bytes. Carefully check commit line changes containing TODOs and fix those. Especially concerning plugins EEPROM-KeymapOProgrmmer and NumPad. This PR comes with quite some changes and both program size and Data usage grow significantly. Nonetheless, this feature might be worth it. If Arduino eventually would introduce a global per-sketch configuration header (there's an ongoing discussion about this in the Arduino community) we could support several alternative implementations of the layer system, let the user select one and select a default one otherwise. As this is currently not possible, I chose to "upgrade" the existing layer class. Signed-off-by: Florian Fleissner <[email protected]>
1 parent 5acb979 commit 1ac7503

File tree

22 files changed

+613
-85
lines changed

22 files changed

+613
-85
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/* -*- mode: c++ -*-
2+
* Basic -- A very basic Kaleidoscope example
3+
* Copyright (C) 2018 Keyboard.io, Inc.
4+
*
5+
* This program is free software: you can redistribute it and/or modify it under
6+
* the terms of the GNU General Public License as published by the Free Software
7+
* Foundation, version 3.
8+
*
9+
* This program is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12+
* details.
13+
*
14+
* You should have received a copy of the GNU General Public License along with
15+
* this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include "Kaleidoscope.h"
19+
20+
#include "Kaleidoscope-LED-ActiveLayerColor.h"
21+
22+
// This example demonstrates how keys can be grouped by
23+
// a decision function that relies on a keymap layer kind of array
24+
// that stores the key group id of every individual key.
25+
//
26+
// Please note that the function groupOfKey(..) may only return values
27+
// in the range [0;5].
28+
29+
enum { AMap, BMap };
30+
31+
/* *INDENT-OFF* */
32+
KEYMAPS(
33+
[AMap] = KEYMAP_STACKED
34+
(
35+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
36+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
37+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
38+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
39+
40+
Key_A, Key_A, Key_A, Key_A,
41+
KeyGroup(KEY_GROUP_2, ShiftToLayer(BMap)),
42+
43+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
44+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
45+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
46+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
47+
48+
Key_A, Key_A, Key_A, Key_A,
49+
KeyGroup(KEY_GROUP_1, ShiftToLayer(BMap))
50+
),
51+
52+
[BMap] = KEYMAP_STACKED
53+
(
54+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
55+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
56+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
57+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
58+
59+
Key_B, Key_B, Key_B, Key_B,
60+
___,
61+
62+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
63+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
64+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
65+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
66+
67+
Key_B, Key_B, Key_B, Key_B,
68+
___
69+
)
70+
)
71+
/* *INDENT-ON* */
72+
73+
KALEIDOSCOPE_INIT_PLUGINS(
74+
LEDControl,
75+
LEDActiveLayerColorEffect
76+
)
77+
78+
KEY_GROUP_IDS_STACKED(
79+
0, 0, 0, 0, 0, 0, 0,
80+
1, 1, 1, 1, 1, 1, 1,
81+
1, 1, 1, 1, 1, 1,
82+
0, 0, 0, 0, 0, 0, 0,
83+
84+
0, 0, 0, 0,
85+
0,
86+
87+
0, 0, 0, 0, 0, 0, 0,
88+
2, 2, 2, 2, 2, 2, 2,
89+
2, 2, 2, 2, 2, 2,
90+
0, 0, 0, 0, 0, 0, 0,
91+
92+
0, 0, 0, 0,
93+
0
94+
)
95+
96+
uint8_t groupOfKey(uint8_t row, uint8_t col) {
97+
return GROUP_OF_KEY(row, col);
98+
}
99+
100+
void setup() {
101+
Kaleidoscope.setup();
102+
103+
static const cRGB layerColormap[] PROGMEM = {
104+
CRGB(128, 0, 0),
105+
CRGB(0, 128, 0)
106+
};
107+
108+
LEDActiveLayerColorEffect.setColormap(layerColormap);
109+
}
110+
111+
void loop() {
112+
Kaleidoscope.loop();
113+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/* -*- mode: c++ -*-
2+
* Basic -- A very basic Kaleidoscope example
3+
* Copyright (C) 2018 Keyboard.io, Inc.
4+
*
5+
* This program is free software: you can redistribute it and/or modify it under
6+
* the terms of the GNU General Public License as published by the Free Software
7+
* Foundation, version 3.
8+
*
9+
* This program is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12+
* details.
13+
*
14+
* You should have received a copy of the GNU General Public License along with
15+
* this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include "Kaleidoscope.h"
19+
20+
#include "Kaleidoscope-LED-ActiveLayerColor.h"
21+
22+
// This example demonstrates how keys can be grouped using conditionals
23+
// in a decision function.
24+
//
25+
// Please note that the function groupOfKey(...) may only return values
26+
// in the range [0;5].
27+
28+
enum { AMap, BMap };
29+
30+
/* *INDENT-OFF* */
31+
KEYMAPS(
32+
[AMap] = KEYMAP_STACKED
33+
(
34+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
35+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
36+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
37+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
38+
39+
Key_A, Key_A, Key_A, Key_A,
40+
KeyGroup(KEY_GROUP_1, ShiftToLayer(BMap)),
41+
42+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
43+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
44+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
45+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
46+
47+
Key_A, Key_A, Key_A, Key_A,
48+
KeyGroup(KEY_GROUP_0 | KEY_GROUP_2, ShiftToLayer(BMap))
49+
),
50+
51+
[BMap] = KEYMAP_STACKED
52+
(
53+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
54+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
55+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
56+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
57+
58+
Key_B, Key_B, Key_B, Key_B,
59+
___,
60+
61+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
62+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
63+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
64+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
65+
66+
Key_B, Key_B, Key_B, Key_B,
67+
___
68+
)
69+
)
70+
/* *INDENT-ON* */
71+
72+
KALEIDOSCOPE_INIT_PLUGINS(
73+
LEDControl,
74+
LEDActiveLayerColorEffect
75+
)
76+
77+
uint8_t groupOfKey(uint8_t row, uint8_t col) {
78+
return row;
79+
}
80+
81+
void setup() {
82+
Kaleidoscope.setup();
83+
84+
static const cRGB layerColormap[] PROGMEM = {
85+
CRGB(128, 0, 0),
86+
CRGB(0, 128, 0)
87+
};
88+
89+
LEDActiveLayerColorEffect.setColormap(layerColormap);
90+
}
91+
92+
void loop() {
93+
Kaleidoscope.loop();
94+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/* -*- mode: c++ -*-
2+
* Basic -- A very basic Kaleidoscope example
3+
* Copyright (C) 2018 Keyboard.io, Inc.
4+
*
5+
* This program is free software: you can redistribute it and/or modify it under
6+
* the terms of the GNU General Public License as published by the Free Software
7+
* Foundation, version 3.
8+
*
9+
* This program is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12+
* details.
13+
*
14+
* You should have received a copy of the GNU General Public License along with
15+
* this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include "Kaleidoscope.h"
19+
20+
#include "Kaleidoscope-LED-ActiveLayerColor.h"
21+
22+
// This example demonstrates the default key grouping mechanism
23+
// where the left hand is assigned to key group 0 (KEY_GROUP_LEFT_HAND),
24+
// the right hand to key group 1 (KEY_GROUP_RIGHT_HAND).
25+
26+
enum { AMap, BMap };
27+
28+
/* *INDENT-OFF* */
29+
KEYMAPS(
30+
[AMap] = KEYMAP_STACKED
31+
(
32+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
33+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
34+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
35+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
36+
37+
Key_A, Key_A, Key_A, Key_A,
38+
KeyGroup(KEY_GROUP_RIGHT_HAND, ShiftToLayer(BMap)),
39+
40+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
41+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
42+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
43+
Key_A, Key_A, Key_A, Key_A, Key_A, Key_A, Key_A,
44+
45+
Key_A, Key_A, Key_A, Key_A,
46+
KeyGroup(KEY_GROUP_LEFT_HAND, ShiftToLayer(BMap))
47+
),
48+
49+
[BMap] = KEYMAP_STACKED
50+
(
51+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
52+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
53+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
54+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
55+
56+
Key_B, Key_B, Key_B, Key_B,
57+
___,
58+
59+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
60+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
61+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
62+
Key_B, Key_B, Key_B, Key_B, Key_B, Key_B, Key_B,
63+
64+
Key_B, Key_B, Key_B, Key_B,
65+
___
66+
)
67+
)
68+
/* *INDENT-ON* */
69+
70+
KALEIDOSCOPE_INIT_PLUGINS(
71+
LEDControl,
72+
LEDActiveLayerColorEffect
73+
)
74+
75+
void setup() {
76+
Kaleidoscope.setup();
77+
78+
static const cRGB layerColormap[] PROGMEM = {
79+
CRGB(128, 0, 0),
80+
CRGB(0, 128, 0)
81+
};
82+
83+
LEDActiveLayerColorEffect.setColormap(layerColormap);
84+
}
85+
86+
void loop() {
87+
Kaleidoscope.loop();
88+
}

src/Kaleidoscope-KeyGroups.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/* -*- mode: c++ -*-
2+
* Kaleidoscope-Hardware-EZ-ErgoDox -- ErgoDox hardware support for Kaleidoscope
3+
* Copyright (C) 2018 Keyboard.io, Inc
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
#pragma once
20+
#include "kaleidoscope/key_groups.h"

src/kaleidoscope/Hardware.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,18 @@
5050
typedef struct cRGB cRGB;
5151

5252
namespace kaleidoscope {
53+
5354
/** Kaleidoscope Hardware base class.
5455
* Essential methods all hardware libraries must implement.
5556
*/
5657
class Hardware {
5758
public:
59+
60+
// This class method can be overridden by hardware implementations.
61+
constexpr static bool isOnLeftHalf(uint8_t /*row*/, uint8_t /*col*/) {
62+
return true;
63+
}
64+
5865
/**
5966
* @defgroup kaleidoscope_hardware_leds Kaleidoscope::Hardware/LEDs
6067
* @{

src/kaleidoscope/hardware/ez/ErgoDox.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ class ErgoDox : public kaleidoscope::Hardware {
5656
static constexpr byte matrix_rows = 14;
5757
static constexpr int8_t led_count = 0;
5858

59+
static constexpr bool isOnLeftHalf(uint8_t row, uint8_t /*col*/) {
60+
return row < 7;
61+
}
62+
5963
void scanMatrix(void);
6064
void readMatrix(void);
6165
void actOnMatrixScan(void);

src/kaleidoscope/hardware/kbdfans/KBD4x.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ class KBD4x: public kaleidoscope::hardware::ATMegaKeyboard {
4545

4646
static constexpr int8_t led_count = 0;
4747

48+
// TODO: Implement
49+
// static constexpr bool isOnLeftHalf(uint8_t row, uint8_t col);
50+
4851
void resetDevice();
4952
};
5053

src/kaleidoscope/hardware/keyboardio/Model01.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,6 @@ void Model01::rebootBootloader() {
255255
// halves, with eight keys per logical row.
256256

257257
constexpr byte HIGH_BIT = B10000000;
258-
constexpr byte HAND_BIT = B00001000;
259258
constexpr byte ROW_BITS = B00110000;
260259
constexpr byte COL_BITS = B00000111;
261260

src/kaleidoscope/hardware/keyboardio/Model01.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ namespace keyboardio {
3737

3838
class Model01 : public kaleidoscope::Hardware {
3939
public:
40+
41+
static constexpr byte HAND_BIT = B00001000;
42+
43+
static constexpr bool isOnLeftHalf(uint8_t /*row*/, uint8_t col) {
44+
// If HAND_BIT is set, we are on the right hand side
45+
return !(col & HAND_BIT);
46+
}
47+
4048
Model01(void);
4149

4250
static constexpr byte matrix_rows = 4;

src/kaleidoscope/hardware/olkb/Planck.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class Planck: public kaleidoscope::hardware::ATMegaKeyboard {
4040
COL_PIN_LIST({ PIN_F1, PIN_F0, PIN_B0, PIN_C7, PIN_F4, PIN_F5, PIN_F6, PIN_F7, PIN_D4, PIN_D6, PIN_B4, PIN_D7 })
4141
);
4242

43+
// TODO: Implement
44+
// static constexpr bool isOnLeftHalf(uint8_t row, uint8_t col);
45+
4346
static constexpr int8_t led_count = 0;
4447
};
4548

0 commit comments

Comments
 (0)