Archived
1
0
This repo is archived. You can view files and clone it, but cannot push or open issues or pull requests.
keybrd/doc/keybrd_library_developer_guide.md

8.9 KiB

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 adding new classes are:

  • I/O expander classes
  • 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 the C++ language including pointers, objects, classes, static class variables, composition, aggregation, inheritance, polymorphism, and enum. Row, Scanner, and Debouncer classes use bit manipulation.

Class inheritance diagrams

Keybrd library class inheritance diagram

    Row

	     ___ ScannerInterface ___
	    /          |             \
	Scanner_uC  Scanner_IOE  Scanner_ShiftRegsPISO


                PortWriteInterface
                 /           \
	       PortInterface   Port_ShiftRegs       (Port class for MOSI shift registers)
	         /        \
	Port_PCA9655E  Port_MCP23S17                (one Port class for each IOE type)
 
 
	  LEDInterface
	   /       \
	LED_uC    LED_Port


	DebouncerInterface
	      |
	Debouncer_Samples

    ScanDelay

	LayerStateInterface
	     |
	LayerState


	Key
	 |____
	 |    \
	 |   Key_LayeredKeysBase
	 |      \____________________
	 |      /                    \
	 |   Key_LayeredKeys      Key_LayeredKeys1
	 |
	 |___________________________
	 |     \                     \
	 |   Key_LayeredScScBase  Key_LayeredCodeScBase
	 |      |                     |
	 |   Key_LayeredScSc      Key_LayeredCodeSc
	 |
	Code
	 |_____________________
	 |     \               \
	 |   Code_LayerLock  Code_LayerHold
	 |
	  \________________________________________________________
	       \           \            \           \              \
	     Code_Sc  Code_Shift  Code_AutoShift  Code_LEDLock  Code_Null
	                             /      \
	                        Code_ScS  Code_ScNS

Dependency diagrams

Dependency diagram of example single-layer keyboard with LEDs

	        ____ Row ______
	       /      |        \
	Scanner_uC  Debouncer  Key ___
	      |                 |     \
	readPins               Code  Code_LEDLock
	                               |
	                             LED_PinNumber

Dependency diagram of example multi-layer keyboard with layer LEDs

	                                          LayerStates
	         ___________ Row ________________/__   |     \
	        /        /            \         /   \  |      \
	Scanner_uC  Debouncer  Key_LayeredKeys / Code_Layer  LED_PinNumber
	       |                           \  /
	  readPins                         Code

Dependency diagram of example shift registers Row

	                  _______ Row _______
	                 /         |         \
	RowScanner_ShiftRegsPISO  Debouncer  Key
	                                      |
	                                     Code

Dependency diagram of example I/O expander matrix with LEDs

	                 _________ Row ________
	                /             \        \
	        __ Scanner_IOE __   Debouncer  Key
	       /       |         \             /  \
	strobePin  PortWrite  PortRead      Code  Code_LEDLock
	             |   \      /   \              |
	             |    PortIOE  readPins       LED_Port
	              \___________________________/ \
                                                pin

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.

Interface class names end with "Interface". Except for Key, to reduce clutter because sketches define so many Key[] arrays.

Layer-class naming conventions

Layer classes are explained in tutorial_3a_multi-layer_keyboard.md.

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

Key_Layered class names start with "Key_Layered" and end with a descriptive name. Example Key_Layered class names:

  • Key_LayeredScSc
  • Key_LayeredKeys

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".
  • Member names use camelCase starting with lowercase letter.
  • Use constants rather than macros, except for header guards.
  • Global const names and static const names use ALL_CAPS_WITH_UNDERSCORE.
  • Macros use ALL_CAPS_WITH_UNDERSCORE and have _MACRO suffix e.g. SAMPLE_COUNT_MACRO
  • Header guards have _H suffix e.g. #ifndef FILE_NAME_H
  • Pointer names are prefixed with "ptr" e.g. ptrRow = &row;
  • Arrays names use the plural of the element name e.g. Row* const = ptrsRows { &row0, &row1 };
  • Pass arrays using array notation rather than pointer notation:
        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 (make memory leaks impossible).

  • Document class interface in .h file, above the class declaration.

  • Code should be self-documenting. A simple function with a good name needs no comment.

  • Code is automatically formatted 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 a list of functions in the order that they are called. The trace is of a one-row single-layer keybrd scan.

    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 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.