From fcaa6d06e9bad0aa847dbf1cc31504853a98dc27 Mon Sep 17 00:00:00 2001 From: wolfv6 Date: Fri, 10 Jun 2016 20:12:56 -0600 Subject: [PATCH] document --- doc/CHANGELOG.md | 19 +++ doc/keybrd_library_developer_guide.md | 136 ++++++++++++++------- doc/planned_features.md | 8 +- src/RowBase.cpp | 9 +- src/RowBase.h | 3 - src/RowScannerInterface.h | 5 - src/RowScanner_PinsBitwise.cpp | 10 +- src/Row_IOE.h | 19 ++- src/Row_uC.h | 15 ++- tutorials/breadboard_keyboard_supplies.ods | Bin 18409 -> 18414 bytes tutorials/tutorial_0_introduction.md | 2 +- 11 files changed, 149 insertions(+), 77 deletions(-) diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 209d0b5..8670255 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -7,6 +7,25 @@ keybrd version 1.0.0 will be released when the public API is stable. ## [Unreleased][unreleased] +## [0.3.2] - 2016-06-10 +### Changed +* Changed uC from scanning port arrays to scanning Arduino pins. + Thereby added support for Arduino boards, Teensy 3, and Teensy LC micro controllers. +* Changed IOE from scanning port arrays to scanning single ports. +* Moved scanner and debouncer into their own classes. + +### Added +* Row_uC +* Row_IOE +* RowScannerInterface +* RowScanner_PinsArray +* RowScanner_PinsBitwise +* DebouncerInterface +* Debouncer_4Samples + +### Removed +* Port arrays + ## [0.3.1] - 2016-06-02 ### Added * RowBase class diff --git a/doc/keybrd_library_developer_guide.md b/doc/keybrd_library_developer_guide.md index 9991e63..b674dcf 100644 --- a/doc/keybrd_library_developer_guide.md +++ b/doc/keybrd_library_developer_guide.md @@ -8,8 +8,8 @@ The most common reason for new classes are: ## Who this guide is for This guide is for the maintainers and developers of the keybrd library and it's extensions. -It is assumed the reader is familiar with C++ language including pointers, objects, classes, static class variables, aggregation, inheritance, polymorphism, and enum. -Some classes use bit manipulation. +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. ## Class inheritance diagrams @@ -17,9 +17,14 @@ Keybrd library class inheritance diagram ``` Matrix - RowBase - | - Row + RowBase + / \ + Row_uC Row_IOE + + RowScannerInterface + / \ + RowScanner_PinsArray RowScanner_PinsBitwise + IOExpanderPort @@ -36,8 +41,13 @@ Keybrd library class inheritance diagram LED_AVR LED_MCP23018 LED_PCA9655E (one LED class for each type of IC) + DebouncerInterface + | + Debouncer_4Samples + + LayerStateInterface - | + | LayerState @@ -66,32 +76,70 @@ Keybrd library class inheritance diagram ## Dependency diagrams -single-layer dependency diagram with LEDs +Example single-layer dependency diagram with LEDs ``` - matrix[1..*] - | - row[1..*]_____________________________ - | \ \ \ - rowPort[1] rowPin[1] colPort[1] keys[1] - | | - colPins[1..*] code[1..*] - | - LED[1] + matrix[1..*] + | + ___ row_uC[1..*] ________ + / \ \ + RowScanner_PinsArray debouncer keys[1..*] + / \ | + strobePin[1] readPins[1..*] code[1..*] + | + LED[1] ``` -multi-layer dependency diagram with LEDs and I/O Expander +Example single-layer dependency diagram I/O Expander ``` - matrix[1..*] - | layerStates[1..*] - row[1..*]_________________________________________/__ | \ - | \ \ \ / \ | \ - rowPort[1] rowPin[1] colPort[1] keys[1] / code_layer[1..*] LED[0..*] - \ / \ | / / - \ / colPins[1..*] key[1..*] / - \ / | / - \ / code[1..*] / - \ / ______________________________________/ + ________ row_uC[1..*] _________ + / \ \ + RowScanner_PinsArray[1] debouncer[1] keys[1..*] + / \ | + strobePin[1] readPins[1..*] code[1..*] + + + ___ row_IOE[1..*] _________ + / \ \ + RowScanner_PinsBitwise[1] debouncer[1] keys[1..*] + / | \ | + rowPort[1] rowPin[1] colPort[1] code[1..*] + \ / \ + \ / colPins[1..*] + \ / + IOExpanderPort[0..*] + +``` + +Example multi-layer dependency diagram with layer LEDs +``` + layerStates[1..*] + ________ row_uC[1..*] _____________________/__ | \ + / \ \ / \ | \ + RowScanner_PinsArray[1] debouncer[1] keys[1..*] / code_layer[1..*] LED[0..*] + / \ | / + strobePin[1] readPins[1..*] code[1..*] + +``` + +Example multi-layer dependency diagram with I/O Expander +``` + + ________ row_uC[1..*] ________________________ _______layerStates[1..*] + / \ \ \ / | + RowScanner_PinsArray[1] debouncer[1] keys[1..*] code_layer[1..*] | + / \ | ________________________| + strobePin[1] readPins[1..*] code[1..*] | + | + | + ___ row_IOE[1..*] _________ __________| + / \ \ / | + RowScanner_PinsBitwise[1] debouncer[1] keys[1..*] code_layer[1..*] | + / | \ | _____________________| + rowPort[1] rowPin[1] colPort[1] code[1..*] + \ / \ + \ / colPins[1..*] + \ / IOExpanderPort[0..*] ``` @@ -162,29 +210,25 @@ Following the style guide makes it easier for the next programmer to understand ## Trace of keybrd scan Arduino does not have a debugger. So here is the next best thing; a list of functions in the order that they are called. +The trace is of a single-layer keybrd scan (no LEDs and no I/O expander). Refer to it like a table of contents while reading the keybrd library. ``` - Matrix::scan() for each row - Row::process() - Row::wait() - Row::scan() - RowPort_*::setActivePin*() strobe row on - for each col port - ColPort_*::read() read col port - RowPort_*::setActivePin*() strobe row off - Row::getRowState() for each col port - for each connected col pin - if key is pressed + Matrix::scan() for each row + RowBase::process() + RowBase::wait() delay time for debounce + RowScanner_PinsArray::scan() strobe row on + for each readPin set rowState bit - Row::debounce() debounce - Row::pressRelease() for each key in row - if falling edge - Key_*::release() scanCode->release() - Code_*::release() Keyboard.release(scancode) - if rising edge - Key_*::press() scanCode->press() - Code_*::press() Keyboard.press(scancode) + strobe row off + Debouncer_4Samples::debounce() debounce + RowBase::pressRelease() for each key in row + if falling edge + Key_*::release() scanCode->release() + Code_*::release() Keyboard.release(scancode) + if rising edge + Key_*::press() scanCode->press() + Code_*::press() Keyboard.press(scancode) ``` ## The Arduino libraries diff --git a/doc/planned_features.md b/doc/planned_features.md index a4182e6..6377b9e 100644 --- a/doc/planned_features.md +++ b/doc/planned_features.md @@ -2,19 +2,19 @@ planned_features is a view of where the keybrd project is headed. Top priority ============ -Redesign elements of debouncer. +Add support for shift registers, for compact split keyboards up to 32 keys per matrix. Med priority ============ -Add support for Teensy LC micro controller - Add 16x16 matrix capability (currently limited to 8x8 matrices) Low priority ============ Add matrix-to-layout mapping array (to decouple matrix from layout) -Change tutorial sketches from teensy 2.0 and PCA9655E-D IOE to Teensy LC and MCP23018 IOE +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 diff --git a/src/RowBase.cpp b/src/RowBase.cpp index 0a345d0..45ac658 100644 --- a/src/RowBase.cpp +++ b/src/RowBase.cpp @@ -24,7 +24,7 @@ For fastest response time, wait() should be placed before scan() or after pressR A keyboard with a faster scan rate responds faster. Follow these step to tune DELAY_MICROSECONDS for maximum scan rate for a given SAMPLE_COUNT: Initialize DELAY_MICROSECONDS in your sketch: - const unsigned int Row::DELAY_MICROSECONDS = 1000; + const unsigned int RowBase::DELAY_MICROSECONDS = 1000; Add this to the sketch's loop() function: debug.print_microseconds_per_scan(); Compile and load the sketch into the microcontroller; microseconds_per_scan is printed every second. @@ -42,12 +42,7 @@ Avoid sampling the switch input at a rate synchronous to events in the environme The largest allowable DELAY_MICROSECONDS is 65535 (.065535 seconds). Polling I2C may slow the scan rate enough so that no additional delay is needed: - const unsigned int Row::DELAY_MICROSECONDS = 0; - -Slow-scan trick for debug messages that print too fast and not aligned, add this to sketch loop(): - delay(500); - Keyboard.println(F("")); -That way debug messages are printed at a managable rate, and each scan starts a new line. + const unsigned int RowBase::DELAY_MICROSECONDS = 0; */ void RowBase::wait() { diff --git a/src/RowBase.h b/src/RowBase.h index 63214a3..6afc4ba 100644 --- a/src/RowBase.h +++ b/src/RowBase.h @@ -5,9 +5,6 @@ #include /* RowBase is an abstract base class. - -Define and initilize DELAY_MICROSECONDS in sketch. - const unsigned int RowBase::DELAY_MICROSECONDS = 0; */ class RowBase { diff --git a/src/RowScannerInterface.h b/src/RowScannerInterface.h index ca45a0f..bb1adcb 100644 --- a/src/RowScannerInterface.h +++ b/src/RowScannerInterface.h @@ -1,11 +1,6 @@ #ifndef ROWSCANNERINTERFACE_H #define ROWSCANNERINTERFACE_H -/* RowScannerInterface is an interface class. -Sets rowEnd and returns rowState. -rowEnd is bitwise, where 1 bit corrsiponds to place immediatly after last key of row. -rowEnd and rowMask are larger type than portMask so that they can not overflow. -*/ #include #include diff --git a/src/RowScanner_PinsBitwise.cpp b/src/RowScanner_PinsBitwise.cpp index 29bd381..42d0a7f 100644 --- a/src/RowScanner_PinsBitwise.cpp +++ b/src/RowScanner_PinsBitwise.cpp @@ -1,7 +1,7 @@ #include "RowScanner_PinsBitwise.h" /* Strobes the row and reads the columns. -Strobe is on for shortest possible time to preserve IR LED on DodoHand's optic switch. +Sets rowEnd and returns rowState. */ uint8_t RowScanner_PinsBitwise::scan(uint16_t& rowEnd) { @@ -16,13 +16,9 @@ uint8_t RowScanner_PinsBitwise::scan(uint16_t& rowEnd) } delayMicroseconds(3); //time to stablize voltage - //read all the port pins + //read the port pins refColPort.read(); -/* shows strobing pin 1 and 2, but realy stobing 0 and 1 todo -Keyboard.print(F(" strobePin=")); -Keyboard.print(strobePin); -Keyboard.print(F(", ")); -*/ + //strobe row off if (activeHigh) { diff --git a/src/Row_IOE.h b/src/Row_IOE.h index 7c856e9..3fc651a 100644 --- a/src/Row_IOE.h +++ b/src/Row_IOE.h @@ -5,14 +5,29 @@ #include #include -/* -Simlar to Row but using RowScanner_PinsBitwise. +/* Row_DH_IOE is a row connected to an Input/Output Expander. Configuration ------------- +Define and initilize DELAY_MICROSECONDS in sketch. Detailed how to is in RowBase.cpp. Instantiation ------------- +Example instantiation of a row: + const uint8_t IOExpanderPort::ADDR = 0x18; + + IOExpanderPort port1(1, 0); + RowPort_PCA9655E rowPort1(port1); + + IOExpanderPort port0(0, 0); + ColPort_PCA9655E colPort0(port0, 1<<0 | 1<<1 | 1<<2 | 1<<3 | 1<<4 | 1<<5 ); + + Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02, &k_03, &k_04, &k_05 }; + Row_IOE row_0(rowPort1, 1<<0, colPort0, ptrsKeys_0); + +Number of pins in colPort0 should equal number of keys in ptrsKeys_0[] array. + if a pin is missing, a key will be unresposive + if a Key pointer is missing, the keyboard will fail in an unprdictable way */ class Row_IOE : public RowBase { diff --git a/src/Row_uC.h b/src/Row_uC.h index 3af67be..bac33ac 100644 --- a/src/Row_uC.h +++ b/src/Row_uC.h @@ -5,13 +5,24 @@ #include #include -/* +/* Row_uC is a row connected to a micro controller. Configuration ------------- +Define and initilize DELAY_MICROSECONDS in sketch. Detailed how to is in RowBase.cpp. Instantiation ------------- - todo - see RowDH +Example instantiation of a row: + + const uint8_t colPins[] = {0,1,2,3,7,8}; + const uint8_t COL_PIN_COUNT = sizeof(colPins)/sizeof(*colPins); + + Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02, &k_03, &k_04, &k_05 }; + Row_DH_uC row_0(21, colPins, COL_PIN_COUNT, ptrsKeys_0); + +Number of colPins should equal number of keys in ptrsKeys_0[] array. + if a colPin is missing, a key will be unresposive + if a Key pointer is missing, the keyboard will fail in an unprdictable way */ class Row_uC : public RowBase { diff --git a/tutorials/breadboard_keyboard_supplies.ods b/tutorials/breadboard_keyboard_supplies.ods index 1e5f2099729eb3b060aa7a12a058ebb27e7a7c5f..95e128846865da006fc3d6b5bb3899d8cdc82dbd 100644 GIT binary patch delta 6805 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 diff --git a/tutorials/tutorial_0_introduction.md b/tutorials/tutorial_0_introduction.md index 0d813c1..74f28cf 100644 --- a/tutorials/tutorial_0_introduction.md +++ b/tutorials/tutorial_0_introduction.md @@ -19,7 +19,7 @@ The tutorials assume the reader: * is new to Arduino, firmware, controllers, and the internal workings of keyboards -> All the tutorial sketches are tested on teensy 2.0 and PCA9655E-D I/O expander +> Most of the tutorial sketches are obsolete and will not compile. Will be updated soon. > The tutorial sketches will be changed to Teensy LC and MCP23018 I/O expander