@@ -13,14 +13,14 @@ Debouncer and I/O expander use bit manipulation. | |||
## Custom Row classes | |||
The keybrd library is flexible for designing custom Rows | |||
* RowBase functions can be overridden in a derived class | |||
* 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 | |||
Row_Ext::keyWasPressed() overrides RowBase::keyWasPressed() | |||
Row_Ext::keyWasPressed() overrides Row::keyWasPressed() | |||
Row_Ext::keyWasPressed() is used to unstick sticky keys | |||
Row_Ext_uC scans the primary matrix | |||
@@ -30,14 +30,14 @@ Row_Ext_uC and Row_Ext_ShiftRegisters are a custom classes composed of stock key | |||
Class inheritance diagram | |||
``` | |||
RowBase | |||
Row | |||
| | |||
Row_Ext (override RowBase::keyWasPressed() ) | |||
Row_Ext (override Row::keyWasPressed() ) | |||
/ \ | |||
Row_Ext_uC Row_Ext_ShiftRegisters (inherit Row_Ext::keyWasPressed() ) | |||
RowScanner_PinsArray RowScanner_SPIShiftRegisters | |||
Scanner_uC Scanner_ShiftRegs74HC165 | |||
``` | |||
@@ -46,16 +46,16 @@ Dependency diagram | |||
________ Row_Ext_uC[1] _______________ | |||
/ \ \ | |||
RowScanner_PinsArray[1] Debouncer_Samples[1] Key[1..*] | |||
Scanner_uC[1] Debouncer_Samples[1] Key[1..*] | |||
/ \ | | |||
strobePin[1] readPins[1..*] Code[1..*] | |||
_____ Row_Ext_ShiftRegisters[1] ___________ | |||
/ \ \ | |||
RowScanner_SPIShiftRegisters[1] Debouncer_Samples[1] Key[1..*] | |||
/ \ | | |||
strobePin[1] ROW_END[1] Code[1..*] | |||
_____ Row_Ext_ShiftRegisters[1] ________ | |||
/ \ \ | |||
Scanner_ShiftRegs74HC165[1] Debouncer_Samples[1] Key[1..*] | |||
/ \ | | |||
strobePin[1] ROW_END[1] Code[1..*] | |||
``` | |||
@@ -63,23 +63,23 @@ Dependency diagram | |||
Keybrd library class inheritance diagram | |||
``` | |||
_______ RowBase ________ | |||
________ Row ___________ | |||
/ | \ | |||
Row_uC Row_ShiftRegisters Row_IOE | |||
Row_uC Row_ShiftRegisters Row_IOE (to be added) | |||
RowScanner_PinsArray RowScanner_PinsBitwise RowScanner_SPIShiftRegisters | |||
Scanner_uC Scanner_Port Scanner_ShiftRegs74HC165 | |||
IOExpanderPort | |||
IOEPort | |||
RowPort | |||
StrobePort | |||
| | |||
RowPort_PCA9655E (one RowPort class for each IOE type) | |||
StrobePort_PCA9655E (one StrobePort class for each IOE type) | |||
ColPort | |||
ReadPort | |||
| | |||
ColPort_PCA9655E (one ColPort class for each IOE type) | |||
ReadPort_PCA9655E (one ReadPort class for each IOE type) | |||
____ LED ____ | |||
/ \ | |||
@@ -124,30 +124,30 @@ Keybrd library class inheritance diagram | |||
Example single-layer dependency diagram with LEDs | |||
``` | |||
___ Row_uC[1..*] ________ | |||
/ \ \ | |||
RowScanner_PinsArray Debouncer Keys[1..*] __ | |||
| \ | |||
Code[1..*] Code_LEDLock[1..*] | |||
| | |||
LED_PinNumber[1] | |||
_ Row_uC[1..*] _ | |||
/ | \ | |||
Scanner_uC Debouncer Keys[1..*] __ | |||
| \ | |||
Code[1..*] Code_LEDLock[1..*] | |||
| | |||
LED_PinNumber[1] | |||
``` | |||
Example multi-layer dependency diagram with layer LEDs | |||
``` | |||
LayerStates[1..*] | |||
________ Row_uC[1..*] _____________________/__ | \ | |||
/ \ \ / \ | \ | |||
RowScanner_PinsArray[1] Debouncer[1] Keys[1..*] / Code_Layer[1..*] LED_PinNumber[0..*] | |||
| / | |||
Code[1..*] | |||
LayerStates[1..*] | |||
________ Row_uC[1..*] ___________/__ | \ | |||
/ | \ / \ | \ | |||
Scanner_uC[1] Debouncer[1] Keys[1..*] / Code_Layer[1..*] LED_PinNumber[0..*] | |||
| / | |||
Code[1..*] | |||
``` | |||
Example secondary matrix with shift registers dependency diagram | |||
``` | |||
Row_ShiftRegisters[1..*] | |||
Row_ShiftRegisters[1..*] | |||
/ \ \ | |||
RowScanner_ShiftRegisters Debouncer Keys[1..*] | |||
| | |||
@@ -159,13 +159,13 @@ Example secondary matrix with I/O Expander dependency diagram with LEDs | |||
``` | |||
___ Row_IOE[1..*] _________ | |||
/ \ \ | |||
RowScanner_PinsBitwise[1] Debouncer[1] Keys[1..*] __ | |||
/ | \ | \ | |||
RowPort[1] RowPin[1] ColPort[1] Code[1..*] Code_LEDLock[1..*] | |||
\ / \ | | |||
\ / ColPins[1..*] LED[1] | |||
\ / | |||
IOExpanderPort[0..*] | |||
__ Scanner_Port[1] _ Debouncer[1] Keys[1..*] __ | |||
/ | \ | \ | |||
StrobePort[1] RowPin[1] ReadPort[1] Code[1..*] Code_LEDLock[1..*] | |||
\ / \ | | |||
\ / ColPins[1..*] LED[1] | |||
\ / | |||
IOEPort[0..*] | |||
``` | |||
@@ -240,13 +240,13 @@ Refer to it like a table of contents while reading the keybrd library. | |||
``` | |||
loop() for each row | |||
RowBase::process() | |||
RowScanner_PinsArray::scan() strobe row on | |||
Row::process() | |||
Scanner_uC::scan() strobe row on | |||
for each readPin | |||
set rowState bit | |||
strobe row off | |||
Debouncer_4Samples::debounce() debounce | |||
RowBase::pressRelease() for each key in row | |||
Row::pressRelease() for each key in row | |||
if falling edge | |||
Key_*::release() scanCode->release() | |||
Code_*::release() Keyboard.release(scancode) |
@@ -3,11 +3,11 @@ 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 RowScanner_SPIShiftRegisters::scan(): | |||
Unused input pins are not grounded, so add this line to Scanner_ShiftRegs74HC165::scan(): | |||
//clear unpowered pins (for testing on breadboard) | |||
rowState &= 0b11110001000100010001000100010001; //todo | |||
Layout | |||
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 | | |||
@@ -32,20 +32,20 @@ Layout | |||
ScanDelay scanDelay(9000); | |||
//active state of left matrix | |||
const bool RowScanner_PinsArray::STROBE_ON = LOW; | |||
const bool RowScanner_PinsArray::STROBE_OFF = HIGH; | |||
const bool Scanner_uC::STROBE_ON = LOW; | |||
const bool Scanner_uC::STROBE_OFF = HIGH; | |||
const uint8_t RowScanner_SPIShiftRegisters::SHIFT_LOAD = 10; | |||
const uint8_t Scanner_ShiftRegs74HC165::SHIFT_LOAD = 10; | |||
//active state of right matrix | |||
const bool RowScanner_SPIShiftRegisters::STROBE_ON = LOW; | |||
const bool RowScanner_SPIShiftRegisters::STROBE_OFF = HIGH; | |||
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 KEY_COUNT = sizeof(readPins)/sizeof(*readPins); | |||
uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins); | |||
// ==================== LEDs =================== | |||
LED_PinNumber LED1(16); | |||
@@ -98,48 +98,48 @@ Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED1); | |||
// ================= LEFT ROWS ================= | |||
Key* ptrsKeys_L0[] = { &o_capsLock, &s_a }; | |||
Row_uC row_L0(0, readPins, ptrsKeys_L0, KEY_COUNT); | |||
Row_uC row_L0(0, readPins, ptrsKeys_L0, READ_PIN_COUNT); | |||
Key* ptrsKeys_L1[] = { &s_b, &s_c }; | |||
Row_uC row_L1(1, readPins, ptrsKeys_L1, KEY_COUNT); | |||
Row_uC row_L1(1, readPins, ptrsKeys_L1, READ_PIN_COUNT); | |||
// ================= RIGHT ROWS ================ | |||
//typedef should be large in /home/wolfv/Documents/Arduino/keybrd_proj/keybrd/src/config_keybrd.h | |||
//Row_ShiftRegisters(STROBE_PIN, ptrsKeys[], KEY_COUNT) | |||
//Row_ShiftRegisters(STROBE_PIN, ptrsKeys[], READ_PIN_COUNT) | |||
//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 }; | |||
const uint8_t KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); | |||
Row_ShiftRegisters row_R0(8, ptrsKeys_R0, KEY_R0_COUNT); | |||
const uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); | |||
Row_ShiftRegisters row_R0(8, ptrsKeys_R0, READ_PIN_COUNT_R0); | |||
//prints a b | |||
Key* ptrsKeys_R1[] = { &s_a, &s_z, &s_z, &s_z, &s_b, &s_z, &s_z, &s_z }; | |||
const uint8_t KEY_R1_COUNT = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1); | |||
Row_ShiftRegisters row_R1(9, ptrsKeys_R1, KEY_R1_COUNT); | |||
const uint8_t READ_PIN_COUNT_R1 = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1); | |||
Row_ShiftRegisters row_R1(9, ptrsKeys_R1, READ_PIN_COUNT_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 }; | |||
const uint8_t KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); | |||
Row_ShiftRegisters row_R0(8, ptrsKeys_R0, KEY_R0_COUNT); | |||
const uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); | |||
Row_ShiftRegisters row_R0(8, ptrsKeys_R0, READ_PIN_COUNT_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 }; | |||
const uint8_t KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); | |||
Row_ShiftRegisters row_R0(8, ptrsKeys_R0, KEY_R0_COUNT); | |||
const uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); | |||
Row_ShiftRegisters row_R0(8, ptrsKeys_R0, READ_PIN_COUNT_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 }; | |||
const uint8_t KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); | |||
Row_ShiftRegisters row_R0(8, ptrsKeys_R0, KEY_R0_COUNT); | |||
const uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); | |||
Row_ShiftRegisters row_R0(8, ptrsKeys_R0, READ_PIN_COUNT_R0); | |||
*/ | |||
//prints 0 1 2 3 3 4 5 6, microseconds_per_scan=87 with SAMPLE_COUNT 4 | |||
@@ -147,16 +147,16 @@ 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 }; | |||
const uint8_t KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); | |||
Row_ShiftRegisters row_R0(0, ptrsKeys_R0, KEY_R0_COUNT); | |||
const uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); | |||
Row_ShiftRegisters row_R0(0, ptrsKeys_R0, READ_PIN_COUNT_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 }; | |||
const uint8_t KEY_R1_COUNT = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1); | |||
Row_ShiftRegisters row_R1(1, ptrsKeys_R1, KEY_R1_COUNT); | |||
const uint8_t READ_PIN_COUNT_R1 = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1); | |||
Row_ShiftRegisters row_R1(1, ptrsKeys_R1, READ_PIN_COUNT_R1); | |||
// ################### MAIN #################### | |||
void setup() |
@@ -1,13 +0,0 @@ | |||
#include "ColPort.h" | |||
uint8_t ColPort::getColPins() | |||
{ | |||
return colPins; | |||
} | |||
uint8_t ColPort::getPortState() | |||
{ | |||
//todo Keyboard.print(" portState="); | |||
//Keyboard.print(portState); | |||
return portState; | |||
} |
@@ -2,19 +2,19 @@ | |||
#define IOEXPANDERPORT_H | |||
#include <inttypes.h> | |||
/* The pins of an IC's port can be split between RowPort, ColPort, and LED. | |||
/* The pins of an IC's port can be split between StrobePort, ReadPort, and LED. | |||
IOExpanderPort contains outputVal, the value of a port's output register. | |||
outputVal is used for port manipulation by classes RowPort and LED. | |||
One port's outputVal can be shared by one RowPort object and multiple LED objects. | |||
IOEPort contains outputVal, the value of a port's output register. | |||
outputVal is used for port manipulation by classes StrobePort and LED. | |||
One port's outputVal can be shared by one StrobePort object and multiple LED objects. | |||
IOExpanderPort is only used by I/O expander port classes. | |||
IOEPort is only used by I/O expander port classes. | |||
AVR port classes do not need a similar class because PORTx is global in the Arduino library. | |||
Instantiation | |||
------------ | |||
Example IOExpanderPort::ADDR initilization: | |||
const uint8_t IOExpanderPort::ADDR = 0x18; | |||
Example IOEPort::ADDR initilization: | |||
const uint8_t IOEPort::ADDR = 0x18; | |||
Be careful with the ADDR. | |||
Table 6 in PCA9655E datasheet lists 8-bit versions of I2C addresses. | |||
The Arduino Wire library uses 7-bit addresses throughout, so drop the low bit. | |||
@@ -29,21 +29,21 @@ outputVal: For pins that are connected to active low rows, set outputVal bit to | |||
Set all other outputVal bits to 0. | |||
Example instantiation for port0 with active low rows on all pins: | |||
IOExpanderPort port0(0, ~0); | |||
IOEPort port0(0, ~0); | |||
Example instantiation for portA with active low rows on pins 0,1,2: | |||
IOExpanderPort portA(0, 1<<0 | 1<<1 | 1<<2 ); | |||
IOEPort portA(0, 1<<0 | 1<<1 | 1<<2 ); | |||
Example instantiation for portB with active high rows on pins 0,1,2: | |||
IOExpanderPort portB(1, 0); | |||
IOEPort portB(1, 0); | |||
*/ | |||
struct IOExpanderPort | |||
struct IOEPort | |||
{ | |||
static const uint8_t ADDR; //I2C address | |||
const uint8_t num; //port number | |||
uint8_t outputVal; //bitwise value of output register | |||
IOExpanderPort(const uint8_t portNumber, uint8_t outputVal) | |||
IOEPort(const uint8_t portNumber, uint8_t outputVal) | |||
: num(portNumber), outputVal(outputVal) {} | |||
}; | |||
#endif |
@@ -4,7 +4,7 @@ | |||
#include <inttypes.h> | |||
#include <Wire.h> | |||
#include <LED.h> | |||
#include "IOExpanderPort.h" | |||
#include "IOEPort.h" | |||
/* A LED_PCA9655E object is an PCA9655E pin that is connected to an LED indicator light. | |||
Input/Ouput Direction configuration is set to ouput in row_Port_PCA9655E.begin() and col_Port_PCA9655E.begin(). | |||
@@ -12,12 +12,12 @@ Input/Ouput Direction configuration is set to ouput in row_Port_PCA9655E.begin() | |||
class LED_PCA9655E: public LED | |||
{ | |||
private: | |||
IOExpanderPort& port; | |||
IOEPort& port; | |||
const uint8_t outputByteCommand; //General Purpose Input/Ouput register address | |||
const uint8_t pin; //bitwise pin to LED | |||
public: | |||
LED_PCA9655E(IOExpanderPort& port, const uint8_t pin) | |||
LED_PCA9655E(IOEPort& port, const uint8_t pin) | |||
: port(port), outputByteCommand(port.num + 2), pin(pin) {} | |||
virtual void on(); |
@@ -0,0 +1,13 @@ | |||
#include "ReadPort.h" | |||
uint8_t ReadPort::getColPins() | |||
{ | |||
return readPins; | |||
} | |||
uint8_t ReadPort::getPortState() | |||
{ | |||
//todo Keyboard.print(" portState="); | |||
//Keyboard.print(portState); | |||
return portState; | |||
} |
@@ -1,19 +1,19 @@ | |||
#ifndef COLPORT_H | |||
#define COLPORT_H | |||
#ifndef READPORT_H | |||
#define READPORT_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
/* | |||
ColPort is an abstract base class. | |||
ReadPort is an abstract base class. | |||
Port classes are the keybrd library's interface to microcontoller ports or I/O expander ports. | |||
*/ | |||
class ColPort | |||
class ReadPort | |||
{ | |||
protected: | |||
const uint8_t colPins; //bitwise pin configuration, 1 means read column | |||
const uint8_t readPins; //bitwise pin configuration, 1 means read column | |||
uint8_t portState; //bitwise pin values, which is set in read() | |||
public: | |||
ColPort(const uint8_t colPins): colPins(colPins), portState(0) {} | |||
ReadPort(const uint8_t readPins): readPins(readPins), portState(0) {} | |||
//read port and store it's pins values in portState | |||
virtual void read()=0; |
@@ -1,24 +1,24 @@ | |||
#include "ColPort_PCA9655E.h" | |||
#include "ReadPort_PCA9655E.h" | |||
/* | |||
configures column port's configuration, input, and pins. | |||
*/ | |||
ColPort_PCA9655E::ColPort_PCA9655E (IOExpanderPort& port, const uint8_t colPins) | |||
: ColPort(colPins), port(port), configurationByteCommand(port.num + 6), inputByteCommand(port.num) | |||
ReadPort_PCA9655E::ReadPort_PCA9655E (IOEPort& port, const uint8_t readPins) | |||
: ReadPort(readPins), port(port), configurationByteCommand(port.num + 6), inputByteCommand(port.num) | |||
{} | |||
void ColPort_PCA9655E::begin() | |||
void ReadPort_PCA9655E::begin() | |||
{ | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(configurationByteCommand); | |||
Wire.write(colPins); //0=configure as output (for LED), 1=configure as input (for read) | |||
Wire.write(readPins); //0=configure as output (for LED), 1=configure as input (for read) | |||
Wire.endTransmission(); | |||
} | |||
/* | |||
Saves all port-pin values to portState. | |||
*/ | |||
void ColPort_PCA9655E::read() | |||
void ReadPort_PCA9655E::read() | |||
{ | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(inputByteCommand); //input immediately before requestFrom |
@@ -1,42 +1,42 @@ | |||
#ifndef COLPORT_PCA9655E_H | |||
#define COLPORT_PCA9655E_H | |||
#ifndef READPORT_PCA9655E_H | |||
#define READPORT_PCA9655E_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <Wire.h> | |||
#include <ColPort.h> | |||
#include "IOExpanderPort.h" | |||
#include <ReadPort.h> | |||
#include "IOEPort.h" | |||
/* One PCA9655E I/O expander port connected to matrix columns. | |||
PCA9655E does not have internal pull-up resistors (PCA9535E does). | |||
Instantiation | |||
------------ | |||
colPins parameter is port's bitwise pin configuration | |||
readPins parameter is port's bitwise pin configuration | |||
1=configure as input (for pins connected to column) | |||
0=configure as output (for LED or not connected to a column) | |||
Example instantiation for column port 0, with pins 2 and 3 connected to columns: | |||
IOExpanderPort port0(0, 0); | |||
ColPort_PCA9655E colPort0(port0, 2<<0 | 1<<3 ); | |||
IOEPort port0(0, 0); | |||
ReadPort_PCA9655E colPort0(port0, 2<<0 | 1<<3 ); | |||
Example instantiation for column port 1, with pins 2 and 3 connected to columns: | |||
IOExpanderPort port1(1, 0); | |||
ColPort_PCA9655E colPort1(port1, 2<<0 | 1<<3 ); | |||
IOEPort port1(1, 0); | |||
ReadPort_PCA9655E colPort1(port1, 2<<0 | 1<<3 ); | |||
colPins are read from pin 0 on up. | |||
readPins are read from pin 0 on up. | |||
Diode orientation | |||
---------------- | |||
Rows, columns, and diode orientation are explained in Matrix.h | |||
*/ | |||
class ColPort_PCA9655E : public ColPort | |||
class ReadPort_PCA9655E : public ReadPort | |||
{ | |||
private: | |||
IOExpanderPort& port; | |||
IOEPort& port; | |||
const uint8_t configurationByteCommand; | |||
const uint8_t inputByteCommand; | |||
public: | |||
//The constructor initialization list is in .cpp | |||
ColPort_PCA9655E(IOExpanderPort& port, const uint8_t colPins); | |||
ReadPort_PCA9655E(IOEPort& port, const uint8_t readPins); | |||
void begin(); | |||
//read port and store result in portState |
@@ -0,0 +1,38 @@ | |||
#include "Row.h" | |||
/* | |||
pressRelease() calls key's press() or release() function if it was pressed or released. | |||
Both parameters are bitwise. | |||
*/ | |||
void Row::pressRelease(const uint8_t READ_PIN_COUNT, const read_pins_t debouncedChanged) | |||
{ | |||
read_pins_t isFallingEdge; //bitwise, 1 means falling edge | |||
read_pins_t isRisingEdge; //bitwise, 1 means rising edge | |||
read_pins_t readMask; //bitwise, active read bit is 1 | |||
uint8_t i; //index for ptrsKeys[i] array | |||
//bit=1 if last debounced changed from 1 to 0, else bit=0 | |||
isFallingEdge = debouncedChanged & ~debounced; | |||
//bit=1 if last debounced changed from 0 to 1, else bit=0 | |||
isRisingEdge = debouncedChanged & debounced; | |||
for (readMask=1, i=0; i < READ_PIN_COUNT; readMask<<=1, i++) //for each key in row | |||
{ | |||
//release before press avoids impossible key sequence | |||
if (readMask & isFallingEdge) //if key was released | |||
{ | |||
ptrsKeys[i]->release(); | |||
} | |||
if (readMask & isRisingEdge) //if key was pressed | |||
{ | |||
ptrsKeys[i]->press(); | |||
keyWasPressed(); | |||
} | |||
} | |||
} | |||
void Row::keyWasPressed() | |||
{ | |||
//empty in Row class. To unstick sticky keys, override keyWasPressed() in derived class. | |||
} |
@@ -1,22 +1,22 @@ | |||
#ifndef ROWBASE_H | |||
#define ROWBASE_H | |||
#ifndef ROW_H | |||
#define ROW_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <config_keybrd.h> | |||
#include <Key.h> | |||
/* RowBase is an abstract base class. | |||
/* Row is an abstract base class. | |||
*/ | |||
class RowBase | |||
class Row | |||
{ | |||
private: | |||
Key *const *const ptrsKeys; //array of Key pointers | |||
virtual void keyWasPressed(); | |||
protected: | |||
read_pins_t debounced; //bitwise, 1 means pressed, 0 means released | |||
void pressRelease(const uint8_t KEY_COUNT, const read_pins_t debouncedChanged); | |||
void pressRelease(const uint8_t READ_PIN_COUNT, const read_pins_t debouncedChanged); | |||
public: | |||
RowBase(Key *const ptrsKeys[]) : ptrsKeys(ptrsKeys), debounced(0) { } | |||
Row(Key *const ptrsKeys[]) : ptrsKeys(ptrsKeys), debounced(0) { } | |||
virtual void process()=0; | |||
}; | |||
#endif |
@@ -1,38 +0,0 @@ | |||
#include "RowBase.h" | |||
/* | |||
pressRelease() calls key's press() or release() function if it was pressed or released. | |||
Both parameters are bitwise. | |||
*/ | |||
void RowBase::pressRelease(const uint8_t KEY_COUNT, const read_pins_t debouncedChanged) | |||
{ | |||
read_pins_t isFallingEdge; //bitwise, 1 means falling edge | |||
read_pins_t isRisingEdge; //bitwise, 1 means rising edge | |||
read_pins_t rowMask; //bitwise, active col bit is 1 | |||
uint8_t col; //index for ptrsKeys[col] array | |||
//bit=1 if last debounced changed from 1 to 0, else bit=0 | |||
isFallingEdge = debouncedChanged & ~debounced; | |||
//bit=1 if last debounced changed from 0 to 1, else bit=0 | |||
isRisingEdge = debouncedChanged & debounced; | |||
for (rowMask=1, col=0; col < KEY_COUNT; rowMask<<=1, col++) //for each key in row | |||
{ | |||
//release before press avoids impossible key sequence | |||
if (rowMask & isFallingEdge) //if key was released | |||
{ | |||
ptrsKeys[col]->release(); | |||
} | |||
if (rowMask & isRisingEdge) //if key was pressed | |||
{ | |||
ptrsKeys[col]->press(); | |||
keyWasPressed(); | |||
} | |||
} | |||
} | |||
void RowBase::keyWasPressed() | |||
{ | |||
//empty in RowBase class. To unstick sticky keys, override keyWasPressed() in derived class. | |||
} |
@@ -1,25 +0,0 @@ | |||
#ifndef ROWSCANNER_PINSBITWISE_H | |||
#define ROWSCANNER_PINSBITWISE_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <RowPort.h> | |||
#include <ColPort.h> | |||
/* RowScanner_PinsBitwise uses bit manipulation to read all pins of one port. | |||
The maximum keys per row is 8, because ports have a maximum of 8 pins each. | |||
*/ | |||
class RowScanner_PinsBitwise | |||
{ | |||
private: | |||
RowPort& refRowPort; //this row's IC port | |||
const uint8_t strobePin; //bitwise, 1 indicates IC pin connected to this row | |||
ColPort& refColPort; | |||
public: | |||
RowScanner_PinsBitwise(RowPort &refRowPort, const uint8_t strobePin, | |||
ColPort& refColPort) | |||
: refRowPort(refRowPort), strobePin(strobePin), | |||
refColPort(refColPort) {} | |||
static const bool STROBE_ON; //logic level of strobe on, active state, HIGH or LOW | |||
virtual ColPort* const scan(); | |||
}; | |||
#endif |
@@ -4,12 +4,12 @@ void Row_ShiftRegisters::process() | |||
{ | |||
//these variables are all bitwise, one bit per key | |||
read_pins_t rowState; //1 means pressed, 0 means released | |||
uint8_t keyCount; | |||
uint8_t readPinCount; | |||
read_pins_t debouncedChanged; //1 means debounced changed | |||
rowState = scanner.scan(keyCount); | |||
rowState = scanner.scan(readPinCount); | |||
debouncedChanged = debouncer.debounce(rowState, debounced); | |||
pressRelease(keyCount, debouncedChanged); | |||
pressRelease(readPinCount, debouncedChanged); | |||
} | |||
void Row_ShiftRegisters::begin() |
@@ -1,8 +1,8 @@ | |||
#ifndef ROW_SHIFTREGISTERS_H | |||
#define ROW_SHIFTREGISTERS_H | |||
#include <RowBase.h> | |||
#include <RowScanner_SPIShiftRegisters.h> | |||
#include <Row.h> | |||
#include <Scanner_ShiftRegs74HC165.h> | |||
#include <Debouncer_4Samples.h> | |||
//#include <Debouncer_Not.h> | |||
@@ -10,10 +10,10 @@ | |||
Instantiation | |||
------------- | |||
Definition of DELAY_MICROSECONDS is explained in RowBase.cpp. | |||
Definition of DELAY_MICROSECONDS is explained in Row.cpp. | |||
Example instantiation of a row: | |||
const unsigned int RowBase::DELAY_MICROSECONDS = 1000; | |||
const unsigned int Row::DELAY_MICROSECONDS = 1000; | |||
todo | |||
@@ -24,15 +24,15 @@ 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_ShiftRegisters : public RowBase | |||
class Row_ShiftRegisters : public Row | |||
{ | |||
private: | |||
RowScanner_SPIShiftRegisters scanner; | |||
Scanner_ShiftRegs74HC165 scanner; | |||
Debouncer_4Samples debouncer; | |||
//Debouncer_Not debouncer; //passed test | |||
public: | |||
Row_ShiftRegisters(const uint8_t STROBE_PIN, Key *const ptrsKeys[], uint8_t KEY_COUNT) | |||
: RowBase(ptrsKeys), scanner(STROBE_PIN, KEY_COUNT) { } | |||
Row_ShiftRegisters(const uint8_t STROBE_PIN, Key *const ptrsKeys[], uint8_t READ_PIN_COUNT) | |||
: Row(ptrsKeys), scanner(STROBE_PIN, READ_PIN_COUNT) { } | |||
void begin(); | |||
void process(); | |||
}; |
@@ -7,20 +7,10 @@ void Row_uC::process() | |||
{ | |||
//these variables are all bitwise, one bit per key | |||
read_pins_t rowState; //1 means pressed, 0 means released | |||
uint8_t keyCount; | |||
uint8_t readPinCount; | |||
read_pins_t debouncedChanged; //1 means debounced changed | |||
rowState = scanner.scan(keyCount); | |||
/* | |||
Keyboard.print(" keyCount="); | |||
Keyboard.print(keyCount); | |||
Keyboard.print(" rowState="); | |||
Keyboard.print(rowState); | |||
*/ | |||
rowState = scanner.scan(readPinCount); | |||
debouncedChanged = debouncer.debounce(rowState, debounced); | |||
/* | |||
Keyboard.print(" debounced="); | |||
Keyboard.print(debounced); | |||
*/ | |||
pressRelease(keyCount, debouncedChanged); | |||
pressRelease(readPinCount, debouncedChanged); | |||
} |
@@ -1,40 +1,40 @@ | |||
#ifndef ROW_H | |||
#define ROW_H | |||
#ifndef ROW_UC_H | |||
#define ROW_UC_H | |||
#include <RowBase.h> | |||
#include <RowScanner_PinsArray.h> | |||
#include <Row.h> | |||
#include <Scanner_uC.h> | |||
#include <Debouncer_4Samples.h> | |||
/* Row_uC is a row connected to a micro controller. | |||
Instantiation | |||
------------- | |||
Definition of DELAY_MICROSECONDS is explained in RowBase.cpp. | |||
Definition of DELAY_MICROSECONDS is explained in Row.cpp. | |||
Example instantiation of a row: | |||
const unsigned int RowBase::DELAY_MICROSECONDS = 1000; | |||
const bool RowScanner_PinsArray::STROBE_ON = LOW; //logic level of strobe on | |||
const bool RowScanner_PinsArray::STROBE_OFF = HIGH; //logic level of strobe off | |||
const unsigned int Row::DELAY_MICROSECONDS = 1000; | |||
const bool Scanner_uC::STROBE_ON = LOW; //logic level of strobe on | |||
const bool Scanner_uC::STROBE_OFF = HIGH; //logic level of strobe off | |||
const uint8_t colPins[] = {0,1,2,3,7,8}; | |||
const uint8_t COL_PIN_COUNT = sizeof(colPins)/sizeof(*colPins); | |||
const uint8_t readPins[] = {0,1,2,3,7,8}; | |||
const uint8_t READ_PIN_COUNT = 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, colPins, COL_PIN_COUNT, ptrsKeys_0); | |||
Row_uC row_0(21, readPins, READ_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 | |||
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 unprdictable way | |||
*/ | |||
class Row_uC : public RowBase | |||
class Row_uC : public Row | |||
{ | |||
private: | |||
RowScanner_PinsArray scanner; | |||
Scanner_uC scanner; | |||
Debouncer_4Samples debouncer; | |||
public: | |||
Row_uC(const uint8_t strobePin, const uint8_t readPins[], | |||
Key *const ptrsKeys[], const uint8_t KEY_COUNT) | |||
: RowBase(ptrsKeys), scanner(strobePin, readPins, KEY_COUNT) { } | |||
Row_uC(const uint8_t strobePin, const uint8_t READ_PINS[], | |||
Key *const ptrsKeys[], const uint8_t READ_PIN_COUNT) | |||
: Row(ptrsKeys), scanner(strobePin, READ_PINS, READ_PIN_COUNT) { } | |||
void process(); | |||
}; | |||
#endif |
@@ -1,32 +1,32 @@ | |||
#include "RowScanner_PinsBitwise.h" | |||
#include "Scanner_Port.h" | |||
/* | |||
Strobes the row and reads the columns. | |||
*/ | |||
ColPort* const RowScanner_PinsBitwise::scan() | |||
ReadPort* const Scanner_Port::scan() | |||
{ | |||
//strobe row on | |||
if (STROBE_ON == LOW) | |||
{ | |||
refRowPort.setActivePinLow(strobePin); | |||
refStrobePort.setActivePinLow(strobePin); | |||
} | |||
else //activeLow | |||
{ | |||
refRowPort.setActivePinHigh(strobePin); | |||
refStrobePort.setActivePinHigh(strobePin); | |||
} | |||
delayMicroseconds(3); //time to stablize voltage | |||
//read the port pins | |||
refColPort.read(); | |||
refReadPort.read(); | |||
//strobe row off | |||
if (STROBE_ON == LOW) | |||
{ | |||
refRowPort.setActivePinHigh(strobePin); | |||
refStrobePort.setActivePinHigh(strobePin); | |||
} | |||
else //activeLow | |||
{ | |||
refRowPort.setActivePinLow(strobePin); | |||
refStrobePort.setActivePinLow(strobePin); | |||
} | |||
return &refColPort; | |||
return &refReadPort; | |||
} |
@@ -0,0 +1,25 @@ | |||
#ifndef SCANNER_PORT_H | |||
#define SCANNER_PORT_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <StrobePort.h> | |||
#include <ReadPort.h> | |||
/* Scanner_Port uses bit manipulation to read all pins of one port. | |||
The maximum keys per row is 8, because ports have a maximum of 8 pins each. | |||
*/ | |||
class Scanner_Port | |||
{ | |||
private: | |||
StrobePort& refStrobePort; //this row's IC port | |||
const uint8_t strobePin; //bitwise, 1 indicates IC pin connected to this row | |||
ReadPort& refReadPort; | |||
public: | |||
Scanner_Port(StrobePort &refStrobePort, const uint8_t strobePin, | |||
ReadPort& refReadPort) | |||
: refStrobePort(refStrobePort), strobePin(strobePin), | |||
refReadPort(refReadPort) {} | |||
static const bool STROBE_ON; //logic level of strobe on, active state, HIGH or LOW | |||
virtual ReadPort* const scan(); | |||
}; | |||
#endif |
@@ -1,24 +1,24 @@ | |||
#include "RowScanner_SPIShiftRegisters.h" | |||
#include "Scanner_ShiftRegs74HC165.h" | |||
//constructor | |||
RowScanner_SPIShiftRegisters::RowScanner_SPIShiftRegisters(const uint8_t STROBE_PIN, uint8_t KEY_COUNT) | |||
: STROBE_PIN(STROBE_PIN), BYTE_COUNT(ceil (float(KEY_COUNT)/8)), KEY_COUNT(KEY_COUNT) | |||
Scanner_ShiftRegs74HC165::Scanner_ShiftRegs74HC165(const uint8_t STROBE_PIN, uint8_t READ_PIN_COUNT) | |||
: STROBE_PIN(STROBE_PIN), BYTE_COUNT(ceil (float(READ_PIN_COUNT)/8)), READ_PIN_COUNT(READ_PIN_COUNT) | |||
{ | |||
//configure controller to communicate with shift register matrix | |||
pinMode(STROBE_PIN, OUTPUT); | |||
pinMode(SHIFT_LOAD, OUTPUT); | |||
} | |||
void RowScanner_SPIShiftRegisters::begin() | |||
void Scanner_ShiftRegs74HC165::begin() | |||
{ | |||
//initialize shift register's shift/load pin | |||
digitalWrite(SHIFT_LOAD, HIGH); | |||
} | |||
/* | |||
Sets keyCount and returns rowState. | |||
Sets readPinCount and returns rowState. | |||
*/ | |||
read_pins_t RowScanner_SPIShiftRegisters::scan(uint8_t& keyCount) | |||
read_pins_t Scanner_ShiftRegs74HC165::scan(uint8_t& readPinCount) | |||
{ | |||
read_pins_t rowState = 0; | |||
@@ -34,7 +34,7 @@ read_pins_t RowScanner_SPIShiftRegisters::scan(uint8_t& keyCount) | |||
//strobe row off | |||
digitalWrite(STROBE_PIN, STROBE_OFF); | |||
keyCount = KEY_COUNT; | |||
readPinCount = READ_PIN_COUNT; | |||
//for testing on breadboard, clear unpowered pins | |||
rowState &= 0b11110001000100010001000100010001; //todo |
@@ -1,29 +1,29 @@ | |||
#ifndef ROWSCANNER_SPI_SHIFTREGISTERS_H | |||
#define ROWSCANNER_SPI_SHIFTREGISTERS_H | |||
#ifndef ROWSCANNER_SHIFTREGS74HC165_H | |||
#define ROWSCANNER_SHIFTREGS74HC165_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <config_keybrd.h> | |||
#include <SPI.h> | |||
#include <RowPort.h> | |||
#include <ColPort.h> | |||
#include <StrobePort.h> | |||
#include <ReadPort.h> | |||
/* RowScanner_SPIShiftRegisters reads shift registers. | |||
/* Scanner_ShiftRegs74HC165 reads shift registers. | |||
shift registers 74HC165 is Parallel-In-Serial-Out (PISO) | |||
Upto 4 shift registers can be in a daisy chained. | |||
In sketch: | |||
const uint8_t RowScanner_SPIShiftRegisters::SHIFT_LOAD = 10; | |||
const uint8_t Scanner_ShiftRegs74HC165::SHIFT_LOAD = 10; | |||
call begin() from setup() | |||
For active low: | |||
const bool RowScanner_SPIShiftRegisters::STROBE_ON = LOW; | |||
const bool RowScanner_SPIShiftRegisters::STROBE_OFF = HIGH; | |||
const bool Scanner_ShiftRegs74HC165::STROBE_ON = LOW; | |||
const bool Scanner_ShiftRegs74HC165::STROBE_OFF = HIGH; | |||
//shift register parallel input pins have 10k pull-down resistors powered | |||
//controller's MISO pin is connected to shift register's complementary serial output (/QH) pin | |||
For active high: | |||
const bool RowScanner_SPIShiftRegisters::STROBE_ON = HIGH; | |||
const bool RowScanner_SPIShiftRegisters::STROBE_OFF = LOW; | |||
const bool Scanner_ShiftRegs74HC165::STROBE_ON = HIGH; | |||
const bool Scanner_ShiftRegs74HC165::STROBE_OFF = LOW; | |||
//shift register parallel input pins have 10k pull-down resistors grounded | |||
//controller's MISO pin is connected to shift register's serial output (QH) pin | |||
@@ -36,7 +36,7 @@ The two parts of a split keyboard can be connected by one of: | |||
* Ethernet cable (has 8 wires, good for 3 rows) | |||
*/ | |||
class RowScanner_SPIShiftRegisters | |||
class Scanner_ShiftRegs74HC165 | |||
{ | |||
private: | |||
static const uint8_t SHIFT_LOAD; //controller's pin number that is connected to shift register's SHIFT_LOAD pin | |||
@@ -44,10 +44,10 @@ class RowScanner_SPIShiftRegisters | |||
static const bool STROBE_OFF; //logic level of strobe off, complement of active state | |||
const uint8_t STROBE_PIN; //Arduino pin number connected to this row | |||
const uint8_t BYTE_COUNT; //number of bytes to read from shift registers | |||
uint8_t KEY_COUNT; | |||
uint8_t READ_PIN_COUNT; | |||
public: | |||
RowScanner_SPIShiftRegisters(const uint8_t STROBE_PIN, uint8_t KEY_COUNT); | |||
virtual read_pins_t scan(uint8_t& KEY_COUNT); | |||
Scanner_ShiftRegs74HC165(const uint8_t STROBE_PIN, uint8_t READ_PIN_COUNT); | |||
virtual read_pins_t scan(uint8_t& READ_PIN_COUNT); | |||
void begin(); | |||
}; | |||
#endif |
@@ -1,8 +1,8 @@ | |||
#include "RowScanner_PinsArray.h" | |||
#include "Scanner_uC.h" | |||
/* constructor | |||
*/ | |||
RowScanner_PinsArray::RowScanner_PinsArray(const uint8_t STROBE_PIN, | |||
Scanner_uC::Scanner_uC(const uint8_t STROBE_PIN, | |||
const uint8_t READ_PINS[], const uint8_t READ_PIN_COUNT) | |||
: STROBE_PIN(STROBE_PIN), READ_PINS(READ_PINS), READ_PIN_COUNT(READ_PIN_COUNT) | |||
{ | |||
@@ -20,7 +20,7 @@ RowScanner_PinsArray::RowScanner_PinsArray(const uint8_t STROBE_PIN, | |||
mode = INPUT; //requires external pull-down resistor | |||
} | |||
//configure cols | |||
//configure read pins | |||
for (uint8_t i=0; i < READ_PIN_COUNT; i++) | |||
{ | |||
pinMode(READ_PINS[i], mode); | |||
@@ -28,7 +28,7 @@ RowScanner_PinsArray::RowScanner_PinsArray(const uint8_t STROBE_PIN, | |||
} | |||
/* scan() Strobes the row and reads the columns. | |||
Sets KEY_COUNT and returns rowState. | |||
Sets READ_PIN_COUNT and returns rowState. | |||
https://www.arduino.cc/en/Tutorial/DigitalPins | |||
https://www.arduino.cc/en/Reference/PinMode | |||
@@ -36,26 +36,28 @@ https://www.arduino.cc/en/Reference/DigitalWrite | |||
https://www.arduino.cc/en/Reference/DigitalRead | |||
https://www.arduino.cc/en/Reference/Constants > Digital Pins modes: INPUT, INPUT_PULLUP, and OUTPUT | |||
*/ | |||
read_pins_t RowScanner_PinsArray::scan(uint8_t& keyCount) | |||
read_pins_t Scanner_uC::scan(uint8_t& readPinCount) | |||
{ | |||
read_pins_t rowState = 0; //bitwise, one col per bit, 1 means key is pressed | |||
read_pins_t rowMask = 1; //bitwise, one col per bit, active col bit is 1 | |||
read_pins_t readMask = 1; //bitwise, one col per bit, active col bit is 1 | |||
//strobe row on | |||
digitalWrite(STROBE_PIN, STROBE_ON); | |||
delayMicroseconds(3); //time to stablize voltage | |||
//read all the column pins | |||
//read all the read pins | |||
for (uint8_t i=0; i < READ_PIN_COUNT; i++) | |||
{ | |||
if ( digitalRead(READ_PINS[i]) == STROBE_ON ) | |||
{ | |||
rowState |= rowMask; | |||
rowState |= readMask; | |||
} | |||
rowMask <<= 1; | |||
readMask <<= 1; | |||
} | |||
//strobe row off | |||
digitalWrite(STROBE_PIN, STROBE_OFF); | |||
keyCount = READ_PIN_COUNT; | |||
readPinCount = READ_PIN_COUNT; | |||
return rowState; | |||
} |
@@ -1,15 +1,15 @@ | |||
#ifndef ROWSCANNER_PINSARRAY_H | |||
#define ROWSCANNER_PINSARRAY_H | |||
#ifndef SCANNER_UC_H | |||
#define SCANNER_UC_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <config_keybrd.h> | |||
#include <RowPort.h> | |||
#include <ColPort.h> | |||
#include <StrobePort.h> | |||
#include <ReadPort.h> | |||
/* RowScanner_PinsArray class uses Arduino pin numbers (not port pin numbers). | |||
Constructor is in RowScanner_PinsArray.cpp | |||
/* Scanner_uC class uses Arduino pin numbers (not port pin numbers). | |||
Constructor is in Scanner_uC.cpp | |||
*/ | |||
class RowScanner_PinsArray | |||
class Scanner_uC | |||
{ | |||
private: | |||
static const bool STROBE_ON; //logic level of strobe on, HIGH or LOW | |||
@@ -18,9 +18,9 @@ class RowScanner_PinsArray | |||
const uint8_t* const READ_PINS; //array of read pin numbers | |||
const uint8_t READ_PIN_COUNT; //number of read pins | |||
public: | |||
RowScanner_PinsArray(const uint8_t STROBE_PIN, | |||
const uint8_t READ_PINS[], const uint8_t READ_PIN_COUNT); //todo rename READ_PIN_COUNT to KEY_COUNT ?? | |||
virtual read_pins_t scan(uint8_t& KEY_COUNT); | |||
Scanner_uC(const uint8_t STROBE_PIN, | |||
const uint8_t READ_PINS[], const uint8_t READ_PIN_COUNT); //todo rename READ_PIN_COUNT to READ_PIN_COUNT ?? | |||
virtual read_pins_t scan(uint8_t& READ_PIN_COUNT); | |||
}; | |||
#endif | |||
@@ -1,13 +1,13 @@ | |||
#ifndef ROWPORT_H | |||
#define ROWPORT_H | |||
#ifndef STROBEPORT_H | |||
#define STROBEPORT_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
/* | |||
RowPort is an abstract base class. | |||
StrobePort is an abstract base class. | |||
Port classes are the keybrd library's interface to microcontoller ports or I/O expander ports. | |||
*/ | |||
class RowPort | |||
class StrobePort | |||
{ | |||
public: | |||
virtual void setActivePinHigh(const uint8_t activePin)=0; |
@@ -1,12 +1,12 @@ | |||
#include "RowPort_PCA9655E.h" | |||
#include "StrobePort_PCA9655E.h" | |||
/* | |||
configures column port's configuration and output. | |||
*/ | |||
RowPort_PCA9655E::RowPort_PCA9655E(IOExpanderPort& port) | |||
StrobePort_PCA9655E::StrobePort_PCA9655E(IOEPort& port) | |||
: port(port), configurationByteCommand(port.num + 6), outputByteCommand(port.num + 2) {} | |||
void RowPort_PCA9655E::begin() | |||
void StrobePort_PCA9655E::begin() | |||
{ | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(configurationByteCommand); | |||
@@ -18,7 +18,7 @@ void RowPort_PCA9655E::begin() | |||
sets activePin pin output to low, does not reset the other pins because they might be used by LEDs. | |||
activePin is port mask, where active pin is 1. | |||
*/ | |||
void RowPort_PCA9655E::setActivePinLow(const uint8_t activePin) | |||
void StrobePort_PCA9655E::setActivePinLow(const uint8_t activePin) | |||
{ | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(outputByteCommand); | |||
@@ -30,7 +30,7 @@ void RowPort_PCA9655E::setActivePinLow(const uint8_t activePin) | |||
sets activePin pin output to high. | |||
activePin is port mask, where active pin is 1. | |||
*/ | |||
void RowPort_PCA9655E::setActivePinHigh(const uint8_t activePin) | |||
void StrobePort_PCA9655E::setActivePinHigh(const uint8_t activePin) | |||
{ | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(outputByteCommand); |
@@ -1,10 +1,10 @@ | |||
#ifndef ROWPORT_PCA9655E_H | |||
#define ROWPORT_PCA9655E_H | |||
#ifndef STROBEPORT_PCA9655E_H | |||
#define STROBEPORT_PCA9655E_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <Wire.h> | |||
#include <RowPort.h> | |||
#include "IOExpanderPort.h" | |||
#include <StrobePort.h> | |||
#include "IOEPort.h" | |||
/* One PCA9655E I/O expander port connected to matrix rows. | |||
@@ -14,12 +14,12 @@ This should normally be called only once. | |||
Instantiation | |||
------------ | |||
Example instantiation for row port 0: | |||
IOExpanderPort port0(0, 0); | |||
RowPort_PCA9655E rowPort0(port0); | |||
IOEPort port0(0, 0); | |||
StrobePort_PCA9655E rowPort0(port0); | |||
Example instantiation for row port 1: | |||
IOExpanderPort port1(1, 0); | |||
RowPort_PCA9655E rowPort1(port1); | |||
IOEPort port1(1, 0); | |||
StrobePort_PCA9655E rowPort1(port1); | |||
Diode orientation | |||
---------------- | |||
@@ -32,16 +32,16 @@ PCA9655E data sheet | |||
http://www.onsemi.com/pub_link/Collateral/PCA9655E-D.PDF | |||
*/ | |||
class RowPort_PCA9655E : public RowPort | |||
class StrobePort_PCA9655E : public StrobePort | |||
{ | |||
private: | |||
IOExpanderPort& port; | |||
IOEPort& port; | |||
const uint8_t configurationByteCommand; | |||
const uint8_t outputByteCommand; | |||
public: | |||
//The constructor initialization list is in .cpp | |||
RowPort_PCA9655E(IOExpanderPort& port); | |||
StrobePort_PCA9655E(IOEPort& port); | |||
void begin(); | |||
virtual void setActivePinLow(const uint8_t activePin); //activePin is a port mask |
@@ -9,9 +9,9 @@ Using smaller types on a 32-bit uC (Teensy LC) would accomplish nothing. | |||
*/ | |||
/* Uncomment a typedef read_pins_t size that covers all col pins of all RowScanner objects i.e. | |||
For RowScanner_PinsArray, RowScanner_PinsArray::READ_PIN_COUNT | |||
For RowScanner_SPIShiftRegisters, RowScanner_SPIShiftRegisters::KEY_COUNT | |||
For RowScanner_PinsBitwise, cover the last 1 bit in RowScanner_PinsBitwise::strobePin | |||
For Scanner_uC, Scanner_uC::READ_PIN_COUNT | |||
For Scanner_ShiftRegs74HC165, Scanner_ShiftRegs74HC165::READ_PIN_COUNT | |||
For Scanner_Port, cover the last 1 bit in Scanner_Port::strobePin | |||
*/ | |||
//typedef uint8_t read_pins_t; | |||
//typedef uint16_t read_pins_t; |