add tutorials and annotate sketches 3c 3d 3e
This commit is contained in:
parent
7773687287
commit
91df530ef2
@ -36,7 +36,7 @@ Example complex keybrd sketch
|
||||
-----------------------------
|
||||
keybrd_DH and its instantiation files contain about 800 lines of code.
|
||||
It emulates the DataHand keyboard.
|
||||
The layout has 52 keys, 4 layers, 6 sub-layers, 2 matrices, 8 LEDs, and blinking LEDs.
|
||||
Its layout has 52 keys, 3 primary layers, 5 sub-layers, 2 matrices, 8 LEDs, and blinking LEDs.
|
||||
|
||||
[keybrd_DH_library_developer_guide.md](https://github.com/wolfv6/keybrd_DH/blob/master/doc/keybrd_DH_library_developer_guide.md)<br>
|
||||
[mainSketch.ino](https://github.com/wolfv6/keybrd_DH/blob/master/examples/keybrd_DH/mainSketch.cpp)<br>
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <Arduino.h>
|
||||
#include <Code.h>
|
||||
|
||||
/* Class Code_Null doesn't do anything. It is usefull for blank codes.
|
||||
/* Class Code_Null doesn't do anything. It is useful for blank codes.
|
||||
*/
|
||||
class Code_Null: public Code
|
||||
{
|
||||
|
@ -176,4 +176,4 @@ Code_ScS s_greaterThan(KEY_PERIOD);
|
||||
Code_ScS s_question(KEY_SLASH);
|
||||
|
||||
// ********** MISC CODES *********
|
||||
Code_Null code_null; //usefull for blank keys
|
||||
Code_Null code_null; //useful for blank keys
|
||||
|
@ -6,13 +6,14 @@ This sketch:
|
||||
|
||||
| Layout | **0** | **1** |
|
||||
|:------:|-------|-------|
|
||||
| **0** | shift | a 1 |
|
||||
| **1** | fn | b 2 |
|
||||
| **0** | a - | b = |
|
||||
| **1** | fn | shift |
|
||||
|
||||
Each cell in the table's body represents a key.
|
||||
The layered keys in column 1 have two layers; one character for each layer.
|
||||
Letters 'a' and 'b' are on the normal layer. Numbers '1' and '2' are on the fn layer.
|
||||
Holding the fn key down makes it the active layer. Releasing the fn key restores the normal layer.
|
||||
The keys in column 1 have two characters each, one character for each layer.
|
||||
"fn" is a layer key. Holding the fn key down makes it the active layer.
|
||||
Releasing the fn key restores the normal layer.
|
||||
Letters 'a' and 'b' are on the normal layer. Symbols '-' and '=' are on the fn layer.
|
||||
*/
|
||||
// ################## GLOBAL ###################
|
||||
// ================= INCLUDES ==================
|
||||
@ -36,33 +37,33 @@ uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins);
|
||||
|
||||
Scanner_uC scanner(LOW, readPins, readPinCount);
|
||||
|
||||
/* =================== CODES ===================
|
||||
The CODES section instantiates six codes, one for each item in the layout.
|
||||
*/
|
||||
// =================== CODES ===================
|
||||
/* ---------------- LAYER CODE -----------------
|
||||
enum assigns layerId numbers to the layers.
|
||||
NORMAL=0 and FN=1. LayerState's default layerId is 0.
|
||||
*/
|
||||
enum layers { NORMAL, FN };
|
||||
|
||||
/* layerState keeps track of the active layer.
|
||||
/*
|
||||
layerState keeps track of the active layer.
|
||||
*/
|
||||
LayerState layerState;
|
||||
|
||||
/*
|
||||
NORMAL=0 and FN=1. LayerState's default layerId is 0.
|
||||
The Code_LayerHold constructor has two parameters:
|
||||
1) the layerId that will be active while the key is held down
|
||||
1) the layerId that will be the active layer while the key is held down
|
||||
2) a LayerState that will keep track of the active layer
|
||||
When l_fn is pressed, it tells layerState to change the active layer to 1.
|
||||
When l_fn is released, it tells layerState that layer 1 is released, and layerState restores the default layer.
|
||||
When l_fn is pressed, it tells layerState to change the active layer to FN.
|
||||
When l_fn is released, it tells layerState that layer FN is released,
|
||||
and layerState restores the active layer to NORMAL (sets active layer to the default layerId 0).
|
||||
*/
|
||||
Code_LayerHold l_fn(FN, layerState);
|
||||
|
||||
// ---------------- SCAN CODES -----------------
|
||||
Code_Sc s_a(KEY_A);
|
||||
Code_Sc s_b(KEY_B);
|
||||
Code_Sc s_1(KEY_1);
|
||||
Code_Sc s_2(KEY_2);
|
||||
Code_Sc s_minus(KEY_MINUS);
|
||||
Code_Sc s_equal(KEY_EQUAL);
|
||||
Code_Sc s_shift(MODIFIERKEY_LEFT_SHIFT);
|
||||
|
||||
/* =================== KEYS ====================
|
||||
@ -71,14 +72,14 @@ The Key_LayeredKeys constructor takes one array of Code pointers - one Code obje
|
||||
|
||||
The Key object names in this sketch start with a "k_" followed by row-column coordinates.
|
||||
*/
|
||||
Key* const ptrsCodes_01[] = { &s_a, &s_1 };
|
||||
Key* const ptrsCodes_00[] = { &s_a, &s_minus };
|
||||
Key_LayeredKeys k_00(ptrsCodes_00);
|
||||
|
||||
Key* const ptrsCodes_01[] = { &s_b, &s_equal };
|
||||
Key_LayeredKeys k_01(ptrsCodes_01);
|
||||
|
||||
Key* const ptrsCodes_11[] = { &s_b, &s_2 };
|
||||
Key_LayeredKeys k_11(ptrsCodes_11);
|
||||
|
||||
/* Key_LayeredKeys has a reference to layerState.
|
||||
Thus Key_LayeredKeys can call layerState to get the active layerId.
|
||||
/*
|
||||
Key_LayeredKeys has a reference to layerState.
|
||||
*/
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||
|
||||
@ -91,15 +92,17 @@ The Code object then sends its scancode over USB.
|
||||
/* =================== ROWS ====================
|
||||
Here we pack Key pointers into row objects.
|
||||
|
||||
Rows are composed of a Key-pointer array.
|
||||
Codes are a kind of Key that only have one layer.
|
||||
So rows can contain a mix of codes and multi-layered keys.
|
||||
Arrays ptrsKeys_0[] and ptrsKeys_1[] contain both Code pointers and Key pointers.
|
||||
Thus rows can contain a mix of codes and multi-layered keys (subtype polymorphism).
|
||||
In this example, Key-pointer arrays contain both Code pointers (&s_shift and &l_fn)
|
||||
and Key pointers (&k_01 and &k_11).
|
||||
*/
|
||||
Key* const ptrsKeys_0[] = { &s_shift, &k_01 };
|
||||
Key* const ptrsKeys_0[] = { &k_00, &k_01 };
|
||||
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0);
|
||||
Row row_0(scanner, 0, ptrsKeys_0, keyCount_0);
|
||||
|
||||
Key* const ptrsKeys_1[] = { &l_fn, &k_11 };
|
||||
Key* const ptrsKeys_1[] = { &l_fn, &s_shift };
|
||||
uint8_t keyCount_1 = sizeof(ptrsKeys_1)/sizeof(*ptrsKeys_1);
|
||||
Row row_1(scanner, 1, ptrsKeys_1, keyCount_1);
|
||||
|
||||
|
@ -6,29 +6,21 @@ This sketch:
|
||||
|
||||
| Layout | **0** | **1** |
|
||||
|:------:|:-----:|:-----:|
|
||||
| **0** | a [ | b ] |
|
||||
| **1** |normal | sym |
|
||||
| **0** | a - | b = |
|
||||
| **1** |Normal | Sym |
|
||||
|
||||
normal layer keys are a b c
|
||||
sym layer keys are brackets [ ] and num
|
||||
num layer keys are 6 7
|
||||
The num layer key is located on the sym layer
|
||||
num layer is active while holding sym+num
|
||||
Pressing the "Normal" layer key locks the Normal layer.
|
||||
Letters 'a' 'b' are on the Normal layer.
|
||||
|
||||
Each cell in the table's body represents a key.
|
||||
The layered keys in column 1 have two layers; one character for each layer.
|
||||
Letters 'a' and 'b' are on the normal layer. Numbers '1' and '2' are on the fn layer.
|
||||
Holding the fn key down makes it the active layer. Releasing the fn key restores the normal layer.
|
||||
Pressing the "Sym" layer key locks the Sym layer.
|
||||
Symbols '-' '=' are on the Sym layer.
|
||||
*/
|
||||
// ################## GLOBAL ###################
|
||||
// ================= INCLUDES ==================
|
||||
//Keys
|
||||
#include <Code_Sc.h>
|
||||
//#include <Code_ScS.h>
|
||||
//#include <Code_Null.h>
|
||||
#include <LayerState.h>
|
||||
#include <Code_LayerLock.h>
|
||||
#include <Code_LayerHold.h>
|
||||
#include <Key_LayeredKeys.h>
|
||||
|
||||
//Matrix
|
||||
@ -45,25 +37,18 @@ uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins);
|
||||
|
||||
Scanner_uC scanner(LOW, readPins, readPinCount);
|
||||
|
||||
/* =================== CODES ===================
|
||||
The CODES section instantiates six codes, one for each item in the layout.
|
||||
*/
|
||||
/* ---------------- LAYER CODE -----------------
|
||||
enum assigns layerId numbers to the layers.
|
||||
*/
|
||||
// =================== CODES ===================
|
||||
// ---------------- LAYER CODE -----------------
|
||||
enum layers { NORMAL, SYM };
|
||||
|
||||
/* layerState keeps track of the active layer.
|
||||
*/
|
||||
LayerState layerState;
|
||||
|
||||
/*
|
||||
NORMAL=0 and FN=1. LayerState's default layerId is 0.
|
||||
The Code_LayerHold constructor has two parameters:
|
||||
1) the layerId that will be active while the key is held down
|
||||
The Code_LayerLock constructor has two parameters:
|
||||
1) the layerId that becomes the active layer when the key is pressed
|
||||
2) a LayerState that will keep track of the active layer
|
||||
When l_fn is pressed, it tells layerState to change the active layer to 1.
|
||||
When l_fn is released, it tells layerState that layer 1 is released, and layerState restores the default layer.
|
||||
When l_normal is pressed, NORMAL becomes the active layer.
|
||||
When l_sym is pressed, SYM becomes the active layer.
|
||||
*/
|
||||
Code_LayerLock l_normal(NORMAL, layerState);
|
||||
Code_LayerLock l_sym(SYM, layerState);
|
||||
@ -71,42 +56,19 @@ Code_LayerLock l_sym(SYM, layerState);
|
||||
// ---------------- SCAN CODES -----------------
|
||||
Code_Sc s_a(KEY_A);
|
||||
Code_Sc s_b(KEY_B);
|
||||
Code_Sc s_minus(KEY_MINUS);
|
||||
Code_Sc s_equal(KEY_EQUAL);
|
||||
|
||||
Code_Sc s_leftBracket(KEY_LEFT_BRACE); //[ ("brace" means curly bracket {})
|
||||
Code_Sc s_rightBracket(KEY_RIGHT_BRACE); //]
|
||||
|
||||
//Code_Null code_null;
|
||||
|
||||
/* =================== KEYS ====================
|
||||
Here we pack Codes into keys.
|
||||
The Key_LayeredKeys constructor takes one array of Code pointers - one Code object per layer.
|
||||
|
||||
The Key object names in this sketch start with a "k_" followed by row-column coordinates.
|
||||
*/
|
||||
Key* const ptrsCodes_00[] = { &s_a, &s_leftBracket };
|
||||
// =================== KEYS ====================
|
||||
Key* const ptrsCodes_00[] = { &s_a, &s_minus };
|
||||
Key_LayeredKeys k_00(ptrsCodes_00);
|
||||
|
||||
Key* const ptrsCodes_01[] = { &s_b, &s_rightBracket };
|
||||
Key* const ptrsCodes_01[] = { &s_b, &s_equal };
|
||||
Key_LayeredKeys k_01(ptrsCodes_01);
|
||||
|
||||
/* Key_LayeredKeys has a reference to layerState.
|
||||
Thus Key_LayeredKeys can call layerState to get the active layerId.
|
||||
*/
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||
|
||||
/* HOW LAYERED OBJECTS WORK
|
||||
When a Key_LayeredKeys object is pressed, it gets the active layer id from layerState.
|
||||
It then uses the layer id as an array index to call the Code of the active layer.
|
||||
The Code object then sends its scancode over USB.
|
||||
*/
|
||||
|
||||
/* =================== ROWS ====================
|
||||
Here we pack Key pointers into row objects.
|
||||
|
||||
Codes are a kind of Key that only have one layer.
|
||||
So rows can contain a mix of codes and multi-layered keys.
|
||||
Arrays ptrsKeys_0[] and ptrsKeys_1[] contain both Code pointers and Key pointers.
|
||||
*/
|
||||
// =================== ROWS ====================
|
||||
Key* const ptrsKeys_0[] = { &k_00, &k_01 };
|
||||
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0);
|
||||
Row row_0(scanner, 0, ptrsKeys_0, keyCount_0);
|
||||
|
@ -1,24 +1,14 @@
|
||||
/* keybrd_3c_sublayerNull.ino
|
||||
|
||||
This sketch:
|
||||
is firmware for a simple 2-layer keyboard
|
||||
runs on the first two rows and columns of a breadboard keyboard
|
||||
is firmware for layout with 2 layers plus 1 sublayer.
|
||||
runs on the first three columns of a breadboard keyboard
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
|:------:|:-----:|:-----:|:-----:|
|
||||
| **0** | a - 1 | b = | c Num |
|
||||
| **1** |Normal | Sym | Enter |
|
||||
|
||||
normal layer keys are a b c
|
||||
sym layer keys are brackets [ ] and num
|
||||
num layer keys are 6 7
|
||||
The num layer key is located on the sym layer
|
||||
num layer is active while holding sym+num
|
||||
|
||||
Each cell in the table's body represents a key.
|
||||
The layered keys in column 1 have two layers; one character for each layer.
|
||||
Letters 'a' and 'b' are on the normal layer. Numbers '1' and '2' are on the fn layer.
|
||||
Holding the fn key down makes it the active layer. Releasing the fn key restores the normal layer.
|
||||
*/
|
||||
// ################## GLOBAL ###################
|
||||
// ================= INCLUDES ==================
|
||||
@ -44,30 +34,20 @@ uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins);
|
||||
|
||||
Scanner_uC scanner(LOW, readPins, readPinCount);
|
||||
|
||||
/* =================== CODES ===================
|
||||
The CODES section instantiates six codes, one for each item in the layout.
|
||||
*/
|
||||
// =================== CODES ===================
|
||||
/* ---------------- LAYER CODE -----------------
|
||||
enum assigns layerId numbers to the layers.
|
||||
One LayerState object manages all 3 layers.
|
||||
*/
|
||||
enum layers { NORMAL, SYM, NUM };
|
||||
|
||||
/* layerState keeps track of the active layer.
|
||||
*/
|
||||
LayerState layerState;
|
||||
|
||||
/*
|
||||
NORMAL=0 and FN=1. LayerState's default layerId is 0.
|
||||
The Code_LayerHold constructor has two parameters:
|
||||
1) the layerId that will be active while the key is held down
|
||||
2) a LayerState that will keep track of the active layer
|
||||
When l_fn is pressed, it tells layerState to change the active layer to 1.
|
||||
When l_fn is released, it tells layerState that layer 1 is released, and layerState restores the default layer.
|
||||
*/
|
||||
Code_LayerLock l_normal(NORMAL, layerState);
|
||||
Code_LayerLock l_sym(SYM, layerState);
|
||||
Code_LayerHold l_num(NUM, layerState);
|
||||
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||
|
||||
// ---------------- SCAN CODES -----------------
|
||||
Code_Sc s_a(KEY_A);
|
||||
Code_Sc s_b(KEY_B);
|
||||
@ -81,38 +61,31 @@ Code_Sc s_1(KEY_1);
|
||||
Code_Null code_null;
|
||||
|
||||
/* =================== KEYS ====================
|
||||
Here we pack Codes into keys.
|
||||
The Key_LayeredKeys constructor takes one array of Code pointers - one Code object per layer.
|
||||
When a Key_LayeredKeys is pressed, layerState returns the active layerId,
|
||||
which could be any of the layerIds in l_normal, l_sym, l_num.
|
||||
|
||||
The Key object names in this sketch start with a "k_" followed by row-column coordinates.
|
||||
The layout has one key with 3 layers, and two keys with 2 layers.
|
||||
But the layer scheme has 3 layers for all three keys.
|
||||
The extra layers are filled with duplicate codes and null codes.
|
||||
*/
|
||||
Key* const ptrsCodes_00[] = { &s_a, &s_minus, &s_1 };
|
||||
Key_LayeredKeys k_00(ptrsCodes_00);
|
||||
|
||||
/*
|
||||
s_equal is duplicated in layer 2.
|
||||
*/
|
||||
Key* const ptrsCodes_01[] = { &s_b, &s_equal, &s_equal };
|
||||
Key_LayeredKeys k_01(ptrsCodes_01);
|
||||
|
||||
/*
|
||||
code_null occupies layer 2. Class Code_Null doesn't do anything. It is useful for blank codes.
|
||||
Remember to fill all layers with codes.
|
||||
If the code_null were omitted from the array, dereferencing ptrsCodes_02[2] could cause a crash.
|
||||
*/
|
||||
Key* const ptrsCodes_02[] = { &s_c, &l_num, &code_null };
|
||||
Key_LayeredKeys k_02(ptrsCodes_02);
|
||||
|
||||
/* Key_LayeredKeys has a reference to layerState.
|
||||
Thus Key_LayeredKeys can call layerState to get the active layerId.
|
||||
*/
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||
|
||||
/* HOW LAYERED OBJECTS WORK
|
||||
When a Key_LayeredKeys object is pressed, it gets the active layer id from layerState.
|
||||
It then uses the layer id as an array index to call the Code of the active layer.
|
||||
The Code object then sends its scancode over USB.
|
||||
*/
|
||||
|
||||
/* =================== ROWS ====================
|
||||
Here we pack Key pointers into row objects.
|
||||
|
||||
Codes are a kind of Key that only have one layer.
|
||||
So rows can contain a mix of codes and multi-layered keys.
|
||||
Arrays ptrsKeys_0[] and ptrsKeys_1[] contain both Code pointers and Key pointers.
|
||||
*/
|
||||
// =================== ROWS ====================
|
||||
Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02 };
|
||||
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0);
|
||||
Row row_0(scanner, 0, ptrsKeys_0, keyCount_0);
|
||||
|
@ -1,30 +1,19 @@
|
||||
/* keybrd_3d_sublayerNested.ino
|
||||
|
||||
This sketch:
|
||||
is firmware for a simple 2-layer keyboard
|
||||
runs on the first two rows and columns of a breadboard keyboard
|
||||
is firmware for layout with 2 layers plus 1 sublayer.
|
||||
runs on the first three columns of a breadboard keyboard
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
|:------:|:-----:|:-----:|:-----:|
|
||||
| **0** | a - 1 | b = | c Num |
|
||||
| **1** |Normal | Sym | Enter |
|
||||
|
||||
normal layer keys are a b c
|
||||
sym layer keys are brackets [ ] and num
|
||||
num layer keys are 6 7
|
||||
The num layer key is located on the sym layer
|
||||
num layer is active while holding sym+num
|
||||
|
||||
Each cell in the table's body represents a key.
|
||||
The layered keys in column 1 have two layers; one character for each layer.
|
||||
Letters 'a' and 'b' are on the normal layer. Numbers '1' and '2' are on the fn layer.
|
||||
Holding the fn key down makes it the active layer. Releasing the fn key restores the normal layer.
|
||||
*/
|
||||
// ################## GLOBAL ###################
|
||||
// ================= INCLUDES ==================
|
||||
//Keys
|
||||
#include <Code_Sc.h>
|
||||
#include <Code_Null.h>
|
||||
#include <LayerState.h>
|
||||
#include <Code_LayerLock.h>
|
||||
#include <Code_LayerHold.h>
|
||||
@ -45,37 +34,35 @@ uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins);
|
||||
|
||||
Scanner_uC scanner(LOW, readPins, readPinCount);
|
||||
|
||||
/* =================== CODES ===================
|
||||
The CODES section instantiates six codes, one for each item in the layout.
|
||||
*/
|
||||
/* ---------------- LAYER CODE -----------------
|
||||
enum assigns layerId numbers to the layers.
|
||||
*/
|
||||
// =================== CODES ===================
|
||||
// ----------------- LAYER CODE ----------------
|
||||
enum layers { NORMAL, SYM };
|
||||
|
||||
/* layerState keeps track of the active layer.
|
||||
*/
|
||||
LayerState layerState;
|
||||
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||
/*
|
||||
NORMAL=0 and FN=1. LayerState's default layerId is 0.
|
||||
The Code_LayerHold constructor has two parameters:
|
||||
1) the layerId that will be active while the key is held down
|
||||
2) a LayerState that will keep track of the active layer
|
||||
When l_fn is pressed, it tells layerState to change the active layer to 1.
|
||||
When l_fn is released, it tells layerState that layer 1 is released, and layerState restores the default layer.
|
||||
*/
|
||||
Code_LayerLock l_normal(NORMAL, layerState);
|
||||
Code_LayerLock l_sym(SYM, layerState);
|
||||
|
||||
//sublayer
|
||||
/*
|
||||
Key_LayeredKeys are associated with layerState.
|
||||
*/
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||
|
||||
/* ---------------- SUBLAYER CODE --------------
|
||||
Sublayers are implemented just like main layers.
|
||||
Here the Num sublayer is given it's own proper LayerState.
|
||||
*/
|
||||
enum subLayers { SUBSYM, SUBNUM };
|
||||
|
||||
LayerState sublayerState;
|
||||
|
||||
Code_LayerHold l_num(SUBNUM, sublayerState);
|
||||
|
||||
/*
|
||||
Key_LayeredKeys1 are associated with sublayerState.
|
||||
Key_LayeredKeys (in layer) and Key_LayeredKeys1 (in sublayer) classes are nearly identical,
|
||||
only the static refLayerState are different.
|
||||
*/
|
||||
LayerStateInterface& Key_LayeredKeys1::refLayerState = sublayerState;
|
||||
|
||||
// ---------------- SCAN CODES -----------------
|
||||
@ -88,18 +75,20 @@ Code_Sc s_equal(KEY_EQUAL);
|
||||
Code_Sc s_enter(KEY_ENTER);
|
||||
|
||||
Code_Sc s_1(KEY_1);
|
||||
Code_Null code_null;
|
||||
|
||||
/* =================== KEYS ====================
|
||||
Here we pack Codes into keys.
|
||||
The Key_LayeredKeys constructor takes one array of Code pointers - one Code object per layer.
|
||||
|
||||
The Key object names in this sketch start with a "k_" followed by row-column coordinates.
|
||||
The key k_sub00 contains codes for layerIds SUBSYM and SUBNUM.
|
||||
(The Num sublayer only has one key because small example. Usually sublayers have multiple keys.)
|
||||
*/
|
||||
|
||||
Key* const ptrsCodes_sub00[] = { &s_minus, &s_1 };
|
||||
Key_LayeredKeys1 k_sub00(ptrsCodes_sub00);
|
||||
|
||||
/*
|
||||
k_sub00 is nested in k_00.
|
||||
The key k_00 contains code and key for layerIds NORMAL and SYS.
|
||||
Notice that k_sub00 is of type Key_LayeredKeys1, while k_00 is of type Key_LayeredKeys.
|
||||
k_sub00 and k_00 are associated with distinct LayerStates.
|
||||
*/
|
||||
Key* const ptrsCodes_00[] = { &s_a, &k_sub00 };
|
||||
Key_LayeredKeys k_00(ptrsCodes_00);
|
||||
|
||||
@ -109,19 +98,7 @@ Key_LayeredKeys k_01(ptrsCodes_01);
|
||||
Key* const ptrsCodes_02[] = { &s_c, &l_num };
|
||||
Key_LayeredKeys k_02(ptrsCodes_02);
|
||||
|
||||
/* HOW LAYERED OBJECTS WORK
|
||||
When a Key_LayeredKeys object is pressed, it gets the active layer id from layerState.
|
||||
It then uses the layer id as an array index to call the Code of the active layer.
|
||||
The Code object then sends its scancode over USB.
|
||||
*/
|
||||
|
||||
/* =================== ROWS ====================
|
||||
Here we pack Key pointers into row objects.
|
||||
|
||||
Codes are a kind of Key that only have one layer.
|
||||
So rows can contain a mix of codes and multi-layered keys.
|
||||
Arrays ptrsKeys_0[] and ptrsKeys_1[] contain both Code pointers and Key pointers.
|
||||
*/
|
||||
// =================== ROWS ====================
|
||||
Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02 };
|
||||
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0);
|
||||
Row row_0(scanner, 0, ptrsKeys_0, keyCount_0);
|
||||
|
@ -1,30 +1,19 @@
|
||||
/* keybrd_3d_sublayerNestedScSc.ino
|
||||
/* keybrd_3e_sublayerNestedScSc.ino
|
||||
|
||||
This sketch:
|
||||
is firmware for a simple 2-layer keyboard
|
||||
runs on the first two rows and columns of a breadboard keyboard
|
||||
is firmware for layout 2 layers plus 1 sublayer.
|
||||
runs on the first three columns of a breadboard keyboard
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
|:------:|:-----:|:-----:|:-----:|
|
||||
| **0** | a - 1 | b = | c Num |
|
||||
| **1** |Normal | Sym | Enter |
|
||||
|
||||
normal layer keys are a b c
|
||||
sym layer keys are brackets [ ] and num
|
||||
num layer keys are 6 7
|
||||
The num layer key is located on the sym layer
|
||||
num layer is active while holding sym+num
|
||||
|
||||
Each cell in the table's body represents a key.
|
||||
The layered keys in column 1 have two layers; one character for each layer.
|
||||
Letters 'a' and 'b' are on the normal layer. Numbers '1' and '2' are on the fn layer.
|
||||
Holding the fn key down makes it the active layer. Releasing the fn key restores the normal layer.
|
||||
*/
|
||||
// ################## GLOBAL ###################
|
||||
// ================= INCLUDES ==================
|
||||
//Keys
|
||||
#include <Code_Sc.h>
|
||||
#include <Code_Null.h>
|
||||
#include <LayerState.h>
|
||||
#include <Code_LayerLock.h>
|
||||
#include <Code_LayerHold.h>
|
||||
@ -45,31 +34,18 @@ uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins);
|
||||
|
||||
Scanner_uC scanner(LOW, readPins, readPinCount);
|
||||
|
||||
/* =================== CODES ===================
|
||||
The CODES section instantiates six codes, one for each item in the layout.
|
||||
*/
|
||||
/* ---------------- LAYER CODE -----------------
|
||||
enum assigns layerId numbers to the layers.
|
||||
*/
|
||||
// =================== CODES ===================
|
||||
// ---------------- LAYER CODE -----------------
|
||||
enum layers { NORMAL, SYM };
|
||||
|
||||
/* layerState keeps track of the active layer.
|
||||
*/
|
||||
LayerState layerState;
|
||||
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||
/*
|
||||
NORMAL=0 and FN=1. LayerState's default layerId is 0.
|
||||
The Code_LayerHold constructor has two parameters:
|
||||
1) the layerId that will be active while the key is held down
|
||||
2) a LayerState that will keep track of the active layer
|
||||
When l_fn is pressed, it tells layerState to change the active layer to 1.
|
||||
When l_fn is released, it tells layerState that layer 1 is released, and layerState restores the default layer.
|
||||
*/
|
||||
Code_LayerLock l_normal(NORMAL, layerState);
|
||||
Code_LayerLock l_sym(SYM, layerState);
|
||||
|
||||
//sublayer
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||
|
||||
// ---------------- SUBLAYER CODE --------------
|
||||
enum subLayers { SUBSYM, SUBNUM };
|
||||
|
||||
LayerState sublayerState;
|
||||
@ -88,16 +64,20 @@ Code_Sc s_equal(KEY_EQUAL);
|
||||
Code_Sc s_enter(KEY_ENTER);
|
||||
|
||||
Code_Sc s_1(KEY_1);
|
||||
Code_Null code_null;
|
||||
|
||||
/* =================== KEYS ====================
|
||||
Here we pack Codes into keys.
|
||||
The Key_LayeredKeys constructor takes one array of Code pointers - one Code object per layer.
|
||||
|
||||
The Key object names in this sketch start with a "k_" followed by row-column coordinates.
|
||||
The key k_sub00 contains codes for layerIds SUBSYM and SUBNUM.
|
||||
Key_LayeredScSc takes two scancode arguments.
|
||||
(The Num sublayer only has one key because small example. Usually sublayers have multiple keys.)
|
||||
*/
|
||||
|
||||
Key_LayeredScSc sub_00(KEY_MINUS, KEY_1);
|
||||
|
||||
/*
|
||||
k_sub00 is nested in k_00.
|
||||
The key k_00 contains code and key for layerIds NORMAL and SYS.
|
||||
Notice that k_sub00 is of type Key_LayeredKeys1, while k_00 is of type Key_LayeredKeys.
|
||||
k_sub00 and k_00 are associated with distinct LayerStates.
|
||||
*/
|
||||
Key* const ptrsCodes_00[] = { &s_a, &sub_00 };
|
||||
Key_LayeredKeys k_00(ptrsCodes_00);
|
||||
|
||||
@ -107,19 +87,7 @@ Key_LayeredKeys k_01(ptrsCodes_01);
|
||||
Key* const ptrsCodes_02[] = { &s_c, &l_num };
|
||||
Key_LayeredKeys k_02(ptrsCodes_02);
|
||||
|
||||
/* HOW LAYERED OBJECTS WORK
|
||||
When a Key_LayeredKeys object is pressed, it gets the active layer id from layerState.
|
||||
It then uses the layer id as an array index to call the Code of the active layer.
|
||||
The Code object then sends its scancode over USB.
|
||||
*/
|
||||
|
||||
/* =================== ROWS ====================
|
||||
Here we pack Key pointers into row objects.
|
||||
|
||||
Codes are a kind of Key that only have one layer.
|
||||
So rows can contain a mix of codes and multi-layered keys.
|
||||
Arrays ptrsKeys_0[] and ptrsKeys_1[] contain both Code pointers and Key pointers.
|
||||
*/
|
||||
// =================== ROWS ====================
|
||||
Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02 };
|
||||
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0);
|
||||
Row row_0(scanner, 0, ptrsKeys_0, keyCount_0);
|
||||
|
@ -13,11 +13,27 @@ Multi-layer nomenclature
|
||||
|
||||
**active layer** - is the layer currently used by the keyboard.
|
||||
|
||||
**default layer** - is the active layer when the keyboard starts up (in class LayerState, default layerId=0).
|
||||
|
||||
**layer scheme** - is a system for changing the active layer while typing (a single-layer scheme does not change layers).
|
||||
|
||||
Code classes
|
||||
------------
|
||||
Code objects only have one scancode or code.
|
||||
Example single-layer Code classes include:
|
||||
* Code_Sc (used in keybrd_2_single-layer.ino)
|
||||
* Code_ScS
|
||||
* Code_ScNS
|
||||
* Code_Shift
|
||||
* Code_LayerHold
|
||||
* Code_LayerLock
|
||||
|
||||
Single-layer keybrd sketches have one Code object per key.
|
||||
Multi-layer keybrd sketches have multiple Code objects per key, one code for each layer.
|
||||
|
||||
A simple multi-layer keybrd sketch
|
||||
----------------------------------
|
||||
The [keybrd_3a_multi-layer.ino](keybrd_3a_multi-layer/keybrd_3a_multi-layer.ino) sketch is for a simple two-layer keyboard.
|
||||
The [keybrd_3a_multi-layerHold.ino](keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino) sketch is for a simple two-layer keyboard.
|
||||
It will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md).
|
||||
|
||||
![basic breadboard keyboard](keybrd_1_breadboard/breadboard_keyboard_2x2.JPG "basic breadboard keyboard")
|
||||
@ -107,28 +123,10 @@ Key_Layered classes include:
|
||||
* Key_LayeredScSc
|
||||
* Key_LayeredCodeSc
|
||||
|
||||
The basic LayerState provided by the keybrd library is sufficient for implementing ordinary layer schemes.
|
||||
For experimental layer schemes, you would need to create a custom LayerState class, and possibly custom Code_Layer and Key_Layered classes as well.
|
||||
|
||||
Single-layer Codes
|
||||
------------------
|
||||
Most Code objects only have one scancode or code.
|
||||
Example single-layer Code classes include:
|
||||
* Code_Sc
|
||||
* Code_ScS
|
||||
* Code_ScNS
|
||||
* Code_Shift
|
||||
* Code_LayerHold
|
||||
* Code_LayerLock
|
||||
|
||||
Exercises
|
||||
---------
|
||||
1) Modify the keybrd_3a_multi-layer.ino sketch to use two Code_LayerLock objects.
|
||||
|
||||
| Layout | **0** | **1** |
|
||||
|:------:|:------:|:------:|
|
||||
| **0** | a 1 | b 2 |
|
||||
| **1** | layer0 | layer1 |
|
||||
Compile and run keybrd_3a_multi-layerHold.ino and keybrd_3b_multi-layerLock.ino
|
||||
Notice how Code_LayerHold and Code_LayerLock objects behave.
|
||||
|
||||
<br>
|
||||
<a rel="license" href="https://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">keybrd tutorial</span> by <a xmlns:cc="https://creativecommons.org/ns" href="https://github.com/wolfv6/keybrd" property="cc:attributionName" rel="cc:attributionURL">Wolfram Volpi</a> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.<br />Permissions beyond the scope of this license may be available at <a xmlns:cc="https://creativecommons.org/ns" href="https://github.com/wolfv6/keybrd/issues/new" rel="cc:morePermissions">https://github.com/wolfv6/keybrd/issues/new</a>.
|
126
tutorials/tutorial_3cde_sublayer_keyboard.md
Normal file
126
tutorials/tutorial_3cde_sublayer_keyboard.md
Normal file
@ -0,0 +1,126 @@
|
||||
Tutorial 3cde - sublayer keyboard
|
||||
=================================
|
||||
This tutorial assumes the reader understands the previous tutorial.
|
||||
|
||||
When you finish this tutorial you will be able to be able to modify a multi-layer keybrd sketch to write your very own multi-layer keyboard firmware.
|
||||
|
||||
Sublayer nomenclature
|
||||
---------------------
|
||||
**primary layer** - is a layer whose layer key is accessible from the default layer.
|
||||
|
||||
**sublayer** - is a layer whose layer key is not accessible from the default layer.
|
||||
|
||||
**layer group** - is a group of layers that occupy the same keys.
|
||||
|
||||
Layer scheme with a sublayer
|
||||
----------------------------
|
||||
This tutorial has 3 example sketches, all using this layout:
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
|:------:|:-----:|:-----:|:-----:|
|
||||
| **0** | a - 1 | b = | c Num |
|
||||
| **1** |Normal | Sym | Enter |
|
||||
|
||||
Each cell in the table's body represents a key.
|
||||
Bottom row keys have one layer.
|
||||
Top row keys have 2 or 3 layers.
|
||||
|
||||
Pressing the "Normal" layer key locks the Normal layer.
|
||||
Letters 'a' 'b' 'c' are on the Normal layer.
|
||||
|
||||
Pressing the "Sym" layer key locks the Sym layer.
|
||||
Symbols '-' '=' are on the Sym layer.
|
||||
|
||||
The "Num" sublayer key is on the Sym layer.
|
||||
If the keyboard is locked on the Sym layer, holding Num down makes Num the active layer.
|
||||
Releasing the Num key restores the Sym layer.
|
||||
Number '1' is on the Num sublayer.
|
||||
|
||||
todo [pic of 3 col bb kb]
|
||||
|
||||
Three example 3 sketches implement the above layout using differently layer schemes.
|
||||
Keybrd provides flexibility todo??
|
||||
Which layer scheme is best depends on the layout.
|
||||
|
||||
3c -
|
||||
-----------
|
||||
keybrd_3c_sublayerNull.ino
|
||||
|
||||
The layer scheme has one LayerState object cover all the layer groups.
|
||||
Duplicate codes and null codes fill the unused space.
|
||||
It's a bit of a kludge, but can be simple if there is little unused space.
|
||||
|
||||
3d -
|
||||
-----------
|
||||
keybrd_3d_sublayerNestedKeys.ino
|
||||
|
||||
The layer scheme has a distinct LayerState object for each layer group.
|
||||
One LayerState object per layer group is preferred because it models the logic of the layout.
|
||||
|
||||
In this example, NORMAL+SYM is the primary layer group, which covers the top-row keys.
|
||||
layerState keeps track of the primary layer group's active layer.
|
||||
|
||||
SUBSYM+SUBNUM is the sublayer group, which covers the top-left key.
|
||||
subLayerState keeps track of the sublayer group's active layer.
|
||||
|
||||
The concepts of "sublayer" and "layer group" are independent.
|
||||
In the following layout for example, l_num and s_enter codes have swapped places.
|
||||
Num is now a primary layer, and SYM2+NUM2 is still layer group2.
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
|:------:|:-----:|:-----:|:-----:|
|
||||
| **0** | a - 1 | b = | c Ent |
|
||||
| **1** |Normal | Sym | Num |
|
||||
|
||||
3e -
|
||||
-----------
|
||||
keybrd_3e_sublayerNestedScSc.ino
|
||||
|
||||
Key_LayeredKeys constructor takes any number of code arguments.
|
||||
Key_LayeredScSc is more specialized. It's constructor takes exactly two scancode arguments.
|
||||
No array was created for the two scancodes.
|
||||
This has advantages when a large sublayer group has two layers:
|
||||
* save SRAM
|
||||
* less clutter in sketch
|
||||
|
||||
with custom layer classes, any layer scheme can be implemented
|
||||
DH is a complex layer scheme implemented with keybrd lib
|
||||
|
||||
Complex layerschemes
|
||||
--------------------
|
||||
The basic LayerState class used in the tutorials is sufficient for implementing many layer schemes.
|
||||
More complicated layer schemes would need custom LayerState classes, and possibly custom Code_Layer and Key_Layered classes as well.
|
||||
|
||||
keybrd_DH is an example of a complex layer scheme (it emulates the DataHand keyboard).
|
||||
It's the most complex layer scheme I know of.
|
||||
The keybrd_DH project is a showcase of the keybrd library's capability.
|
||||
Don't let the complexity scare you; most layer schemes are much simpler.
|
||||
|
||||
keybrd_DH's layout has 3 layers and 5 sub-layers.
|
||||
Most of the layer classes are custom classes, which reside in the keybrd_DH library.
|
||||
Layer classes used by keybrd_DH are listed below.
|
||||
The length of the list gives a hint of the layer scheme's complexity.
|
||||
|
||||
DH Code_Layer classes include:
|
||||
* Code_LayerLock
|
||||
* Code_LayerLockMF_Protector
|
||||
* Code_LayerState_Toggle
|
||||
|
||||
DH LayerState classes include:
|
||||
* LayerState
|
||||
* LayerState_DH
|
||||
* LayerState_NAS
|
||||
|
||||
DH Key_Layered classes include:
|
||||
* Key_LayeredKeys
|
||||
* Key_LayeredScSc
|
||||
* Key_LayeredNav
|
||||
* Key_LayeredDoublePressToggle
|
||||
* Key_LayeredCodeSc_MF
|
||||
* Key_LayeredOperator
|
||||
* Key_LayeredNumber
|
||||
* Key_LayeredNumber_00
|
||||
|
||||
Exercises
|
||||
---------
|
||||
|
Reference in New Issue
Block a user