2016-05-09 14:05:08 +00:00
Tutorial 3a - multi-layer keyboard
==================================
2016-07-22 08:11:38 +00:00
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.
2016-05-09 14:05:08 +00:00
2016-07-18 02:26:00 +00:00
Multi-layer nomenclature
------------------------
2016-07-18 02:03:03 +00:00
**[layers](http://deskthority.net/wiki/Layer)** - are key bindings provided by the keyboard firmware. For example,
2016-09-28 19:56:10 +00:00
* The classic [IBM Model M keyboard ](http://en.wikipedia.org/wiki/IBM_PC_keyboard ) has one layer.
2016-05-09 14:05:08 +00:00
* Many compact keyboards have an additional [Fn layer ](http://en.wikipedia.org/wiki/Fn_key ).
* The [Neo layout ](http://neo-layout.org/index_en.html ) has 6 layers.
2016-05-28 18:37:40 +00:00
**layer id** - is an integer used to identify a layer.
2016-05-09 14:05:08 +00:00
**active layer** - is the layer currently used by the keyboard.
2016-09-28 19:56:10 +00:00
**default layer** - is the active layer when the keyboard starts up.
2016-09-21 02:24:22 +00:00
2016-07-18 02:03:03 +00:00
**layer scheme** - is a system for changing the active layer while typing (a single-layer scheme does not change layers).
2016-09-21 02:24:22 +00:00
Code classes
------------
2016-09-28 19:56:10 +00:00
Code objects only have one scancode or one layer code.
Example Code classes include:
* Code_Sc
2016-09-21 02:24:22 +00:00
* Code_ScS
* Code_ScNS
* Code_Shift
* Code_LayerHold
* Code_LayerLock
2016-09-28 19:56:10 +00:00
Single-layer keys contain one Code object.
Multi-layer keys contain multiple Code objects, one code for each layer.
2016-09-21 02:24:22 +00:00
2016-07-18 02:26:00 +00:00
A simple multi-layer keybrd sketch
----------------------------------
2016-09-21 02:24:22 +00:00
The [keybrd_3a_multi-layerHold.ino ](keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino ) sketch is for a simple two-layer keyboard.
2016-07-18 02:26:00 +00:00
It will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md ](tutorial_1_breadboard_keyboard.md ).
2016-07-18 02:03:03 +00:00
2016-09-28 19:56:10 +00:00
![basic breadboard keyboard ](keybrd_1_breadboard/basic_breadboard_keyboard_front.JPG "basic breadboard keyboard" )
2016-07-18 02:03:03 +00:00
2016-09-17 05:45:12 +00:00
The sketch annotations explain how multi-layer keyboards work.
2016-07-18 02:03:03 +00:00
The sketch uses three layer-scheme classes:
* LayerState
* Code_LayerHold
2016-09-18 06:42:21 +00:00
* Key_LayeredKeys
2016-07-18 02:03:03 +00:00
The internal workings of these three classes are revealed in the next section.
2016-05-09 14:05:08 +00:00
2016-07-18 02:26:00 +00:00
Pseudo code for simple layer scheme
-----------------------------------
The following pseudo code is of three keybrd library classes.
2016-07-18 02:03:03 +00:00
It has just enough detail to show the internal workings of layer schemes.
2016-05-09 14:05:08 +00:00
2016-09-20 01:46:03 +00:00
**Code_Layer** objects change the active layer.
2016-09-17 05:45:12 +00:00
When a Code_Layer object is pressed, it tells LayerState to update the active layer.
2016-05-10 15:05:25 +00:00
```
2016-09-17 05:45:12 +00:00
class Code_Layer
2016-05-10 15:05:25 +00:00
{
2016-09-28 19:56:10 +00:00
const int layerId;
2016-07-18 02:03:03 +00:00
LayerState& refLayerState;
2016-09-20 01:46:03 +00:00
press() { refLayerState.setActiveLayer(layerId); }
2016-07-18 02:03:03 +00:00
};
2016-05-10 15:05:25 +00:00
```
2016-05-09 14:05:08 +00:00
2016-09-20 01:46:03 +00:00
**LayerState** objects keep track of the activeLayer.
2016-05-28 21:16:32 +00:00
A LayerState's activeLayer is always up to date.
2016-05-10 15:05:25 +00:00
```
2016-05-28 21:16:32 +00:00
class LayerState
2016-05-10 15:05:25 +00:00
{
2016-07-18 02:03:03 +00:00
int activeLayer;
2016-09-20 01:46:03 +00:00
setActiveLayer(int layerId) { activeLayer = layerId; }
2016-07-18 02:03:03 +00:00
getActiveLayer() { return activeLayer; }
};
2016-05-10 15:05:25 +00:00
```
2016-05-09 14:05:08 +00:00
2016-09-28 19:56:10 +00:00
**Key_LayeredKeys** objects contain arrays of keys, one key for each layer.
Key_LayeredKeys objects use layerIds as array indexes.
2016-09-20 01:46:03 +00:00
When a Key_LayeredKeys object is pressed, it gets the active layerId from LayerState, and sends the corresponding key.
2016-05-10 15:05:25 +00:00
```
2016-09-18 06:42:21 +00:00
class Key_LayeredKeys
2016-05-10 15:05:25 +00:00
{
2016-07-18 02:03:03 +00:00
Key** ptrsKeys; //array of Key pointers, one Key pointer per layer
LayerState& refLayerState;
2016-09-20 01:46:03 +00:00
press() { layerId = refLayerState.getActiveLayer();
ptrsKeys[layerId]->press(); }
2016-07-18 02:03:03 +00:00
};
2016-05-10 15:05:25 +00:00
```
2016-05-11 15:25:48 +00:00
Dependency diagram
```
2016-09-20 01:46:03 +00:00
+------------+
| Code_Layer |
+------------+
|
|setActiveLayer()
|
v
+------------+
| LayerState |
+------------+
^
|
|getActiveLayer()
|
+-----------------+
| Key_LayeredKeys |
+-----------------+
2016-05-11 15:25:48 +00:00
```
2016-07-18 02:26:00 +00:00
Layer-scheme classes
--------------------
2016-05-10 15:05:25 +00:00
There are several layer scheme-classes to choose from.
You can view all the class definitions in the [keybrd library ](../src/ ).
2016-09-17 05:45:12 +00:00
Code_Layer classes include:
2016-05-09 14:05:08 +00:00
* Code_LayerHold
* Code_LayerLock
2016-05-28 21:16:32 +00:00
A basic LayerState class is:
* LayerState
2016-05-10 15:05:25 +00:00
2016-05-28 18:37:40 +00:00
Key_Layered classes include:
2016-09-18 06:42:21 +00:00
* Key_LayeredKeys
2016-09-22 02:29:40 +00:00
* Key_LayeredScSc (covered in next tutorial)
2016-09-17 18:31:14 +00:00
* Key_LayeredCodeSc
2016-05-09 14:05:08 +00:00
2016-09-28 19:56:10 +00:00
The association between Codes, Keys, and Rows
---------------------------------------------
Codes, Keys, and Rows are associated by class compositions:
```
Each Code object contains one scancode or one layercode.
Each Key contains either
* one Code object (single-layer)
* multiple Code objects (multi-layer)
* Key object (key nested in key)
Each Row contains Key objects.
```
You may have been wondering why Code pointers are in Key pointers arrays.
You don't need to know the reasons to write a sketch.
For the curious, two reasons are explained below.
1) Single-layer keys is the first reason you see Code pointers in a Key pointers array.
Rows contain keys. The keys can be Single-layer or Multi-layer.
Wrapping a code in a single-layer key before placing it a row is tedious.
It is more convenient to place a code directly in a row.
Codes are a kind of Key (polymorphism), so that rows can contain codes and keys.
From keybrd_3a_multi-layerHold.ino:
```
Key* const ptrsKeys_0[] = { & k_00, & k_01 };
Row row_0(scanner, 0, ptrsKeys_0, keyCount_0);
Key* const ptrsKeys_1[] = { & l_fn, & s_shift };
Row row_1(scanner, 1, ptrsKeys_1, keyCount_1);
```
row0's ptrsKeys_0[] array contains pointers to Keys.
row1's ptrsKeys_1[] array contains pointers to Codes.
2) Sublayers (nested keys) is the second reason you see Code pointers in a Key pointers array.
Layered keys usually contain just codes. When nesting keys, layered keys contain keys.
Codes are a kind of Key (polymorphism), so that layered keys can contain both codes and keys.
From keybrd_3d_sublayerNested.ino:
```
Key* const ptrsKeys_sub00[] = { & s_minus, & s_1 };
Key_LayeredKeys1 k_sub00(ptrsKeys_sub00);
Key* const ptrsKeys_00[] = { & s_a, & k_sub00 };
Key_LayeredKeys k_00(ptrsKeys_00);
```
k_00's ptrsKeys_00[] array contains pointers to code s_a and key k_sub00.
2016-07-18 02:26:00 +00:00
Exercises
---------
2016-09-22 02:29:40 +00:00
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 ).
2016-09-21 02:24:22 +00:00
Notice how Code_LayerHold and Code_LayerLock objects behave.
2016-05-11 15:25:48 +00:00
2016-09-22 02:29:40 +00:00
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 |
2016-07-18 02:26:00 +00:00
< br >
2016-07-21 20:20:07 +00:00
< 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 > .
2016-07-18 02:03:03 +00:00