@@ -21,7 +21,7 @@ Keybrd library class inheritance diagram | |||
___ ScannerInterface ___ | |||
/ | \ | |||
Scanner_uC Scanner_IOE Scanner_ShiftRegsPISO | |||
Scanner_uC Scanner_IOE Scanner_ShiftRegsRead | |||
PortWriteInterface |
@@ -122,7 +122,7 @@ The following instructions are for setting active state for a Scanner_uC class | |||
(Scanner_ShiftRegs74HC165 and Scanner_Port classes is similar). | |||
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: | |||
``` | |||
Scanner_uC scanner(LOW, readPins, readPinCount); |
@@ -10,7 +10,7 @@ | |||
#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), | |||
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, |
@@ -2,7 +2,7 @@ | |||
This sketch: | |||
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** | | |||
|:------:|-------|-------| |
@@ -0,0 +1,67 @@ | |||
/* 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(); | |||
} |
@@ -0,0 +1,109 @@ | |||
/* 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(); | |||
} |
@@ -1,6 +1,6 @@ | |||
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. | |||
@@ -28,14 +28,16 @@ Pressing the Alpha-layer key locks the Alpha layer. | |||
Letters 'a' 'b' 'c' are on the Alpha 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. | |||
Number '1' is on the Num sublayer. | |||
Releasing the Num key makes the locked layer active. | |||
Sublayers are very flexible. | |||
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: | |||
@@ -138,8 +140,8 @@ The top row is easily implemented in one layer group with duplicate keys filling | |||
| **0** | a - 1 | b = = | c Ent Ent | layer group with three layers: Alpha Sym Num | |||
| **1** | | | | | |||
Complex layerschemes | |||
-------------------- | |||
Complex 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. | |||
Any layer scheme can be implemented with the right custom layer classes. |
@@ -0,0 +1,45 @@ | |||
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>. |