This guide if for maintaining and writing new classes for the keybrd library and its extension libraries. The most common reason for adding new classes are:
This guide is for the maintainers and developers of the keybrd library and it’s extensions. It is assumed the reader is familiar with C++ language including pointers, objects, classes, static class variables, composition, aggregation, inheritance, polymorphism, and enum. Row, Scanner, and Debouncer classes use bit manipulation.
Row classes are central to the keybrd library. Row is an abstract base class that allows flexibility for designing derived Row classes:
This example illustrates the custom Row classes for a fictional keybrd_Ext extension library. The keybrd_Ext library is for a split keyboard with sticky keys and a matrix on each hand.
Row_Ext::keyWasPressed() overrides Row::keyWasPressed()
Row_Ext::keyWasPressed() is used to unstick sticky keys
Row_Ext_uC and Row_Ext_ShiftRegisters are a custom classes composed of stock keybrd library classes.
Row_Ext_uC uses Scanner_uC to scan the primary matrix.
Row_Ext_ShiftRegisters uses Scanner_ShiftRegs74HC165 to scan the secondary matrix.
Class inheritance diagram
Row
|
Row_Ext (override Row::keyWasPressed() )
/ \
Row_Ext_uC Row_Ext_ShiftRegisters (inherit Row_Ext::keyWasPressed() )
Scanner_uC Scanner_ShiftRegs74HC165
Dependency diagram
________ Row_Ext_uC[1] ______________
/ | \
Scanner_uC[1] Debouncer_Samples[1] Key[1..*]
/ |
strobePin[1] Code[1..*]
_________ Row_Ext_ShiftRegisters[1] ________
/ \ \
Scanner_ShiftRegs74HC165[1] Debouncer_Samples[1] Key[1..*]
| |
strobePin[1] Code[1..*]
Keybrd library class inheritance diagram
________ Row ___________
/ | \
Row_uC Row_ShiftRegisters Row_IOE (to be added)
Scanner_uC Scanner_Port Scanner_ShiftRegs74HC165
PortIOE
PortWrite
|
PortWrite_PCA9655E (one PortWrite class for each IOE type)
PortRead
|
PortRead_PCA9655E (one PortRead class for each IOE type)
_ LED _
/ \
LED_uC LED_PCA9655E
DebouncerInterface
|
Debouncer_Samples
ScanDelay
LayerStateInterface
|
LayerState
Key __
| \
| Key_LayeredKeysArray
|
Code
|_____________________
| \ \
| Code_LayerLock Code_LayerHold
|
|___________________________
| \ \
| Code_LayeredScScBase Code_LayeredCodeScBase
| | |
| Code_LayeredScSc Code_LayeredCodeSc
|
|__________________________________________
\ \ \ \
Code_Sc Code_Shift Code_AutoShift Code_LEDLock
/ \
Code_ScS Code_ScNS
Dependency diagram of example single-layer keyboard with LEDs
_ Row_uC[1..*] _
/ | \
Scanner_uC Debouncer Keys[1..*] __
| \
Code[1..*] Code_LEDLock[1..*]
|
LED_PinNumber[1]
Dependency diagram of example multi-layer keyboard with layer LEDs
LayerStates[1..*]
________ Row_uC[1..*] ___________/__ | \
/ | \ / \ | \
Scanner_uC[1] Debouncer[1] Keys[1..*] / Code_Layer[1..*] LED_PinNumber[0..*]
| /
Code[1..*]
Dependency diagram of example secondary matrix with shift registers
Row_ShiftRegisters[1..*]
/ \ \
RowScanner_ShiftRegisters Debouncer Keys[1..*]
|
Code[1..*]
Dependency diagram of example secondary matrix with I/O Expander and LEDs
___ Row_IOE[1..*] _________
/ \ \
_ Scanner_Port[1] _ Debouncer[1] Keys[1..*] __
/ | \ | \
PortWrite[1] RowPin[1] PortRead[1] Code[1..*] Code_LEDLock[1..*]
\ / \ |
\ / ColPins[1..*] LED[1]
\ /
PortIOE[0..*]
Class names start with upper case letter. Most derived-class names start with the base class name followed by “_” and a name e.g.
Code
|
Code_LayerLock
This convention leads to class names that convey information about the classes inheritance. Underscore delineates base class name and sub-class name. Capital letters delineate words.
Code_Layer class names are concatenations of “Code_“, “Layer” or layer name, and persistence. Example persistences are:
Example Code_Layer class names:
LayerState class names start with “LayerState” and end with a descriptive name. Example LayerState class names:
Code_Layered class names start with “Code_Layered” and end with a descriptive name. Example Code_Layered class names:
Following the style guide makes it easier for the next programmer to understand your code.
void printArray(char[] array);
not
void printArray( char* array);
Arduino does not have a debugger. So here is the next best thing; a list of functions in the order that they are called. The trace is of a one-row single-layer keybrd scan. Refer to it like a table of contents while reading the keybrd library.
loop() for each row
Row::process()
Scanner_uC::scan() strobe row on
for each readPin
set readState bit
strobe row off
Debouncer_Samples::debounce() debounce
Row::send() for each key in row
if falling edge
Key_*::release() scanCode->release()
Code_*::release() Keyboard.release(scancode)
if rising edge
Key_*::press() scanCode->press()
Code_*::press() Keyboard.press(scancode)
scanDelay.delay();
The keybrd libraries compile on the Arduino IDE and make extensive use of the following Arduino libraries:
#include <Arduino.h>
#include <Wire.h>
#include <Keyboard.h>
#include <Mouse.h>
keybrd guide by Wolfram Volpi is licensed under a Creative Commons Attribution 4.0 International License.
Permissions beyond the scope of this license may be available at https://github.com/wolfv6/keybrd/issues/new.