The sketch is small because the keybrd library takes care of the low-level details. | The sketch is small because the keybrd library takes care of the low-level details. | ||||
The keybrd tutorial 1 shows how to make a breadboard keyboard. | The keybrd tutorial 1 shows how to make a breadboard keyboard. | ||||
The [keybrd tutorials](tutorials) 2, 3, and 4 show how to create custom keybrd firmware. | |||||
The remaining [keybrd tutorials](tutorials) show how to create custom keybrd firmware. | |||||
Example complex keybrd sketch | Example complex keybrd sketch | ||||
----------------------------- | ----------------------------- |
keybrd Library Developer's Guide | keybrd Library Developer's Guide | ||||
================================ | ================================ | ||||
This guide contains diagrams, naming conventions, and a style guide, | |||||
which are useful when designing new classes for the keybrd library and its extension libraries. | |||||
This guide if for maintaining and writing new classes for the keybrd library and its extension libraries. | |||||
The most common reason for new classes are: | The most common reason for new classes are: | ||||
* Port classes for micro controller or I/O expanders | * Port classes for micro controller or I/O expanders | ||||
* custom layer schemes for multi-layer keyboards | * custom layer schemes for multi-layer keyboards | ||||
``` | ``` | ||||
Code | Code | ||||
| | | | ||||
Code_Sc | |||||
Code_LayerLock | |||||
``` | ``` | ||||
This convention leads to class names that convey information about the classes inheritance. | This convention leads to class names that convey information about the classes inheritance. | ||||
* **ITEM_COUNT** is a constant number of items. | * **ITEM_COUNT** is a constant number of items. | ||||
* **itemCount** is a variable number of items. | * **itemCount** is a variable number of items. | ||||
* Use header guards CLASS_NAME_H. | * Use header guards CLASS_NAME_H. | ||||
* Prefix pointer name with "ptr" e.g. ptrRow = &row | |||||
* Prefix pointer name with "ptr" e.g. ptrRow = &row; | |||||
* Name arrays using the plural of element name e.g. Row* const = ptrsRows { &row0, &row1 }; | * Name arrays using the plural of element name e.g. Row* const = ptrsRows { &row0, &row1 }; | ||||
* Pass arrays using array notation rather than pointer notation. Use | * Pass arrays using array notation rather than pointer notation. Use | ||||
``` | ``` | ||||
* If class has any non-[POD](http://en.wikipedia.org/wiki/Plain_old_data_structure) data members, [do not inline constructors and destructors](http://www.chromium.org/developers/coding-style/cpp-dos-and-donts). | * If class has any non-[POD](http://en.wikipedia.org/wiki/Plain_old_data_structure) data members, [do not inline constructors and destructors](http://www.chromium.org/developers/coding-style/cpp-dos-and-donts). | ||||
* Document class interface in .h file, above the class declaration. | * Document class interface in .h file, above the class declaration. | ||||
* Code should be self-documenting. The only comments should be things that may need clarification. A simple function with a good name needs no comment. | * Code should be self-documenting. The only comments should be things that may need clarification. A simple function with a good name needs no comment. | ||||
* Code is automatically formated before being pushed to the keybrd repository | |||||
The options file doc/astyle_cpp specifies the format: | |||||
* Code is automatically formated before being pushed to the keybrd repository. | |||||
The [astyle_cpp](astyle_cpp) file specifies the format: | |||||
* Allman style indentation | * Allman style indentation | ||||
* indent 4 spaces | * indent 4 spaces | ||||
* replace tabs with spaces | * replace tabs with spaces |
Teensy LC is preferred over the older Teensy 2.0 for it's larger memory capacity and lower price. | Teensy LC is preferred over the older Teensy 2.0 for it's larger memory capacity and lower price. | ||||
## Getting started with Teensy, Arduino IDE, and keybrd | ## Getting started with Teensy, Arduino IDE, and keybrd | ||||
The Arduino IDE is used to edit and compile sketches, and then load them on to the microcontroller. | |||||
The Arduino IDE is used to | |||||
1. edit sketches | |||||
2. compile sketches into HEX files | |||||
3. load the HEX file onto the microcontroller | |||||
Teensyduino is a software add-on for the Arduino IDE that allows it to compile to Teensy. | Teensyduino is a software add-on for the Arduino IDE that allows it to compile to Teensy. | ||||
The following install and setup steps create an Arduino development environment for keybrd sketches. | The following install and setup steps create an Arduino development environment for keybrd sketches. | ||||
### Install Arduino IDE and Teensyduino | ### Install Arduino IDE and Teensyduino | ||||
Following install steps are modified from the [Teensyduino download page](https://www.pjrc.com/teensy/td_download.html) | |||||
The following install steps are modified from the [Teensyduino download page](https://www.pjrc.com/teensy/td_download.html) | |||||
For Linux: | For Linux: | ||||
Unpack keybrd-master.zip into your Arduino directory on your system (default location is ~/Documents/Arduino/). | Unpack keybrd-master.zip into your Arduino directory on your system (default location is ~/Documents/Arduino/). | ||||
### keybrd library and keybrd extension libraries | |||||
### Install keybrd library and keybrd extension libraries | |||||
<!-- todo update after testing Arduino library manager --> | <!-- todo update after testing Arduino library manager --> | ||||
The keybrd library contains the foundation classes for creating a keyboard firmware. | The keybrd library contains the foundation classes for creating a keyboard firmware. | ||||
For emphasis, it is referred to as the "core keybrd library". | |||||
For emphasis, it is sometimes referred to as the "core keybrd library". | |||||
keybrd extension libraries contain additional classes that extend the keyboard library. | keybrd extension libraries contain additional classes that extend the keyboard library. | ||||
keybrd extension library names are prefixed with "keybrd_". | keybrd extension library names are prefixed with "keybrd_". | ||||
* Arduino/libraries/keybrd/ | * Arduino/libraries/keybrd/ | ||||
* Arduino/libraries/keybrd_DH/ | * Arduino/libraries/keybrd_DH/ | ||||
A keybrd extension library allows classes to be shared by multiple sketches without polluting the core keybrd library with classes that few other keyboards can use. | |||||
A keybrd extension library allows classes to be shared by multiple sketches without polluting the core keybrd library with classes that other keyboards can not use. | |||||
### Setup Arduino IDE for compiling keybrd firmware | ### Setup Arduino IDE for compiling keybrd firmware | ||||
From the Arduino IDE tool bar, select: | From the Arduino IDE tool bar, select: | ||||
The example sketch names use the following conventions. | The example sketch names use the following conventions. | ||||
**keybrd_extension_feature_version.ino** | |||||
**keybrd_feature_version.ino** | |||||
where | where | ||||
* **keybrd_extension** is the extension library name e.g. keybrd_DH | |||||
* **feature** is distinguishing feature of keybrd sketch e.g. breadboard, LED, sound, Dvorak | |||||
* **version** is version number | |||||
* **keybrd** is the library name e.g. keybrd, keybrd_DH | |||||
* **feature** is a distinguishing feature of the keybrd sketch e.g. breadboard, LED, sound, Dvorak | |||||
* **version** is the sketch's version number | |||||
The first two fields are mandatory, the remaining fields are optional. | |||||
The first field are mandatory, the remaining fields are optional. | |||||
## Diode orientation | ## Diode orientation | ||||
The physical martix rows and columns on a keyboard can be in any direction or shape. | The physical martix rows and columns on a keyboard can be in any direction or shape. | ||||
**Layer scheme** - is a system for changing layers while typing. | **Layer scheme** - is a system for changing layers while typing. | ||||
A single-layer scheme does not change layers. | A single-layer scheme does not change layers. | ||||
**Layout** - is a grid of keys. Key caps are often labeled to show a keyboard's layout. | |||||
**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 connected by rows and columns. | **[Matrix](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/)** - is a collection of switches connected by rows and columns. | ||||
*/ | */ | ||||
// ---------------- LAYER CODE ----------------- | // ---------------- LAYER CODE ----------------- | ||||
/* | /* | ||||
enum assings ID numbers to the layers. | |||||
enum assings Id numbers to the layers. | |||||
*/ | */ | ||||
enum layers { NORMAL, FN }; | enum layers { NORMAL, FN }; | ||||
/* | /* | ||||
*/ | */ | ||||
StateLayers stateLayer; | StateLayers stateLayer; | ||||
/* | /* | ||||
The Code_LayerHold constructor parameter specifies a layer ID number and a StateLayer. | |||||
The Code_LayerHold constructor parameter specifies a layer Id number and a StateLayer. | |||||
When l_fn is pressed, it tells stateLayer to change the active layer to 1. | When l_fn is pressed, it tells stateLayer to change the active layer to 1. | ||||
When l_fn is released, it tells stateLayer to restore the normal layer. | When l_fn is released, it tells stateLayer to restore the normal layer. | ||||
*/ | */ | ||||
one array of Code pointers | one array of Code pointers | ||||
Key_LayeredKeysArray objects are multi-layered - one Code object per layer. | Key_LayeredKeysArray objects are multi-layered - one Code object per layer. | ||||
Layer ID numbers are array indexes for the Key_LayeredKeysArray. | |||||
Defining layer ID numbers with enum insures that they are a series of intergers starting at 0. | |||||
Layer Id numbers are used as array indexes for the Key_LayeredKeysArray. | |||||
Defining layer Id numbers with enum insures that they are a series of intergers starting at 0. | |||||
The Key object names in this sketch start with a "k_" followed by matrix-row-column coordinates. | The Key object names in this sketch start with a "k_" followed by matrix-row-column coordinates. | ||||
*/ | */ |
/* | /* | ||||
The right matrix is scanned by an I/O expander. | The right matrix is scanned by an I/O expander. | ||||
The micro-controller and I/O expander use address 0x18 to communicate with each other over I2C. | |||||
I/O expander I2C address is configured by hardware pins. | |||||
ADDR is a static variable of class IOExpanderPort. | ADDR is a static variable of class IOExpanderPort. | ||||
*/ | */ | ||||
const uint8_t IOExpanderPort::ADDR = 0x18; | const uint8_t IOExpanderPort::ADDR = 0x18; | ||||
One port is connected to the matrix's rows. The other port is connected to the matrix's columns. | One port is connected to the matrix's rows. The other port is connected to the matrix's columns. | ||||
The IOExpanderPort constructor parameters specify the port number and initial output value. | The IOExpanderPort constructor parameters specify the port number and initial output value. | ||||
I/O Expander and AVR have similar constructor parameters for RowPort and ColPort. | |||||
port1_R is port 1 and has an initial output value of 0. | port1_R is port 1 and has an initial output value of 0. | ||||
rowPort1_R uses port1_R. | rowPort1_R uses port1_R. |
> Some of the pictures do not match the sketches, they will be updated after changing to Teensy LC | > Some of the pictures do not match the sketches, they will be updated after changing to Teensy LC | ||||
> Schematic diagrams are missing from tutorials 2 and 4, they will be added after changing to Teensy LC | |||||
You will need a breadboard keyboard with a Teensy 2.0 controller to run the tutorial sketches. | You will need a breadboard keyboard with a Teensy 2.0 controller to run the tutorial sketches. | ||||
If you use a different controller, you may have to change port classes. | If you use a different controller, you may have to change port classes. | ||||
If you already have a keyboard with an Arduino compatible controller, you can use that instead of a breadboard keyboard. | If you already have a keyboard with an Arduino compatible controller, you can use that instead of a breadboard keyboard. |
* follow pin connections table (below) and consult pinout diagram in | * follow pin connections table (below) and consult pinout diagram in | ||||
[Teensy2_pinout.txt](../doc/Teensy2_pinout.txt) | [Teensy2_pinout.txt](../doc/Teensy2_pinout.txt) | ||||
<!-- todo replace this table with a schematic | |||||
This schematic was written by consulting the micro-controller's datasheet and using the ?? tool. | |||||
todo add a schematic | |||||
this table might not match the sketches | |||||
<!-- This schematic was written by consulting the micro-controller's datasheet and using the ?? tool. | |||||
this table might not match the sketches, replace with a schematic | |||||
**Teensy 2.0 pin connections table** | **Teensy 2.0 pin connections table** | ||||
Tutorial 2 - single-layer keyboard | Tutorial 2 - single-layer keyboard | ||||
======================================= | ======================================= | ||||
[keybrd_2_single-layer_annotated.ino](keybrd_2_single-layer_annotated/keybrd_2_single-layer_annotated.ino) explains how a keybrd sketch works. | [keybrd_2_single-layer_annotated.ino](keybrd_2_single-layer_annotated/keybrd_2_single-layer_annotated.ino) explains how a keybrd sketch works. | ||||
You can view the class definitions in the [keybrd library](../src/). | You can view the class definitions in the [keybrd library](../src/). | ||||
After reading the sketch you will be able to modify it to suite your own single-layer keyboard design. | After reading the sketch you will be able to modify it to suite your own single-layer keyboard design. |
## Pseudo code for simple layer scheme | ## Pseudo code for simple layer scheme | ||||
The following pseudo code has just enough detail to show how layer schemes work. | The following pseudo code has just enough detail to show how layer schemes work. | ||||
**Layer** objects control the active layer. | |||||
There is one Key_Layer object for each layer. Each Key_Layer object has a unique layer number. | |||||
When a Layer object is pressed, it tells StateLayer to change the active layer. | |||||
**Layer** objects select the active layer. | |||||
When a Layer object is pressed, it tells StateLayer to update the active layer. | |||||
There is one Key_Layer object for each layer. Each Key_Layer object has a unique layer Id number. | |||||
``` | ``` | ||||
class Key_Layer | class Key_Layer | ||||
{ | { | ||||
int layer | int layer | ||||
StateLayer& refState | |||||
press() { refState.setLayer(layer) } | |||||
StateLayer& refStateLayer | |||||
press() { refStateLayer.setLayer(layer) } | |||||
} | } | ||||
``` | ``` | ||||
A **StateLayer** object's activeLayer is always up to date. | |||||
A **StateLayer**'s activeLayer is always up to date. | |||||
``` | ``` | ||||
class StateLayer | class StateLayer | ||||
{ | { | ||||
} | } | ||||
``` | ``` | ||||
**Layered** objects contain one scancode for each layer. | |||||
**Layered** objects contain an array of Key pointers, one Key pointer for each layer. | |||||
Layer Id numbers are used as array indexes in the Key_Layered ptrsKeys array. | |||||
When a Layered object is pressed, it gets the active layer from StateLayer, and then presses the key of the active layer. | When a Layered object is pressed, it gets the active layer from StateLayer, and then presses the key of the active layer. | ||||
``` | ``` | ||||
class Key_Layered | class Key_Layered | ||||
{ | { | ||||
Key** ptrsKeys //array of Key pointers, one Key per layer | |||||
StateLayer& refState | |||||
press() { layer = refState.getLayer() | |||||
Key** ptrsKeys //array of Key pointers, one Key pointer per layer | |||||
StateLayer& refStateLayer | |||||
press() { layer = refStateLayer.getActiveLayer() | |||||
ptrsKeys[layer]->press() } | ptrsKeys[layer]->press() } | ||||
} | } | ||||
``` | ``` | ||||
* Code_LayerHold | * Code_LayerHold | ||||
* Code_LayerLock | * Code_LayerLock | ||||
<!-- todo --> | |||||
(Future version of keybrd library may change all Code classes to Key classes.) | (Future version of keybrd library may change all Code classes to Key classes.) | ||||
## A simple multi-layer keybrd sketch | ## A simple multi-layer keybrd sketch |
~ ! @ # $ % ^ & * () _ {} | < > : ? | ~ ! @ # $ % ^ & * () _ {} | < > : ? | ||||
The keybrd library does this by automatically sending the MODIFIERKEY_SHIFT scancode. | |||||
The keybrd library does this by automatically sending a MODIFIERKEY_SHIFT scancode. | |||||
The [keybrd_3_autoShift_annotated.ino](keybrd_3_autoShift_annotated/keybrd_3_autoShift_annotated.ino) sketch explains the AutoShift feature. | The [keybrd_3_autoShift_annotated.ino](keybrd_3_autoShift_annotated/keybrd_3_autoShift_annotated.ino) sketch explains the AutoShift feature. | ||||
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. |
* Serial CLock signal (SCL) | * Serial CLock signal (SCL) | ||||
* Serial DAta signal (SDA) | * Serial DAta signal (SDA) | ||||
A capacitor on the power pin smooths power to the I/O expander. | |||||
A decoupling capacitor on the power pin dampens noise coming in through the power wire. | |||||
The microcontroller and I/O expander communicate via [I2C](http://en.wikipedia.org/wiki/I%C2%B2C) bus, which consists of two signals: SCL and SDA. | The microcontroller and I/O expander communicate via [I2C](http://en.wikipedia.org/wiki/I%C2%B2C) bus, which consists of two signals: SCL and SDA. | ||||
Two resistors pull-up voltage on the SCL and SDA. | Two resistors pull-up voltage on the SCL and SDA. | ||||
I/O expander I2C address is configured by three hardware pins (AD0, AD1, AD2). | |||||
I/O expander I2C address is configured by hardware pins. | |||||
The MCP23018 with all address pins grounded has an I2C address of ?? todo. | |||||
The I/O expander has two ports. Each port has eight pins. | The I/O expander has two ports. Each port has eight pins. | ||||
One port is connected to the matrix's rows. The other port is connected to the matrix's columns. | One port is connected to the matrix's rows. The other port is connected to the matrix's columns. | ||||
## Building a split keyboard with I/O Expander | ## Building a split keyboard with I/O Expander | ||||
The split keyboard is built on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md) | |||||
We will build a split keyboard adding parts to the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md) | |||||
<!-- todo add schematic with a capacitor to IOE power | |||||
todo add schematic | |||||
<!-- schematic with IOE power decoupling capacitor | |||||
This schematic was written by consulting the I/O expander's datasheet and using the ?? tool. --> | This schematic was written by consulting the I/O expander's datasheet and using the ?? tool. --> | ||||
Continuing from the basic breadboard keyboard instructions: | Continuing from the basic breadboard keyboard instructions: | ||||
<!-- At some point in the future, Markdown may support starting ordered lists at an arbitrary number. --> | |||||
4. Insert the I/O expander | 4. Insert the I/O expander | ||||
5. Install I/O expander power | 5. Install I/O expander power | ||||
* ground | |||||
* power | |||||
* capacitor | |||||
* ground | |||||
* power | |||||
* capacitor | |||||
6. Install I2C bus | 6. Install I2C bus | ||||
* SCL | |||||
* SDA | |||||
* pull-up resistors on SCL and SDA | |||||
* SCL | |||||
* SDA | |||||
* pull-up resistors on SCL and SDA | |||||
7. configure I2C address | 7. configure I2C address | ||||
The keybrd library contains the foundation classes for creating a keyboard firmware. | The keybrd library contains the foundation classes for creating a keyboard firmware. | ||||
keybrd extension libraries extend the core keyboard library. | keybrd extension libraries extend the core keyboard library. | ||||
keybrd extension library names are prefixed by "keybrd_" and are listed in: | |||||
keybrd extension library names are prefixed by "keybrd_" and are listed in: todo keybrd extension libraries are not listed yet | |||||
* [Arduino Playground](http://playground.arduino.cc/Main/InterfacingWithHardware#keyb) > find "keybrd" | * [Arduino Playground](http://playground.arduino.cc/Main/InterfacingWithHardware#keyb) > find "keybrd" | ||||
* Arduino Library-Manager (Arduino IDE > Sketch > Include Library > Manage Libraries > Filter your search: keybrd) | * Arduino Library-Manager (Arduino IDE > Sketch > Include Library > Manage Libraries > Filter your search: keybrd) | ||||
======================================================================= | ======================================================================= | ||||
Publishing and listing your keybrd extension library allows others to find and install your library. | Publishing and listing your keybrd extension library allows others to find and install your library. | ||||
The keybrd extension library name should start with "keybrd_" so that it is easy for people to find. | The keybrd extension library name should start with "keybrd_" so that it is easy for people to find. | ||||
The directory structure of the library depends on where it will be listed. | The directory structure of the library depends on where it will be listed. | ||||
## Publishing anywhere with listing on Arduino Playground LibraryList | ## Publishing anywhere with listing on Arduino Playground LibraryList |