Browse Source

add tutorials and annotate sketches 3c 3d 3e

tags/v0.6.0
wolfv6 7 years ago
parent
commit
91df530ef2

+ 1
- 1
README.md View File

@@ -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>

+ 1
- 1
src/Code_Null.h View File

@@ -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
{

+ 1
- 1
src/objects_scancode.h View File

@@ -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

+ 28
- 25
tutorials/keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino View File

@@ -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_LayeredKeys k_01(ptrsCodes_01);
Key* const ptrsCodes_00[] = { &s_a, &s_minus };
Key_LayeredKeys k_00(ptrsCodes_00);

Key* const ptrsCodes_11[] = { &s_b, &s_2 };
Key_LayeredKeys k_11(ptrsCodes_11);
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.
/*
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);


+ 20
- 58
tutorials/keybrd_3b_multi-layerLock/keybrd_3b_multi-layerLock.ino View File

@@ -6,29 +6,21 @@ This sketch:

| Layout | **0** | **1** |
|:------:|:-----:|:-----:|
| **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

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.
| **0** | a - | b = |
| **1** |Normal | Sym |

Pressing the "Normal" layer key locks the Normal layer.
Letters 'a' 'b' are on 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);

+ 20
- 47
tutorials/keybrd_3c_sublayerNull/keybrd_3c_sublayerNull.ino View File

@@ -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);

+ 27
- 50
tutorials/keybrd_3d_sublayerNestedKeys/keybrd_3d_sublayerNestedKeys.ino View File

@@ -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);

+ 19
- 51
tutorials/keybrd_3e_sublayerNestedScSc/keybrd_3e_sublayerNestedScSc.ino View File

@@ -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);

tutorials/tutorial_3a_multi-layer_keyboard.md → tutorials/tutorial_3ab_multi-layer_keyboard.md View File

@@ -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
- 0
tutorials/tutorial_3cde_sublayer_keyboard.md View 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
---------


tutorials/tutorial_3b_autoShift.md → tutorials/tutorial_3f_autoShift.md View File