2016-05-09 14:05:08 +00:00
keybrd Library Developer's Guide
================================
2016-05-11 18:46:53 +00:00
This guide if for maintaining and writing new classes for the keybrd library and its extension libraries.
2016-05-09 19:41:29 +00:00
The most common reason for new classes are:
2016-05-09 14:05:08 +00:00
* Port classes for micro controller or I/O expanders
* custom layer schemes for multi-layer keyboards
* experimental features
## Who this guide is for
2016-05-09 19:41:29 +00:00
This guide is for the maintainers and developers of the keybrd library and it's extensions.
2016-06-11 02:12:56 +00:00
It is assumed the reader is familiar with C++ language including pointers, objects, classes, static class variables, composition, aggregation, inheritance, polymorphism, and enum.
Debouncer and I/O expander use bit manipulation.
2016-05-09 14:05:08 +00:00
2016-07-04 03:26:38 +00:00
## Custom Row classes
The keybrd library is flexible for designing custom Rows
* RowBase functions can be overridden in a derived class
* choice of Debouncers
* choice of Scanners
2016-05-09 14:05:08 +00:00
2016-07-04 23:29:24 +00:00
this example illustrates the custom Row classes for a fictional keybrd_Ext extension library
the keybrd_Ext library is for a split keyboard with a matrix on each hand
other custom Row classes would have a similar structure
2016-07-04 03:26:38 +00:00
2016-07-04 23:29:24 +00:00
Row_Ext::keyWasPressed() overrides RowBase::keyWasPressed()
2016-07-04 03:26:38 +00:00
Row_Ext::keyWasPressed() is used to unstick sticky keys
Row_Ext_uC scans the primary matrix
Row_Ext_ShiftRegisters scans the secondary matrix
2016-07-04 23:29:24 +00:00
Row_Ext_uC and Row_Ext_ShiftRegisters are a custom classes composed of stock keybrd library classes
2016-07-04 03:26:38 +00:00
Class inheritance diagram
2016-05-09 14:05:08 +00:00
```
2016-07-04 03:26:38 +00:00
RowBase
|
2016-07-04 23:29:24 +00:00
Row_Ext (override RowBase::keyWasPressed() )
2016-07-04 03:26:38 +00:00
/ \
2016-07-04 23:29:24 +00:00
Row_Ext_uC Row_Ext_ShiftRegisters (inherit Row_Ext::keyWasPressed() )
2016-06-11 02:12:56 +00:00
RowScannerInterface
/ \
2016-07-04 03:26:38 +00:00
RowScanner_PinsArray RowScanner_SPIShiftRegisters
2016-06-11 02:12:56 +00:00
2016-07-04 03:26:38 +00:00
```
Dependency diagram
```
________ Row_Ext_uC[1] _______________
/ \ \
RowScanner_PinsArray[1] Debouncer_Samples[1] Key[1..*]
2016-07-04 23:29:24 +00:00
/ \ |
2016-07-04 03:26:38 +00:00
strobePin[1] readPins[1..*] Code[1..*]
2016-07-04 23:29:24 +00:00
_____ Row_Ext_ShiftRegisters[1] ___________
/ \ \
2016-07-04 03:26:38 +00:00
RowScanner_SPIShiftRegisters[1] Debouncer_Samples[1] Key[1..*]
/ \ |
strobePin[1] ROW_END[1] Code[1..*]
```
## Class inheritance diagrams
Keybrd library class inheritance diagram
```
2016-07-04 23:29:24 +00:00
_______ RowBase ________
2016-07-04 03:26:38 +00:00
/ | \
Row_uC Row_ShiftRegisters Row_IOE
2016-07-04 23:29:24 +00:00
_____ RowScannerInterface ______
/ | \
2016-07-04 03:26:38 +00:00
RowScanner_PinsArray RowScanner_PinsBitwise RowScanner_SPIShiftRegisters
2016-05-09 14:05:08 +00:00
2016-07-04 23:29:24 +00:00
2016-05-09 14:05:08 +00:00
IOExpanderPort
2016-07-04 23:29:24 +00:00
RowPort
|
RowPort_PCA9655E (one RowPort class for each IOE type)
2016-05-09 14:05:08 +00:00
2016-07-04 23:29:24 +00:00
ColPort
|
ColPort_PCA9655E (one ColPort class for each IOE type)
2016-05-09 14:05:08 +00:00
2016-07-04 23:29:24 +00:00
____ LED ____
/ \
LED_PinNumber LED_PCA9655E
2016-05-09 14:05:08 +00:00
2016-06-11 02:12:56 +00:00
DebouncerInterface
|
Debouncer_4Samples
2016-07-05 21:45:58 +00:00
ScanDelay
2016-06-11 02:12:56 +00:00
2016-05-28 21:16:32 +00:00
LayerStateInterface
2016-06-11 02:12:56 +00:00
|
2016-05-28 21:16:32 +00:00
LayerState
2016-05-09 14:05:08 +00:00
Key __
| \
| Key_LayeredKeysArray
|
Code
|_____________________
| \ \
| Code_LayerLock Code_LayerHold
|
|___________________________
| \ \
| Code_LayeredScScBase Code_LayeredCodeScBase
| | |
| Code_LayeredScSc Code_LayeredCodeSc
|
|__________________________________________
\ \ \ \
2016-07-04 23:29:24 +00:00
Code_Sc Code_Shift Code_AutoShift Code_LEDLock
2016-05-09 14:05:08 +00:00
/ | \
Code_ScS Code_ScNS Code_ScNS_00
```
2016-05-11 15:25:48 +00:00
## Dependency diagrams
2016-05-09 14:05:08 +00:00
2016-06-11 02:12:56 +00:00
Example single-layer dependency diagram with LEDs
2016-05-09 14:05:08 +00:00
```
2016-07-04 23:29:24 +00:00
___ Row_uC[1..*] ________
2016-06-11 02:12:56 +00:00
/ \ \
2016-07-04 23:29:24 +00:00
RowScanner_PinsArray Debouncer Keys[1..*] __
| \
Code[1..*] Code_LEDLock[1..*]
|
LED_PinNumber[1]
2016-06-11 02:12:56 +00:00
```
Example multi-layer dependency diagram with layer LEDs
```
2016-07-04 23:29:24 +00:00
LayerStates[1..*]
________ Row_uC[1..*] _____________________ /__ | \
2016-06-11 02:12:56 +00:00
/ \ \ / \ | \
2016-07-04 23:29:24 +00:00
RowScanner_PinsArray[1] Debouncer[1] Keys[1..*] / Code_Layer[1..*] LED_PinNumber[0..*]
| /
Code[1..*]
2016-06-11 02:12:56 +00:00
```
2016-07-04 23:29:24 +00:00
Example secondary matrix with shift registers dependency diagram
2016-07-04 03:26:38 +00:00
```
2016-07-04 23:29:24 +00:00
Row_ShiftRegisters[1..*]
/ \ \
RowScanner_ShiftRegisters Debouncer Keys[1..*]
|
Code[1..*]
2016-07-04 03:26:38 +00:00
```
2016-07-04 23:29:24 +00:00
Example secondary matrix with I/O Expander dependency diagram with LEDs
2016-06-11 02:12:56 +00:00
```
2016-07-04 23:29:24 +00:00
___ Row_IOE[1..*] _________
/ \ \
RowScanner_PinsBitwise[1] Debouncer[1] Keys[1..*] __
/ | \ | \
RowPort[1] RowPin[1] ColPort[1] Code[1..*] Code_LEDLock[1..*]
\ / \ |
\ / ColPins[1..*] LED[1]
2016-06-11 02:12:56 +00:00
\ /
2016-07-04 23:29:24 +00:00
IOExpanderPort[0..*]
2016-05-09 14:05:08 +00:00
```
## Class naming conventions
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
|
2016-05-11 18:46:53 +00:00
Code_LayerLock
2016-05-09 14:05:08 +00:00
```
This convention leads to class names that convey information about the classes inheritance.
2016-05-09 19:41:29 +00:00
Underscore delineates base class name and sub-class name. Capital letters delineate words.
2016-05-09 14:05:08 +00:00
2016-05-28 18:37:40 +00:00
## Layer-class naming conventions
*Code_Layer* class names are concatenations of "Code_", "Layer" or layer name, and persistence.
Example persistences are:
* "Lock" - layer remains active after the layer key is released
* "Hold" - layer is active for as long as layer key is held down
Example Code_Layer class names:
* Code_LayerHold
* Code_LayerLock
2016-05-28 21:16:32 +00:00
*LayerState* class names start with "LayerState" and end with a descriptive name.
Example LayerState class names:
* LayerState - basic LayerState class in keybrd library
* LayerState_DH - main LayerState for the keybrd_DH library
* LayerState_MF - LayerState for Mouse Function sub-layers in the keybrd_DH library
2016-05-28 18:37:40 +00:00
*Code_Layered* class names start with "Code_Layered" and end with a descriptive name.
Example Code_Layered class names:
* Code_LayeredScSc
* Key_LayeredKeysArray
2016-05-09 14:05:08 +00:00
## Style guide
Following the style guide makes it easier for the next programmer to understand your code.
2016-05-09 19:41:29 +00:00
* For class names, see above section "Class naming conventions"
2016-05-09 14:05:08 +00:00
* For member names, use camelCase starting with lowercase letter.
* Use constants rather than macros, except for header guards.
* For constant names that could be macros, use ALL_CAPS_AND_UNDERSCORE.
* **ITEM_COUNT** is a constant number of items.
* **itemCount** is a variable number of items.
* Use header guards CLASS_NAME_H.
2016-05-11 18:46:53 +00:00
* Prefix pointer name with "ptr" e.g. ptrRow = &row;
2016-05-09 19:41:29 +00:00
* Name arrays using the plural of element name e.g. Row* const = ptrsRows { & row0, & row1 };
2016-05-09 14:05:08 +00:00
* Pass arrays using array notation rather than pointer notation. Use
```
void printArray(char[] array);
not
void printArray( char* array);
```
2016-05-09 19:41:29 +00:00
* In constructor's initialization list, use same names for fields and constructor parameters.
* Do not use new or malloc (making memory leaks impossible).
2016-05-09 14:05:08 +00:00
* Document class interface in .h file, above the class declaration.
2016-05-09 21:38:10 +00:00
* 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.
2016-05-11 18:46:53 +00:00
* Code is automatically formated before being pushed to the keybrd repository.
The [astyle_cpp ](astyle_cpp ) file specifies the format:
2016-05-09 14:05:08 +00:00
* Allman style indentation
* indent 4 spaces
* replace tabs with spaces
* maximum code width of 100 columns
2016-05-09 21:38:10 +00:00
<!-- http://stackoverflow.com/questions/2198241/best - practice - for - c - function - commenting -->
2016-05-10 15:05:25 +00:00
## Trace of keybrd scan
2016-06-05 20:43:53 +00:00
Arduino does not have a debugger.
So here is the next best thing; a list of functions in the order that they are called.
2016-06-11 02:12:56 +00:00
The trace is of a single-layer keybrd scan (no LEDs and no I/O expander).
2016-05-09 14:05:08 +00:00
Refer to it like a table of contents while reading the keybrd library.
```
2016-07-04 23:29:24 +00:00
loop() for each row
2016-06-11 02:12:56 +00:00
RowBase::process()
RowScanner_PinsArray::scan() strobe row on
for each readPin
2016-05-09 14:05:08 +00:00
set rowState bit
2016-06-11 02:12:56 +00:00
strobe row off
Debouncer_4Samples::debounce() debounce
RowBase::pressRelease() 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)
2016-07-05 21:45:58 +00:00
scanDelay.delay();
2016-05-09 14:05:08 +00:00
```
## The Arduino libraries
The keybrd libraries compile on the Arduino IDE and make extensive use of the following [Arduino libraries ](https://www.arduino.cc/en/Reference/Libraries ):
#include < Arduino.h >
#include < Wire.h >
#include < Keyboard.h >
#include < Mouse.h >
2016-05-11 15:25:48 +00:00
2016-05-11 19:09:18 +00:00
< a rel = "license" href = "http://creativecommons.org/licenses/by/4.0/" > < img alt = "Creative Commons License" style = "border-width:0" src = "https://i.creativecommons.org/l/by/4.0/88x31.png" / > < / a > < br / > < span xmlns:dct = "http://purl.org/dc/terms/" property = "dct:title" > keybrd guide< / span > by < a xmlns:cc = "http://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 = "http://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 = "http://creativecommons.org/ns#" href = "https://github.com/wolfv6/keybrd/issues/new" rel = "cc:morePermissions" > https://github.com/wolfv6/keybrd/issues/new< / a > .