|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- keybrd Library Developer's Guide
- ================================
- 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:
- * Port classes for micro controller or I/O expanders
- * custom layer schemes for multi-layer keyboards
- * experimental features
-
- ## Who this guide is for
- 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.
- Debouncer and I/O expander use bit manipulation.
-
- ## 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
-
- 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
-
- Row_Ext::keyWasPressed() overrides RowBase::keyWasPressed()
- Row_Ext::keyWasPressed() is used to unstick sticky keys
-
- Row_Ext_uC scans the primary matrix
- Row_Ext_ShiftRegisters scans the secondary matrix
- Row_Ext_uC and Row_Ext_ShiftRegisters are a custom classes composed of stock keybrd library classes
-
- Class inheritance diagram
- ```
-
- RowBase
- |
- Row_Ext (override RowBase::keyWasPressed() )
- / \
- Row_Ext_uC Row_Ext_ShiftRegisters (inherit Row_Ext::keyWasPressed() )
-
-
- RowScannerInterface
- / \
- RowScanner_PinsArray RowScanner_SPIShiftRegisters
-
- ```
-
- Dependency diagram
- ```
-
- ________ Row_Ext_uC[1] _______________
- / \ \
- RowScanner_PinsArray[1] Debouncer_Samples[1] Key[1..*]
- / \ |
- strobePin[1] readPins[1..*] Code[1..*]
-
-
- _____ Row_Ext_ShiftRegisters[1] ___________
- / \ \
- RowScanner_SPIShiftRegisters[1] Debouncer_Samples[1] Key[1..*]
- / \ |
- strobePin[1] ROW_END[1] Code[1..*]
-
- ```
-
- ## Class inheritance diagrams
-
- Keybrd library class inheritance diagram
- ```
- _______ RowBase ________
- / | \
- Row_uC Row_ShiftRegisters Row_IOE
-
- _____ RowScannerInterface ______
- / | \
- RowScanner_PinsArray RowScanner_PinsBitwise RowScanner_SPIShiftRegisters
-
-
- IOExpanderPort
-
- RowPort
- |
- RowPort_PCA9655E (one RowPort class for each IOE type)
-
- ColPort
- |
- ColPort_PCA9655E (one ColPort class for each IOE type)
-
- ____ LED ____
- / \
- LED_PinNumber LED_PCA9655E
-
-
- DebouncerInterface
- |
- Debouncer_4Samples
-
- 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 Code_ScNS_00
-
- ```
-
- ## Dependency diagrams
-
- Example single-layer dependency diagram with LEDs
- ```
- ___ Row_uC[1..*] ________
- / \ \
- RowScanner_PinsArray Debouncer Keys[1..*] __
- | \
- Code[1..*] Code_LEDLock[1..*]
- |
- LED_PinNumber[1]
-
- ```
-
- Example multi-layer dependency diagram with layer LEDs
- ```
- LayerStates[1..*]
- ________ Row_uC[1..*] _____________________/__ | \
- / \ \ / \ | \
- RowScanner_PinsArray[1] Debouncer[1] Keys[1..*] / Code_Layer[1..*] LED_PinNumber[0..*]
- | /
- Code[1..*]
-
- ```
-
- Example secondary matrix with shift registers dependency diagram
- ```
- Row_ShiftRegisters[1..*]
- / \ \
- RowScanner_ShiftRegisters Debouncer Keys[1..*]
- |
- Code[1..*]
-
- ```
-
- Example secondary matrix with I/O Expander dependency diagram with LEDs
- ```
- ___ 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]
- \ /
- IOExpanderPort[0..*]
-
- ```
-
- ## 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
- |
- 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.
-
- ## 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
-
- *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
-
- *Code_Layered* class names start with "Code_Layered" and end with a descriptive name.
- Example Code_Layered class names:
- * Code_LayeredScSc
- * Key_LayeredKeysArray
-
- ## Style guide
- Following the style guide makes it easier for the next programmer to understand your code.
- * For class names, see above section "Class naming conventions"
- * 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.
- * Prefix pointer name with "ptr" e.g. ptrRow = &row;
- * 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
- ```
- void printArray(char[] array);
- not
- void printArray( char* array);
- ```
- * In constructor's initialization list, use same names for fields and constructor parameters.
- * Do not use new or malloc (making memory leaks impossible).
- * 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 is automatically formated before being pushed to the keybrd repository.
- The [astyle_cpp](astyle_cpp) file specifies the format:
- * Allman style indentation
- * indent 4 spaces
- * replace tabs with spaces
- * maximum code width of 100 columns
-
- <!-- http://stackoverflow.com/questions/2198241/best-practice-for-c-function-commenting -->
-
- ## Trace of keybrd scan
- 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 single-layer keybrd scan (no LEDs and no I/O expander).
- Refer to it like a table of contents while reading the keybrd library.
-
- ```
- loop() for each row
- RowBase::process()
- RowScanner_PinsArray::scan() strobe row on
- for each readPin
- set rowState bit
- 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)
- scanDelay.delay();
-
- ```
-
- ## 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>
-
- <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>.
|