Browse Source

move Debug variables to static

tags/v0.5.0
wolfv6 7 years ago
parent
commit
c9a3abd4e7
62 changed files with 643 additions and 1033 deletions
  1. 66
    0
      CONTRIBUTING.md
  2. 25
    18
      README.md
  3. 24
    10
      doc/CHANGELOG.md
  4. 14
    0
      doc/PLANNED_FEATURES.md
  5. 0
    37
      doc/Teensy2_pinout.txt
  6. 1
    1
      doc/astyle_cpp
  7. 65
    55
      doc/keybrd_library_developer_guide.md
  8. 61
    78
      doc/keybrd_library_user_guide.md
  9. 0
    21
      doc/planned_features.md
  10. 0
    165
      examples/keybrd_shift_register/keybrd_shift_register.ino
  11. BIN
      images/datahand.jpg
  12. 1
    1
      library.properties
  13. 4
    4
      src/Code_AutoShift.h
  14. 14
    14
      src/Code_LEDLock.cpp
  15. 1
    1
      src/Debouncer_Samples.cpp
  16. 6
    0
      src/Debug.cpp
  17. 0
    4
      src/Debug.h
  18. 2
    2
      src/Key_LayeredKeysArray.h
  19. 1
    1
      src/PortRead_PCA9655E.cpp
  20. 1
    1
      src/Row.cpp
  21. 2
    2
      src/Row.h
  22. 2
    1
      src/Row_ShiftRegisters.h
  23. 2
    2
      src/Row_uC.h
  24. 1
    1
      src/ScanDelay.h
  25. 1
    1
      src/Scanner_Port.cpp
  26. 6
    5
      src/Scanner_ShiftRegs74HC165.h
  27. 1
    1
      src/Scanner_uC.cpp
  28. 1
    1
      src/Scanner_uC.h
  29. 0
    53
      src/getFreeSRAM.h
  30. BIN
      tutorials/breadboard_keyboard_supplies.ods
  31. 0
    0
      tutorials/keybrd_1_breadboard/120px-Diode_pinout_en_fr.svg.png
  32. 0
    0
      tutorials/keybrd_1_breadboard/breadboard_keyboard_2x2.JPG
  33. BIN
      tutorials/keybrd_1_breadboard/breadboard_keyboard_2x2_overhead.JPG
  34. 0
    0
      tutorials/keybrd_1_breadboard/diodes_bend_en_masse.JPG
  35. 0
    0
      tutorials/keybrd_1_breadboard/diodes_cut.JPG
  36. 49
    0
      tutorials/keybrd_1_breadboard/keybrd_1_breadboard.ino
  37. BIN
      tutorials/keybrd_1_breadboard/switch_orientation.JPG
  38. BIN
      tutorials/keybrd_1_breadboard_images/breadboard_keyboard_2x2_overhead.JPG
  39. BIN
      tutorials/keybrd_1_breadboard_images/switch_orientation.JPG
  40. 8
    8
      tutorials/keybrd_2_single-layer/keybrd_2_single-layer.ino
  41. 6
    6
      tutorials/keybrd_3a_multi-layer/keybrd_3a_multi-layer.ino
  42. 0
    102
      tutorials/keybrd_4b_split_keyboard_with_shift_registers/keybrd_4b_split_keyboard_with_shift_registers.ino
  43. BIN
      tutorials/keybrd_4b_split_keyboard_with_shift_registers/shift_reg_back.JPG
  44. BIN
      tutorials/keybrd_4b_split_keyboard_with_shift_registers/shift_reg_front.JPG
  45. BIN
      tutorials/keybrd_4b_split_keyboard_with_shift_registers/shift_reg_side.JPG
  46. 0
    158
      tutorials/keybrd_4c_split_with_IOE_notgit/keybrd_4b_split_with_IOE.ino
  47. 3
    3
      tutorials/keybrd_5_LEDs/keybrd_5_LEDs.ino
  48. 4
    4
      tutorials/keybrd_6_active_high/keybrd_6_active_high.ino
  49. BIN
      tutorials/keybrd_6_active_high/pull_down_resistors.JPG
  50. 1
    0
      tutorials/tutorial_0_introduction.md
  51. 13
    10
      tutorials/tutorial_10_writing_your_own_port_classes.md
  52. 67
    46
      tutorials/tutorial_1_breadboard_keyboard.md
  53. 9
    6
      tutorials/tutorial_2_single-layer_keyboard.md
  54. 21
    11
      tutorials/tutorial_3a_multi-layer_keyboard.md
  55. 13
    8
      tutorials/tutorial_3b_autoShift.md
  56. 0
    77
      tutorials/tutorial_4b_split_keyboard_with_shift_registers.md
  57. 0
    70
      tutorials/tutorial_4c_split_keyboard_with_IOE_notgit.md
  58. 94
    0
      tutorials/tutorial_5_LEDs.md
  59. 19
    14
      tutorials/tutorial_6_active_high.md
  60. 8
    7
      tutorials/tutorial_8a_using_someone_else's_keybrd_extension_library.md
  61. 11
    5
      tutorials/tutorial_8b_creating_and_publishing_your_own_keybrd_extension_library.md
  62. 15
    18
      tutorials/tutorial_9_breaking_up_a_sketch_into_smaller_files.md

+ 66
- 0
CONTRIBUTING.md View File

@@ -0,0 +1,66 @@
Contributing to keybrd
======================
We'd love for you to contribute to the keybrd project.
Improvement suggestions
-----------------------
We need to know what improvements to the keybrd library would help you create your keyboard design.
Before requesting an improvement, please check [planned_features list](doc/planned_features.md)
Submit improvement suggestions to [GitHub issues](https://github.com/wolfv6/Keybrd/issues).
* The issue title should start with "suggestion:" followed by a descriptive title
* Provide a use case
* Explain why the improvement is useful
* Site other product examples where this improvement exists
Bug reports
-----------
A bug report is the first step in making the keybrd library work the way it's supposed to work.
Please provide enough information so we can reproduce the bug behaviour!
* Complete sketch (copy & paste, attachment, or a link to the code)
* Screenshot or the exact text of error messages
* Describe the observed behavior and explain which behavior you expected
* Which controller your using
* Wiring details - how exactly have you connected the hardware (a photo's worth 1000 words)
* Arduino IDE version number
* keybrd library version number
* Any other information needed to reproduce the problem...
Code contributions
------------------
Unsure where to begin contributing to keybrd code?
You can start by looking through the improvement suggestions, bug reports, and [planned_features](doc/planned_features.md).
Git commit message style guide:
* Limit the first line to 72 characters summary
* Second line should be empty, followed by body of the commit message
* Use the imperative present tense (use "Add feature", not "Added feature", not "Adds feature")
* Reference an improvement suggestion or bug report
* Sometimes a bulleted list is a good format to convey the changes of a commit
User contributions
------------------
Any project requires various kinds of contributions to succeed.
A thriving project is more than a pile of code.
It's the packaging, explanation, outreach, and empathy of maintainers that make a good project great.
User Contributions can be in the form of:
* Blog - You have a fresh perspective of how the keybrd library works.
This makes you the perfect person to write an introductory blog explaining the project.
A healthy project needs the perspective of many people.
* Documentation - Suggest a clarification, simplification, correction, or other improvement.
We need the perspective of people new to the project to see these things.
Sometimes just changing a word or two makes a big difference.
* [What we currently need from keybrd users](todo geekhack) lists tasks for the keybrd project's current stage of development.
Text file documentation style guide:
* Use Markdown with a .md suffix.
* "Underline" first-level (=) and second-level (-) headings (because easier to read in plain text).
* Capitalize first letter of headings (no extra capitalization in headings).
Submitting a Pull Request
-------------------------
Pull Request is the preferred way to contribute code and documentation.
If you want to contribute some other way, please make a request in the [GitHub issues](https://github.com/wolfv6/Keybrd/issues).

+ 25
- 18
README.md View File

@@ -1,10 +1,12 @@
keybrd library for creating keyboard firmware
====================================================
=============================================
keybrd library is an open source library for creating custom-keyboard firmware.
The keybrd library allows keyboard designers to develop and publish their firmware simply as possible.
The resulting keyboard firmware is compatible with standard USB keyboard drivers.
keybrd library can support any keyboard configuration:
* one-piece
* split with shift registers
* split with I/O expander
* single-layer
* multiple-layer
@@ -16,35 +18,40 @@ Multiple-layer keyboards can write symbols without using the shift key:
keybrd library leverages the Arduino environment to create keyboard firmware.
The Arduino development environment is free, and easy for novice programmers to setup and learn.
The keybrd library has been tested on the Teensy 2.0 microcontroller, MCP23018 I/O expander, and PCA9655E I/O expander.
The keybrd library has been tested on Teensy LC, Teensy 2.0, 74HC165 shift registers, and PCA9655E I/O expander.
> The public API should not be considered stable.
> Currently the keybrd library is limited to 8x8 matrices, which is enough for compact split keyboards.
> The keybrd library is in Beta testing. The public API should not be considered stable.
Example minimal keybrd sketch
-----------------------------
<!-- todo after teensy LC bb, copy and remove annotations from keybrd_single-layer_2_annotated.ino -->
A [minimal keybrd sketch](tutorials/keybrd_2_single-layer_annotated/keybrd_2_single-layer_annotated.ino).
has about 50 lines of code and runs on a 4-key keyboard.
It runs on a breadboard and has rows, columns, and diodes just like the big keyboards.
A [minimal keybrd sketch](/tutorials/keybrd_1_breadboard/keybrd_1_breadboard.ino)
is 40 lines of code for a 4-key keyboard.
The sketch is small because the keybrd library takes care of the low-level details.
It runs the breadboard keyboard in this picture.
The keybrd tutorial 1 shows how to make a breadboard keyboard.
The remaining [keybrd tutorials](tutorials) show how to create custom keybrd firmware.
<img src="tutorials/keybrd_1_breadboard/breadboard_keyboard_2x2.JPG" title="breadboard keyboard" alt="breadboard keyboard" style="height:290px;width:328px;">
Example complex keybrd sketch
-----------------------------
The keybrd_DH emulates the DataHand keyboard.
It has 72 keys, 4 layers, 6 sub-layers, 2 matrices, 8 LEDs, and blinking LEDs.
The keybrd_DH and its instantiation files contain about 800 lines of code.
keybrd_DH and its instantiation files contain about 800 lines of code.
It emulates the DataHand keyboard.
The layout has 52 keys, 4 layers, 6 sub-layers, 2 matrices, 8 LEDs, and blinking LEDs.
[keybrd_DH_library_developer_guide.md](https://github.com/wolfv6/keybrd_DH/blob/master/doc/keybrd_DH_library_developer_guide.md)<br>
[mainSketch.ino](https://github.com/wolfv6/keybrd_DH/blob/master/examples/keybrd_DH/mainSketch.cpp)<br>
[instantiations_ports.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_ports.h)<br>
[instantiations_LEDs.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_LEDs.h)<br>
[instantiations_codes.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_codes.h)<br>
[instantiations_matrix.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_matrix.h)
[instantiations_pins.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_pins.h)<br>
[instantiations_scancodes.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_scancodes.h)<br>
[instantiations_layercodes.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_layercodes.h)<br>
[instantiations_rows_L.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_rows_L.h)<br>
[instantiations_rows_R.h](https://github.com/wolfv6/keybrd_DH/blob/master/src/instantiations_rows_R.h)
![hweller](images/datahand.jpg "DataHand")
Support
-------
[Guides](doc) and [tutorials](tutorials) are provided.
Please ask a questions in [issues](https://github.com/wolfv6/Keybrd/issues) if something is not clear.
keybrd tutorial_1 shows how to make a breadboard keyboard.
The remaining [keybrd tutorials](tutorials) show how to create custom keybrd firmware.
Please ask questions in [keybrd library for keyboard firmware](geekhack todo) thread if something is not clear.

+ 24
- 10
doc/CHANGELOG.md View File

@@ -1,24 +1,34 @@
# Change Log for keybrd library
Change Log for keybrd library
=============================
All notable changes to the keybrd project will be documented in this file.
This project adheres to Semantic Versioning 2.0.0(http://semver.org/).
keybrd version 0.x.x is for initial development. The public API should not be considered stable.
keybrd version 0.x.x is for initial development.
keybrd version 1.0.0 will be released when the public API is stable.
## Unreleased
## 0.5.0 (2016-07-18)
<!-- Unreleased
------------------ -->
0.5.0 (2016-07-19)
------------------
* Enhancements
* Update tutorials
* Add tutorials for shift registers, LEDs, active high
* Backward incompatible changes
* Add 32x32 matrix capability to Row_uC
* Add STROBE_ON and STROBE_OFF to scanner class, to set active state
* Rename classes
## 0.4.1 (2016-06-21)
0.4.1 (2016-06-21)
------------------
* Enhancements
* Add config_keybrd.h for size configurations.
* Add RowScanner_SPI-ShiftRegisters for compact split keyboards up to 32 keys per matrix.
* Add LED_PinNumber for controlling indicator lights by pin number.
## 0.4.0 (2016-06-10)
0.4.0 (2016-06-10)
------------------
* Enhancements
* Add Row_uC
* Add Row_IOE
@@ -36,12 +46,14 @@ keybrd version 1.0.0 will be released when the public API is stable.
* Move scanner and debouncer into their own classes.
* Remove Port arrays
## 0.3.1 (2016-06-02)
0.3.1 (2016-06-02)
------------------
* Enhancements
* Add RowBase class
* Add Row::debounce()
## 0.3.0 (2016-05-09)
0.3.0 (2016-05-09)
------------------
* Enhancements
* Add Tutorials
@@ -51,14 +63,16 @@ keybrd version 1.0.0 will be released when the public API is stable.
* Moved sketches to examples directory
* Replace Key_Layered dependency on LayerManager with LayerState class
## 0.2.0 (2016-02-25)
0.2.0 (2016-02-25)
------------------
* Enhancements
* Add Port classes for micro-controllers and I/O expanders
* Add DH_2565 sketch with DataHand layout
* Add Sticky mouse button (SMB) for DataHand layout
* Add Supporting documentation
## 0.1.0 (2015-02-10)
0.1.0 (2015-02-10)
------------------
* Enhancements
* The library runs on Teensy 2.0 microcontroller and MCP23018 I/O expander
* Limited to 8x8 matrix, which is enough for compact or split keyboards

+ 14
- 0
doc/PLANNED_FEATURES.md View File

@@ -0,0 +1,14 @@
planned_features is a view of where the keybrd project is headed.
Top priority
============
* Beta testing
* Schematics for tutorials
Medium priority
===============
* Add matrix-to-layout mapping array (to decouple key matrix from layout)
Low priority
============
* MCP23S18 I/O expander with Serial Peripheral Interface (SPI)

+ 0
- 37
doc/Teensy2_pinout.txt View File

@@ -1,37 +0,0 @@
Teensy 2.0 Pinout Diagram
-------------------------
USB is on top in the diagram.
Inner columns are pin numbers, outer columns are port+bit pin name.
```
ground GND USB VCC +5v power
B0 0 21 F0
B1 1 20 F1
B2 2 19 F4
B3 3 18 F5
B7 4 17 F6
SCL D0 5 16 F7
SDA D1 6 15 B6
D2 7 14 B5
D3 8 13 B4
C6 9 12 D7
C7 10 11 D6 Do not use pin D6 for scanning keyboard matrix
LED on pin D6 pulls voltage down and will always return low

BOTTOM EDGE (USB on top, pins from left to right)
PIN# port+bit function
23 D5
VCC 5v power
GND ground
RST reset
22 D4

MIDDLE (below USB, pins from left to right)
PIN# port+bit function
24 E6
Ref
```

Teensy 2.0 pin assignment on https://www.pjrc.com/teensy/pinout.html
Teensy 2.0 pinout with pin numbers on http://www.pjrc.com/teensy/td_digital.html
Identifying and naming ports is useful when instantiating RowPorts and ColPorts.
Keybrd library was tested on Teensy 2.0

+ 1
- 1
doc/astyle_cpp View File

@@ -1,5 +1,5 @@
# this file specifies style for keybrd C++ and Arduino sketch .ino files
# Artistic Style is a console application for formatting C++ and Java source code
# this file specifies style for keybrd C++ and Arduino sketch .ino files
# http://sourceforge.net/projects/astyle/files/ download
# http://astyle.sourceforge.net/astyle.html manual

+ 65
- 55
doc/keybrd_library_developer_guide.md View File

@@ -1,36 +1,39 @@
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 I/O expanders
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
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.
Row, Scanner, and Debouncer classes use bit manipulation.
## Custom Row classes
The keybrd library is flexible for designing custom Rows
* Row functions can be overridden in a derived class
* choice of Debouncers
* choice of Scanners
Custom Row classes
------------------
Row classes are central to the keybrd library.
Row is an abstract base class that allows flexibility for designing derived Row classes:
* Row 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
This example illustrates the custom Row classes for a fictional keybrd_Ext extension library.
The keybrd_Ext library is for a split keyboard with sticky keys and a matrix on each hand.
Row_Ext::keyWasPressed() overrides Row::keyWasPressed()
Row_Ext::keyWasPressed() overrides Row::keyWasPressed()<br>
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
Row_Ext_uC and Row_Ext_ShiftRegisters are a custom classes composed of stock keybrd library classes.<br>
Row_Ext_uC uses Scanner_uC to scan the primary matrix.<br>
Row_Ext_ShiftRegisters uses Scanner_ShiftRegs74HC165 to scan the secondary matrix.
Class inheritance diagram
```
Row
Row
|
Row_Ext (override Row::keyWasPressed() )
/ \
@@ -44,22 +47,23 @@ Class inheritance diagram
Dependency diagram
```
________ Row_Ext_uC[1] _______________
/ \ \
Scanner_uC[1] Debouncer_Samples[1] Key[1..*]
/ \ |
strobePin[1] readPins[1..*] Code[1..*]
________ Row_Ext_uC[1] ______________
/ | \
Scanner_uC[1] Debouncer_Samples[1] Key[1..*]
/ |
strobePin[1] Code[1..*]
_____ Row_Ext_ShiftRegisters[1] ________
/ \ \
_________ Row_Ext_ShiftRegisters[1] ________
/ \ \
Scanner_ShiftRegs74HC165[1] Debouncer_Samples[1] Key[1..*]
/ \ |
strobePin[1] ROW_END[1] Code[1..*]
| |
strobePin[1] Code[1..*]
```
## Class inheritance diagrams
Class inheritance diagrams
--------------------------
Keybrd library class inheritance diagram
```
@@ -71,7 +75,7 @@ Keybrd library class inheritance diagram
Scanner_uC Scanner_Port Scanner_ShiftRegs74HC165
PortIOE
PortIOE
PortWrite
|
@@ -81,14 +85,14 @@ Keybrd library class inheritance diagram
|
PortRead_PCA9655E (one PortRead class for each IOE type)
____ LED ____
/ \
LED_PinNumber LED_PCA9655E
_ LED _
/ \
LED_uC LED_PCA9655E
DebouncerInterface
|
Debouncer_4Samples
Debouncer_Samples
ScanDelay
@@ -115,14 +119,15 @@ Keybrd library class inheritance diagram
|__________________________________________
\ \ \ \
Code_Sc Code_Shift Code_AutoShift Code_LEDLock
/ | \
Code_ScS Code_ScNS Code_ScNS_00
/ \
Code_ScS Code_ScNS
```
## Dependency diagrams
Dependency diagrams
-------------------
Example single-layer dependency diagram with LEDs
Dependency diagram of example single-layer keyboard with LEDs
```
_ Row_uC[1..*] _
/ | \
@@ -134,7 +139,7 @@ Example single-layer dependency diagram with LEDs
```
Example multi-layer dependency diagram with layer LEDs
Dependency diagram of example multi-layer keyboard with layer LEDs
```
LayerStates[1..*]
________ Row_uC[1..*] ___________/__ | \
@@ -145,7 +150,7 @@ Example multi-layer dependency diagram with layer LEDs
```
Example secondary matrix with shift registers dependency diagram
Dependency diagram of example secondary matrix with shift registers
```
Row_ShiftRegisters[1..*]
/ \ \
@@ -155,7 +160,7 @@ Example secondary matrix with shift registers dependency diagram
```
Example secondary matrix with I/O Expander dependency diagram with LEDs
Dependency diagram of example secondary matrix with I/O Expander and LEDs
```
___ Row_IOE[1..*] _________
/ \ \
@@ -169,7 +174,8 @@ Example secondary matrix with I/O Expander dependency diagram with LEDs
```
## Class naming conventions
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.
```
@@ -181,7 +187,8 @@ Most derived-class names start with the base class name followed by "_" and a na
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
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
@@ -202,7 +209,8 @@ Example Code_Layered class names:
* Code_LayeredScSc
* Key_LayeredKeysArray
## Style guide
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.
@@ -211,7 +219,7 @@ Following the style guide makes it easier for the next programmer to understand
* 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 element name e.g. Row* const = ptrsRows { &row0, &row1 };
* 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);
@@ -219,7 +227,7 @@ Following the style guide makes it easier for the next programmer to understand
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).
* 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.
@@ -231,32 +239,34 @@ Following the style guide makes it easier for the next programmer to understand
<!-- http://stackoverflow.com/questions/2198241/best-practice-for-c-function-commenting -->
## Trace of keybrd scan
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).
The trace is of a one-row single-layer keybrd scan.
Refer to it like a table of contents while reading the keybrd library.
```
loop() for each row
Row::process()
Scanner_uC::scan() strobe row on
Scanner_uC::scan() strobe row on
for each readPin
set rowState bit
set readState bit
strobe row off
Debouncer_4Samples::debounce() debounce
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)
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 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>

+ 61
- 78
doc/keybrd_library_user_guide.md View File

@@ -1,9 +1,7 @@
keybrd Library User's Guide
===========================
keybrd is an open source library for creating custom-keyboard firmware.
The resulting keyboard firmware is compatible with standard USB keyboard drivers.
This guide shows how to
keybrd is a library for creating custom-keyboard firmware.
This guide shows how to:
* set up the Arduino development environment
* install the keybrd library
* compile and load keybrd firmware
@@ -11,16 +9,19 @@ This guide shows how to
The Arduino development environment is free and simple as possible.
Its easy for novice programmers to setup and learn.
## Who this guide is for
Who this guide is for
---------------------
This guide is for anyone who wants to use the keybrd library to develop keyboard firmware.
A reader with programming experience, but no C++ experience, would understand the tutorials well enough to modify existing keybrd sketches.
An experienced C++ programmer would be able to write original sketches and classes.
The library is written in the C++ language and uses pointers, objects, classes, static class variables, aggregation, inheritance, and enum.
The library is written in the C++ language.
keybrd sketches use keybrd classes, objects pointers, aggregation, and static class variables.
## Microcontroller board requirements
The keybrd library works with Teensy and Arduino boards.
Microcontroller board requirements
----------------------------------
The keybrd library works with Teensy and Arduino compatible boards.
[Teensy LC](https://www.pjrc.com/teensy/teensyLC.html) has 8K RAM, which is more than enough memory for any keyboard.
@@ -28,7 +29,8 @@ keybrd has been tested on the DodoHand keyboard with Teensy 2.0 and PCA9655E I/O
Teensy LC is preferred over the older Teensy 2.0 for it's larger memory capacity and lower price.
## Getting started with Teensy, Arduino IDE, and keybrd
Getting started with Teensy, Arduino IDE, and keybrd
----------------------------------------------------
The Arduino IDE is used to
1. edit sketches
@@ -43,7 +45,7 @@ Teensyduino is a software add-on for the Arduino IDE that allows it to compile t
The following install and setup steps create an Arduino development environment for keybrd sketches.
### Install Arduino IDE and Teensyduino
The following install steps are modified from the [Teensyduino download page](https://www.pjrc.com/teensy/td_download.html)
The following install steps are modified from the [Teensyduino download page](https://www.pjrc.com/teensy/td_download.html).
For Linux:
@@ -63,37 +65,38 @@ For Linux:
Run the teensyduino installer and fill the form fields:
Arduino location to install Teensyduino: /opt/arduino-1.x.x
Libraries to Install: None
Libraries to Install: keybrd
4. Launch Arduino IDE from /opt/arduino-1.x.x/arduino
<!-- todo no longer needed, delete after testing Arduino library manager
### Download and unpack keybrd-master.zip into your Arduino directory
<!-- todo update after testing Arduino library manager
link from tutorial 7 ## Publishing
link from tutorial 8 ## Publishing
https://www.arduino.cc/en/Guide/Libraries
* Installing Additional Arduino Libraries
* Using the Library Manager
-->
Down load keybrd-master.zip from the [Download ZIP](https://github.com/wolfv6/keybrd) button.
Unpack keybrd-master.zip into your Arduino directory on your system (default location is ~/Documents/Arduino/).
-->
### Install keybrd library and keybrd extension libraries
<!-- todo update after testing Arduino library manager -->
### Install keybrd extension libraries
The keybrd library contains the foundation classes for creating a keyboard firmware.
For emphasis, it is sometimes referred to as the "core keybrd library".
keybrd extension libraries contain additional classes that extend the keyboard library.
keybrd extension library names are prefixed with "keybrd_".
The Arduino IDE looks for libraries in Arduino/libraries/.
For example, the DodoHand keyboard requires that the core keybrd library and the keybrd_DH extension library be installed:
* Arduino/libraries/keybrd/
* Arduino/libraries/keybrd_DH/
Instructions for installing Arduino libraries are at: http://www.arduino.cc/en/Guide/Libraries
A Sketchbook is a folder that the Arduino IDE uses to store sketches and libraries.
The default location for Arduino libraries is ~/Documents/Arduino/libraries/.
A keybrd extension library allows classes to be shared by multiple sketches without polluting the core keybrd library with classes that other keyboards can not use.
For example, the DodoHand keyboard requires the core keybrd library and the keybrd_DH extension library.
After installing the libraries, my Arduino directory looks like this:
* ~/Documents/Arduino/libraries/keybrd/
* ~/Documents/Arduino/libraries/keybrd_DH/
### Setup Arduino IDE for compiling keybrd firmware
From the Arduino IDE tool bar, select:
@@ -104,33 +107,28 @@ These are optional:
* File > Preferences > Compiler warnings: All
* File > Preferences > check: Use external editor
A Sketchbook is a folder that the Arduino IDE uses to store sketches and libraries.
The default location for [Arduino libraries](https://www.arduino.cc/en/Guide/Libraries) is in
~/Documents/Arduino/libraries/
### Compile and load keybrd sketch
If it isn't already plugged in, plug the USB cable into the computer and controller.
> CAUTION: It is possible to loose control of your keyboard when running a keybrd sketch.
> If the keybrd sketch has a mouse object, it is also possible to loose control of your mouse.
> If the keybrd sketch has a mouse object, it is possible to loose control of your mouse too.
> USB keyboard protocol is capable of spewing characters and mouse commands at up to 500 per second.
> Take the following precautions before uploading an untested keybrd sketch to a controller:
> * Save all files and close dangerous applications.
> * Park the cursor in an editor opened to a test file.
> That way you can immediately see if the controller starts spewing characters.
> * Be prepared to turn off the controller:
> turn off Teensy Loader's green "Auto" button and push Teensy's reset button
> if that fails, unplug Teensy USB
> turn off Teensy Loader's green "Auto" button and push Teensy's reset button or unplug Teensy USB.
Compile and load workflow:
1. Open a keybrd sketch in the Arduino IDE.
2. Prepare for loosing control of keyboard and mouse.
3. On the Arduino IDE, click the Upload button.
4. The Teensy boot loader window opens;
you might need to press and release the pushbutton on the Teensy circuit board.
4. The Teensy boot loader window opens
(you might need to press and release the pushbutton on the Teensy circuit board).
## Example keybrd sketches
Example keybrd sketches
-----------------------
Example keybrd sketches are in the examples and tutorials directories.
Extension libraries have their example sketches similarly located.
@@ -140,18 +138,16 @@ The example sketch names use the following conventions.
where
* **keybrd** is the library name e.g. keybrd, keybrd_DH
* **feature** is a distinguishing feature of the keybrd sketch e.g. breadboard, LED, sound, Dvorak
* **version** is the sketch's version number
The first field are mandatory, the version optional.
* **feature** is a distinguishing feature of the keybrd sketch e.g. keyboard name, sound, Dvorak
* **version** is the sketch's version number (optional)
## Active state and diode orientation
Active state and diode orientation
----------------------------------
Active state is set in the sketch by variables STROBE_ON and STROBE_OFF.
The following instructions are for setting active state for a Scanner_uC class.
Scanner_ShiftRegs74HC165 and Scanner_Port classes is similar.
The following instructions are for setting active state for a Scanner_uC class
(Scanner_ShiftRegs74HC165 and Scanner_Port classes is similar).
For active low:
* Use internal pull-down resistors.
* Orient diodes with cathode (banded end) towards the write pins (row)
* Use these two lines in the sketch:
```
@@ -168,61 +164,48 @@ For active high:
const bool Scanner_uC::STROBE_OFF = LOW;
```
![Diode](../tutorials/keybrd_1_breadboard_images/120px-Diode_pinout_en_fr.svg.png)
Diagram is of typical through-the-hole [diode](https://en.wikipedia.org/wiki/Diode) in same alignment as diode symbol.
Cross bar and band depict the cathode.
## Troubleshooting check list
The following is a listing of items to check when a new keybrd sketch or keyboard is having trouble.
Troubleshooting check list
--------------------------
The following is a listing of items to check when a new keybrd sketch or keyboard hardware is having trouble.
Development-environment items to check:
* If the keyboard has an I/O expander, power cycle (replug the USB) after loading the HEX file.
* If compile error: 'KEY_A' was not declared in this scope
From the Arduino IDE tool bar, select: Tools > USB Type > Keyboard + Mouse + Joystick
* For compile error:
```
'KEY_A' was not declared in this scope
```
Where 'KEY_A' could be any scan code.
Fix this from the Arduino IDE tool bar: Tools > USB Type > Keyboard + Mouse + Joystick
Sketch items to check:
* For each row, number of keys in Row should equal number of colPort pins.
In this example, row_0 has six colPort pins in ptrsColPorts, and six keys in ptrsKeys_0:
* For each row, number of read pins in Row should equal number of keys.
In this example, row_0 has 2 read pins and 2 keys:
```
ColPort_AVR colPortB(DDRB, PORTB, PINB, 1<<0 | 1<<1 | 1<<2 | 1<<3 );
ColPort_AVR colPortD(DDRD, PORTD, PIND, 1<<2 | 1<<3 );
uint8_t readPins[] = {14, 15};
uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins);
ColPort* const ptrsColPorts[] = { &colPortB, &colPortD };
const uint8_t COL_PORT_COUNT = sizeof(ptrsColPorts)/sizeof(*ptrsColPorts);
const Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02, &k_03, &k_04, &k_05 };
Row row_0(ptrsKeys_0, &rowPortF, 1<<0, ptrsColPorts, COL_PORT_COUNT);
```
* Some of the constructors take array-element-count arguments, make sure that the correct counts are passed to the constructors. Or use sizeof() like this example:
```
Row* const ptrsRows[] = { &row0, &row1, &row2, &row3 };
const uint8_t ROW_COUNT = sizeof(ptrsRows)/sizeof(*ptrsRows);
Matrix matrix(ptrsRows, ROW_COUNT, 1);
Key* ptrsKeys_0[] = { &s_a, &s_b };
Row_uC row_0(0, readPins, READ_PIN_COUNT, ptrsKeys_0);
```
* Some of the constructors take array-element-count arguments, make sure that the correct counts are passed to the constructors. Or use sizeof() like the preceding example.
* For multi-layered keyboards, the number of codes in each Key_Layered should equal the number of layers.
Hardware items to check:
* Connections
* Diode orientation
* 5 volts across power and ground
* To validate keyboard hardware, modify the simple single-layer keybrd sketch from the tutorial.
<!-- todo after teensy LC bb, link to minimal keybrd sketch
[minimal keybrd sketch](blob/master/tutorials/keybrd_2_single-layer_annotated/keybrd_2_single-layer_annotated.ino).
-->
* 3.3 or 5 volts across power and ground
* To validate keyboard hardware, modify the simple [keybrd_1_breadboard.ino](../tutorials/keybrd_1_breadboard/keybrd_1_breadboard.ino) sketch.
## Keybrd nomenclature
Keybrd nomenclature
-------------------
**[scancode](http://en.wikipedia.org/wiki/Scancode)** -
Is a 16-bit integer assigned to a key position on a keyboard.
The keyboard sends a scancode to the computer for every key press and release.
**[Layers](http://deskthority.net/wiki/Layer)** -
are key bindings provided by the keyboard firmware.
The standard [IBM PC keyboard](http://en.wikipedia.org/wiki/IBM_PC_keyboard) has one layer.
Many compact keyboards have an additional [Fn layer](http://en.wikipedia.org/wiki/Fn_key).
The [Neo layout](http://neo-layout.org/index_en.html) has 6 layers.
**[layers](http://deskthority.net/wiki/Layer)** - are key bindings provided by the keyboard firmware. For example,
* The classic [IBM PC keyboard](http://en.wikipedia.org/wiki/IBM_PC_keyboard) has one layer.
* Many compact keyboards have an additional [Fn layer](http://en.wikipedia.org/wiki/Fn_key).
* The [Neo layout](http://neo-layout.org/index_en.html) has 6 layers.
**Layer id** - is an integer assigned to a layer.

+ 0
- 21
doc/planned_features.md View File

@@ -1,21 +0,0 @@
planned_features is a view of where the keybrd project is headed.
Top priority
============
MCP23S18 I/O expander with Serial Peripheral Interface (SPI)
Med priority
============
Add matrix-to-layout mapping array (to decouple matrix from layout)
Low priority
============
Update tutorials:
* Currently tutorial sketches are obsolete and won't compile
* Change tutorial sketches from teensy 2.0 and PCA9655E-D IOE to Teensy LC and MCP23018 IOE
Add more tutorials:
* tutorial_5_LEDs.md
* tutorial_6_mapping_matrix_to_layout.md
* tutorial_9_active_high.md
* add schematics to tutorials

+ 0
- 165
examples/keybrd_shift_register/keybrd_shift_register.ino View File

@@ -1,165 +0,0 @@
/* keybrd_shift_reg.ino
Tested on Teensy LC and daisy chained 74HC165 shift registers

The keyboard hardware for this sketch has 4 shift registers,
with every 4th input pin connected to a pull-down resistor and matrix column, also the 31st key.
Unused input pins are not grounded, so add this line to Scanner_ShiftRegs74HC165::scan():
//clear unpowered pins (for testing on breadboard)
rowState &= 0b11110001000100010001000100010001;

Layout Layout
| Left | **0**|**1**| | Right |**0**|**1**|**2**|**3**|**4**|**5**|**6**|**7**|**8**|
|:-----:|------|-----| |:-----:|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| **0** |capLck| a | | **0** | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| **1** | b | c | | **1** | a | b | c | d | e | f | g | h | i |
*/
// ################## GLOBAL ###################
// ================= INCLUDES ==================
#include <Debug.h>
#include <ScanDelay.h>
#include <LED_uC.h>
#include <SPI.h>

//Codes
#include <Code_Sc.h>
#include <Code_LEDLock.h>

//Matrix
#include <Row_uC.h>
#include <Row_ShiftRegisters.h>

// =============== CONFIGURATION ===============
ScanDelay scanDelay(9000);

//set left matrix for active low
const bool Scanner_uC::STROBE_ON = LOW;
const bool Scanner_uC::STROBE_OFF = HIGH;

const uint8_t Scanner_ShiftRegs74HC165::SHIFT_LOAD = 10;

//set right matrix for active low
const bool Scanner_ShiftRegs74HC165::STROBE_ON = LOW;
const bool Scanner_ShiftRegs74HC165::STROBE_OFF = HIGH;

Debug debug;

// ================= LEFT PINS =================
uint8_t readPins[] = {14, 15};
uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins);

// ==================== LEDs ===================
LED_uC LED1(16);

// =================== CODES ===================
Code_Sc s_a(KEY_A);
Code_Sc s_b(KEY_B);
Code_Sc s_c(KEY_C);
Code_Sc s_d(KEY_D);
Code_Sc s_e(KEY_E);
Code_Sc s_f(KEY_F);
Code_Sc s_g(KEY_G);
Code_Sc s_h(KEY_H);
Code_Sc s_i(KEY_I);

Code_Sc s_u(KEY_U);
Code_Sc s_v(KEY_V);
Code_Sc s_w(KEY_W);
Code_Sc s_x(KEY_X);

Code_Sc s_z(KEY_Z);

Code_Sc s_0(KEY_0);
Code_Sc s_1(KEY_1);
Code_Sc s_2(KEY_2);
Code_Sc s_3(KEY_3);
Code_Sc s_4(KEY_4);
Code_Sc s_5(KEY_5);
Code_Sc s_6(KEY_6);
Code_Sc s_7(KEY_7);
Code_Sc s_8(KEY_8);

Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED1);

// ================= LEFT ROWS =================
Key* ptrsKeys_L0[] = { &o_capsLock, &s_a };
Row_uC row_L0(0, readPins, READ_PIN_COUNT, ptrsKeys_L0);

Key* ptrsKeys_L1[] = { &s_b, &s_c };
Row_uC row_L1(1, readPins, READ_PIN_COUNT, ptrsKeys_L1);

// ================= RIGHT ROWS ================
//typedef should be large in /home/wolfv/Documents/Arduino/keybrd_proj/keybrd/src/config_keybrd.h
//Row_ShiftRegisters(strobePin, readPinCount, ptrsKeys[])
//the s_z are place holders and should not print

/*
//prints 0 1
Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z };
Row_ShiftRegisters row_R0(8, sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0), ptrsKeys_R0);

//prints a b
Key* ptrsKeys_R1[] = { &s_a, &s_z, &s_z, &s_z, &s_b, &s_z, &s_z, &s_z };
Row_ShiftRegisters row_R1(9, sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1), ptrsKeys_R1);
*/
/*
//prints 0 1 2
Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z,
&s_2, &s_z, &s_z, &s_z };
Row_ShiftRegisters row_R0(8, sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0), ptrsKeys_R0);
*/
/*
//prints 0 1 2 3
Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z,
&s_2, &s_z, &s_z, &s_z, &s_3, &s_z, &s_z, &s_z };
Row_ShiftRegisters row_R0(8, sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0), ptrsKeys_R0);
*/
/*
//prints 0 1 2 3 4 5
Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z,
&s_2, &s_z, &s_z, &s_z, &s_3, &s_z, &s_z, &s_z,
&s_4, &s_z, &s_z, &s_z, &s_5, &s_z, &s_z, &s_z };
Row_ShiftRegisters row_R0(8, sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0), ptrsKeys_R0);
*/

//prints 0 1 2 3 3 4 5 6, microseconds_per_scan=87 with SAMPLE_COUNT 4
Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z,
&s_2, &s_z, &s_z, &s_z, &s_3, &s_z, &s_z, &s_z,
&s_4, &s_z, &s_z, &s_z, &s_5, &s_z, &s_z, &s_z,
&s_6, &s_z, &s_z, &s_z, &s_3, &s_4, &s_5, &s_6 };
Row_ShiftRegisters row_R0(0, sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0), ptrsKeys_R0);

//prints a b c d u v w x
Key* ptrsKeys_R1[] = { &s_a, &s_z, &s_z, &s_z, &s_b, &s_z, &s_z, &s_z,
&s_c, &s_z, &s_z, &s_z, &s_d, &s_z, &s_z, &s_z,
&s_e, &s_z, &s_z, &s_z, &s_f, &s_z, &s_z, &s_z,
&s_g, &s_z, &s_z, &s_z, &s_u, &s_v, &s_w, &s_x };
Row_ShiftRegisters row_R1(1, sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1), ptrsKeys_R1);

// ################### MAIN ####################
void setup()
{
Keyboard.begin();
SPI.begin();
row_R0.begin();
row_R1.begin();

debug.wait_for_OS(LED1, 6);
Keyboard.println(F("keybrd_shift_reg.ino"));
}

void loop()
{
//left matrix
row_L0.process();
row_L1.process();

//right matrix
row_R0.process();
row_R1.process();

scanDelay.delay();

//delay(100);
//Keyboard.println("");
//debug.print_microseconds_per_scan();
}

BIN
images/datahand.jpg View File


+ 1
- 1
library.properties View File

@@ -6,4 +6,4 @@ sentence=A library for creating custom-keyboard firmware.
paragraph=<br>Create keyboards with any configuration:<br>one-piece, split with I/O expander, single-layer, multiple-layer
category=Device Control
url=https://github.com/wolfv6/keybrd
architectures=avr
architectures=*

+ 4
- 4
src/Code_AutoShift.h View File

@@ -8,8 +8,8 @@ Code_AutoShift can manage one or more shift keys.
Example initialization:
const Code_Shift s_shift(MODIFIERKEY_LEFT_SHIFT);
const Code_Shift *const ptrsS[] = { &s_shift };
const Code_Shift *const *const Code_AutoShift::ptrsShifts = ptrsS;
const Code_Shift*const ptrsS[] = { &s_shift };
const Code_Shift*const *const Code_AutoShift::ptrsShifts = ptrsS;
const uint8_t Code_AutoShift::shiftCount = sizeof(ptrsS)/sizeof(*ptrsS);
The two Code_Shift pointer arrays (ptrsShifts and ptrsS) must have distinct names.
@@ -18,14 +18,14 @@ The shift state for Code_ScS and Code_ScNS are changed and restored:
Code_ScS object is a scancode shifted e.g. '%' in symbols layer
Code_ScNS object is a scancode not shifted e.g. '5' in numbers layer
keyboards without Code_ScS and Code_ScNS can omit ptrsShifts[] array and
keyboards without Code_ScS and Code_ScNS can omit ptrsShifts[] array and
and place scancode MODIFIERKEY_LEFT_SHIFT directly in Code_Sc:
Code_Sc s_shift(MODIFIERKEY_LEFT_SHIFT);
*/
class Code_AutoShift : public Code
{
private:
static Code_Shift *const *const ptrsShifts; //array of Code_Shift pointers
static Code_Shift*const *const ptrsShifts; //array of Code_Shift pointers
static const uint8_t shiftCount;
protected:
bool isShifted() const;

+ 14
- 14
src/Code_LEDLock.cpp View File

@@ -16,14 +16,14 @@ Code_LEDLock::Code_LEDLock(const uint16_t scancode, LED& refLED)
case KEY_SCROLL_LOCK:
USB_LED_bit = 1<<2;
break;
/* guessing at these case names:
case KEY_COMPOSE: //for separate accent keys
USB_LED_bit = 1<<3; break;
break;
case KEY_KANA: //for Japanese keyboards
USB_LED_bit = 1<<4; break;
break;
*/
/* guessing at these case names:
case KEY_COMPOSE: //for separate accent keys
USB_LED_bit = 1<<3; break;
break;
case KEY_KANA: //for Japanese keyboards
USB_LED_bit = 1<<4; break;
break;
*/
}
}
@@ -51,12 +51,12 @@ TMK firmware, which is not Arduino, uses variable "usb_led" instead of "keyboard
*/
void Code_LEDLock::updateLED() const
{
/* KEY_SCROLL_LOCK is not working on Linux with Teensy2.0.
This debug code prints "keyboard_leds=0" when scrollLock is pressed:
Keyboard.print(F(" keyboard_leds="));
Keyboard.print(keyboard_leds); //KEY_NUM_LOCK:1, KEY_CAPS_LOCK:2, KEY_SCROLL_LOCK:0
Keyboard.print(" ");
*/
/* KEY_SCROLL_LOCK is not working on Linux with Teensy2.0.
This debug code prints "keyboard_leds=0" when scrollLock is pressed:
Keyboard.print(F(" keyboard_leds="));
Keyboard.print(keyboard_leds); //KEY_NUM_LOCK:1, KEY_CAPS_LOCK:2, KEY_SCROLL_LOCK:0
Keyboard.print(" ");
*/
if (keyboard_leds & USB_LED_bit) //if USB_LED_bit is set
{
refLED.off(); //LED on-off seem inverted, but it works for active low and active high

+ 1
- 1
src/Debouncer_Samples.cpp View File

@@ -19,7 +19,7 @@ Output from keybrd/examples/debounce_unit_test.cpp with SAMPLE_COUNT_MACRO 4:
isFallingEdge: 000000000000000000001
isRisingEdge: 000000000001000000000
There is a latency equal to SAMPLE_COUNT_MACRO, between button press and debounced signal.
samples[SAMPLE_COUNT_MACRO] is a ring buffer. samplesIndex is it's current write index.
SAMPLE_COUNT_MACRO is the number of consecutive equal samples needed to debounce.
SAMPLE_COUNT_MACRO is a macro because it defines samples[SAMPLE_COUNT_MACRO] array size at compile time.

+ 6
- 0
src/Debug.cpp View File

@@ -2,6 +2,9 @@
void Debug::printMicrosecondsPerScan()
{
static unsigned long nextTime = 0;
static unsigned int scanCount = 0;
if (millis() >= nextTime)
{
Keyboard.print(1000000/scanCount); //print microseconds per scan
@@ -13,6 +16,9 @@ void Debug::printMicrosecondsPerScan()
}
void Debug::printScansPerSecond()
{
static unsigned long nextTime = 0;
static unsigned int scanCount = 0;
if (millis() >= nextTime)
{
Keyboard.print(scanCount); //print scans per second

+ 0
- 4
src/Debug.h View File

@@ -5,10 +5,6 @@

class Debug
{
private:
unsigned long nextTime = 0;
unsigned int scanCount = 0;

public:
void printMicrosecondsPerScan(); //print microseconds per scan every second
void printScansPerSecond(); //print scans per second every second

+ 2
- 2
src/Key_LayeredKeysArray.h View File

@@ -14,11 +14,11 @@ the Key object of the active layer is called.
class Key_LayeredKeysArray : public Key
{
private:
Key *const *const ptrsKeys; //array of Key pointers, one Key per layer
Key*const *const ptrsKeys; //array of Key pointers, one Key per layer
uint8_t layer; //active layer when key was pressed
static LayerStateInterface& refLayerState;
public:
Key_LayeredKeysArray(Key *const ptrsKeys[]): ptrsKeys(ptrsKeys) {}
Key_LayeredKeysArray(Key* const ptrsKeys[]): ptrsKeys(ptrsKeys) {}
virtual void press();
virtual void release();
};

+ 1
- 1
src/PortRead_PCA9655E.cpp View File

@@ -5,7 +5,7 @@ configures column port's configuration, input, and pins.
*/
PortRead_PCA9655E::PortRead_PCA9655E (PortIOE& port, const uint8_t readPins)
: PortRead(readPins), port(port),
configurationByteCommand(port.num + 6), inputByteCommand(port.num)
configurationByteCommand(port.num + 6), inputByteCommand(port.num)
{}
void PortRead_PCA9655E::begin()

+ 1
- 1
src/Row.cpp View File

@@ -31,7 +31,7 @@ void Row::send(const uint8_t readPinCount, const read_pins_t debouncedChanged)
}
}
}
void Row::keyWasPressed()
{
//empty in Row class. To unstick sticky keys, override keyWasPressed() in derived Row class.

+ 2
- 2
src/Row.h View File

@@ -15,10 +15,10 @@ class Row
virtual void keyWasPressed();
protected:
read_pins_t debounced; //bitwise state of keys after debouncing
// 1 means pressed, 0 means released
// 1 means pressed, 0 means released
void send(const uint8_t readPinCount, const read_pins_t debouncedChanged);
public:
Row(Key *const ptrsKeys[]) : ptrsKeys(ptrsKeys), debounced(0) { }
Row(Key* const ptrsKeys[]) : ptrsKeys(ptrsKeys), debounced(0) { }
virtual void process()=0;
};
#endif

+ 2
- 1
src/Row_ShiftRegisters.h View File

@@ -39,7 +39,8 @@ class Row_ShiftRegisters : public Row
Debouncer_Samples debouncer;
const uint8_t readPinCount; //number of read pins
public:
Row_ShiftRegisters(const uint8_t strobePin, const uint8_t readPinCount, Key *const ptrsKeys[])
Row_ShiftRegisters(const uint8_t strobePin, const uint8_t readPinCount,
Key* const ptrsKeys[])
: Row(ptrsKeys), scanner(strobePin, readPinCount), readPinCount(readPinCount) { }
void begin();
void process();

+ 2
- 2
src/Row_uC.h View File

@@ -33,9 +33,9 @@ class Row_uC : public Row
const uint8_t readPinCount;
public:
Row_uC(const uint8_t strobePin, const uint8_t readPins[], const uint8_t readPinCount,
Key *const ptrsKeys[])
Key* const ptrsKeys[])
: Row(ptrsKeys), scanner(strobePin, readPins, readPinCount),
readPinCount(readPinCount) { }
readPinCount(readPinCount) { }
void process();
};
#endif

+ 1
- 1
src/ScanDelay.h View File

@@ -20,7 +20,7 @@ Adjust the value of DELAY_MICROSECONDS and repeat until:
DEBOUNCE_TIME can be obtained from the switch's datasheet. Some switch bounce times are:
Cherry MX specifies 5msec bounce time http://www.cherrycorp.com/english/switches/key/mx.htm
hasu measured Cherry MX bounce times .3ms to 1.4ms http://geekhack.org/index.php?topic=42385.0
Tactile switch MJTP series bounce 10 ms http://www.apem.com/files/apem/brochures/MJTP_6MM.pdf
Tactile switch MJTP series bounce 10 ms http://www.apem.com/files/apem/brochures/MJTP_6MM.pdf

The largest allowable DELAY_MICROSECONDS is 65535 (65.535 ms).


+ 1
- 1
src/Scanner_Port.cpp View File

@@ -16,6 +16,6 @@ uint8_t Scanner_Port::scan()

//strobe off
refPortWrite.write(strobePin, STROBE_OFF);
return readState;
}

+ 6
- 5
src/Scanner_ShiftRegs74HC165.h View File

@@ -33,11 +33,12 @@ In addition, each row needs to be connected to a strobe pin from the controller.
class Scanner_ShiftRegs74HC165
{
private:
static const uint8_t SHIFT_LOAD; //controller's pin number that is connected to shift register's SHIFT_LOAD pin
static const bool STROBE_ON; //logic level of strobe on, active state HIGH or LOW
static const bool STROBE_OFF; //logic level of strobe off, complement of active state
const uint8_t strobePin; //Arduino pin number connected to this row
const uint8_t byte_count; //number of bytes to read from shift registers
static const uint8_t SHIFT_LOAD; //controller's pin number that is
// connected to shift register's SHIFT_LOAD pin
static const bool STROBE_ON; //logic level of strobe on, active state HIGH or LOW
static const bool STROBE_OFF; //logic level of strobe off, complement of active state
const uint8_t strobePin; //Arduino pin number connected to this row
const uint8_t byte_count; //number of bytes to read from shift registers
public:
Scanner_ShiftRegs74HC165(const uint8_t strobePin, const uint8_t readPinCount);
virtual read_pins_t scan();

+ 1
- 1
src/Scanner_uC.cpp View File

@@ -11,7 +11,7 @@ https://www.arduino.cc/en/Reference/Constants > Digital Pins modes: INPUT, INPUT
/* constructor
*/
Scanner_uC::Scanner_uC(const uint8_t strobePin,
const uint8_t readPins[], const uint8_t readPinCount)
const uint8_t readPins[], const uint8_t readPinCount)
: strobePin(strobePin), readPins(readPins), readPinCount(readPinCount)
{
uint8_t mode;

+ 1
- 1
src/Scanner_uC.h View File

@@ -20,7 +20,7 @@ class Scanner_uC
const uint8_t readPinCount; //number of read pins
public:
Scanner_uC(const uint8_t strobePin,
const uint8_t readPins[], const uint8_t readPinCount);
const uint8_t readPins[], const uint8_t readPinCount);
virtual read_pins_t scan();
};
#endif

+ 0
- 53
src/getFreeSRAM.h View File

@@ -1,53 +0,0 @@
// getFreeSRAM.h copied from
// http://andybrown.me.uk/2011/01/01/debugging-avr-dynamic-memory-allocation/
/*
* memdebug.h
*
* Created on: 15 Dec 2010
* Author: Andy Brown
*
* Use without attribution is permitted provided that this
* header remains intact and that these terms and conditions
* are followed:
*
* http://andybrown.me.uk/ws/terms-and-conditions
*/

#include <inttypes.h>

extern unsigned int __bss_end;
extern unsigned int __heap_start;
extern void *__brkval;

//measure and return amount of free SRAM
/*
uint16_t getFreeSRAM()
{
uint8_t newVariable;
// if heap is empty, use bss as start memory address
if ((uint16_t)__brkval == 0)
{
return (((uint16_t)&newVariable) - ((uint16_t)&__bss_end));
}
// else use heap end as the start of the memory address
else
{
return (((uint16_t)&newVariable) - ((uint16_t)__brkval));
}
};
*/
// uint32_t for Teensy LC
uint32_t getFreeSRAM()
{
uint8_t newVariable;
// if heap is empty, use bss as start memory address
if ((uint32_t)__brkval == 0)
{
return (((uint32_t)&newVariable) - ((uint32_t)&__bss_end));
}
// else use heap end as the start of the memory address
else
{
return (((uint32_t)&newVariable) - ((uint32_t)__brkval));
}
};

BIN
tutorials/breadboard_keyboard_supplies.ods View File


tutorials/keybrd_1_breadboard_images/120px-Diode_pinout_en_fr.svg.png → tutorials/keybrd_1_breadboard/120px-Diode_pinout_en_fr.svg.png View File


tutorials/keybrd_1_breadboard_images/breadboard_keyboard_2x2.JPG → tutorials/keybrd_1_breadboard/breadboard_keyboard_2x2.JPG View File


BIN
tutorials/keybrd_1_breadboard/breadboard_keyboard_2x2_overhead.JPG View File


tutorials/keybrd_1_breadboard_images/diodes_bend_en_masse.JPG → tutorials/keybrd_1_breadboard/diodes_bend_en_masse.JPG View File


tutorials/keybrd_1_breadboard_images/diodes_cut.JPG → tutorials/keybrd_1_breadboard/diodes_cut.JPG View File


+ 49
- 0
tutorials/keybrd_1_breadboard/keybrd_1_breadboard.ino View File

@@ -0,0 +1,49 @@
/* keybrd_1_breadboard.ino

| Layout | **0** | **1** |
|:------:|-------|-------|
| **0** | 1 | a |
| **1** | b | c |
*/
// ################## GLOBAL ###################
// ================= INCLUDES ==================
#include <ScanDelay.h>
#include <Code_Sc.h>
#include <Row_uC.h>

// ============ SPEED CONFIGURATION ============
ScanDelay scanDelay(9000);

// ================ ACTIVE STATE ===============
const bool Scanner_uC::STROBE_ON = LOW;
const bool Scanner_uC::STROBE_OFF = HIGH;

// =================== PINS ====================
uint8_t readPins[] = {14, 15};
uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins);

// =================== CODES ===================
Code_Sc s_1(KEY_1);
Code_Sc s_a(KEY_A);
Code_Sc s_b(KEY_B);
Code_Sc s_c(KEY_C);

// =================== ROWS ====================
Key* ptrsKeys_0[] = { &s_1, &s_a };
Row_uC row_0(0, readPins, READ_PIN_COUNT, ptrsKeys_0);

Key* ptrsKeys_1[] = { &s_b, &s_c };
Row_uC row_1(1, readPins, READ_PIN_COUNT, ptrsKeys_1);

// ################### MAIN ####################
void setup()
{
Keyboard.begin();
}

void loop()
{
row_0.process();
row_1.process();
scanDelay.delay();
}

BIN
tutorials/keybrd_1_breadboard/switch_orientation.JPG View File


BIN
tutorials/keybrd_1_breadboard_images/breadboard_keyboard_2x2_overhead.JPG View File


BIN
tutorials/keybrd_1_breadboard_images/switch_orientation.JPG View File


+ 8
- 8
tutorials/keybrd_2_single-layer/keybrd_2_single-layer.ino View File

@@ -14,15 +14,14 @@ This layout table shows how keys are arranged on the keyboard:
The layout's row and column numbers are in the headers.
Each cell in the table's body represents a key.

The sketch is annotated with a walk-through narrative enclosed in comment blocks.
The following sketch is annotated with a walk-through narrative enclosed in comment blocks.
Each comment block explains the next one or two lines of code.

keybrd objects are instantiated under the "GLOBAL" heading.
The keyboard runs at the end of the sketch, under the "MAIN" heading.
*/
// ################## GLOBAL ###################
// ================= INCLUDES ==================
/*
/* ================= INCLUDES ==================
All the includes in this sketch are to keybrd library classes.
*/
#include <ScanDelay.h>
@@ -43,7 +42,7 @@ STROBE_ON and STROBE_OFF define the logic levels for the strobe.
"Active low" means that if a switch is pressed (active), the read pin is low.
To make this sketch active low, STROBE_ON should be LOW (tutorial 6 coveres this in more detail).
*/
const bool Scanner_uC::STROBE_ON = LOW; //set matrix for active low
const bool Scanner_uC::STROBE_ON = LOW; //set scanner for active low
const bool Scanner_uC::STROBE_OFF = HIGH;

/* ================= PINS =================
@@ -51,7 +50,8 @@ Micro-controller 14 and 15 are connected to the matrix columns.
These readPins detect which keys are pressed while a row is strobed.

sizeof() is used to compute the number of array elements.
This eliminates the risk of forgetting to update the count after adding or removing an element.
This eliminates the risk of forgetting to update the count
after adding or removing an element from the array.
*/
uint8_t readPins[] = {14, 15};
uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins);
@@ -69,11 +69,11 @@ Code_Sc s_c(KEY_C);
Code_Sc s_shift(MODIFIERKEY_LEFT_SHIFT);

/* =================== ROWS ====================
Here we pack Code objects into row objects.
Here we pack Code objects into Row objects.
The Row objects names in this sketch start with a "row_" followed by a row number.

Row_uC constructor has four parameters:
1) stobePin connected to the row.
1) strobePin connected to the row.
2) readPins[] connected to the colums.
3) the number of readPins.
4) ptrsKeys[] containing all the Code objects of the row, one Code object per key.
@@ -95,7 +95,7 @@ void setup()

/*
loop() continually scans the matrix, one row at a time.
Each row object strobes the strobePin and reads the readPins.
Each row object strobes its strobePin and reads the readPins.
And when a key press is detected, the row sends the key's scancode.

scanDelay creates time intervals between matrix scans.

+ 6
- 6
tutorials/keybrd_3a_multi-layer/keybrd_3a_multi-layer.ino View File

@@ -11,7 +11,7 @@ This sketch:

Each cell in the table's body represents a key.
The layered keys in row 0 have two layers; one character for each layer.
Letters 'a' and 'b' are on the normal layer. Numbers '1' and '2' are one the fn layer.
Letters 'a' and 'b' are on the normal layer. Numbers '1' and '2' are on the fn layer.
Holding the fn key down makes it the active layer. Releasing the fn key restores the normal layer.
*/
// ################## GLOBAL ###################
@@ -52,8 +52,8 @@ LayerState layerState;
/*
NORMAL=0 and FN=1. LayerState's default layer id is 0.
The Code_LayerHold constructor has two parameters:
1) the layer that will be active while the key is held down.
2) the LayerState
1) the layer that will be active while the key is held down.
2) a LayerState
When l_fn is pressed, it tells layerState to change the active layer to 1.
When l_fn is released, it tells layerState that layer 1 is released, and layerState restores the default layer.
*/
@@ -72,7 +72,7 @@ The Key_LayeredKeysArray constructor takes one array of Code pointers - one Code
Key_LayeredKeysArray uses layer id numbers as array indexes.
Thus Key_LayeredKeysArray calls the Code corresponding to the active layer id.

The Key object names in this sketch start with a "k_" followed by matrix-row-column coordinates.
The Key object names in this sketch start with a "k_" followed by row-column coordinates.
*/
Key* const ptrsCodes_01[] = { &s_a, &s_1 };
Key_LayeredKeysArray k_01(ptrsCodes_01);
@@ -94,8 +94,8 @@ It then uses the layer id as an array index to send the scancode for the active
Here we pack Key pointers into row objects.

Codes are a kind of Key that only have one layer.
So rows can contain a mix of multi-layered keys and codes.
Arrays ptrsKeys_0[] and ptrsKeys_1[] contain both Key pointers and Code pointers.
So rows can contain a mix of codes and multi-layered keys.
Arrays ptrsKeys_0[] and ptrsKeys_1[] contain both Code pointers and Key pointers.
*/
Key* const ptrsKeys_0[] = { &s_shift, &k_01 };
Row_uC row_0(0, readPins, READ_PIN_COUNT, ptrsKeys_0);

+ 0
- 102
tutorials/keybrd_4b_split_keyboard_with_shift_registers/keybrd_4b_split_keyboard_with_shift_registers.ino View File

@@ -1,102 +0,0 @@
/* tutorial_4a_split_keyboard_with_shift_registers.ino
Tested on Teensy LC and two 74HC165 shift registers.

The right matrix has 2 shift registers daisy chained.
Every 4th input pin has a pull-up resistor and matrix column.
Unused input pins are powered.

Layout Layout
| Left | **0**| | Right |**0**|**1**|**2**|**3**|
|:-----:|------| |:-----:|-----|-----|-----|-----|
| **0** | x | | **0** | 0 | 1 | 2 | 3 |
| **1** | y | | **1** | a | b | c | d |
*/
// ################## GLOBAL ###################
// ================= INCLUDES ==================
//Codes
#include <Code_Sc.h>
#include <Code_LEDLock.h>

//Matrix
#include <SPI.h>
#include <Row_uC.h>
#include <Row_ShiftRegisters.h>
#include <ScanDelay.h>

// =============== CONFIGURATION ===============
ScanDelay scanDelay(9000);

//set left matrix for active low
const bool Scanner_uC::STROBE_ON = LOW;
const bool Scanner_uC::STROBE_OFF = HIGH;

const uint8_t Scanner_ShiftRegs74HC165::SHIFT_LOAD = 10;

//set right matrix for active low
const bool Scanner_ShiftRegs74HC165::STROBE_ON = LOW;
const bool Scanner_ShiftRegs74HC165::STROBE_OFF = HIGH;

// ================= LEFT PINS =================
uint8_t readPins[] = {14};
uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins);

// =================== CODES ===================
Code_Sc s_a(KEY_A);
Code_Sc s_b(KEY_B);
Code_Sc s_c(KEY_C);
Code_Sc s_d(KEY_D);

Code_Sc s_x(KEY_X);
Code_Sc s_y(KEY_Y);

Code_Sc s_z(KEY_Z);

Code_Sc s_0(KEY_0);
Code_Sc s_1(KEY_1);
Code_Sc s_2(KEY_2);
Code_Sc s_3(KEY_3);

// ================= LEFT ROWS =================
Key* ptrsKeys_L0[] = { &s_x };
Row_uC row_L0(0, readPins, READ_PIN_COUNT, ptrsKeys_L0);

Key* ptrsKeys_L1[] = { &s_y };
Row_uC row_L1(1, readPins, READ_PIN_COUNT, ptrsKeys_L1);

/* ================= RIGHT ROWS ================
Instantiating a Row_ShiftRegistersis similar to instantiating a Row_uC.

The s_z are place holders where the input pins are powered; they should not send scancodes.
*/

//should send 0 1 2 3
Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z,
&s_2, &s_z, &s_z, &s_z, &s_3, &s_z, &s_z, &s_z };
Row_ShiftRegisters row_R0(0, sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0), ptrsKeys_R0);

//should send a b c d
Key* ptrsKeys_R1[] = { &s_a, &s_z, &s_z, &s_z, &s_b, &s_z, &s_z, &s_z,
&s_c, &s_z, &s_z, &s_z, &s_d, &s_z, &s_z, &s_z };
Row_ShiftRegisters row_R1(1, sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1), ptrsKeys_R1);

// ################### MAIN ####################
void setup()
{
Keyboard.begin();
SPI.begin();
row_R0.begin();
row_R1.begin();
}

void loop()
{
//left matrix
row_L0.process();
row_L1.process();

//right matrix
row_R0.process();
row_R1.process();

scanDelay.delay();
}

BIN
tutorials/keybrd_4b_split_keyboard_with_shift_registers/shift_reg_back.JPG View File


BIN
tutorials/keybrd_4b_split_keyboard_with_shift_registers/shift_reg_front.JPG View File


BIN
tutorials/keybrd_4b_split_keyboard_with_shift_registers/shift_reg_side.JPG View File


+ 0
- 158
tutorials/keybrd_4c_split_with_IOE_notgit/keybrd_4b_split_with_IOE.ino View File

@@ -1,158 +0,0 @@
/* keybrd_4_split_with_IOE_annotated.ino

This sketch:
is a simple 1-layer keyboard
runs on two matrices of a breadboard keyboard
is annotated with a walk-through narrative

This layout table shows left and right matrices:

| Left | **0** | **1** | | Right | **0** | **1** |
|:-----:|-------|-------|-|:-----:|-------|-------|
| **0** | a | b | | **0** | 1 | 2 |
| **1** | shift | c | | **1** | 3 | shift |

MARTIX NAMING CONVENTION
Since this keyboard has two matrices, we need a naming convention to distinguish the matrices.
Matrix IDs are the letters 'L' and 'R' (left and right).
Port object names and Port pointer array names end with matrix ID:
port1_R
rowPortF_L rowPort1_R
port0_R
colPortB_L colPort0_R
ptrsColPorts_L ptrsColPorts_R
COL_PORT_L_COUNT COL_PORT_R_COUNT

Key pointer array names and Row objects names end with matrix ID and row number:
ptrsKeys_L0 ptrsKeys_R0
row_L0 row_R0

Matrix object names end with matrix ID:
matrix_L matrix_R
*/
// ################## GLOBAL ###################
// ================= INCLUDES ==================
//Ports
#include <RowPort_AVR_Optic.h>
#include <ColPort_AVR.h>
#include <IOExpanderPort.h>
#include <RowPort_PCA9655E.h>
#include <ColPort_PCA9655E.h>

//Codes
#include <Code_Sc.h>

//Matrix
#include <Row.h>
#include <Matrix.h>

// ============ SPEED CONFIGURATIONS ============
const unsigned int Row::DELAY_MICROSECONDS = 1000;

// ================ LEFT PORTS =================
/*
The left matrix is scanned by a micro-controller.
*/
RowPort_AVR_Optic rowPortF_L(DDRF, PORTF);

ColPort_AVR colPortB_L(DDRB, PORTB, PINB, 1<<0 | 1<<1 );
ColPort* const ptrsColPorts_L[] = { &colPortB_L };
const uint8_t COL_PORT_L_COUNT = sizeof(ptrsColPorts_L)/sizeof(*ptrsColPorts_L);

// =============== RIGHT PORTS =================
/*
The right matrix is scanned by an I/O expander.

I/O expander I2C address is configured by hardware pins.
ADDR is a static variable of class IOExpanderPort.
*/
const uint8_t IOExpanderPort::ADDR = 0x18;

/*
The I/O expander has two ports. Each port has eight pins.
One port is connected to the matrix's rows. The other port is connected to the matrix's columns.

The IOExpanderPort constructor parameters specify the port number and initial output value.

port1_R is port 1 and has an initial output value of 0.
rowPort1_R uses port1_R.
*/
IOExpanderPort port1_R(1, 0);
RowPort_PCA9655E rowPort1_R(port1_R);

/*
port0_R is port 0 and has an initial output value of 0.
colPort0_R uses port0_R to read pin 0 and pin 1.
*/
IOExpanderPort port0_R(0, 0);
ColPort_PCA9655E colPort0_R(port0_R, 1<<0 | 1<<1 );

/*
ColPort pointers are packed into an array.
*/
ColPort* const ptrsColPorts_R[] = { &colPort0_R };
const uint8_t COL_PORT_R_COUNT = sizeof(ptrsColPorts_R)/sizeof(*ptrsColPorts_R);

// =================== CODES ===================
/*
Codes are not grouped into left and right because codes are independent of layout.
- a keyboard can have differnt layouts
- some codes may appear on both matrices
*/
Code_Sc s_shiftL(MODIFIERKEY_LEFT_SHIFT);
Code_Sc s_shiftR(MODIFIERKEY_RIGHT_SHIFT);

Code_Sc s_a(KEY_A);
Code_Sc s_b(KEY_B);
Code_Sc s_c(KEY_C);
Code_Sc s_1(KEY_1);
Code_Sc s_2(KEY_2);
Code_Sc s_3(KEY_3);

// ================ LEFT MATRIX ================
// ---------------- LEFT ROWS ------------------
Key* const ptrsKeys_L0[] = { &s_a, &s_b };
Row row_L0(rowPortF_L, 1<<0, ptrsColPorts_L, COL_PORT_L_COUNT, ptrsKeys_L0);

Key* const ptrsKeys_L1[] = { &s_c, &s_shiftL };
Row row_L1(rowPortF_L, 1<<1, ptrsColPorts_L, COL_PORT_L_COUNT, ptrsKeys_L1);

// ---------------- LEFT MATRIX ----------------
Row* const ptrsRows_L[] = { &row_L0, &row_L1 };
const uint8_t ROW_L_COUNT = sizeof(ptrsRows_L)/sizeof(*ptrsRows_L);

Matrix matrix_L(ptrsRows_L, ROW_L_COUNT, 1);

// ================ RIGHT MATRIX ===============
// ---------------- RIGHT ROWS -----------------
Key* const ptrsKeys_R0[] = { &s_1, &s_2 };
Row row_R0(rowPort1_R, 1<<0, ptrsColPorts_R, COL_PORT_R_COUNT, ptrsKeys_R0);

Key* const ptrsKeys_R1[] = { &s_3, &s_shiftR };
Row row_R1(rowPort1_R, 1<<1, ptrsColPorts_R, COL_PORT_R_COUNT, ptrsKeys_R1);

// ---------------- RIGHT MATRIX ---------------
Row* const ptrsRows_R[] = { &row_R0, &row_R1 };
const uint8_t ROW_R_COUNT = sizeof(ptrsRows_R)/sizeof(*ptrsRows_R);

Matrix matrix_R(ptrsRows_R, ROW_R_COUNT, 1);

// ################### MAIN ####################
void setup()
{
/*
Call begin() for I/O expander's rowPort and colPort.
*/
rowPort1_R.begin();
colPort0_R.begin();
Keyboard.begin();
}

/*
loop() continually scans both Matrix objects.
*/
void loop()
{
matrix_L.scan();
matrix_R.scan();
}

+ 3
- 3
tutorials/keybrd_5_LEDs/keybrd_5_LEDs.ino View File

@@ -35,8 +35,8 @@ uint8_t readPins[] = {14, 15};
uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins);

/* ==================== LEDs ===================
The LED_uC constructor parameter is for an Aduino pin that is connected to an LED.
LED_uC objects are passed to other objects that want to turn the LED on or off.
The LED_uC constructor parameter is for an Aduino pin number that is connected to an LED.
LED objects are passed to other objects that want to turn the LED on or off.
In this example, the LED_uC objects are named after the states they indicate.

The prtsLayerLEDs[] array contains one LED per layer, it is used to indicate the current layer.
@@ -60,7 +60,7 @@ LayerState_LED layerState(prtsLayerLEDs);
Code_LayerHold l_fn(FN, layerState);

/* ---------------- SCAN CODES -----------------
When a Code_LEDLock object is pressed, it sends a scancodes and updates the its LED.
When a Code_LEDLock object is pressed, it sends its scancode and updates the its LED.
Scancodes can be one of KEY_CAPS_LOCK, KEY_SCROLL_LOCK, or KEY_NUM_LOCK.
For example, when o_capsLock is pressed, it sends KEY_CAPS_LOCK scancode and updates LED_CapsLck.
*/

+ 4
- 4
tutorials/keybrd_6_active_high/keybrd_6_active_high.ino View File

@@ -1,13 +1,13 @@
/* keybrd_6_active_high.ino

This sketch:
is the tutorial 2 sketch with STROBE_ON/STROBE_OFF values swapped
is the tutorial 1 sketch with STROBE_ON/STROBE_OFF values swapped
is active high 1-layer keyboard
runs on the first two rows and columns of a active-high breadboard keyboard

| Layout | **0** | **1** |
|:------:|-------|-------|
| **0** | shift | a |
| **0** | 1 | a |
| **1** | b | c |
*/

@@ -35,13 +35,13 @@ uint8_t readPins[] = {14, 15};
uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins);

// =================== CODES ===================
Code_Sc s_1(KEY_1);
Code_Sc s_a(KEY_A);
Code_Sc s_b(KEY_B);
Code_Sc s_c(KEY_C);
Code_Sc s_shift(MODIFIERKEY_LEFT_SHIFT);

// =================== ROWS ====================
Key* ptrsKeys_0[] = { &s_shift, &s_a };
Key* ptrsKeys_0[] = { &s_1, &s_a };
Row_uC row_0(0, readPins, READ_PIN_COUNT, ptrsKeys_0);

Key* ptrsKeys_1[] = { &s_b, &s_c };

BIN
tutorials/keybrd_6_active_high/pull_down_resistors.JPG View File


+ 1
- 0
tutorials/tutorial_0_introduction.md View File

@@ -12,4 +12,5 @@ The tutorials assume the reader:
* is familiar with C++
* is new to Arduino, firmware, controllers, and the internal workings of keyboards

<br>
<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 tutorial</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>.

+ 13
- 10
tutorials/tutorial_10_writing_your_own_port_classes.md View File

@@ -1,15 +1,18 @@
Tutorial 8 - writing your own port classes
==========================================
Port classes are the keybrd library's interface to microcontoller ports and I/O expander ports.
Tutorial 10 - writing your own port classes
===========================================
Port classes are the keybrd library's interface to I/O expander ports.

To write your own port classes:
1) Get a copy of the controller or I/O expander datasheet.
2) Study keybrd port classes that use a similar IC.
3) Consider looking for other open-source keyboard code that uses the same IC e.g. TMK keyboard firmware.
4) Write your RowPort_* class to inherit from RowPort class.
5) Write your ColPort_* class to inherit from ColPort class.
1. Get a copy of the controller or I/O expander datasheet.
2. Study other keybrd Port classes.

Writing port classes is the most technically demanding task in the keybrd library.
It might be faster to designing your keyboard around one of the controllers or I/O expanders that already have port classes in the keybrd library.
For example, the keybrd_DH library use these keybrd classes for its PCA9655E I/O:
* PortWrite_PCA9655E
* PortRead_PCA9655E
* LED_PCA9655E

Debugging I/O expander code is hard because SPI or I2C protocol adds a level of indirection.
If you haven't written Arduino code for an I/O expander before, learn from an Arduiono I/O expander tutorial before attempting it here.

<br>
<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 tutorial</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>.

+ 67
- 46
tutorials/tutorial_1_breadboard_keyboard.md View File

@@ -5,11 +5,11 @@ The keyboad will be used in tutorials 2 through 7.
When you finish this tutorial you will have a working keyboard and understand how a key matrix works.
## Why a solderless breadboard keyboard is useful
Breadboard keyboards have row-column matrices and diodes just like the big keyboards.
Why a solderless breadboard keyboard is useful
----------------------------------------------
Breadboard keyboards have key matrices and diodes just like the big keyboards.
A breadboard is the easiest way to learn keyboard electronics.
A novice won't get everything right the first time.
Learning is fun when mistakes are easily corrected.
Compared to PCBs, breadboard keyboards make learning faster because:
* Mistakes are easily corrected; no soldering and desoldering
@@ -17,38 +17,37 @@ Compared to PCBs, breadboard keyboards make learning faster because:
* A small keyboard is easier to trouble shoot
Breadboard keyboards are useful for:
* learning keyboard electronics - micro controllers, diodes, shift registers, I/O expanders
* learning keyboard electronics - micro controller, key matrix, diode, shift registers, I/O expander
* learning the firmware development workflow
* prototyping circuits before making a PCB
Arduino simulation software might be another way; I haven't tried that.
Arduino simulation software is an alternative to breadboards; I haven't tried that.
## Breadboard keyboard starter kit
Breadboard keyboard starter kit
-------------------------------
The parts needed to build the tutorial Breadboard Keyboards are listed in [breadboard_keyboard_supplies.ods](breadboard_keyboard_supplies.ods).
The tutorials use a Teensy LC controller, but any Arduino-compatible controller should work.
The tutorials use a Teensy LC controller, but any Arduino-compatible controller with SRAM should work.
You will need two tools:
* Wire cutters (or nail clipper)
* Wire cutters
* A multi-meter for trouble shooting
Wire striper and lead forming tool are optional.
## How a breadboard works
How a breadboard works
----------------------
To understand the breadboard keyboard you will need to know the internal parts of a breadboard:
* bus strip
* terminal strip
These are explained in [How to Use a Breadboard](https://learn.sparkfun.com/tutorials/how-to-use-a-breadboard)
## How a keyboard matrix works
This excellent article explains how the microcontroller, matrix, switches and diodes work together:
[How a Key Matrix Work](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/)
## Building a basic breadboard keyboard
Building a basic breadboard keyboard
------------------------------------
The basic breadboard keyboard has 4 switches.
![basic breadboard keyboard](keybrd_1_breadboard_images/breadboard_keyboard_2x2.JPG "basic breadboard keyboard")
![basic breadboard keyboard](keybrd_1_breadboard/breadboard_keyboard_2x2.JPG "basic breadboard keyboard")
A Teensy LC microcontroller in on the left.
A key matrix with 4 switches is to the right.
@@ -57,8 +56,7 @@ The key matrix has two two columns.
Short wires connect terminal strips into matrix columns.
Jumper wires connect the columns to the microcontroller.
The key matrix has two two rows.
Breadboard bus strips are matrix rows.
Two bus strips are used as matrix rows.
A jumper connects the top row to the microcontroller.
A short wire connects the bottom row to the microcontroller.
@@ -66,49 +64,72 @@ Switch-diode pairs, in series, connect rows to columns.
Tutorials 2 and 3 use the basic breadboard keyboard pictured above.
Tutorials 4, 5, and 6 will add more components to the basic breadboard keyboard.
Positioning components as shown on the picture will provide space for those components.
![pic of shift registers, LEDs, active high on one bb]
Positioning components as shown in the picture will provide space for those components.
Breadboard keyboard assembly instructions:
1. Bend and cut leads to fit breadboard.
* tactile-switch-lead
* diodes (save the cut offs for steps 2, 3, and tutorial 4)
* tactile-switch-lead
* diodes (save the cut offs for steps 2, 3, and tutorial 4)
![bend diodes](keybrd_1_breadboard_images/diodes_bend_en_masse.JPG "bend diodes")
![bend diodes](keybrd_1_breadboard/diodes_bend_en_masse.JPG "bend diodes")
![cut diodes](keybrd_1_breadboard_images/diodes_cut.JPG "cut diodes")
![cut diodes](keybrd_1_breadboard/diodes_cut.JPG "cut diodes")
2. Insert parts into the breadboard as shown in the picture.
* The breadboard is oriented with the red bus strips on top and blue bus strips on the bottom
* The breadboard is oriented with the red bus strips on top and blue bus strips on the bottom
(this is important because tutorials will refer to the "red bus" and the "blue bus")
* Teensy LC is positioned such that:
* terminal strips above Teensy have three holes exposed
* terminal strips below Teensy have two holes exposed
(the holes will be used in later tutorials)
* switch leads are oriented to connect diodes to columns (pictured below)
* diode cut offs connect terminal strips into columns
* diodes connect to the blue bus, orient with cathode (banded end) towards the row (bus strip)
* Teensy LC is on the left
* switch leads are oriented to connect diodes to columns (pictured below)
* diode cut offs connect terminal strips into columns
* diodes connect switches to blue buses, orient with cathode (banded end) towards the row (bus strip)
![switch orientation](keybrd_1_breadboard/switch_orientation.JPG "switch orientation")
![switch orientation](keybrd_1_breadboard_images/switch_orientation.JPG "switch orientation")
![basic breadboard keyboard overhead](keybrd_1_breadboard_images/breadboard_keyboard_2x2_overhead.JPG "basic breadboard keyboard overhead")
![basic breadboard keyboard overhead](keybrd_1_breadboard/breadboard_keyboard_2x2_overhead.JPG "basic breadboard keyboard overhead")
3. Insert jumper wires to connect Arduino pins to the matrix rows and columns.
* [Teensy LC pinout diagram](https://www.pjrc.com/teensy/card6a_rev2.png).
* row_0 is the top row, and col_0 is the left column
* [Teensy LC pinout diagram](https://www.pjrc.com/teensy/card6a_rev2.png).
* row_0 is the top row, and col_0 is the left column
| Pin number | Connects to |
|------------|-------------|
| 0 | row_0 |
| 1 | row_1 |
| 14 | col_0 |
| 15 | col_1 |
Compiling and loading the keyboard firmware
-------------------------------------------
Follow the [keybrd Library User's Guide](../doc/keybrd_library_user_guide.md) to set up the Arduino environment.
| Pin number | connected to |
|------------|--------------|
| 0 | row_0 |
| 1 | row_1 |
| 14 | col_0 |
| 15 | col_1 |
Compile and load the [keybrd_1_breadboard.ino](/tutorials/keybrd_1_breadboard/keybrd_1_breadboard.ino) sketch into the keyboard's controller.
The operating system will take 1 to 6 seconds to recognize the USB keyboard.
Then pressing the keys should type the characters 1, a, b, c.
## Compiling and loading the keyboard firmware
Follow the [keybrd Library User's Guide](../doc/keybrd_library_user_guide.md) to set up the Arduino environment.
How a key matrix works
----------------------
Congratulations, you have a working breadboard keyboard.
Now we fill in some details of how it all works.
This excellent article explains how key matrix, diodes, and ghosting work:
[How a Key Matrix Work](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/)
In the article:
output pins power columns and input pins detect the power on rows.
The breadboard keyboards in this series of tutorials do it the other way:
output pins power rows and input pins detect the power on columns.
The keybrd library uses the word "strobe".
Strobe pins are output pins connected to rows.
One row at a time is strobed for the purpose of reading input pins.
Compile and load the [keybrd_2_single-layer.ino](keybrd_2_single-layer/keybrd_2_single-layer.ino) sketch into the keyboard's controller.
Exercises
---------
1) replace the diodes with wires (cutoffs) and intentionally cause ghosting.
<br><br>
<br>
<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 tutorial</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>.

+ 9
- 6
tutorials/tutorial_2_single-layer_keyboard.md View File

@@ -4,13 +4,16 @@ The easiest way to learn the keyboard library is to read some simple sketches.
[keybrd_2_single-layer_annotated.ino](keybrd_2_single-layer_annotated/keybrd_2_single-layer_annotated.ino) is a simple sketch with annotations that explain how a keybrd sketch works.
The sketch will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md)
![basic breadboard keyboard](keybrd_1_breadboard_images/breadboard_keyboard_2x2.JPG "basic breadboard keyboard")
Class definitions can be viewed in the [keybrd library](../src/).
After reading the sketch you will be able to modify it to suite your own single-layer keyboard design.
## Exercises
1) Add a third column to the breadboard keyboard and sketch.
![basic breadboard keyboard](keybrd_1_breadboard/breadboard_keyboard_2x2.JPG "basic breadboard keyboard")
Exercises
---------
1) Read some of the class definitions used in the sketch.
The classes are defined in the [keybrd library](../src/).
2) Add a third column to the breadboard keyboard and sketch.
<br><br>
<br>
<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 tutorial</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>.

+ 21
- 11
tutorials/tutorial_3a_multi-layer_keyboard.md View File

@@ -2,7 +2,8 @@ Tutorial 3a - multi-layer keyboard
==================================
When you finish this tutorial you will be able to be able to modify a multi-layer keybrd sketch to write your very own multi-layer keyboard design.
## Multi-layer nomenclature
Multi-layer nomenclature
------------------------
**[layers](http://deskthority.net/wiki/Layer)** - are key bindings provided by the keyboard firmware. For example,
* The classic [IBM PC keyboard](http://en.wikipedia.org/wiki/IBM_PC_keyboard) has one layer.
* Many compact keyboards have an additional [Fn layer](http://en.wikipedia.org/wiki/Fn_key).
@@ -14,11 +15,12 @@ When you finish this tutorial you will be able to be able to modify a multi-laye
**layer scheme** - is a system for changing the active layer while typing (a single-layer scheme does not change layers).
## A simple multi-layer keybrd sketch
A simple multi-layer keybrd sketch
----------------------------------
The [keybrd_3a_multi-layer.ino](keybrd_3a_multi-layer/keybrd_3a_multi-layer.ino) sketch is for a simple two-layer keyboard.
It will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md)
It will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md).
![basic breadboard keyboard](keybrd_1_breadboard_images/breadboard_keyboard_2x2.JPG "basic breadboard keyboard")
![basic breadboard keyboard](keybrd_1_breadboard/breadboard_keyboard_2x2.JPG "basic breadboard keyboard")
Read the sketch annotations to understand how multi-layer keyboards work.
The sketch uses three layer-scheme classes:
@@ -28,8 +30,9 @@ The sketch uses three layer-scheme classes:
The internal workings of these three classes are revealed in the next section.
## Pseudo code for simple layer scheme
The following is pseudo code of three keybrd library classes.
Pseudo code for simple layer scheme
-----------------------------------
The following pseudo code is of three keybrd library classes.
It has just enough detail to show the internal workings of layer schemes.
**Key_Layer** objects change the active layer when pressed.
@@ -56,7 +59,7 @@ class LayerState
```
**Key_LayeredKeysArray** objects contain an array of keys, one key for each layer.
Key_LayeredKeysArray use layer ids as array indexes to send the appropriate key.
Key_LayeredKeysArray use layer ids as array indexes.
When a Key_LayeredKeysArray object is pressed, it gets the active layer from LayerState, and sends the corresponding key.
```
class Key_LayeredKeysArray
@@ -88,7 +91,8 @@ Dependency diagram
| Key_LayeredKeysArray |
+----------------------+
```
## Layer-scheme classes
Layer-scheme classes
--------------------
There are several layer scheme-classes to choose from.
You can view all the class definitions in the [keybrd library](../src/).
@@ -105,7 +109,11 @@ Key_Layered classes include:
* Code_LayeredCodeSc
* Code_LayeredCodeCode
## Single-layer Codes
The basic LayerState provided by the keybrd library is sufficient for implementing ordinary layer schemes.
For experimental layer schemes, you would need to create a custom LayerState class, and possibly Key_Layer and Key_Layered custom layer classes as well.
Single-layer Codes
------------------
Most Code objects only have one scancode or code.
Example single-layer Code classes include:
* Code_Sc
@@ -115,13 +123,15 @@ Example single-layer Code classes include:
* Code_LayerHold
* Code_LayerLock
## Exercises
Exercises
---------
1) Modify the keybrd_3_multi-layer.ino sketch to use two Code_LayerLock objects.
| Layout | **0** | **1** |
|:------:|--------|--------|
|:------:|:------:|:------:|
| **0** | a 1 | b 2 |
| **1** | layer0 | layer1 |
<br>
<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 tutorial</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>.

+ 13
- 8
tutorials/tutorial_3b_autoShift.md View File

@@ -1,24 +1,29 @@
Tutorial 3b - autoShift
=======================
Some mulit-layer keyboards have a symbols layer that writes symbols without using the shift key:
Some multi-layer keyboards have a symbols layer that writes symbols without using the shift key:
~ ! @ # $ % ^ & * () _ {} | < > : ?
The keybrd library does this by automatically sending a MODIFIERKEY_SHIFT scancode.
The [keybrd_3_autoShift_annotated.ino](keybrd_3_autoShift_annotated/keybrd_3_autoShift_annotated.ino) sketch explains the AutoShift feature.
After reading the sketch you too will be able to automatically shifted characters.
Two keybrd classes use AutoShift:
* Code_ScS
* Code_ScNS
## Exercises
1) Modify the keybrd_3_autoShift_annotated sketch to make a 3-layer keyboard with two Code_LayerHold objects.
The [keybrd_3_autoShift.ino](keybrd_3_autoShift/keybrd_3_autoShift.ino) sketch explains the AutoShift feature.
It will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md).
After reading the sketch you too will be able to automatically shifted characters.
![basic breadboard keyboard](keybrd_1_breadboard/breadboard_keyboard_2x2.JPG "basic breadboard keyboard")
Exercises
---------
1) Modify the keybrd_3_autoShift_annotated sketch to make a 3-layer keyboard with a default layer and two Code_LayerHold objects.
| Layout | **0** | **1** |
|:------:|-------|-------|
|:------:|:-----:|:-----:|
| **0** | a ! 6 | b @ 7 |
| **1** | sym | num |
| **1** |. sym .|. num .|
<br>
<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 tutorial</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>.

+ 0
- 77
tutorials/tutorial_4b_split_keyboard_with_shift_registers.md View File

@@ -1,77 +0,0 @@
keybrd Tutorial 4b - split keyboard with shift registers
========================================================
When you finish this tutorial you will be able to be able to modify a 2-matrix keybrd sketch to suite your own split keyboard design.

## Overview of split keyboard with shift registers
The breadboard in the following picture models a split keyboard.

The primary matrix on the left has one column, which is read by a microcontroller pin.
The secondary matrix on the right has 4 columns, which are read by the shift register input pins.
The primary and secondary matrices share the same rows, which are strobed by micro-controller pins.
Both matrices are active low.

![breadboard keyboard with shift_registers](keybrd_4b_split_keyboard_with_shift_registers/shift_reg_front.JPG )

## Building a split keyboard with shift registers
The breadboard keyboard modifies the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md)

Add components to the breadboard as shown in the picture.

The shift register is a SN74HC165N. Details are in the SN74HC165N datasheet.

Each shift register has a small notch on one end to identify pin 1.
In the picture, 1 pins are on the right end.
Shift registers are chained together by colored wires that lay flat on the breadboard.

Each shift register has 8 parallel input pins, 4 on each side.
The breadboard doesn't have enough room for 16 columns; only 4 columns are connected to the shift registers.
Every 4th input pin is connected to a matrix column and a pull-up resistor.
Unused input pins are connected to power.
The red bus strips power the pull up resistors and unused input pins.

A decoupling capacitor between the power and ground wires dampens noise coming in through those wires.

![breadboard keyboard with shift_registers](keybrd_4b_split_keyboard_with_shift_registers/shift_reg_side.JPG )

![breadboard keyboard with shift_registers](keybrd_4b_split_keyboard_with_shift_registers/shift_reg_back.JPG )

Blue bus strips are used for strobing rows

I apologize for not having a schematic. This table should help you figure out the pictures:

<!-- todo add schematic -->

```
74HC165 left (upper half of breadboard)
NAME PIN# I/O DESCRIPTION DESTINATION PIN# CHAIN (wires flat on breadboard)
SH/LD 1 I shift or load input Teensy LC CS0 10 red wire
CLK 2 I clock input Teensy LC SCK0 13 green wire
D4 3 I parallel input pull-up resistor red bus
D5 4 I parallel input power red bus
D6 5 I parallel input power red bus
D7 6 I parallel input power red bus
/QH 7 O ~serial output Teensy LC MISO0 12
GND 8 ground gnd black wire

74HC165 right (lower half of breadboard)
NAME PIN# I/O DESCRIPTION DESTINATION CHAIN (wires flat on breadboard)
VCC 16 power pin Teensy LC 3.3V red bus
CLK INH 15 I clock inhibit gnd black wire
D3 14 I parallel input power red bus
D2 13 I parallel input power red bus
D1 12 I parallel input power red bus
D0 11 I parallel input pull-up resistor red bus
SER 10 I serial input next QH yellow wire
QH 9 O serial output previous SER yellow wire

```
## Sketch for split keyboard with shift registers
[keybrd_4b_split_keyboard_with_shift_registers.ino](keybrd_4b_split_keyboard_with_shift_registers/keybrd_4b_split_keyboard_with_shift_registers.ino) is a simple sketch with two shift registers.
The sketch will run on the above breadboard keyboard.
Annotations in the sketch explain the code.

## Exercises
1. Guess what happens if an unused input pin is not powered? Try it.

<br><br>
<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 tutorial</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>.

+ 0
- 70
tutorials/tutorial_4c_split_keyboard_with_IOE_notgit.md View File

@@ -1,70 +0,0 @@
keybrd Tutorial 4 - split keyboard with I/O Expander
====================================================
When you finish this tutorial you will be able to be able to modify a 2-matrix keybrd sketch to suite your own split keyboard design.

## Overview of split keyboard with I/O Expander
The breadboard in this picture models a split keyboard.
![breadboard keyboard with 2 rows and 4 columns of keys](images/breadboard_keyboard_2x5_labeled.jpg "2x5 breadboard keyboard")

The breadboard's four bus strips are used as rows.
Two rows (blue bus strips) are connected to the microcontroller.
Two rows (red bus strips) are connected to the shift registers.

The breadboard's four bus strips are used as rows.
Two rows connect to a microcontroller, and two rows connected to a I/O expander.

The I/O expander has a small notch on one end, which identifies pin 1.
In the picture, pin 1 is on the right end.

The microcontroller and I/O expander are connected by 4 jumper wires:
* ground
* power
* Serial CLock signal (SCL)
* Serial DAta signal (SDA)

A decoupling capacitor on the power pin dampens noise coming in through the power and ground wires.

The microcontroller and I/O expander communicate via [I2C](http://en.wikipedia.org/wiki/I%C2%B2C) bus, which consists of two signals: SCL and SDA.
Two resistors pull-up voltage on the SCL and SDA.

I/O expander I2C address is configured by hardware pins.
The MCP23018 with all address pins grounded has an I2C address of ?? todo.

The I/O expander has two ports. Each port has eight pins.
One port is connected to the matrix's rows. The other port is connected to the matrix's columns.

## Building a split keyboard with I/O Expander
We will build a split keyboard adding parts to the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md)

todo add schematic

<!-- schematic with IOE power decoupling capacitor
This schematic was written by consulting the I/O expander's datasheet and using the ?? tool. -->

Continuing from the basic breadboard keyboard instructions:

<!-- At some point in the future, Markdown may support starting ordered lists at an arbitrary number. -->

4. Insert the I/O expander

5. Install I/O expander power
* ground
* power
* capacitor

6. Install I2C bus
* SCL
* SDA
* pull-up resistors on SCL and SDA

7. configure I2C address

8. Assemble key matrix as shown in the picture.

9. Connect I/O expander ports to matrix rows and columns

## Sketch for split keyboard with I/O Expander
The [keybrd_4_split_with_IOE_annotated.ino](keybrd_4_split_with_IOE_annotated/keybrd_4_split_with_IOE_annotated.ino)
sketch explains how the I/O Expander works on a keyboard.

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

+ 94
- 0
tutorials/tutorial_5_LEDs.md View File

@@ -0,0 +1,94 @@
Tutorial 5 - indicator LEDs
===========================
Keyboards often have LEDs to indicate CapsLock, NumLock, and other states.
It's one of the first things we look at when a keyboard produces unexpected results.

Adding LEDs to the basic breadboard keyboard
--------------------------------------------
The breadboard keyboard modifies the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md)

Add components to the breadboard as shown in the picture.

The three clear plastic cylinders are LEDs.
LED anodes (the longer lead) are powered by 4.7k Ohm current limiting resistors connected to pins 16, 17, and 21.
LED cathodes (the shorter lead) are grounded by a common terminal strip.

!["LEDs"](keybrd_5_LEDs/LEDs_back.JPG "LEDs")

keybrd sketch for driving LEDs
------------------------------
[keybrd_5_LEDs.ino](keybrd_5_LEDs/keybrd_5_LEDs.ino) is a simple sketch with three LEDs.
The sketch will run on the above breadboard keyboard.
As usual, the sketch annotations explain the code.

LED brightness
--------------
An LED's current limiting resistor value effects the brightness of the LED.
Lets see how much visual difference resistance makes.
Replace an LED's 4.7k Ohm resistor with a 270 Ohm resistor.

It doesn't matter which end of the LED the resistor is on, the important thing is that the resistor and LED are in series.

Less resistance makes the LED brighter.
Too little resistance will burn out the LED.
Connecting an LED directly to power will destroy the LED in a bright flash (do not look directly at the LED if you try this).

2-mA LEDs are bright enough for keyboard indicator lights.
Or you can use more resistance on a 20-mA LED to make it dimmer.

LED current limiting resistor values
------------------------------------
Never connect an LED directly from ground to power. Doing so would destroy the LED.

This formula calculates the minimum resistance for maximum LED brightness:
```
output-pin Supply Voltage Vs
LED Forward Voltage Vf
Forward Current If

minimum current limiting restiance R = (Vs - Vf) / If
```

For Forward Current, use the smaller of:
* Current capacity of output pin
* Continuous Forward Current of LED

Teensy LC output-pin capacities are:
* four 20 mA pins (5, 16, 17, 21)
* nineteen 5 mA pins
* Teensy LC on-board LED is on pin 13.
It has a current-limiting resistor on the board, and does not provide enough power for another LED.

For Teensy LC 20 mA pin and the TT Electronics OVLLx8C7 LED:
```
output-pin Supply Voltage Vs = 3.3 volts
LED Forward Voltage Vf = 2.2 volts
max pin Current If = 20 mA
max LED Current If = 20 mA

minimum current limiting restiance R = (Vs - Vf) / If = 55 Ohms
```
It is safe to use more resistance.

Calculating the resistance for the Teensy LC 5 mA pin is left as an exercise.

Through-the-hole resistors have color coded bands that indicate resistance value.
https://en.wikipedia.org/wiki/Electronic_color_code#Resistor_color-coding

Exercises
---------
1) In this exercise you will calculate the minimum current limiting resistance needed for your output pin and LED.

For your micro controller, find:
* Supply Voltage coming out of the output pins
* Current (mA) capacity of the output pins

From your LED's datasheet, find:
* Forward Voltage
* Continuous Forward Current (mA)

Calculate the minimum resistance needed for your LED and Supply Voltage.
There are several "LED current limiting resistor calculators" on line.

<br>
<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 tutorial</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>.

+ 19
- 14
tutorials/tutorial_6_active_high.md View File

@@ -3,52 +3,53 @@ Tutorial 6 - Active high
This tutorial pulls together several concepts needed to understand active state in the context of a keyboard.
Skip to the end of this tutorial if you just want to copy an active-high keyboard.

## Pull-up resistors
Pull-up resistors
-----------------
There are many sources that explain "pull-up resistors", so I won't repeat it here.
Here is a [good tutorial on Pull-up Resistors](https://learn.sparkfun.com/tutorials/pull-up-resistors/what-is-a-pull-up-resistor).

## Active low
All the preceding breadboard keyboards in this tutorial series have used active low with internal pull-up resistors.
Active low
----------
All the keyboards up to this point in the tutorial series have used active low with internal pull-up resistors.

"Active low" means that if a switch is pressed (active state), the read pin is low.
When the switch is released (inactive state), the pull-up resistor pulls the read pin high.
Active low requires pull-up resistors.

The following table traces the strobe current from left to right (0 is ground, 1 is power).
If the switch is closed, the strobe current passes through the switch and pulls the read pin low.
If the switch is open, the pull-up resistor pulls the read pin high.
<br>

|Strobe pin on | Diode orientation | Switch position | Pull resistor | Read pin state |
|:------------:|:------------------:|:---------------:|:-------------:|:---------------:|
| 0 | cathode -:<- anode | close | 1 pull-up | 0 active low |
| 0 | cathode -:<- anode | open | 1 pull-up | 1 inactive high |
<br>
Arduino boards have internal pull-up resistors, which saves on parts and labor compared to manually adding external pull resistors.
If you are designing a keyboard, go with active low.

To make a keyboard active low:
* Use internal pull-up resistors if the IC has them
* Orient diodes with cathode (banded end) towards the write pins (row)
* Define strobe on and off in the sketch like this:
* Define strobe on and strobe off in the sketch like this:
```
const bool Scanner_uC::STROBE_ON = LOW;
const bool Scanner_uC::STROBE_OFF = HIGH;
```

## Active high
Active high
-----------
"Active high" means that if a switch is pressed (active), the read pin is high.
When the switch is released (inactive), the pull-down resistor pulls the read pin low.
Active high requires pull-down resistors.

The following table traces the strobe current from left to right (0 is ground, 1 is power).
If the switch is closed, the strobe current passes through the switch and pulls the read pin high.
If the switch is open, the pull-up resistor pulls the read pin low.
If the switch is open, the pull-down resistor pulls the read pin low.
<br>

|Strobe pin on | Diode orientation | Switch position | Pull resistor | Read pin state |
|:------------:|:------------------:|:---------------:|:-------------:|:---------------:|
| 1 | anode ->:- cathode | close | 0 pull-down | 1 active high |
| 1 | anode ->:- cathode | open | 0 pull-down | 0 inactive low |
<br>
Arduino boards do not have internal pull-down resistors.
If you want to use active low, you will have to add external pull-down resistors to the read pins.

@@ -61,7 +62,8 @@ To make a keyboard active high:
const bool Scanner_uC::STROBE_OFF = LOW;
```

## Making an active-high keyboard
Making a breadboard keyboard active-high
----------------------------------------
This tutorial converts the basic breadboard keyboard from tutorial 1 to active high.
By comparing the above tables, one can see what changes need to be made:
* add external pull-down resistors to the read pins
@@ -71,6 +73,9 @@ By comparing the above tables, one can see what changes need to be made:
The red bus is grounded.
The pull-down resistors plug into the red bus and column read pins.

The [keybrd_6_active_highsketch.ino](keybrd_6_active_high/keybrd_6_active_high.ino) is the tutorial 2 sketch with STROBE_ON and STROBE_OFF values swapped.
The [keybrd_6_active_highsketch.ino](keybrd_6_active_high/keybrd_6_active_high.ino) is the tutorial 1 sketch with STROBE_ON and STROBE_OFF values swapped.

![pull_down_resistors.JPG](keybrd_6_active_high/pull_down_resistors.JPG "Active-high diodes and pull-down resistors")

<br>
<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 tutorial</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>.

+ 8
- 7
tutorials/tutorial_8a_using_someone_else's_keybrd_extension_library.md View File

@@ -1,15 +1,16 @@
Tutorial 7a - using someone else's keybrd extension library
========================================================
The keybrd library contains the foundation classes for creating a keyboard firmware.
keybrd extension libraries extend the core keyboard library.
Tutorial 8a - using someone else's keybrd extension library
===========================================================
The keybrd library contains the classes needed for creating most keyboard firmware.
keybrd extension libraries extend the keyboard library with custom classes.

keybrd extension library names are prefixed by "keybrd_" and are listed in: todo keybrd extension libraries are not listed yet
keybrd extension library names are prefixed by "keybrd_" and are listed in:
* [Arduino Playground](http://playground.arduino.cc/Main/InterfacingWithHardware#keyb) > find "keybrd"
* Arduino Library-Manager (Arduino IDE > Sketch > Include Library > Manage Libraries > Filter your search: keybrd)

Instructions for installing a library are at:
Instructions for installing a library on Arduino IDE are at:
http://www.arduino.cc/en/Guide/Libraries

Once a keybrd extension library is installed, it's classes can be included in a sketch.
Once a keybrd extension library is installed, it's classes can be included in your sketch.

<br>
<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 tutorial</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>.

+ 11
- 5
tutorials/tutorial_8b_creating_and_publishing_your_own_keybrd_extension_library.md View File

@@ -1,11 +1,12 @@
Tutorial 7b - creating and publishing your own keybrd extension library
Tutorial 8b - creating and publishing your own keybrd extension library
=======================================================================
Publishing and listing your keybrd extension library allows others to find and install your library.
The keybrd extension library name should start with "keybrd_" so that it is easy for people to find.

The directory structure of the library depends on where it will be listed.

## Publishing anywhere with listing on Arduino Playground LibraryList
Publishing anywhere with listing on Arduino Playground LibraryList
------------------------------------------------------------------
Arduino Playground LibraryList can list a library with any directory structure.
The directory structure of your keybrd extension library can be as simple as:

@@ -33,7 +34,8 @@ Instructions for listing a library on the Arduino playgound LibraryList are at:
Add your keybrd library to the Keyboard/Keypads sublist:
http://playground.arduino.cc/Main/InterfacingWithHardware#keyb

## Publishing on GitHub with listing on Arduino Library-Manager and Arduino Playground LibraryList
Publishing on GitHub with listing on Arduino Library-Manager and Arduino Playground LibraryList
-----------------------------------------------------------------------------------------------
The advantage of using GitHub is that users can submit pull requests.
The advantage of using Arduino Library-Manager is that users can install your library through the Arduino IDE.

@@ -61,16 +63,19 @@ Your keybrd extension library should have a library.properties file and a src fo

The library.properties file is described in
https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification

Example library.properties file:
```
name=keybrd_MyKeyboard
version=1.2.3
author=Me
maintainer=Me
sentence=An extension to the keybrd library for the My keyboard.
sentence=An extension to the keybrd library for the MyKeyboard.
paragraph=This library demonstrates my feature.
category=Device Control
url=https://github.com/Me/keybrd_MyKeyboard
architectures=Teensy LC
architectures=*
```

Instructions for listing a library on Arduino Library Manager are at:
https://github.com/arduino/Arduino/wiki/Library-Manager-FAQ
@@ -80,4 +85,5 @@ After it has been accepted into the Arduino IDE Library Manager, add your librar
Sign in at http://playground.arduino.cc/Main/LibraryList and add keybrd libraries to Keyboard/Keypads sublist:
http://playground.arduino.cc/Main/InterfacingWithHardware#keyb

<br>
<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 tutorial</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>.

+ 15
- 18
tutorials/tutorial_9_breaking_up_a_sketch_into_smaller_files.md View File

@@ -1,34 +1,31 @@
Tutorial 8 - breaking up a sketch into smaller files
Tutorial 9 - breaking up a sketch into smaller files
====================================================
A keybrd sketch can become quite lengthy, which can make it harder to navigate and understand.

The keybrd_DH sketch has about 800 lines of code; 700 of which are for instantiating objects.
The object instantiations are grouped into four files located in the keybrd_DH library, and included in keybrd_DH.ino:
The object instantiations are grouped into six files located in the keybrd_DH library, and included in keybrd_DH.ino:

// ========= OBJECT INSTANTIATIONS =============
#include <instantiations_ports.h>
#include <instantiations_LEDs.h>
#include <instantiations_codes.h>
#include <instantiations_matrix.h>
// ========= INSTANTIATE THE KEYBOARD ==========
#include "config.h"
#include <instantiations_pins.h>
#include <instantiations_scancodes.h>
#include <instantiations_layercodes.h>
#include <instantiations_rows_L.h>
#include <instantiations_rows_R.h>

Splitting your code into groups of instantiations also provides organizational and reusability benefits.

Example 1.
You have three versions of LED indicators you are experimenting with:
instantiations_LEDs_1.h
instantiations_LEDs_2.h
instantiations_LEDs_3.h
* instantiations_LEDs_1.h
* instantiations_LEDs_2.h
* instantiations_LEDs_3.h

Example 2.
You use Colemak and want QWERTY users to to try your new keyboard design.
So you publish your keybrd extension library with two versions of instantiations_matrix.h:
instantiations_matrix_colemak.h
instantiations_matrix_QWERTY.h

Example 3.
You want to try someone else's keybrd sketch, but your controller and matrix are different.
So you replace two of your object instantiation files with your own:
instantiations_ports.h
instantiations_matrix.h
* instantiations_matrix_colemak.h
* instantiations_matrix_QWERTY.h

<br>
<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 tutorial</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>.