diff --git a/src/DebouncerInterface.h b/src/DebouncerInterface.h index dab6ecd..1c6d56b 100644 --- a/src/DebouncerInterface.h +++ b/src/DebouncerInterface.h @@ -3,7 +3,7 @@ #include -/* DebouncerInterface is an interface class. +/* debounce() takes rawSignal and returns debounced signal. Signals are bitwise. */ class DebouncerInterface diff --git a/src/Row.cpp b/src/Row.cpp index f370365..cdf8fdf 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -1,4 +1,28 @@ #include "Row.h" + +/* constructor +*/ +Row::Row(ScannerInterface& refScanner, const uint8_t strobePin, + Key* const ptrsKeys[], const uint8_t readPinCount) + : refScanner(refScanner), strobePin(strobePin), + ptrsKeys(ptrsKeys), readPinCount(readPinCount), debounced(0) +{ + refScanner.begin(strobePin); +} + +/* process() scans the row and calls any newly pressed or released keys. +Bitwise variables are 1 bit per key. +*/ +void Row::process() +{ + read_pins_t readState; //bitwise, 1 means key is pressed, 0 means released + read_pins_t debouncedChanged; //bitwise, 1 means debounced changed + + readState = refScanner.scan(strobePin); + debouncedChanged = debouncer.debounce(readState, debounced); + send(readPinCount, debouncedChanged); +} + /* send() calls key's press() or release() function if key was pressed or released. Both parameters are bitwise. diff --git a/src/Row.h b/src/Row.h index a0b797a..a042aea 100644 --- a/src/Row.h +++ b/src/Row.h @@ -5,19 +5,29 @@ #include #include #include +#include +#include -/* Row is an abstract base class. +/* +strobePin has one of two formats: + * if refScanner a Scanner_uC, then strobePin is an Arduino pin number connected to this row + * if refScanner a Scanner_IOE, then strobePin is bitwise, 1 indicating IC pin connected to this row */ class Row { private: + ScannerInterface& refScanner; + const uint8_t strobePin; //pin connected to this row (details above) Key *const *const ptrsKeys; //array of Key pointers + const uint8_t readPinCount; //number of read pins + Debouncer_Samples debouncer; virtual void keyWasPressed(); - protected: + protected://todo is protected needed? read_pins_t debounced; //bitwise state of keys after debouncing, 1=pressed, 0=released void send(const uint8_t readPinCount, const read_pins_t debouncedChanged); public: - Row(Key* const ptrsKeys[]) : ptrsKeys(ptrsKeys), debounced(0) { } - virtual void process()=0; + Row(ScannerInterface& refScanner, const uint8_t strobePin, + Key* const ptrsKeys[], const uint8_t readPinCount); + void process(); }; #endif diff --git a/src/Row_IOE.cpp b/src/Row_IOE.cpp deleted file mode 100644 index 066623a..0000000 --- a/src/Row_IOE.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "Row_IOE.h" - -void Row_IOE::process() -{ - //these variables are all bitwise, one bit per key - uint8_t readState; //1 means pressed, 0 means released - uint8_t debouncedChanged; //1 means debounced changed - - readState = scanner.scan(); - debouncedChanged = debouncer.debounce(readState, debounced); - send(readPinCount, debouncedChanged); -} diff --git a/src/Row_IOE.h b/src/Row_IOE.h deleted file mode 100644 index 2461c84..0000000 --- a/src/Row_IOE.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef ROW_IOE_H -#define ROW_IOE_H - -#include -#include -#include -class PortWriteInterface; -class PortReadInterface; - -/* Row_IOE is a row connected to an I/O Expander. -Configuration and Instantiation instructions are in keybrd/src/Row_uC.h -*/ -class Row_IOE : public Row -{ - private: - Scanner_Port scanner; - Debouncer_Samples debouncer; - const uint8_t readPinCount; - public: - Row_IOE(PortWriteInterface& refPortWrite, const uint8_t strobePin, - PortReadInterface& refPortRead, const uint8_t readPinCount, Key *const ptrsKeys[]) - : Row(ptrsKeys), scanner(refPortWrite, strobePin, refPortRead), - readPinCount(readPinCount) { } - void process(); -}; -#endif diff --git a/src/Row_ShiftRegisters.cpp b/src/Row_ShiftRegisters.cpp deleted file mode 100644 index cdeee48..0000000 --- a/src/Row_ShiftRegisters.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "Row_ShiftRegisters.h" - -/* Call begin() once in sketch setup() -*/ -void Row_ShiftRegisters::begin() -{ - scanner.begin(); -} - -/* process() scans the row and calls any newly pressed or released keys. -Bitwise variables are 1 bit per key. -*/ -void Row_ShiftRegisters::process() -{ - read_pins_t readState; //bitwise, 1 means key is pressed, 0 means released - read_pins_t debouncedChanged; //bitwise, 1 means debounced changed - - readState = scanner.scan(); - debouncedChanged = debouncer.debounce(readState, debounced); - send(readPinCount, debouncedChanged); -} diff --git a/src/Row_ShiftRegisters.h b/src/Row_ShiftRegisters.h deleted file mode 100644 index a3f5aac..0000000 --- a/src/Row_ShiftRegisters.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef ROW_SHIFTREGISTERS_H -#define ROW_SHIFTREGISTERS_H - -#include -#include -#include - -/* Row_ShiftRegisters is a row connected to shift registers. - -Instantiation -------------- -Scanner_ShiftRegs74HC165.h has instructions for hardware and setting active state. -Example instantiation of a Row_ShiftRegisters: - - const uint8_t Scanner_ShiftRegs74HC165::SHIFT_LOAD = 10; - const bool Scanner_ShiftRegs74HC165::STROBE_ON = LOW; //active low - const bool Scanner_ShiftRegs74HC165::STROBE_OFF = HIGH; - - Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02, &k_03, &k_04, &k_05 }; - uint8_t readPinCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0); - Row_ShiftRegisters row_0(1, readPinCount_0, ptrsKeys_0); - -call begin() from sketch setup(): - void setup() - { - Keyboard.begin(); - SPI.begin(); - row_0.begin(); - } - -readPinCount should equal number of keys in ptrsKeys_0[] array. - if readPinCount is too small, a key will be unresponsive - if readPinCount is too large, the keyboard will fail in an unpredictable way -*/ -class Row_ShiftRegisters : public Row -{ - private: - Scanner_ShiftRegs74HC165 scanner; - 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(ptrsKeys), scanner(strobePin, readPinCount), readPinCount(readPinCount) { } - void begin(); - void process(); -}; -#endif diff --git a/src/Row_uC.cpp b/src/Row_uC.cpp deleted file mode 100644 index aba7ae5..0000000 --- a/src/Row_uC.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "Row_uC.h" - -/* process() scans the row and calls any newly pressed or released keys. -Bitwise variables are 1 bit per key. -*/ -void Row_uC::process() -{ - read_pins_t readState; //bitwise, 1 means key is pressed, 0 means released - read_pins_t debouncedChanged; //bitwise, 1 means debounced changed - - readState = scanner.scan(); - debouncedChanged = debouncer.debounce(readState, debounced); - send(readPinCount, debouncedChanged); -} diff --git a/src/Row_uC.h b/src/Row_uC.h deleted file mode 100644 index d94fe0c..0000000 --- a/src/Row_uC.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef ROW_UC_H -#define ROW_UC_H - -#include -#include -#include - -/* Row_uC is a row connected to a microcontroller. - -Instantiation -------------- -keybrd_library_developer_guide.md has instructions for ## Active state and diode orientation -Example instantiation of a Row_uC: - - const bool Scanner_uC::STROBE_ON = LOW; //logic level of strobe on, active low - const bool Scanner_uC::STROBE_OFF = HIGH; //logic level of strobe off - - const uint8_t readPins[] = {0,1,2,3,7,8}; - const uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins); - - Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02, &k_03, &k_04, &k_05 }; - Row_uC row_0(21, readPins, readPinCount, ptrsKeys_0); - -Number of readPins should equal number of keys in ptrsKeys_0[] array. - if a readPins is missing, a key will be unresposive - if a Key pointer is missing, the keyboard will fail in an unpredictable way -*/ -class Row_uC : public Row -{ - private: - Scanner_uC scanner; - Debouncer_Samples debouncer; - const uint8_t readPinCount; - public: - Row_uC(const uint8_t strobePin, const uint8_t readPins[], const uint8_t readPinCount, - Key* const ptrsKeys[]) - : Row(ptrsKeys), scanner(strobePin, readPins, readPinCount), - readPinCount(readPinCount) { } - void process(); -}; -#endif diff --git a/src/ScannerInterface.h b/src/ScannerInterface.h new file mode 100644 index 0000000..6b27994 --- /dev/null +++ b/src/ScannerInterface.h @@ -0,0 +1,14 @@ +#ifndef SCANNERINTERFACE_H +#define SCANNERINTERFACE_H + +#include + +/* scan() retuns state of readPins. +*/ +class ScannerInterface +{ + public: + virtual void begin(const uint8_t strobePin)=0; + virtual read_pins_t scan(const uint8_t strobePin)=0; +}; +#endif diff --git a/src/Scanner_Port.cpp b/src/Scanner_Port.cpp index a855bb4..f168d30 100644 --- a/src/Scanner_Port.cpp +++ b/src/Scanner_Port.cpp @@ -3,7 +3,7 @@ /* scan() strobes the row's strobePin and retuns state of port's input pins. Bitwise variables are 1 bit per key. */ -uint8_t Scanner_Port::scan() +uint8_t Scanner_Port::scan(const uint8_t strobePin) { uint8_t readState; //bitwise, 1 means key is pressed, 0 means released diff --git a/src/Scanner_Port.h b/src/Scanner_Port.h index a6c92da..2ff8c5f 100644 --- a/src/Scanner_Port.h +++ b/src/Scanner_Port.h @@ -18,13 +18,10 @@ class Scanner_Port static const bool STROBE_ON; //HIGH or LOW logic level of strobe on, active state static const bool STROBE_OFF; //logic level of strobe off, complement of STROBE_ON PortWriteInterface& refPortWrite; //the IC port containing the strobePin - const uint8_t strobePin; //bitwise, 1 indicates IC pin connected to this row PortReadInterface& refPortRead; //the IC's read port public: - Scanner_Port(PortWriteInterface &refPortWrite, const uint8_t strobePin, - PortReadInterface& refPortRead) - : refPortWrite(refPortWrite), strobePin(strobePin), - refPortRead(refPortRead) {} - uint8_t scan(); + Scanner_Port(PortWriteInterface &refPortWrite, PortReadInterface& refPortRead) + : refPortWrite(refPortWrite), refPortRead(refPortRead) {} + uint8_t scan(const uint8_t strobePin); }; #endif diff --git a/src/Scanner_uC.cpp b/src/Scanner_uC.cpp index d86f3ac..09f93c0 100644 --- a/src/Scanner_uC.cpp +++ b/src/Scanner_uC.cpp @@ -10,47 +10,51 @@ 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) - : strobePin(strobePin), readPins(readPins), readPinCount(readPinCount) +Scanner_uC::Scanner_uC(const bool strobeOn, const uint8_t readPins[], const uint8_t readPinCount) + : strobeOn(strobeOn), strobeOff(!strobeOn), readPins(readPins), readPinCount(readPinCount) { uint8_t mode; - //configure row - pinMode(strobePin, OUTPUT); - - if (STROBE_ON == LOW) //if active low - { - mode = INPUT_PULLUP; //use internal pull-up resistor - } - else //if active high - { - mode = INPUT; //requires external pull-down resistor - } - //configure read pins + if (strobeOn == LOW) //if active low + { + mode = INPUT_PULLUP; //use internal pull-up resistor + } + else //if active high + { + mode = INPUT; //requires external pull-down resistor + } + for (uint8_t i=0; i < readPinCount; i++) { pinMode(readPins[i], mode); } } +/* +Configure row-strobe pin to output. +*/ +void Scanner_uC::begin(const uint8_t strobePin) +{ + pinMode(strobePin, OUTPUT); +} + /* scan() strobes the row's strobePin and retuns state of readPins. Bitwise variables are 1 bit per key. */ -read_pins_t Scanner_uC::scan() +read_pins_t Scanner_uC::scan(const uint8_t strobePin) { read_pins_t readState = 0; //bitwise, 1 means key is pressed, 0 means released read_pins_t readMask = 1; //bitwise, active bit is 1 //strobe row on - digitalWrite(strobePin, STROBE_ON); + digitalWrite(strobePin, strobeOn); delayMicroseconds(3); //time to stablize voltage //read all the read pins for (uint8_t i=0; i < readPinCount; i++) { - if ( digitalRead(readPins[i]) == STROBE_ON ) + if ( digitalRead(readPins[i]) == strobeOn ) { readState |= readMask; } @@ -58,7 +62,7 @@ read_pins_t Scanner_uC::scan() } //strobe row off - digitalWrite(strobePin, STROBE_OFF); + digitalWrite(strobePin, strobeOff); return readState; } diff --git a/src/Scanner_uC.h b/src/Scanner_uC.h index bc69169..f344e1b 100644 --- a/src/Scanner_uC.h +++ b/src/Scanner_uC.h @@ -4,24 +4,23 @@ #include #include #include -#include -#include +#include +//#include todo not needed? +//#include /* Scanner_uC class uses Arduino pin numbers (not port pin numbers). -Constructor is in Scanner_uC.cpp +Limit number of readPins to size of read_pins_t, which is defined in config_keybrd.h */ -class Scanner_uC +class Scanner_uC : public ScannerInterface { private: - static const bool STROBE_ON; //logic level of strobe on, HIGH or LOW - static const bool STROBE_OFF; //logic level of strobe off, complement of STROBE_ON - const uint8_t strobePin; //Arduino pin number connected to this row + const bool strobeOn; //logic level of strobe on, HIGH or LOW + const bool strobeOff; //logic level of strobe off, complement of strobeOn const uint8_t* const readPins; //array of read pin numbers - const uint8_t readPinCount; //number of read pins + const uint8_t readPinCount; //number of readPins public: - Scanner_uC(const uint8_t strobePin, - const uint8_t readPins[], const uint8_t readPinCount); - virtual read_pins_t scan(); + Scanner_uC(const bool strobeOn, const uint8_t readPins[], const uint8_t readPinCount); + void begin(const uint8_t strobePin); + virtual read_pins_t scan(const uint8_t strobePin); }; #endif - diff --git a/tutorials/keybrd_1_breadboard/keybrd_1_breadboard.ino b/tutorials/keybrd_1_breadboard/keybrd_1_breadboard.ino index 398f3e9..980fdb1 100644 --- a/tutorials/keybrd_1_breadboard/keybrd_1_breadboard.ino +++ b/tutorials/keybrd_1_breadboard/keybrd_1_breadboard.ino @@ -2,38 +2,40 @@ | Layout | **0** | **1** | |:------:|-------|-------| -| **0** | 1 | a | -| **1** | b | c | +| **0** | 1 | a | +| **1** | 2 | b | */ // ################## GLOBAL ################### // ================= INCLUDES ================== +#include #include #include -#include +#include // ============ SPEED CONFIGURATION ============ ScanDelay scanDelay(9000); -// ================ ACTIVE STATE =============== -const bool Scanner_uC::STROBE_ON = LOW; -const bool Scanner_uC::STROBE_OFF = HIGH; - -// =================== PINS ==================== +// ================== SCANNER ================== uint8_t readPins[] = {14, 15}; -uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins); +uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins); + +Scanner_uC scanner(LOW, readPins, readPinCount); // =================== 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_1(KEY_1); +Code_Sc s_2(KEY_2); // =================== ROWS ==================== Key* ptrsKeys_0[] = { &s_1, &s_a }; -Row_uC row_0(0, readPins, READ_PIN_COUNT, ptrsKeys_0); +uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0); +Row row_0(scanner, 0, ptrsKeys_0, keyCount_0); -Key* ptrsKeys_1[] = { &s_b, &s_c }; -Row_uC row_1(1, readPins, READ_PIN_COUNT, ptrsKeys_1); +Key* ptrsKeys_1[] = { &s_2, &s_b }; +uint8_t keyCount_1 = sizeof(ptrsKeys_1)/sizeof(*ptrsKeys_1); +Row row_1(scanner, 1, ptrsKeys_1, keyCount_1); // ################### MAIN #################### void setup() diff --git a/tutorials/tutorial_1_breadboard_keyboard.md b/tutorials/tutorial_1_breadboard_keyboard.md index 75221f5..07ade64 100644 --- a/tutorials/tutorial_1_breadboard_keyboard.md +++ b/tutorials/tutorial_1_breadboard_keyboard.md @@ -99,7 +99,7 @@ Breadboard keyboard assembly instructions: * 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 diodes with cathode (banded end) towards the row (bus strip) + * diodes connect switches to rows; orient diodes with cathode (banded end) towards the row (blue bus strip) ![switch orientation](keybrd_1_breadboard/switch_orientation.JPG "switch orientation")