keybrd library is an open source library for creating custom-keyboard firmware.
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
Tento repozitář je archivovaný. Můžete prohlížet soubory, klonovat, ale nemůžete nahrávat a vytvářet nové úkoly a požadavky na natažení.

keybrd_library_developer_guide.md 12KB

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 from a fictional keybrd_Ext library the keybrd_Ext library library is for a split keyboard with a matrix on each hand the diagrams show the design decisions made by the developer

Row_Ext overrides RowBase::keyWasPressed() Row_Ext::keyWasPressed() is used to unstick sticky keys

Row_Ext_uC scans the primary matrix Row_Ext_uC is a custom class composed of stock keybrd library classes

Row_Ext_ShiftRegisters scans the secondary matrix Row_Ext_ShiftRegisters is a custom class 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()

/home/wolfv/Documents/Arduino/keybrd_proj/keybrd/doc/keybrd_library_developer_guide.md
                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_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)


    DebouncerInterface
          |
    Debouncer_4Samples


    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

Example single-layer dependency diagram with LEDs

                 matrix[1..*]
                   |
             ___ row_uC[1..*] ________
            /               \         \
    RowScanner_PinsArray  debouncer  keys[1..*]
      /             \                  |
    strobePin[1]  readPins[1..*]     code[1..*]
                                       |
                                     LED[1]

Example single-layer dependency diagram I/O Expander

             ________ row_uC[1..*] _________
            /                     \         \
    RowScanner_PinsArray[1]  debouncer[1]  keys[1..*]
      /             \                        |
    strobePin[1]  readPins[1..*]           code[1..*]

    
                     ___ row_IOE[1..*] _________
                    /             \             \
      RowScanner_PinsBitwise[1]  debouncer[1]  keys[1..*]
         /         |        \                    |
    rowPort[1]  rowPin[1]  colPort[1]          code[1..*]
         \                /   \
          \              /   colPins[1..*]
           \            /
          IOExpanderPort[0..*] 

Example multi-layer dependency diagram with layer LEDs

                                                        layerStates[1..*]
             ________ row_uC[1..*] _____________________/__    |         \
            /                     \         \          /   \   |          \
    RowScanner_PinsArray[1]  debouncer[1]  keys[1..*] / code_layer[1..*]  LED[0..*]
      /             \                        |       /
    strobePin[1]  readPins[1..*]           code[1..*]

Example multi-layer dependency diagram with shift registers

    Row_ShiftRegisters

Example multi-layer dependency diagram with I/O Expander

                                                        
             ________ row_uC[1..*] ________________________     _______layerStates[1..*]
            /                     \         \              \   /             |
    RowScanner_PinsArray[1]  debouncer[1]  keys[1..*]   code_layer[1..*]     |
      /             \                        |       ________________________|
    strobePin[1]  readPins[1..*]           code[1..*]                        |
                                                                             |
                                                                             |
                     ___ row_IOE[1..*] _________                   __________|
                    /             \             \                 /          |
      RowScanner_PinsBitwise[1]  debouncer[1]  keys[1..*]  code_layer[1..*]  |
         /         |        \                    |      _____________________|
    rowPort[1]  rowPin[1]  colPort[1]          code[1..*]
         \                /   \
          \              /   colPins[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 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. 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.

    Matrix::scan()                              for each row
        RowBase::process()
            RowBase::wait()                         delay time for debounce
            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)

The Arduino libraries

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>

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.