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, aggregation, inheritance, polymorphism, and enum. Some classes use bit manipulation. ## Class inheritance diagrams Keybrd library class inheritance diagram ``` Matrix RowBase | Row IOExpanderPort _______ RowPort _______ / | \ RowPort_AVR RowPort_MCP23018 RowPort_PCA9655E (one RowPort class for each type of IC) _______ ColPort _______ / | \ ColPort_AVR ColPort_MCP23018 ColPort_PCA9655E (one ColPort class for each type of IC) _____ LED ______ / | \ LED_AVR LED_MCP23018 LED_PCA9655E (one LED class for each type of IC) 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_LockLED / | \ Code_ScS Code_ScNS Code_ScNS_00 ``` ## Dependency diagrams single-layer dependency diagram with LEDs ``` matrix[1..*] | row[1..*]_____________________________ | \ \ \ rowPort[1] rowPin[1] colPort[1] keys[1] | | colPins[1..*] code[1..*] | LED[1] ``` multi-layer dependency diagram with LEDs and I/O Expander ``` matrix[1..*] | layerStates[1..*] row[1..*]_________________________________________/__ | \ | \ \ \ / \ | \ rowPort[1] rowPin[1] colPort[1] keys[1] / code_layer[1..*] LED[0..*] \ / \ | / / \ / colPins[1..*] key[1..*] / \ / | / \ / code[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 ## 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. Refer to it like a table of contents while reading the keybrd library. ``` Matrix::scan() for each row Row::process() Row::wait() Row::scan() RowPort_*::setActivePin*() strobe row on for each col port ColPort_*::read() read col port RowPort_*::setActivePin*() strobe row off Row::getRowState() for each col port for each connected col pin if key is pressed set rowState bit Row::debounce() debounce Row::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) ``` ## 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 #include #include #include Creative Commons License
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.