update split keyboard tutorials 4a 4b 4c and sketches
This commit is contained in:
parent
91df530ef2
commit
9f910d73ad
@ -40,7 +40,7 @@ Its layout has 52 keys, 3 primary layers, 5 sub-layers, 2 matrices, 8 LEDs, and
|
|||||||
|
|
||||||
[keybrd_DH_library_developer_guide.md](https://github.com/wolfv6/keybrd_DH/blob/master/doc/keybrd_DH_library_developer_guide.md)<br>
|
[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>
|
[mainSketch.ino](https://github.com/wolfv6/keybrd_DH/blob/master/examples/keybrd_DH/mainSketch.cpp)<br>
|
||||||
[instantiations_pins.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_pins.h)<br>
|
[instantiations_scannersLEDs.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_pins.h)<br>
|
||||||
[instantiations_scancodes.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_scancodes.h)<br>
|
[instantiations_scancodes.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_scancodes.h)<br>
|
||||||
[instantiations_layercodes.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_layercodes.h)<br>
|
[instantiations_layercodes.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_layercodes.h)<br>
|
||||||
[instantiations_rows_L.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_rows_L.h)<br>
|
[instantiations_rows_L.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_rows_L.h)<br>
|
||||||
|
@ -21,6 +21,7 @@ Initializes shift register's shift/load pin.
|
|||||||
*/
|
*/
|
||||||
void Scanner_ShiftRegsPISOSingleRow::begin()
|
void Scanner_ShiftRegsPISOSingleRow::begin()
|
||||||
{
|
{
|
||||||
|
SPI.begin();
|
||||||
digitalWrite(slaveSelect, HIGH);
|
digitalWrite(slaveSelect, HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,9 +13,9 @@ Using smaller types on a 32-bit uC (Teensy LC) would accomplish nothing.
|
|||||||
For Scanner_ShiftRegsPISO: read_pins_t bits >= Scanner_ShiftRegsPISO::byte_count * 8
|
For Scanner_ShiftRegsPISO: read_pins_t bits >= Scanner_ShiftRegsPISO::byte_count * 8
|
||||||
(For Scanner_IOE: I/O expanders are assumed to have 8 bits per port or less)
|
(For Scanner_IOE: I/O expanders are assumed to have 8 bits per port or less)
|
||||||
*/
|
*/
|
||||||
typedef uint8_t read_pins_t;
|
//typedef uint8_t read_pins_t;
|
||||||
//typedef uint16_t read_pins_t;
|
//typedef uint16_t read_pins_t;
|
||||||
//typedef uint32_t read_pins_t;
|
typedef uint32_t read_pins_t;
|
||||||
|
|
||||||
/* SAMPLE_COUNT_MACRO is used in Debouncer_Samples.h
|
/* SAMPLE_COUNT_MACRO is used in Debouncer_Samples.h
|
||||||
SAMPLE_COUNT_MACRO = 4 is very reliable for a keyboard.
|
SAMPLE_COUNT_MACRO = 4 is very reliable for a keyboard.
|
||||||
|
@ -72,11 +72,11 @@ 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.
|
The Key object names in this sketch start with a "k_" followed by row-column coordinates.
|
||||||
*/
|
*/
|
||||||
Key* const ptrsCodes_00[] = { &s_a, &s_minus };
|
Key* const ptrsKeys_00[] = { &s_a, &s_minus };
|
||||||
Key_LayeredKeys k_00(ptrsCodes_00);
|
Key_LayeredKeys k_00(ptrsKeys_00);
|
||||||
|
|
||||||
Key* const ptrsCodes_01[] = { &s_b, &s_equal };
|
Key* const ptrsKeys_01[] = { &s_b, &s_equal };
|
||||||
Key_LayeredKeys k_01(ptrsCodes_01);
|
Key_LayeredKeys k_01(ptrsKeys_01);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Key_LayeredKeys has a reference to layerState.
|
Key_LayeredKeys has a reference to layerState.
|
||||||
|
@ -7,10 +7,10 @@ This sketch:
|
|||||||
| Layout | **0** | **1** |
|
| Layout | **0** | **1** |
|
||||||
|:------:|:-----:|:-----:|
|
|:------:|:-----:|:-----:|
|
||||||
| **0** | a - | b = |
|
| **0** | a - | b = |
|
||||||
| **1** |Normal | Sym |
|
| **1** | Alpha | Sym |
|
||||||
|
|
||||||
Pressing the "Normal" layer key locks the Normal layer.
|
Pressing the "Alpha" layer key locks the Alpha layer.
|
||||||
Letters 'a' 'b' are on the Normal layer.
|
Letters 'a' 'b' are on the Alpha layer.
|
||||||
|
|
||||||
Pressing the "Sym" layer key locks the Sym layer.
|
Pressing the "Sym" layer key locks the Sym layer.
|
||||||
Symbols '-' '=' are on the Sym layer.
|
Symbols '-' '=' are on the Sym layer.
|
||||||
@ -39,7 +39,7 @@ Scanner_uC scanner(LOW, readPins, readPinCount);
|
|||||||
|
|
||||||
// =================== CODES ===================
|
// =================== CODES ===================
|
||||||
// ---------------- LAYER CODE -----------------
|
// ---------------- LAYER CODE -----------------
|
||||||
enum layers { NORMAL, SYM };
|
enum layers { ALPHA, SYM };
|
||||||
|
|
||||||
LayerState layerState;
|
LayerState layerState;
|
||||||
|
|
||||||
@ -47,10 +47,10 @@ LayerState layerState;
|
|||||||
The Code_LayerLock constructor has two parameters:
|
The Code_LayerLock constructor has two parameters:
|
||||||
1) the layerId that becomes the active layer when the key is pressed
|
1) the layerId that becomes the active layer when the key is pressed
|
||||||
2) a LayerState that will keep track of the active layer
|
2) a LayerState that will keep track of the active layer
|
||||||
When l_normal is pressed, NORMAL becomes the active layer.
|
When l_normal is pressed, ALPHA becomes the active layer.
|
||||||
When l_sym is pressed, SYM becomes the active layer.
|
When l_sym is pressed, SYM becomes the active layer.
|
||||||
*/
|
*/
|
||||||
Code_LayerLock l_normal(NORMAL, layerState);
|
Code_LayerLock l_normal(ALPHA, layerState);
|
||||||
Code_LayerLock l_sym(SYM, layerState);
|
Code_LayerLock l_sym(SYM, layerState);
|
||||||
|
|
||||||
// ---------------- SCAN CODES -----------------
|
// ---------------- SCAN CODES -----------------
|
||||||
@ -60,11 +60,11 @@ Code_Sc s_minus(KEY_MINUS);
|
|||||||
Code_Sc s_equal(KEY_EQUAL);
|
Code_Sc s_equal(KEY_EQUAL);
|
||||||
|
|
||||||
// =================== KEYS ====================
|
// =================== KEYS ====================
|
||||||
Key* const ptrsCodes_00[] = { &s_a, &s_minus };
|
Key* const ptrsKeys_00[] = { &s_a, &s_minus };
|
||||||
Key_LayeredKeys k_00(ptrsCodes_00);
|
Key_LayeredKeys k_00(ptrsKeys_00);
|
||||||
|
|
||||||
Key* const ptrsCodes_01[] = { &s_b, &s_equal };
|
Key* const ptrsKeys_01[] = { &s_b, &s_equal };
|
||||||
Key_LayeredKeys k_01(ptrsCodes_01);
|
Key_LayeredKeys k_01(ptrsKeys_01);
|
||||||
|
|
||||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ This sketch:
|
|||||||
| Layout | **0** | **1** | **2** |
|
| Layout | **0** | **1** | **2** |
|
||||||
|:------:|:-----:|:-----:|:-----:|
|
|:------:|:-----:|:-----:|:-----:|
|
||||||
| **0** | a - 1 | b = | c Num |
|
| **0** | a - 1 | b = | c Num |
|
||||||
| **1** |Normal | Sym | Enter |
|
| **1** | Alpha | Sym | Enter |
|
||||||
|
|
||||||
*/
|
*/
|
||||||
// ################## GLOBAL ###################
|
// ################## GLOBAL ###################
|
||||||
@ -38,11 +38,11 @@ Scanner_uC scanner(LOW, readPins, readPinCount);
|
|||||||
/* ---------------- LAYER CODE -----------------
|
/* ---------------- LAYER CODE -----------------
|
||||||
One LayerState object manages all 3 layers.
|
One LayerState object manages all 3 layers.
|
||||||
*/
|
*/
|
||||||
enum layers { NORMAL, SYM, NUM };
|
enum layers { ALPHA, SYM, NUM };
|
||||||
|
|
||||||
LayerState layerState;
|
LayerState layerState;
|
||||||
|
|
||||||
Code_LayerLock l_normal(NORMAL, layerState);
|
Code_LayerLock l_normal(ALPHA, layerState);
|
||||||
Code_LayerLock l_sym(SYM, layerState);
|
Code_LayerLock l_sym(SYM, layerState);
|
||||||
Code_LayerHold l_num(NUM, layerState);
|
Code_LayerHold l_num(NUM, layerState);
|
||||||
|
|
||||||
@ -68,22 +68,22 @@ 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.
|
But the layer scheme has 3 layers for all three keys.
|
||||||
The extra layers are filled with duplicate codes and null codes.
|
The extra layers are filled with duplicate codes and null codes.
|
||||||
*/
|
*/
|
||||||
Key* const ptrsCodes_00[] = { &s_a, &s_minus, &s_1 };
|
Key* const ptrsKeys_00[] = { &s_a, &s_minus, &s_1 };
|
||||||
Key_LayeredKeys k_00(ptrsCodes_00);
|
Key_LayeredKeys k_00(ptrsKeys_00);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
s_equal is duplicated in layer 2.
|
s_equal is duplicated in layer 2.
|
||||||
*/
|
*/
|
||||||
Key* const ptrsCodes_01[] = { &s_b, &s_equal, &s_equal };
|
Key* const ptrsKeys_01[] = { &s_b, &s_equal, &s_equal };
|
||||||
Key_LayeredKeys k_01(ptrsCodes_01);
|
Key_LayeredKeys k_01(ptrsKeys_01);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
code_null occupies layer 2. Class Code_Null doesn't do anything. It is useful for blank codes.
|
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.
|
Remember to fill all layers with codes.
|
||||||
If the code_null were omitted from the array, dereferencing ptrsCodes_02[2] could cause a crash.
|
If the code_null were omitted from the array, dereferencing ptrsKeys_02[2] could cause a crash.
|
||||||
*/
|
*/
|
||||||
Key* const ptrsCodes_02[] = { &s_c, &l_num, &code_null };
|
Key* const ptrsKeys_02[] = { &s_c, &l_num, &code_null };
|
||||||
Key_LayeredKeys k_02(ptrsCodes_02);
|
Key_LayeredKeys k_02(ptrsKeys_02);
|
||||||
|
|
||||||
// =================== ROWS ====================
|
// =================== ROWS ====================
|
||||||
Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02 };
|
Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02 };
|
||||||
|
@ -7,7 +7,7 @@ This sketch:
|
|||||||
| Layout | **0** | **1** | **2** |
|
| Layout | **0** | **1** | **2** |
|
||||||
|:------:|:-----:|:-----:|:-----:|
|
|:------:|:-----:|:-----:|:-----:|
|
||||||
| **0** | a - 1 | b = | c Num |
|
| **0** | a - 1 | b = | c Num |
|
||||||
| **1** |Normal | Sym | Enter |
|
| **1** | Alpha | Sym | Enter |
|
||||||
|
|
||||||
*/
|
*/
|
||||||
// ################## GLOBAL ###################
|
// ################## GLOBAL ###################
|
||||||
@ -36,11 +36,11 @@ Scanner_uC scanner(LOW, readPins, readPinCount);
|
|||||||
|
|
||||||
// =================== CODES ===================
|
// =================== CODES ===================
|
||||||
// ----------------- LAYER CODE ----------------
|
// ----------------- LAYER CODE ----------------
|
||||||
enum layers { NORMAL, SYM };
|
enum layers { ALPHA, SYM };
|
||||||
|
|
||||||
LayerState layerState;
|
LayerState layerState;
|
||||||
|
|
||||||
Code_LayerLock l_normal(NORMAL, layerState);
|
Code_LayerLock l_normal(ALPHA, layerState);
|
||||||
Code_LayerLock l_sym(SYM, layerState);
|
Code_LayerLock l_sym(SYM, layerState);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -49,8 +49,7 @@ Key_LayeredKeys are associated with layerState.
|
|||||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||||
|
|
||||||
/* ---------------- SUBLAYER CODE --------------
|
/* ---------------- SUBLAYER CODE --------------
|
||||||
Sublayers are implemented just like main layers.
|
Sublayers are implemented just like primary layers.
|
||||||
Here the Num sublayer is given it's own proper LayerState.
|
|
||||||
*/
|
*/
|
||||||
enum subLayers { SUBSYM, SUBNUM };
|
enum subLayers { SUBSYM, SUBNUM };
|
||||||
|
|
||||||
@ -80,23 +79,23 @@ Code_Sc s_1(KEY_1);
|
|||||||
The key k_sub00 contains codes for layerIds SUBSYM and SUBNUM.
|
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.)
|
(The Num sublayer only has one key because small example. Usually sublayers have multiple keys.)
|
||||||
*/
|
*/
|
||||||
Key* const ptrsCodes_sub00[] = { &s_minus, &s_1 };
|
Key* const ptrsKeys_sub00[] = { &s_minus, &s_1 };
|
||||||
Key_LayeredKeys1 k_sub00(ptrsCodes_sub00);
|
Key_LayeredKeys1 k_sub00(ptrsKeys_sub00);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
k_sub00 is nested in k_00.
|
k_sub00 is nested in k_00.
|
||||||
The key k_00 contains code and key for layerIds NORMAL and SYS.
|
The key k_00 contains code and key for layerIds ALPHA and SYM.
|
||||||
Notice that k_sub00 is of type Key_LayeredKeys1, while k_00 is of type Key_LayeredKeys.
|
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.
|
k_sub00 and k_00 are associated with distinct LayerStates.
|
||||||
*/
|
*/
|
||||||
Key* const ptrsCodes_00[] = { &s_a, &k_sub00 };
|
Key* const ptrsKeys_00[] = { &s_a, &k_sub00 };
|
||||||
Key_LayeredKeys k_00(ptrsCodes_00);
|
Key_LayeredKeys k_00(ptrsKeys_00);
|
||||||
|
|
||||||
Key* const ptrsCodes_01[] = { &s_b, &s_equal };
|
Key* const ptrsKeys_01[] = { &s_b, &s_equal };
|
||||||
Key_LayeredKeys k_01(ptrsCodes_01);
|
Key_LayeredKeys k_01(ptrsKeys_01);
|
||||||
|
|
||||||
Key* const ptrsCodes_02[] = { &s_c, &l_num };
|
Key* const ptrsKeys_02[] = { &s_c, &l_num };
|
||||||
Key_LayeredKeys k_02(ptrsCodes_02);
|
Key_LayeredKeys k_02(ptrsKeys_02);
|
||||||
|
|
||||||
// =================== ROWS ====================
|
// =================== ROWS ====================
|
||||||
Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02 };
|
Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02 };
|
||||||
|
@ -7,7 +7,7 @@ This sketch:
|
|||||||
| Layout | **0** | **1** | **2** |
|
| Layout | **0** | **1** | **2** |
|
||||||
|:------:|:-----:|:-----:|:-----:|
|
|:------:|:-----:|:-----:|:-----:|
|
||||||
| **0** | a - 1 | b = | c Num |
|
| **0** | a - 1 | b = | c Num |
|
||||||
| **1** |Normal | Sym | Enter |
|
| **1** | Alpha | Sym | Enter |
|
||||||
|
|
||||||
*/
|
*/
|
||||||
// ################## GLOBAL ###################
|
// ################## GLOBAL ###################
|
||||||
@ -36,13 +36,16 @@ Scanner_uC scanner(LOW, readPins, readPinCount);
|
|||||||
|
|
||||||
// =================== CODES ===================
|
// =================== CODES ===================
|
||||||
// ---------------- LAYER CODE -----------------
|
// ---------------- LAYER CODE -----------------
|
||||||
enum layers { NORMAL, SYM };
|
enum layers { ALPHA, SYM };
|
||||||
|
|
||||||
LayerState layerState;
|
LayerState layerState;
|
||||||
|
|
||||||
Code_LayerLock l_normal(NORMAL, layerState);
|
Code_LayerLock l_normal(ALPHA, layerState);
|
||||||
Code_LayerLock l_sym(SYM, layerState);
|
Code_LayerLock l_sym(SYM, layerState);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Key_LayeredKeys are associated with layerState.
|
||||||
|
*/
|
||||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||||
|
|
||||||
// ---------------- SUBLAYER CODE --------------
|
// ---------------- SUBLAYER CODE --------------
|
||||||
@ -52,6 +55,9 @@ LayerState sublayerState;
|
|||||||
|
|
||||||
Code_LayerHold l_num(SUBNUM, sublayerState);
|
Code_LayerHold l_num(SUBNUM, sublayerState);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Key_LayeredScSc is associated with layerState.
|
||||||
|
*/
|
||||||
LayerStateInterface& Key_LayeredScSc::refLayerState = sublayerState;
|
LayerStateInterface& Key_LayeredScSc::refLayerState = sublayerState;
|
||||||
|
|
||||||
// ---------------- SCAN CODES -----------------
|
// ---------------- SCAN CODES -----------------
|
||||||
@ -74,18 +80,17 @@ Key_LayeredScSc sub_00(KEY_MINUS, KEY_1);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
k_sub00 is nested in k_00.
|
k_sub00 is nested in k_00.
|
||||||
The key k_00 contains code and key for layerIds NORMAL and SYS.
|
The key k_00 contains code and key for layerIds ALPHA and SYM.
|
||||||
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.
|
k_sub00 and k_00 are associated with distinct LayerStates.
|
||||||
*/
|
*/
|
||||||
Key* const ptrsCodes_00[] = { &s_a, &sub_00 };
|
Key* const ptrsKeys_00[] = { &s_a, &sub_00 };
|
||||||
Key_LayeredKeys k_00(ptrsCodes_00);
|
Key_LayeredKeys k_00(ptrsKeys_00);
|
||||||
|
|
||||||
Key* const ptrsCodes_01[] = { &s_b, &s_equal };
|
Key* const ptrsKeys_01[] = { &s_b, &s_equal };
|
||||||
Key_LayeredKeys k_01(ptrsCodes_01);
|
Key_LayeredKeys k_01(ptrsKeys_01);
|
||||||
|
|
||||||
Key* const ptrsCodes_02[] = { &s_c, &l_num };
|
Key* const ptrsKeys_02[] = { &s_c, &l_num };
|
||||||
Key_LayeredKeys k_02(ptrsCodes_02);
|
Key_LayeredKeys k_02(ptrsKeys_02);
|
||||||
|
|
||||||
// =================== ROWS ====================
|
// =================== ROWS ====================
|
||||||
Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02 };
|
Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02 };
|
||||||
|
@ -6,8 +6,8 @@ This sketch:
|
|||||||
|
|
||||||
| Layout | **0** | **1** |
|
| Layout | **0** | **1** |
|
||||||
|:------:|-------|-------|
|
|:------:|-------|-------|
|
||||||
| **0** | shift | a ! |
|
| **0** | a ! | b @ |
|
||||||
| **1** | fn | b @ |
|
| **1** | fn | shift |
|
||||||
|
|
||||||
The layered keys in row 0 have two layers; one character for each layer.
|
The layered keys in row 0 have two layers; one character for each layer.
|
||||||
Letters 'a' and 'b' are on the normal layer. Symbols '!' and '@' are one the fn layer.
|
Letters 'a' and 'b' are on the normal layer. Symbols '!' and '@' are one the fn layer.
|
||||||
@ -74,7 +74,7 @@ const uint8_t Code_AutoShift::shiftCount = sizeof(ptrsS)/sizeof(*ptrsS);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
HOW SHIFT WORKS
|
HOW SHIFT WORKS
|
||||||
When a shift key is pressed, a standard keyboard driver will temporarily modify the normal action of another key when pressed together.
|
When a shift key is pressed, a standard keyboard driver will temporarily modify the action of other scancodes.
|
||||||
KEY_1 writes '1'
|
KEY_1 writes '1'
|
||||||
MODIFIERKEY_LEFT_SHIFT + KEY_1 writes '!'
|
MODIFIERKEY_LEFT_SHIFT + KEY_1 writes '!'
|
||||||
|
|
||||||
@ -90,21 +90,21 @@ When the user presses '!' or '@' on the fn layer:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// =================== KEYS ====================
|
// =================== KEYS ====================
|
||||||
Key* const ptrsCodes_01[] = { &s_a, &s_exclamation };
|
Key* const ptrsKeys_00[] = { &s_a, &s_exclamation };
|
||||||
Key_LayeredKeys k_01(ptrsCodes_01);
|
Key_LayeredKeys k_00(ptrsKeys_00);
|
||||||
|
|
||||||
Key* const ptrsCodes_11[] = { &s_b, &s_at };
|
Key* const ptrsKeys_01[] = { &s_b, &s_at };
|
||||||
Key_LayeredKeys k_11(ptrsCodes_11);
|
Key_LayeredKeys k_01(ptrsKeys_01);
|
||||||
|
|
||||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||||
|
|
||||||
// =================== ROWS ====================
|
// =================== ROWS ====================
|
||||||
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);
|
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0);
|
||||||
Row row_0(scanner, 0, ptrsKeys_0, keyCount_0);
|
Row row_0(scanner, 0, ptrsKeys_0, keyCount_0);
|
||||||
//Row row_0(0, readPins, READ_PIN_COUNT, ptrsKeys_0);
|
//Row row_0(0, readPins, READ_PIN_COUNT, ptrsKeys_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);
|
uint8_t keyCount_1 = sizeof(ptrsKeys_1)/sizeof(*ptrsKeys_1);
|
||||||
Row row_1(scanner, 1, ptrsKeys_1, keyCount_1);
|
Row row_1(scanner, 1, ptrsKeys_1, keyCount_1);
|
||||||
//Row row_1(1, readPins, READ_PIN_COUNT, ptrsKeys_1);
|
//Row row_1(1, readPins, READ_PIN_COUNT, ptrsKeys_1);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* tutorial_4a_split_keyboard_with_shift_registers.ino
|
/* tutorial_4b_split_keyboard_with_shift_registers.ino
|
||||||
Tested on Teensy LC and two 74HC165 shift registers.
|
Tested on Teensy LC and two 74HC165 shift registers.
|
||||||
|
|
||||||
The right matrix has 2 shift registers daisy chained.
|
The right matrix has 2 shift registers daisy chained.
|
||||||
@ -19,7 +19,6 @@ The right matrix has 2 shift registers daisy chained.
|
|||||||
#include <Row.h>
|
#include <Row.h>
|
||||||
|
|
||||||
//Right matrix
|
//Right matrix
|
||||||
//#include <SPI.h>//needed?? todo
|
|
||||||
#include <Scanner_ShiftRegsPISOSingleRow.h>
|
#include <Scanner_ShiftRegsPISOSingleRow.h>
|
||||||
|
|
||||||
// =============== CONFIGURATION ===============
|
// =============== CONFIGURATION ===============
|
||||||
@ -45,13 +44,20 @@ Code_Sc s_4(KEY_4);
|
|||||||
Code_Sc s_5(KEY_5);
|
Code_Sc s_5(KEY_5);
|
||||||
Code_Sc s_6(KEY_6);
|
Code_Sc s_6(KEY_6);
|
||||||
|
|
||||||
// =============== LEFT MATRIX =================
|
// ================= SCANNERS ==================
|
||||||
|
// --------------- LEFT SCANNER ----------------
|
||||||
uint8_t readPins_L[] = {14};
|
uint8_t readPins_L[] = {14};
|
||||||
uint8_t readPinCount_L = sizeof(readPins_L)/sizeof(*readPins_L);
|
uint8_t readPinCount_L = sizeof(readPins_L)/sizeof(*readPins_L);
|
||||||
|
|
||||||
Scanner_uC scanner_L(LOW, readPins_L, readPinCount_L); //active LOW
|
Scanner_uC scanner_L(LOW, readPins_L, readPinCount_L); //active LOW
|
||||||
|
|
||||||
//rows
|
/* --------------- RIGHT SCANNER ---------------
|
||||||
|
use slaveSelect pin SS (Arduino pin 10) for fastest scan
|
||||||
|
*/
|
||||||
|
Scanner_ShiftRegsPISOSingleRow scanner_R(HIGH, SS, 2); //active HIGH
|
||||||
|
|
||||||
|
// =================== ROWS ====================
|
||||||
|
// ----------------- LEFT ROWS -----------------
|
||||||
Key* ptrsKeys_L0[] = { &s_x };
|
Key* ptrsKeys_L0[] = { &s_x };
|
||||||
uint8_t KEY_COUNT_L0 = sizeof(ptrsKeys_L0)/sizeof(*ptrsKeys_L0);
|
uint8_t KEY_COUNT_L0 = sizeof(ptrsKeys_L0)/sizeof(*ptrsKeys_L0);
|
||||||
Row row_L0(scanner_L, 0, ptrsKeys_L0, KEY_COUNT_L0);
|
Row row_L0(scanner_L, 0, ptrsKeys_L0, KEY_COUNT_L0);
|
||||||
@ -60,11 +66,7 @@ Key* ptrsKeys_L1[] = { &s_y };
|
|||||||
uint8_t KEY_COUNT_L1 = sizeof(ptrsKeys_L1)/sizeof(*ptrsKeys_L1);
|
uint8_t KEY_COUNT_L1 = sizeof(ptrsKeys_L1)/sizeof(*ptrsKeys_L1);
|
||||||
Row row_L1(scanner_L, 1, ptrsKeys_L1, KEY_COUNT_L1);
|
Row row_L1(scanner_L, 1, ptrsKeys_L1, KEY_COUNT_L1);
|
||||||
|
|
||||||
// =============== RIGHT MATRIX ================
|
// ----------------- RIGHT ROWS ----------------
|
||||||
//use slaveSelect pin SS (Arduino pin 10) for fastest scan
|
|
||||||
Scanner_ShiftRegsPISOSingleRow scanner_R(HIGH, SS, 2); //active HIGH
|
|
||||||
|
|
||||||
//rows
|
|
||||||
Key* ptrsKeys_R0[] = { &s_6, &s_5, &s_4, &s_3, //shift register on right
|
Key* ptrsKeys_R0[] = { &s_6, &s_5, &s_4, &s_3, //shift register on right
|
||||||
&s_c, &s_d, &s_e, &s_f,
|
&s_c, &s_d, &s_e, &s_f,
|
||||||
&s_2, &s_1, &s_0, &s_g, //shift register on left
|
&s_2, &s_1, &s_0, &s_g, //shift register on left
|
||||||
@ -75,7 +77,6 @@ Row row_R0(scanner_R, 0, ptrsKeys_R0, sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0));
|
|||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
Keyboard.begin();
|
Keyboard.begin();
|
||||||
SPI.begin();//todo move to begin()
|
|
||||||
scanner_R.begin();
|
scanner_R.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
/* keybrd_4c_split_with_IOE.ino
|
/* keybrd_4c_split_keyboard_with_IOE.ino
|
||||||
|
|
||||||
This sketch:
|
This sketch:
|
||||||
is a simple 1-layer keyboard
|
is a simple 1-layer keyboard
|
||||||
runs on two matrices of a breadboard keyboard
|
runs on two matrices of a breadboard keyboard
|
||||||
is annotated with a walk-through narrative
|
|
||||||
|
|
||||||
This layout table shows left and right matrices:
|
This layout table shows left and right matrices:
|
||||||
|
|
||||||
@ -30,8 +29,7 @@ This layout table shows left and right matrices:
|
|||||||
// ============ SPEED CONFIGURATION ============
|
// ============ SPEED CONFIGURATION ============
|
||||||
ScanDelay scanDelay(9000);
|
ScanDelay scanDelay(9000);
|
||||||
|
|
||||||
// ================ LEFT SCANNER ===============
|
/* ================ LEFT SCANNER ===============
|
||||||
/*
|
|
||||||
Left matrix rows work the same as the ones in keybrd_2_single-layer.ino
|
Left matrix rows work the same as the ones in keybrd_2_single-layer.ino
|
||||||
*/
|
*/
|
||||||
uint8_t readPins[] = {14, 15};
|
uint8_t readPins[] = {14, 15};
|
||||||
@ -39,8 +37,7 @@ const uint8_t READPIN_COUNT = sizeof(readPins)/sizeof(*readPins);
|
|||||||
|
|
||||||
Scanner_uC scanner_L(LOW, readPins, READPIN_COUNT);
|
Scanner_uC scanner_L(LOW, readPins, READPIN_COUNT);
|
||||||
|
|
||||||
// =============== RIGHT SCANNER ===============
|
/* =============== RIGHT SCANNER ===============
|
||||||
/*
|
|
||||||
The right matrix is scanned by an I/O expander.
|
The right matrix is scanned by an I/O expander.
|
||||||
|
|
||||||
The I/O expander device address is configured by hardware pins.
|
The I/O expander device address is configured by hardware pins.
|
||||||
@ -48,13 +45,12 @@ DEVICE_ADDR is a static variable of class PortIOE.
|
|||||||
*/
|
*/
|
||||||
const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address with all 3 ADDR pins are grounded
|
const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address with all 3 ADDR pins are grounded
|
||||||
|
|
||||||
todo explain port num and shift notation <<
|
|
||||||
/*
|
/*
|
||||||
port_B stobes the row while port_A reads the colums.
|
port_B stobes the row while port_A reads the colums.
|
||||||
|
|
||||||
port_A is assigned port identification number 0.
|
port_A is assigned port identification number 0.
|
||||||
port_A is assigned to portRead, which reads port_A pins 0 and 1.
|
port_A is assigned to portRead, which reads port_A pins 0 and 1.
|
||||||
"<<" (bit shift left) and "|" (or) are bitwise operators.
|
"<<" (bit shift left) and "|" (OR) are bitwise operators.
|
||||||
Pin numbers to be read are to the right of "1<<" and delimited by "|".
|
Pin numbers to be read are to the right of "1<<" and delimited by "|".
|
||||||
*/
|
*/
|
||||||
PortIOE port_A(0);
|
PortIOE port_A(0);
|
||||||
@ -81,18 +77,17 @@ Code_Sc s_2(KEY_2);
|
|||||||
Code_Sc s_3(KEY_3);
|
Code_Sc s_3(KEY_3);
|
||||||
Code_Sc s_4(KEY_4);
|
Code_Sc s_4(KEY_4);
|
||||||
|
|
||||||
// =================== ROWS ====================
|
/* =================== ROWS ====================
|
||||||
/*
|
|
||||||
Left row names contain the letter 'L', while right row names conatain the letter 'R'.
|
Left row names contain the letter 'L', while right row names conatain the letter 'R'.
|
||||||
|
|
||||||
The first parameteer of a Row constructor specifies the scanner.
|
The first parameteer of a Row constructor specifies the scanner.
|
||||||
The second parameter of the Row constructor specifies the Row's strobePin.
|
The second parameter of the Row constructor specifies the Row's strobePin.
|
||||||
strobePin has one of two formats:
|
strobePin has one of two formats:
|
||||||
* if refScanner a Scanner_uC, then strobePin is an Arduino pin number connected to this row
|
* if refScanner a Scanner_uC, then strobePin is an Arduino pin number connected to this row
|
||||||
* otherwise strobePin is a bit pattern, 1 indicating an IC pin connected to this row
|
* otherwise strobePin is a bit pattern, 1 indicating an IC pin connected to the row
|
||||||
*/
|
*/
|
||||||
// ---------------- LEFT ROWS ------------------
|
/* ---------------- LEFT ROWS ------------------
|
||||||
/* The left rows have a Scanner_uC and Arduino pin numbers to strobe.
|
The left rows have a Scanner_uC and Arduino pin numbers to strobe.
|
||||||
*/
|
*/
|
||||||
Key* ptrsKeys_L0[] = { &s_1, &s_2 };
|
Key* ptrsKeys_L0[] = { &s_1, &s_2 };
|
||||||
const uint8_t KEY_COUNT_L0 = sizeof(ptrsKeys_L0)/sizeof(*ptrsKeys_L0);
|
const uint8_t KEY_COUNT_L0 = sizeof(ptrsKeys_L0)/sizeof(*ptrsKeys_L0);
|
||||||
@ -102,8 +97,7 @@ Key* ptrsKeys_L1[] = { &s_a, &s_b };
|
|||||||
const uint8_t KEY_COUNT_L1 = sizeof(ptrsKeys_L1)/sizeof(*ptrsKeys_L1);
|
const uint8_t KEY_COUNT_L1 = sizeof(ptrsKeys_L1)/sizeof(*ptrsKeys_L1);
|
||||||
Row row_L1(scanner_L, 1, ptrsKeys_L1, KEY_COUNT_L1);
|
Row row_L1(scanner_L, 1, ptrsKeys_L1, KEY_COUNT_L1);
|
||||||
|
|
||||||
// ---------------- RIGHT ROWS -----------------
|
/* ---------------- RIGHT ROWS -----------------
|
||||||
/*
|
|
||||||
The right rows have a Scanner_IOE and pin bits to strobe.
|
The right rows have a Scanner_IOE and pin bits to strobe.
|
||||||
*/
|
*/
|
||||||
Key* ptrsKeys_R0[] = { &s_3, &s_4 };
|
Key* ptrsKeys_R0[] = { &s_3, &s_4 };
|
||||||
@ -117,7 +111,6 @@ Row row_R1(scanner_R, 1<<1, ptrsKeys_R1, KEY_COUNT_R1);
|
|||||||
// ################### MAIN ####################
|
// ################### MAIN ####################
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
delay(7000); //todo
|
|
||||||
Keyboard.begin();
|
Keyboard.begin();
|
||||||
scanner_R.begin();
|
scanner_R.begin();
|
||||||
}
|
}
|
@ -72,11 +72,11 @@ Code_Sc s_1(KEY_1);
|
|||||||
Code_Sc s_2(KEY_2);
|
Code_Sc s_2(KEY_2);
|
||||||
|
|
||||||
// =================== KEYS ====================
|
// =================== KEYS ====================
|
||||||
Key* const ptrsCodes_01[] = { &s_a, &s_1 };
|
Key* const ptrsKeys_01[] = { &s_a, &s_1 };
|
||||||
Key_LayeredKeys k_01(ptrsCodes_01);
|
Key_LayeredKeys k_01(ptrsKeys_01);
|
||||||
|
|
||||||
Key* const ptrsCodes_11[] = { &s_b, &s_2 };
|
Key* const ptrsKeys_11[] = { &s_b, &s_2 };
|
||||||
Key_LayeredKeys k_11(ptrsCodes_11);
|
Key_LayeredKeys k_11(ptrsKeys_11);
|
||||||
|
|
||||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||||
|
|
||||||
|
@ -120,14 +120,22 @@ A basic LayerState class is:
|
|||||||
|
|
||||||
Key_Layered classes include:
|
Key_Layered classes include:
|
||||||
* Key_LayeredKeys
|
* Key_LayeredKeys
|
||||||
* Key_LayeredScSc
|
* Key_LayeredScSc (covered in next tutorial)
|
||||||
* Key_LayeredCodeSc
|
* Key_LayeredCodeSc
|
||||||
|
|
||||||
Exercises
|
Exercises
|
||||||
---------
|
---------
|
||||||
Compile and run keybrd_3a_multi-layerHold.ino and keybrd_3b_multi-layerLock.ino
|
1) Compile and run [keybrd_3a_multi-layerHold.ino](keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino)
|
||||||
|
and [keybrd_3b_multi-layerLock.ino](keybrd_3b_multi-layerLock/keybrd_3b_multi-layerLock.ino).
|
||||||
Notice how Code_LayerHold and Code_LayerLock objects behave.
|
Notice how Code_LayerHold and Code_LayerLock objects behave.
|
||||||
|
|
||||||
|
2) Modify the keybrd_3a_multi-layerHold.ino sketch to make a 3-layer keyboard with two Code_LayerHold keys.
|
||||||
|
|
||||||
|
| Layout | **0** | **1** |
|
||||||
|
|:------:|:-----:|:-----:|
|
||||||
|
| **0** | a - 1 | b = 2 |
|
||||||
|
| **1** | sym | num |
|
||||||
|
|
||||||
<br>
|
<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>.
|
<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>.
|
||||||
|
|
||||||
|
@ -6,12 +6,18 @@ When you finish this tutorial you will be able to be able to modify a multi-laye
|
|||||||
|
|
||||||
Sublayer nomenclature
|
Sublayer nomenclature
|
||||||
---------------------
|
---------------------
|
||||||
**primary layer** - is a layer whose layer key is accessible from the default layer.
|
These definitions are specific to the keybrd library.
|
||||||
|
|
||||||
**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 group** - is a group of layers that occupy the same keys.
|
||||||
|
|
||||||
|
**primary layer group** - is a layer group containing the default layer.
|
||||||
|
|
||||||
|
**sublayer group** - is a layer group nested in a layer of another layer group.
|
||||||
|
|
||||||
|
**primary layer** - is a layer within the primary layer group.
|
||||||
|
|
||||||
|
**sublayer** - is a layer within the sublayer group.
|
||||||
|
|
||||||
Layer scheme with a sublayer
|
Layer scheme with a sublayer
|
||||||
----------------------------
|
----------------------------
|
||||||
This tutorial has 3 example sketches, all using this layout:
|
This tutorial has 3 example sketches, all using this layout:
|
||||||
@ -19,87 +25,95 @@ This tutorial has 3 example sketches, all using this layout:
|
|||||||
| Layout | **0** | **1** | **2** |
|
| Layout | **0** | **1** | **2** |
|
||||||
|:------:|:-----:|:-----:|:-----:|
|
|:------:|:-----:|:-----:|:-----:|
|
||||||
| **0** | a - 1 | b = | c Num |
|
| **0** | a - 1 | b = | c Num |
|
||||||
| **1** |Normal | Sym | Enter |
|
| **1** | Alpha | Sym | Enter |
|
||||||
|
|
||||||
Each cell in the table's body represents a key.
|
Each cell in the table's body represents a key.
|
||||||
Bottom row keys have one layer.
|
Bottom row keys have one layer.
|
||||||
Top row keys have 2 or 3 layers.
|
Top row keys have 2 or 3 layers.
|
||||||
|
|
||||||
Pressing the "Normal" layer key locks the Normal layer.
|
Pressing the "Alpha" layer key locks the Alpha layer.
|
||||||
Letters 'a' 'b' 'c' are on the Normal layer.
|
Letters 'a' 'b' 'c' are on the Alpha layer.
|
||||||
|
|
||||||
Pressing the "Sym" layer key locks the Sym layer.
|
Pressing the "Sym" layer key locks the Sym layer.
|
||||||
Symbols '-' '=' are on the Sym layer.
|
Symbols '-' '=' and "Num" layer key 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.
|
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.
|
Releasing the Num key restores the Sym layer.
|
||||||
Number '1' is on the Num sublayer.
|
Number '1' is on the Num sublayer.
|
||||||
|
|
||||||
todo [pic of 3 col bb kb]
|
todo [pic of 3 col bb kb]
|
||||||
|
|
||||||
Three example 3 sketches implement the above layout using differently layer schemes.
|
Three example sketches implement the above layout using differently layer schemes.
|
||||||
Keybrd provides flexibility todo??
|
|
||||||
Which layer scheme is best depends on the layout.
|
Which layer scheme is best depends on the layout.
|
||||||
|
|
||||||
3c -
|
Sketch 3c - one layer group
|
||||||
-----------
|
---------------------------
|
||||||
keybrd_3c_sublayerNull.ino
|
Refer to keybrd_3c_sublayerNull.ino
|
||||||
|
|
||||||
The layer scheme has one LayerState object cover all the layer groups.
|
The top row has one layer group with 3 layers.
|
||||||
|
Num layer is unused to the right of 1.
|
||||||
Duplicate codes and null codes fill the unused space.
|
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.
|
It's a bit of a kludge, but can be simple if there is little unused space.
|
||||||
|
|
||||||
3d -
|
layerState contains the active layer for the layer group.
|
||||||
-----------
|
|
||||||
keybrd_3d_sublayerNestedKeys.ino
|
|
||||||
|
|
||||||
The layer scheme has a distinct LayerState object for each layer group.
|
Sketch 3d - two layer groups
|
||||||
One LayerState object per layer group is preferred because it models the logic of the layout.
|
----------------------------
|
||||||
|
Refer to keybrd_3d_sublayerNestedKeys.ino
|
||||||
|
|
||||||
In this example, NORMAL+SYM is the primary layer group, which covers the top-row keys.
|
The top row has two layer groups.
|
||||||
layerState keeps track of the primary layer group's active layer.
|
* NORMAL+SYM is the primary layer group. It covers the top-row keys.
|
||||||
|
* SYM1+NUM1 is a sublayer group nested in the SYM layer. The subgroup covers the top-left key.
|
||||||
|
|
||||||
SUBSYM+SUBNUM is the sublayer group, which covers the top-left key.
|
Two layer groups model the logic of the layout accurately
|
||||||
subLayerState keeps track of the sublayer group's active layer.
|
(the previous example was a kluge because it only had one layer group).
|
||||||
|
|
||||||
The concepts of "sublayer" and "layer group" are independent.
|
There should be one LayerState object for each layer group. In this example:
|
||||||
In the following layout for example, l_num and s_enter codes have swapped places.
|
* layerState contains the active layer for the primary layer group.
|
||||||
Num is now a primary layer, and SYM2+NUM2 is still layer group2.
|
* sublayerState contains the active layer for the sublayer group.
|
||||||
|
|
||||||
|
Sketch 3e - specialized layered keys
|
||||||
|
------------------------------------
|
||||||
|
Refer to keybrd_3e_sublayerNestedScSc.ino
|
||||||
|
|
||||||
|
Key_LayeredKeys constructor takes any number of code or key arguments.
|
||||||
|
Key_LayeredScSc is more specialized. It's constructor takes exactly two scancode arguments.
|
||||||
|
A Key_LayeredScSc object could be instantiated with Key_LayeredKeysArray.
|
||||||
|
But using Key_LayeredScSc has advantages when a large sublayer group has two layers:
|
||||||
|
* no array is created for the two scancodes
|
||||||
|
* less clutter in sketch
|
||||||
|
* save SRAM
|
||||||
|
|
||||||
|
Key_Layered classes include:
|
||||||
|
* Key_LayeredKeys (any number of codes or keys)
|
||||||
|
* Key_LayeredScSc (specialized for two scancodes)
|
||||||
|
* Key_LayeredCodeSc (specialized for one code and one scancode)
|
||||||
|
|
||||||
|
Sublayer layer-key placement
|
||||||
|
----------------------------
|
||||||
|
A layer key to a sublayer can be place in one of two places:
|
||||||
|
* on layer the sublayer group is nested in (layout above has Num-layer key on Sym layer)
|
||||||
|
* on a single-layer key (layout below has Num-layer key on bottom row) (some people would not call this arrangement a sublayer)
|
||||||
|
|
||||||
| Layout | **0** | **1** | **2** |
|
| Layout | **0** | **1** | **2** |
|
||||||
|:------:|:-----:|:-----:|:-----:|
|
|:------:|:-----:|:-----:|:-----:|
|
||||||
| **0** | a - 1 | b = | c Ent |
|
| **0** | a - 1 | b = | c Ent |
|
||||||
| **1** |Normal | Sym | Num |
|
| **1** | Alpha | 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
|
Complex layerschemes
|
||||||
--------------------
|
--------------------
|
||||||
The basic LayerState class used in the tutorials is sufficient for implementing many layer schemes.
|
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.
|
More complicated layer schemes would need custom LayerState classes, and possibly custom Code_Layer and Key_Layered classes as well.
|
||||||
|
Any layer scheme can be implemented with the right custom layer classes.
|
||||||
|
|
||||||
keybrd_DH is an example of a complex layer scheme (it emulates the DataHand keyboard).
|
[keybrd_DH](https://github.com/wolfv6/keybrd_DH) is an example of a complex layer scheme (it emulates the DataHand keyboard).
|
||||||
|
The keybrd_DH sketch is a showcase of the keybrd library's capability.
|
||||||
It's the most complex layer scheme I know of.
|
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.
|
Don't let the complexity scare you; most layer schemes are much simpler.
|
||||||
|
|
||||||
keybrd_DH's layout has 3 layers and 5 sub-layers.
|
Layer-scheme classes used by keybrd_DH are listed below.
|
||||||
Most of the layer classes are custom classes, which reside in the keybrd_DH library.
|
The layer scheme classes are organized into three categories, as is "Layer-scheme classes" in the previous tutorial.
|
||||||
Layer classes used by keybrd_DH are listed below.
|
Most of the layer-scheme classes are custom classes, which reside in the keybrd_DH library.
|
||||||
The length of the list gives a hint of the layer scheme's complexity.
|
|
||||||
|
|
||||||
DH Code_Layer classes include:
|
DH Code_Layer classes include:
|
||||||
* Code_LayerLock
|
* Code_LayerLock
|
||||||
@ -123,4 +137,10 @@ DH Key_Layered classes include:
|
|||||||
|
|
||||||
Exercises
|
Exercises
|
||||||
---------
|
---------
|
||||||
|
Modify keybrd_3e_sublayerNestedScSc.ino by adding the number '2' to the Num layer group.
|
||||||
|
The layout is below.
|
||||||
|
|
||||||
|
| Layout | **0** | **1** | **2** |
|
||||||
|
|:------:|:-----:|:-----:|:-----:|
|
||||||
|
| **0** | a - 1 | b = 2 | c Num |
|
||||||
|
| **1** | Alpha | Sym | Enter |
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
Tutorial 3b - autoShift
|
Tutorial 3f - autoShift
|
||||||
=======================
|
=======================
|
||||||
Some multi-layer keyboards have a symbols layer that writes symbols without using the shift key:
|
Some multi-layer keyboards have a symbols layer that writes symbols without using the shift key:
|
||||||
|
|
||||||
~ ! @ # $ % ^ & * () _ {} | < > : ?
|
~ ! @ # $ % ^ & * () _ {} | < > : ?
|
||||||
|
|
||||||
The keybrd library does this by automatically sending a MODIFIERKEY_SHIFT scancode.
|
The keybrd AutoShift class automatically sends a MODIFIERKEY_SHIFT scancode as needed.
|
||||||
|
|
||||||
Two keybrd classes use AutoShift:
|
Two keybrd classes use AutoShift:
|
||||||
* Code_ScS
|
* Code_ScS
|
||||||
* Code_ScNS
|
* Code_ScNS
|
||||||
|
|
||||||
The [keybrd_3b_autoShift.ino](keybrd_3b_autoShift/keybrd_3b_autoShift.ino) sketch explains the AutoShift feature.
|
The [keybrd_3f_autoShift.ino](keybrd_3f_autoShift/keybrd_3f_autoShift.ino) sketch explains the AutoShift feature.
|
||||||
It will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md).
|
It will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md).
|
||||||
After reading the sketch you too will be able to automatically shifted characters.
|
After reading the sketch you too will be able to automatically shifted characters.
|
||||||
|
|
||||||
@ -18,12 +17,19 @@ After reading the sketch you too will be able to automatically shifted character
|
|||||||
|
|
||||||
Exercises
|
Exercises
|
||||||
---------
|
---------
|
||||||
1) Modify the keybrd_3b_autoShift sketch to make a 3-layer keyboard with a default layer and two Code_LayerHold objects.
|
1) Modify the keybrd_3f_autoShift sketch to make a 3-layer keyboard with a default layer and two Code_LayerHold objects.
|
||||||
|
|
||||||
| Layout | **0** | **1** |
|
| Layout | **0** | **1** |
|
||||||
|:------:|:-----:|:-----:|
|
|:------:|:-----:|:-----:|
|
||||||
| **0** | a ! 6 | b @ 7 |
|
| **0** | a ! 1 | b @ 2 |
|
||||||
| **1** | sym | num |
|
| **1** | sym | num |
|
||||||
|
|
||||||
|
2) Modify the keybrd_3f_autoShift sketch to write 1 and 2, regardless of if shift is held down or not (hint: use Code_ScNS).
|
||||||
|
|
||||||
|
| Layout | **0** | **1** |
|
||||||
|
|:------:|-------|-------|
|
||||||
|
| **0** | a 1 | b 2 |
|
||||||
|
| **1** | fn | shift |
|
||||||
|
|
||||||
<br>
|
<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>.
|
<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>.
|
||||||
|
58
tutorials/tutorial_4a_connecting_split_keyboards.md
Normal file
58
tutorials/tutorial_4a_connecting_split_keyboards.md
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
keybrd Tutorial 4a - Connecting split keyboards
|
||||||
|
===============================================
|
||||||
|
Split keyboards have left and right parts:
|
||||||
|
* one keyboard half contains the controller and USB port.
|
||||||
|
* the other keyboard half can contain shift registers or an I/O expander.
|
||||||
|
|
||||||
|
The two halves need to be connected.
|
||||||
|
The preferred connection method depends on the number of keys, number of available controller pins, cable flexibility, LEDs, and cost.
|
||||||
|
|
||||||
|
## Split keyboard connections table
|
||||||
|
|
||||||
|
| connection type | controller pins | wire count | max keys |
|
||||||
|
|:----------------------:|:---------------:|:----------:|:--------:|
|
||||||
|
| just cable | 6 | 6 | 9 |
|
||||||
|
| just cable | 7 | 7 | 12 |
|
||||||
|
| just cable | 8 | 8 | 16 |
|
||||||
|
| just cable | 9 | 9 | 20 |
|
||||||
|
| | | | |
|
||||||
|
| 2 PISO shift registers | 3 | 5 | 16 |
|
||||||
|
| 3 PISO shift registers | 3 | 5 | 24 |
|
||||||
|
| | | | |
|
||||||
|
| I/O expander SPI | 4 | 6 | 64 |
|
||||||
|
| I/O expander I2C | 2 | 4 | 64 |
|
||||||
|
|
||||||
|
Fewer wires makes a cable more flexible.
|
||||||
|
A flexibility cable makes it easy to position the keyboard and route the cable.
|
||||||
|
But if there are enough pins on the controller, just using a cable with more wires is simpler and costs less.
|
||||||
|
|
||||||
|
I/O Expanders can power LEDs, while PISO shift registers can not.
|
||||||
|
|
||||||
|
I2C is a little slow if the I/O expander is scanning more than 4 rows.
|
||||||
|
|
||||||
|
## Cables table
|
||||||
|
|
||||||
|
| connector name | wire count |
|
||||||
|
|:-----------------------------------------------------:|:----------:|
|
||||||
|
| TRRS | 4 |
|
||||||
|
| 6-pin mini-DIN connector (PS/2) | 4 |
|
||||||
|
| USB 2 | 4 |
|
||||||
|
| 4P4C Modular connector (RJ9, RJ10, RJ22) handset plug | 4 |
|
||||||
|
| 6P4C Modular connector (RJ-14) 2-line phone | 4 |
|
||||||
|
| 6P6C Modular connector (RJ12) 3-line phone | 6 |
|
||||||
|
| eSATA | 7 |
|
||||||
|
| 8p8c Modular connector (RJ45) Ethernet | 8 |
|
||||||
|
| USB 3.0, 3.1 | 9 |
|
||||||
|
|
||||||
|
Only ready-made cables that are widely available are listed.
|
||||||
|
There are hundreds of other connectors listed at http://pinouts.ru/
|
||||||
|
There are also wireless options if you don't mind adding complexity and maintaining a battery.
|
||||||
|
|
||||||
|
The 8-wire "GearIT Cat 6 Ethernet Flat Patch Cable 7 Feet" is very flexible.
|
||||||
|
It's available at Walmart if you want to feel the merchandise before you buy.
|
||||||
|
All the modular connectors are flat.
|
||||||
|
|
||||||
|
For prototyping on perfboards, consider a 0.1” header.
|
||||||
|
|
||||||
|
<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>.
|
@ -1,16 +1,16 @@
|
|||||||
keybrd Tutorial 4b - split keyboard with shift registers
|
keybrd Tutorial 4b - split keyboard with shift registers
|
||||||
========================================================
|
========================================================
|
||||||
When you finish this tutorial you will be able to be able to modify a split keybrd sketch with 10 to 24 keys on the peripheral hand.
|
When you finish this tutorial you will be able to be able to modify a split keybrd sketch with 10 to 24 keys on the shift registers.
|
||||||
|
|
||||||
Overview of split keyboard with shift registers
|
Overview of split keyboard with shift registers
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
Only the right matrix is shown. The left matrix was omitted to reduce clutter.
|
Only the right matrix is shown. The left matrix is not needed and was omitted to reduce clutter.
|
||||||
|
|
||||||
The layout has 2 rows and 7 columns.
|
The right-matrix layout has 2 rows and 7 columns.
|
||||||
Electronically, the matrix only has one row.
|
Electronically, the matrix only has one row.
|
||||||
Diodes are not needed because there is only one row.
|
Diodes are not needed because there is only one row.
|
||||||
|
|
||||||
The two black rectangles are shift registers daisy chained together.
|
The two black rectangles are SN74HC165N shift registers daisy chained together.
|
||||||
Shift register details are in the SN74HC165N datasheet.
|
Shift register details are in the SN74HC165N datasheet.
|
||||||
|
|
||||||
![breadboard keyboard with shift_registers](keybrd_4b_split_keyboard_with_shift_registers/shift_reg_front.JPG )
|
![breadboard keyboard with shift_registers](keybrd_4b_split_keyboard_with_shift_registers/shift_reg_front.JPG )
|
||||||
@ -20,7 +20,7 @@ Building a split breadboard keyboard with shift registers
|
|||||||
Add components to the breadboard as shown in the picture.
|
Add components to the breadboard as shown in the picture.
|
||||||
|
|
||||||
Each shift register has a small notch on one end to identify pin 1.
|
Each shift register has a small notch on one end to identify pin 1.
|
||||||
In the picture, pin 1s are on the left end.
|
In the picture, pin 1s are on the left end, towards the controller.
|
||||||
Shift registers are chained together by colored wires that lay flat on the breadboard.
|
Shift registers are chained together by colored wires that lay flat on the breadboard.
|
||||||
|
|
||||||
Each shift register has 8 parallel input pins, 4 on each side.
|
Each shift register has 8 parallel input pins, 4 on each side.
|
||||||
@ -32,17 +32,17 @@ A decoupling capacitor between the power and ground wires prevents power disturb
|
|||||||
|
|
||||||
Switches are connected to power (red bus) and shift register input pins (jumpers).
|
Switches are connected to power (red bus) and shift register input pins (jumpers).
|
||||||
|
|
||||||
I apologize for not having a schematic. This table should help you figure out the pictures:
|
I apologize for not providing a schematic. This table should help you figure out the pictures:
|
||||||
|
|
||||||
```
|
```
|
||||||
74HC165 left (lower half of breadboard)
|
74HC165 left (lower half of breadboard)
|
||||||
NAME PIN# DESCRIPTION TO TEENSY LC PIN# CHAIN
|
NAME PIN# DESCRIPTION TO TEENSY LC PIN# CHAIN
|
||||||
SH/LD 1 shift or load input CS0 10 green wire
|
SH/LD 1 shift or load input CS0 10 green wire
|
||||||
CLK 2 clock input SCK0 13 yellow wire
|
CLK 2 clock input SCK0 13 yellow wire
|
||||||
D4 3 parallel input blue bus
|
D4 3 parallel input
|
||||||
D5 4 parallel input blue bus
|
D5 4 parallel input
|
||||||
D6 5 parallel input blue bus
|
D6 5 parallel input
|
||||||
D7 6 parallel input blue bus
|
D7 6 parallel input
|
||||||
/QH 7 ~serial output
|
/QH 7 ~serial output
|
||||||
GND 8 ground gnd blue bus
|
GND 8 ground gnd blue bus
|
||||||
|
|
||||||
@ -50,10 +50,10 @@ GND 8 ground gnd blue bus
|
|||||||
NAME PIN# DESCRIPTION TO TEENSY LC PIN# CHAIN
|
NAME PIN# DESCRIPTION TO TEENSY LC PIN# CHAIN
|
||||||
VCC 16 power pin 3.3V red wire
|
VCC 16 power pin 3.3V red wire
|
||||||
CLK INH 15 clock inhibit blue bus
|
CLK INH 15 clock inhibit blue bus
|
||||||
D3 14 parallel input blue bus
|
D3 14 parallel input
|
||||||
D2 13 parallel input blue bus
|
D2 13 parallel input
|
||||||
D1 12 parallel input blue bus
|
D1 12 parallel input
|
||||||
D0 11 parallel input blue bus
|
D0 11 parallel input
|
||||||
SER 10 serial input blue wire to next QH
|
SER 10 serial input blue wire to next QH
|
||||||
QH 9 serial output MISO0 12 blue wire to previous SER
|
QH 9 serial output MISO0 12 blue wire to previous SER
|
||||||
|
|
||||||
@ -62,20 +62,20 @@ SER 10 serial input blue wire to next QH
|
|||||||
Sketch for split keyboard with shift registers
|
Sketch for split keyboard with shift registers
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
[keybrd_4b_split_keyboard_with_shift_registers.ino](keybrd_4b_split_keyboard_with_shift_registers/keybrd_4b_split_keyboard_with_shift_registers.ino) is a simple sketch with two shift registers.
|
[keybrd_4b_split_keyboard_with_shift_registers.ino](keybrd_4b_split_keyboard_with_shift_registers/keybrd_4b_split_keyboard_with_shift_registers.ino) is a simple sketch with two shift registers.
|
||||||
The sketch will run on the above breadboard keyboard.
|
It will run on the above breadboard keyboard.
|
||||||
|
|
||||||
The sketch has code for both left and right matrix.
|
|
||||||
Notice that the left matrix is active low, while the right matrix is active high.
|
|
||||||
|
|
||||||
Exercises
|
Exercises
|
||||||
---------
|
---------
|
||||||
1. Guess what happens if an unused input pin is not grounded? Try it.
|
1. Guess what happens if an unused input pin is not grounded? Try it.
|
||||||
|
|
||||||
2. Add a left matrix to Teensy.
|
2. Add a left matrix to the controller.
|
||||||
There is room between Teensy and the shift registers for a 1-column matrix.
|
There is room between Teensy and the shift registers for a 1-column matrix.
|
||||||
The bus strips are occupied by the right keys, so use terminal strips instead.
|
The bus strips are occupied by the right keys, so use terminal strips instead.
|
||||||
Other wise it is similar to the 2-column matrix in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md).
|
Other wise it is similar to the 2-column matrix in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md).
|
||||||
|
|
||||||
|
The sketch already has code for both left and right matrix.
|
||||||
|
Notice that the left matrix is active low, while the right matrix is active high.
|
||||||
|
|
||||||
<br>
|
<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>.
|
<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>.
|
||||||
|
|
||||||
|
@ -13,10 +13,10 @@ Two rows (red buses) are connected to the I/O expander.
|
|||||||
|
|
||||||
The I/O expander is a MCP23S17.
|
The I/O expander is a MCP23S17.
|
||||||
It has a small notch on one end, which identifies pin 1.
|
It has a small notch on one end, which identifies pin 1.
|
||||||
In the picture, pin 1 is on the right end.
|
In the picture, pin 1 is on the left end.
|
||||||
|
|
||||||
The MCP23S17 communicates via SPI protocol, where Teensy LC is the master, and MCP23S17 is slave.
|
The MCP23S17 communicates via SPI protocol, where Teensy LC is the master, and MCP23S17 is slave.
|
||||||
The Teensy LC and MCP23S17 are connected by 6 jumper wires:
|
The Teensy LC and MCP23S17 are connected via 6 jumper wires:
|
||||||
|
|
||||||
|CONNECTION |Teensy LC|MCP23S17|
|
|CONNECTION |Teensy LC|MCP23S17|
|
||||||
|:------------------:|---------|--------|
|
|:------------------:|---------|--------|
|
||||||
|
Reference in New Issue
Block a user