___ ScannerInterface ___ | ___ ScannerInterface ___ | ||||
/ | \ | / | \ | ||||
Scanner_uC Scanner_IOE Scanner_ShiftRegsPISO | |||||
Scanner_uC Scanner_IOE Scanner_ShiftRegsRead | |||||
PortWriteInterface | PortWriteInterface |
(Scanner_ShiftRegs74HC165 and Scanner_Port classes is similar). | (Scanner_ShiftRegs74HC165 and Scanner_Port classes is similar). | ||||
For active low: | For active low: | ||||
* Orient diodes with cathode (banded end) towards the write pins (row) | |||||
* Orient diodes with cathode (banded end) towards the write pins (strobe) | |||||
* Instantiate the scanner in the sketch with activeState LOW, like this: | * Instantiate the scanner in the sketch with activeState LOW, like this: | ||||
``` | ``` | ||||
Scanner_uC scanner(LOW, readPins, readPinCount); | Scanner_uC scanner(LOW, readPins, readPinCount); |
#include "Debouncer_Not.h" | #include "Debouncer_Not.h" | ||||
/* | /* | ||||
strobePin has one of two formats: | |||||
strobePin has one of two formats: todo | |||||
* if strobe pin is on uC (strobe for Scanner_uC or Scanner_ShiftRegsRead), | * if strobe pin is on uC (strobe for Scanner_uC or Scanner_ShiftRegsRead), | ||||
then strobePin is an Arduino pin number connected to this row. | then strobePin is an Arduino pin number connected to this row. | ||||
* if strobe pin is on I/O expander (strobe for Scanner_IOE), then strobePin is bit pattern, | * if strobe pin is on I/O expander (strobe for Scanner_IOE), then strobePin is bit pattern, |
This sketch: | This sketch: | ||||
is firmware for a simple 2-layer keyboard | is firmware for a simple 2-layer keyboard | ||||
runs on the first two rows and columns of a breadboard keyboard | |||||
runs on the basic breadboard keyboard | |||||
| Layout | **0** | **1** | | | Layout | **0** | **1** | | ||||
|:------:|-------|-------| | |:------:|-------|-------| |
/* keybrd_7a_mapping_single-layer.ino | |||||
This sketch: | |||||
is modified from keybrd_2_single.ino by swaping readPins numbers with Row-pin numbers | |||||
runs on basic breadboard keyboard modified by flipping diodes, anodes towards rows (blue bus) | |||||
demonstrates mapping from LAYOUT to MATRIX on a single-layer keyboard | |||||
| Layout | **0** | **1** | | |||||
|:------:|-------|-------| | |||||
| **0** | 1 | 2 | | |||||
| **1** | a | b | | |||||
*/ | |||||
// ################## GLOBAL ################### | |||||
// ================= INCLUDES ================== | |||||
#include <Code_Sc.h> | |||||
#include <Row.h> | |||||
#include <Scanner_uC.h> | |||||
#include <ScanDelay.h> | |||||
// ============ SPEED CONFIGURATION ============ | |||||
ScanDelay scanDelay(9000); | |||||
// ================== SCANNER ================== | |||||
uint8_t readPins[] = {0, 1}; | |||||
uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins); | |||||
Scanner_uC scanner(LOW, readPins, readPinCount); | |||||
// =================== 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); | |||||
/* ================== LAYOUT =================== | |||||
Keyboard layout is the placement of keys. | |||||
*/ | |||||
Key* const ptrsLayout[2][2] = { //[row][col] | |||||
//col0 col1 | |||||
{ &s_1, &s_2 }, //row0 | |||||
{ &s_a, &s_b } //row1 | |||||
}; | |||||
/* ================== MATRIX =================== | |||||
// --------------- KEY MAPPINGS ---------------- | |||||
ptrsLayout[row][col] coordinates correspond to the elements in the layout. | |||||
The Keys are transposed (layout rows are placed in matrix columns). | |||||
*/ | |||||
Key* ptrsKeys_0[] = { ptrsLayout[0][0], ptrsLayout[1][0] }; | |||||
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0); | |||||
Row row_0(scanner, 14, ptrsKeys_0, keyCount_0); | |||||
Key* ptrsKeys_1[] = { ptrsLayout[0][1], ptrsLayout[1][1] }; | |||||
uint8_t keyCount_1 = sizeof(ptrsKeys_1)/sizeof(*ptrsKeys_1); | |||||
Row row_1(scanner, 15, ptrsKeys_1, keyCount_1); | |||||
// ################### MAIN #################### | |||||
void setup() | |||||
{ | |||||
} | |||||
void loop() | |||||
{ | |||||
row_0.process(); | |||||
row_1.process(); | |||||
scanDelay.delay(); | |||||
} |
/* keybrd_7b_mapping_multi-layer.ino | |||||
This sketch: | |||||
is modified from keybrd_3a_multi-layerHold.ino by swaping readPins numbers with Row-pin numbers | |||||
runs on basic breadboard keyboard modified by flipping diodes, anodes towards rows (blue bus) | |||||
demonstrates mapping from LAYOUT to MATRIX on a multi-layer keyboard | |||||
assumes you undstand keybrd Tutorial 2 - keybrd multi-layer | |||||
| Layout | **0** | **1** | | |||||
|:------:|-------|-------| | |||||
| **0** | a - | b = | | |||||
| **1** | fn | shift | | |||||
*/ | |||||
// ################## GLOBAL ################### | |||||
// ================= INCLUDES ================== | |||||
//Keys | |||||
#include <Code_Sc.h> | |||||
#include <LayerState.h> | |||||
#include <Code_LayerHold.h> | |||||
#include <Key_LayeredKeys.h> | |||||
//Matrix | |||||
#include <Row.h> | |||||
#include <Scanner_uC.h> | |||||
#include <ScanDelay.h> | |||||
// ============ SPEED CONFIGURATION ============ | |||||
ScanDelay scanDelay(9000); | |||||
// ================== SCANNER ================== | |||||
uint8_t readPins[] = {0, 1}; | |||||
uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins); | |||||
Scanner_uC scanner(LOW, readPins, readPinCount); | |||||
// =================== CODES =================== | |||||
// ---------------- LAYER CODE ----------------- | |||||
enum layerIds { NORMAL, FN }; | |||||
LayerState layerState; | |||||
Code_LayerHold l_fn(FN, 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_shift(MODIFIERKEY_LEFT_SHIFT); | |||||
/* ================== LAYOUT =================== | |||||
Keyboard layout is the placement of keys. | |||||
nullptrs are place holders that are not mapped to the matrix. | |||||
By convention, single-layer keys are placed on layer0, and nulls are placed in the remaining layers. | |||||
If you replace a null with a code, make sure its coordinate is in the KEYS MAPPING section. | |||||
Each non-nullptr array element consums 4 bytes of SRAM (on Teensy LC 32 bit controller). | |||||
*/ | |||||
Key* const ptrsLayout[2][2][2] = { //[layer][row][col] | |||||
//layer0 | |||||
{//col0 col1 | |||||
{ &s_a, &s_b }, //row0 | |||||
{ &l_fn, &s_shift } //row1 | |||||
}, | |||||
//layer1 | |||||
{//col0 col1 | |||||
{ &s_minus, &s_equal }, //row0 | |||||
{ nullptr, nullptr } //row1 | |||||
} | |||||
}; | |||||
/* ================== MATRIX =================== | |||||
ptrsLayout[layer][row][col] coordinates correspond to the elements in the layout. | |||||
// --------------- CODE MAPPINGS --------------- | |||||
Each ptrsLayout in this section maps a Code to one layer in a Key. | |||||
Only Key_LayeredKeys are instantiated in this section. | |||||
*/ | |||||
Key* const ptrsKeys_00[] = { ptrsLayout[0][0][0], ptrsLayout[1][0][0] }; // { &s_a, &s_minus }; | |||||
Key_LayeredKeys k_00(ptrsKeys_00); | |||||
Key* const ptrsKeys_01[] = { ptrsLayout[0][0][1], ptrsLayout[1][0][1] }; // { &s_b, &s_equal }; | |||||
Key_LayeredKeys k_01(ptrsKeys_01); | |||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState; | |||||
/* --------------- KEY MAPPINGS ---------------- | |||||
The Keys are transposed (layout rows are placed in matrix columns). | |||||
ptrsLayout elements are from the LAYOUT section. | |||||
Key_LayeredKeys are from the CODE MAPPINGS section. | |||||
*/ | |||||
Key* const ptrsKeys_0[] = { &k_00, ptrsLayout[0][1][0] }; // { { &s_a, &s_minus }, &l_fn }; | |||||
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0); | |||||
Row row_0(scanner, 14, ptrsKeys_0, keyCount_0); | |||||
Key* const ptrsKeys_1[] = { &k_01, ptrsLayout[0][1][1] }; // { { &s_b, &s_equal }, &s_shift }; | |||||
uint8_t keyCount_1 = sizeof(ptrsKeys_1)/sizeof(*ptrsKeys_1); | |||||
Row row_1(scanner, 15, ptrsKeys_1, keyCount_1); | |||||
// ################### MAIN #################### | |||||
void setup() | |||||
{ | |||||
} | |||||
void loop() | |||||
{ | |||||
row_0.process(); | |||||
row_1.process(); | |||||
scanDelay.delay(); | |||||
} |
Tutorial 3cde - sublayer keyboard | Tutorial 3cde - sublayer keyboard | ||||
================================= | ================================= | ||||
This tutorial assumes you have read tutorial_3ab_multi-layer_keyboard. | |||||
This tutorial assumes you understand tutorial_3ab_multi-layer_keyboard. | |||||
When you finish this tutorial you will be able to be able to modify a multi-layer keybrd sketch. | When you finish this tutorial you will be able to be able to modify a multi-layer keybrd sketch. | ||||
Letters 'a' 'b' 'c' are on the Alpha 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 '-' '=' and "Num" layer key are on the Sym layer. | |||||
Symbols '-' '=' and 'Num' layer key are on the Sym layer. | |||||
If the keyboard is locked on the Sym layer, holding Num down makes it the active layer. | If the keyboard is locked on the Sym layer, holding Num down makes it the active layer. | ||||
Number '1' is on the Num sublayer. | Number '1' is on the Num sublayer. | ||||
Releasing the Num key makes the locked layer active. | Releasing the Num key makes the locked layer active. | ||||
Sublayers are very flexible. | |||||
Example sketches 3c, 3d, and 3e implement the above layout. | Example sketches 3c, 3d, and 3e implement the above layout. | ||||
Each sketch uses a different layer scheme. | |||||
Each sketch demonstrates a different layer scheme. | |||||
Which approach works best depends on the layout. | |||||
The sketches will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md) with a 3rd column added to pin 16: | The sketches will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md) with a 3rd column added to pin 16: | ||||
| **0** | a - 1 | b = = | c Ent Ent | layer group with three layers: Alpha Sym Num | | **0** | a - 1 | b = = | c Ent Ent | layer group with three layers: Alpha Sym Num | ||||
| **1** | | | | | | **1** | | | | | ||||
Complex layerschemes | |||||
-------------------- | |||||
Complex layer schemes | |||||
--------------------- | |||||
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. | Any layer scheme can be implemented with the right custom layer classes. |
keybrd Tutorial 7ab - mapping layout to matrix | |||||
============================================ | |||||
After reading this tutorial you will be able to map a keyboard layout to a keyboard matrix. | |||||
Keyboard mapping nomenclature | |||||
----------------------------- | |||||
**[Keyboard layout](http://en.wikipedia.org/wiki/Keyboard_layout)** - is the placement of keys. Key caps are often labeled to show a keyboard's layout. | |||||
**[Matrix](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/)** - is a collection of switches electrically connected into rows and columns. | |||||
**[Transpose](https://en.wikipedia.org/wiki/Transpose)** - is the mapping of layout rows to matrix columns. Used when diodes are oriented with anodes towards the matrix rows. | |||||
When to use mapping | |||||
------------------- | |||||
In most of the other keybrd tutorial examples: | |||||
* layout and matrix are congruent | |||||
* active-low keyboard diodes are oriented with cathodes towards the matrix rows | |||||
(or active-high keyboard diodes are oriented with anodes towards the matrix rows) | |||||
There is no standard way keyboards are manufactured. Some variations are: | |||||
* irregular matrix | |||||
* active-low keyboard diodes are oriented with anodes towards the matrix rows | |||||
* active-high keyboard diodes are oriented with cathodes towards the matrix rows | |||||
* I/O expander pins connect to matrix out of order | |||||
Any of these variations can use a mapping to align a layout with the matrix. | |||||
Mapping a layout to a matrix | |||||
---------------------------- | |||||
Modify the basic breadboard keyboard by flipping diodes, so that anodes are towards matrix rows (blue bus). | |||||
The [keybrd_7a_mapping_single-layer.ino](keybrd_7a_mapping_single-layer/keybrd_7a_mapping_single-layer.ino) sketch will run on the keyboard. | |||||
Annotations in the sketch explain how mapping from LAYOUT to MATRIX works. | |||||
The [keybrd_7b_mapping_multi-layer.ino](keybrd_7b_mapping_multi-layer/keybrd_7b_mapping_multi-layer.ino) sketch will run on the same keyboard. | |||||
Exercise | |||||
-------- | |||||
1) Make a keyboard with an irregular matrix. | |||||
* Modify the basic breadboard keyboard by crossing the columns. | |||||
* Modify the keybrd_2_single-layer.ino sketch by mapping the layout to the irregular matrix. | |||||
![crossed columns](keybrd_7_mapping_layout_to_matix/crossed_columns.jpg "crossed columns") | |||||
<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>. |