diff --git a/README.md b/README.md
index 3917e5e..12eb66c 100644
--- a/README.md
+++ b/README.md
@@ -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)
[mainSketch.ino](https://github.com/wolfv6/keybrd_DH/blob/master/examples/keybrd_DH/mainSketch.cpp)
diff --git a/src/Code_Null.h b/src/Code_Null.h
index 903355c..5ab74b1 100644
--- a/src/Code_Null.h
+++ b/src/Code_Null.h
@@ -3,7 +3,7 @@
#include
#include
-/* 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
{
diff --git a/src/objects_scancode.h b/src/objects_scancode.h
index ff2dd3d..f80481e 100644
--- a/src/objects_scancode.h
+++ b/src/objects_scancode.h
@@ -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
diff --git a/tutorials/keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino b/tutorials/keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino
index f945a7d..8dad50a 100644
--- a/tutorials/keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino
+++ b/tutorials/keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino
@@ -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);
diff --git a/tutorials/keybrd_3b_multi-layerLock/keybrd_3b_multi-layerLock.ino b/tutorials/keybrd_3b_multi-layerLock/keybrd_3b_multi-layerLock.ino
index 1a11c19..48b96f7 100644
--- a/tutorials/keybrd_3b_multi-layerLock/keybrd_3b_multi-layerLock.ino
+++ b/tutorials/keybrd_3b_multi-layerLock/keybrd_3b_multi-layerLock.ino
@@ -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
-//#include
-//#include
#include
#include
-#include
#include
//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);
diff --git a/tutorials/keybrd_3c_sublayerNull/keybrd_3c_sublayerNull.ino b/tutorials/keybrd_3c_sublayerNull/keybrd_3c_sublayerNull.ino
index 1d2ce1f..e3de03c 100644
--- a/tutorials/keybrd_3c_sublayerNull/keybrd_3c_sublayerNull.ino
+++ b/tutorials/keybrd_3c_sublayerNull/keybrd_3c_sublayerNull.ino
@@ -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);
diff --git a/tutorials/keybrd_3d_sublayerNestedKeys/keybrd_3d_sublayerNestedKeys.ino b/tutorials/keybrd_3d_sublayerNestedKeys/keybrd_3d_sublayerNestedKeys.ino
index 7d16c91..167c3ed 100644
--- a/tutorials/keybrd_3d_sublayerNestedKeys/keybrd_3d_sublayerNestedKeys.ino
+++ b/tutorials/keybrd_3d_sublayerNestedKeys/keybrd_3d_sublayerNestedKeys.ino
@@ -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
-#include
#include
#include
#include
@@ -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);
diff --git a/tutorials/keybrd_3e_sublayerNestedScSc/keybrd_3e_sublayerNestedScSc.ino b/tutorials/keybrd_3e_sublayerNestedScSc/keybrd_3e_sublayerNestedScSc.ino
index c88f14f..6be426a 100644
--- a/tutorials/keybrd_3e_sublayerNestedScSc/keybrd_3e_sublayerNestedScSc.ino
+++ b/tutorials/keybrd_3e_sublayerNestedScSc/keybrd_3e_sublayerNestedScSc.ino
@@ -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
-#include
#include
#include
#include
@@ -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);
diff --git a/tutorials/tutorial_3a_multi-layer_keyboard.md b/tutorials/tutorial_3ab_multi-layer_keyboard.md
similarity index 84%
rename from tutorials/tutorial_3a_multi-layer_keyboard.md
rename to tutorials/tutorial_3ab_multi-layer_keyboard.md
index c2381e4..010b295 100644
--- a/tutorials/tutorial_3a_multi-layer_keyboard.md
+++ b/tutorials/tutorial_3ab_multi-layer_keyboard.md
@@ -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.
keybrd tutorial by Wolfram Volpi is licensed under a Creative Commons Attribution 4.0 International License.
Permissions beyond the scope of this license may be available at https://github.com/wolfv6/keybrd/issues/new.
diff --git a/tutorials/tutorial_3cde_sublayer_keyboard.md b/tutorials/tutorial_3cde_sublayer_keyboard.md
new file mode 100644
index 0000000..d99d966
--- /dev/null
+++ b/tutorials/tutorial_3cde_sublayer_keyboard.md
@@ -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
+---------
+
diff --git a/tutorials/tutorial_3b_autoShift.md b/tutorials/tutorial_3f_autoShift.md
similarity index 100%
rename from tutorials/tutorial_3b_autoShift.md
rename to tutorials/tutorial_3f_autoShift.md