Scanner_uC Scanner_Port Scanner_ShiftRegs74HC165 | Scanner_uC Scanner_Port Scanner_ShiftRegs74HC165 | ||||
IOEPort | |||||
PortIOE | |||||
StrobePort | |||||
PortWrite | |||||
| | | | ||||
StrobePort_PCA9655E (one StrobePort class for each IOE type) | |||||
PortWrite_PCA9655E (one PortWrite class for each IOE type) | |||||
ReadPort | |||||
PortRead | |||||
| | | | ||||
ReadPort_PCA9655E (one ReadPort class for each IOE type) | |||||
PortRead_PCA9655E (one PortRead class for each IOE type) | |||||
____ LED ____ | ____ LED ____ | ||||
/ \ | / \ | ||||
``` | ``` | ||||
___ Row_IOE[1..*] _________ | ___ Row_IOE[1..*] _________ | ||||
/ \ \ | / \ \ | ||||
__ Scanner_Port[1] _ Debouncer[1] Keys[1..*] __ | |||||
/ | \ | \ | |||||
StrobePort[1] RowPin[1] ReadPort[1] Code[1..*] Code_LEDLock[1..*] | |||||
_ Scanner_Port[1] _ Debouncer[1] Keys[1..*] __ | |||||
/ | \ | \ | |||||
PortWrite[1] RowPin[1] PortRead[1] Code[1..*] Code_LEDLock[1..*] | |||||
\ / \ | | \ / \ | | ||||
\ / ColPins[1..*] LED[1] | \ / ColPins[1..*] LED[1] | ||||
\ / | \ / | ||||
IOEPort[0..*] | |||||
PortIOE[0..*] | |||||
``` | ``` | ||||
#include <inttypes.h> | #include <inttypes.h> | ||||
#include <Wire.h> | #include <Wire.h> | ||||
#include <LED.h> | #include <LED.h> | ||||
#include <StrobePort_PCA9655E.h> | |||||
#include <PortWrite_PCA9655E.h> | |||||
/* A LED_PCA9655E object is an PCA9655E pin that is connected to an LED indicator light. | /* A LED_PCA9655E object is an PCA9655E pin that is connected to an LED indicator light. | ||||
Input/Ouput Direction configuration are set to ouput in StrobePort_PCA9655E.begin() and ReadPort_PCA9655E.begin(). | |||||
Input/Ouput Direction configuration are set to ouput in PortWrite_PCA9655E.begin() and PortRead_PCA9655E.begin(). | |||||
*/ | */ | ||||
class LED_PCA9655E: public LED | class LED_PCA9655E: public LED | ||||
{ | { | ||||
private: | private: | ||||
//IOEPort& port; | |||||
//PortIOE& port; | |||||
//const uint8_t outputByteCommand; //General Purpose Input/Ouput register address | //const uint8_t outputByteCommand; //General Purpose Input/Ouput register address | ||||
StrobePort_PCA9655E& refPort; | |||||
PortWrite_PCA9655E& refPort; | |||||
const uint8_t pin; //bitwise pin to LED | const uint8_t pin; //bitwise pin to LED | ||||
public: | public: | ||||
LED_PCA9655E(StrobePort_PCA9655E& refPort, const uint8_t pin) | |||||
LED_PCA9655E(PortWrite_PCA9655E& refPort, const uint8_t pin) | |||||
: refPort(refPort), pin(pin) {} | : refPort(refPort), pin(pin) {} | ||||
virtual void on(); | virtual void on(); |
#ifndef IOEXPANDERPORT_H | |||||
#define IOEXPANDERPORT_H | |||||
#ifndef PORTIOE_H | |||||
#define PORTIOE_H | |||||
#include <inttypes.h> | #include <inttypes.h> | ||||
/* The pins of an IC's port can be split between StrobePort, ReadPort, and LED. | |||||
/* The pins of an IC's port can be split between PortWrite, PortRead, and LED. | |||||
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. | |||||
PortIOE contains outputVal, the value of a port's output register. | |||||
outputVal is used for port manipulation by classes PortWrite and LED. | |||||
One port's outputVal can be shared by one PortWrite object and multiple LED objects. | |||||
IOEPort is only used by I/O expander port classes. | |||||
PortIOE 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. | AVR port classes do not need a similar class because PORTx is global in the Arduino library. | ||||
Instantiation | Instantiation | ||||
------------ | ------------ | ||||
Example IOEPort::ADDR initilization: | |||||
const uint8_t IOEPort::ADDR = 0x18; | |||||
Example PortIOE::ADDR initilization: | |||||
const uint8_t PortIOE::ADDR = 0x18; | |||||
Be careful with the ADDR. | Be careful with the ADDR. | ||||
Table 6 in PCA9655E datasheet lists 8-bit versions of I2C addresses. | 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. | The Arduino Wire library uses 7-bit addresses throughout, so drop the low bit. | ||||
Set all other outputVal bits to 0. | Set all other outputVal bits to 0. | ||||
Example instantiation for port0 with active low rows on all pins: | Example instantiation for port0 with active low rows on all pins: | ||||
IOEPort port0(0, ~0); | |||||
PortIOE port0(0, ~0); | |||||
Example instantiation for portA with active low rows on pins 0,1,2: | Example instantiation for portA with active low rows on pins 0,1,2: | ||||
IOEPort portA(0, 1<<0 | 1<<1 | 1<<2 ); | |||||
PortIOE portA(0, 1<<0 | 1<<1 | 1<<2 ); | |||||
Example instantiation for portB with active high rows on pins 0,1,2: | Example instantiation for portB with active high rows on pins 0,1,2: | ||||
IOEPort portB(1, 0); | |||||
PortIOE portB(1, 0); | |||||
*/ | */ | ||||
struct IOEPort | |||||
struct PortIOE | |||||
{ | { | ||||
static const uint8_t ADDR; //I2C address | static const uint8_t ADDR; //I2C address | ||||
const uint8_t num; //port number | const uint8_t num; //port number | ||||
uint8_t outputVal; //bitwise value of output register | uint8_t outputVal; //bitwise value of output register | ||||
IOEPort(const uint8_t portNumber, uint8_t outputVal) | |||||
PortIOE(const uint8_t portNumber, uint8_t outputVal) | |||||
: num(portNumber), outputVal(outputVal) {} | : num(portNumber), outputVal(outputVal) {} | ||||
}; | }; | ||||
#endif | #endif |
#ifndef READPORT_H | |||||
#define READPORT_H | |||||
#ifndef PORTREAD_H | |||||
#define PORTREAD_H | |||||
#include <Arduino.h> | #include <Arduino.h> | ||||
#include <inttypes.h> | #include <inttypes.h> | ||||
/* | /* | ||||
ReadPort is an abstract base class. | |||||
PortRead is an abstract base class. | |||||
Port classes are the keybrd library's interface to microcontoller ports or I/O expander ports. | Port classes are the keybrd library's interface to microcontoller ports or I/O expander ports. | ||||
*/ | */ | ||||
class ReadPort | |||||
class PortRead | |||||
{ | { | ||||
protected: | protected: | ||||
const uint8_t READ_PINS; //bitwise pin configuration, 1 means read column | const uint8_t READ_PINS; //bitwise pin configuration, 1 means read column | ||||
public: | public: | ||||
ReadPort(const uint8_t READ_PINS): READ_PINS(READ_PINS) {} | |||||
PortRead(const uint8_t READ_PINS): READ_PINS(READ_PINS) {} | |||||
//read port and return readState | //read port and return readState | ||||
virtual uint8_t read()=0; | virtual uint8_t read()=0; |
#include "ReadPort_PCA9655E.h" | |||||
#include "PortRead_PCA9655E.h" | |||||
/* | /* | ||||
configures column port's configuration, input, and pins. | configures column port's configuration, input, and pins. | ||||
*/ | */ | ||||
ReadPort_PCA9655E::ReadPort_PCA9655E (IOEPort& port, const uint8_t READ_PINS) | |||||
: ReadPort(READ_PINS), port(port), configurationByteCommand(port.num + 6), inputByteCommand(port.num) | |||||
PortRead_PCA9655E::PortRead_PCA9655E (PortIOE& port, const uint8_t READ_PINS) | |||||
: PortRead(READ_PINS), port(port), configurationByteCommand(port.num + 6), inputByteCommand(port.num) | |||||
{} | {} | ||||
void ReadPort_PCA9655E::begin() | |||||
void PortRead_PCA9655E::begin() | |||||
{ | { | ||||
Wire.beginTransmission(port.ADDR); | Wire.beginTransmission(port.ADDR); | ||||
Wire.write(configurationByteCommand); | Wire.write(configurationByteCommand); | ||||
/* | /* | ||||
Saves all port-pin values to portState. | Saves all port-pin values to portState. | ||||
*/ | */ | ||||
uint8_t ReadPort_PCA9655E::read() | |||||
uint8_t PortRead_PCA9655E::read() | |||||
{ | { | ||||
Wire.beginTransmission(port.ADDR); | Wire.beginTransmission(port.ADDR); | ||||
Wire.write(inputByteCommand); //input immediately before requestFrom | Wire.write(inputByteCommand); //input immediately before requestFrom |
#ifndef READPORT_PCA9655E_H | |||||
#define READPORT_PCA9655E_H | |||||
#ifndef PORTREAD_PCA9655E_H | |||||
#define PORTREAD_PCA9655E_H | |||||
#include <Arduino.h> | #include <Arduino.h> | ||||
#include <inttypes.h> | #include <inttypes.h> | ||||
#include <Wire.h> | #include <Wire.h> | ||||
#include <ReadPort.h> | |||||
#include "IOEPort.h" | |||||
#include <PortRead.h> | |||||
#include "PortIOE.h" | |||||
/* One PCA9655E I/O expander port connected to matrix columns. | /* One PCA9655E I/O expander port connected to matrix columns. | ||||
PCA9655E does not have internal pull-up resistors (PCA9535E does). | PCA9655E does not have internal pull-up resistors (PCA9535E does). | ||||
0=configure as output (for LED or not connected to a 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: | Example instantiation for column port 0, with pins 2 and 3 connected to columns: | ||||
IOEPort port0(0, 0); | |||||
ReadPort_PCA9655E colPort0(port0, 2<<0 | 1<<3 ); | |||||
PortIOE port0(0, 0); | |||||
PortRead_PCA9655E colPort0(port0, 2<<0 | 1<<3 ); | |||||
Example instantiation for column port 1, with pins 2 and 3 connected to columns: | Example instantiation for column port 1, with pins 2 and 3 connected to columns: | ||||
IOEPort port1(1, 0); | |||||
ReadPort_PCA9655E colPort1(port1, 2<<0 | 1<<3 ); | |||||
PortIOE port1(1, 0); | |||||
PortRead_PCA9655E colPort1(port1, 2<<0 | 1<<3 ); | |||||
READ_PINS are read from pin 0 on up. | READ_PINS are read from pin 0 on up. | ||||
---------------- | ---------------- | ||||
Rows, columns, and diode orientation are explained in Matrix.h | Rows, columns, and diode orientation are explained in Matrix.h | ||||
*/ | */ | ||||
class ReadPort_PCA9655E : public ReadPort | |||||
class PortRead_PCA9655E : public PortRead | |||||
{ | { | ||||
private: | private: | ||||
IOEPort& port; | |||||
PortIOE& port; | |||||
const uint8_t configurationByteCommand; | const uint8_t configurationByteCommand; | ||||
const uint8_t inputByteCommand; | const uint8_t inputByteCommand; | ||||
public: | public: | ||||
//The constructor initialization list is in .cpp | //The constructor initialization list is in .cpp | ||||
ReadPort_PCA9655E(IOEPort& port, const uint8_t READ_PINS); | |||||
PortRead_PCA9655E(PortIOE& port, const uint8_t READ_PINS); | |||||
void begin(); | void begin(); | ||||
//read port and store result in portState | //read port and store result in portState |
#ifndef STROBEPORT_H | |||||
#define STROBEPORT_H | |||||
#ifndef PORTWRITE_H | |||||
#define PORTWRITE_H | |||||
#include <Arduino.h> | #include <Arduino.h> | ||||
#include <inttypes.h> | #include <inttypes.h> | ||||
/* | /* | ||||
StrobePort is an abstract base class. | |||||
PortWrite is an abstract base class. | |||||
Port classes are the keybrd library's interface to microcontoller ports or I/O expander ports. | Port classes are the keybrd library's interface to microcontoller ports or I/O expander ports. | ||||
*/ | */ | ||||
class StrobePort | |||||
class PortWrite | |||||
{ | { | ||||
public: | public: | ||||
virtual void write(const uint8_t pin, const bool level)=0; | virtual void write(const uint8_t pin, const bool level)=0; |
#include "StrobePort_PCA9655E.h" | |||||
#include "PortWrite_PCA9655E.h" | |||||
/* | /* | ||||
configures column port's configuration and output. | configures column port's configuration and output. | ||||
*/ | */ | ||||
StrobePort_PCA9655E::StrobePort_PCA9655E(IOEPort& port) | |||||
PortWrite_PCA9655E::PortWrite_PCA9655E(PortIOE& port) | |||||
: port(port), configurationByteCommand(port.num + 6), outputByteCommand(port.num + 2) {} | : port(port), configurationByteCommand(port.num + 6), outputByteCommand(port.num + 2) {} | ||||
void StrobePort_PCA9655E::begin() | |||||
/* | |||||
If PortRead_PCA9655E is instantiated on the same port, do not use PortWrite_PCA9655E::begin(). | |||||
Use PortRead_PCA9655E::begin() instead. Otherwise READ_PINS could be overwritten. | |||||
*/ | |||||
void PortWrite_PCA9655E::begin() | |||||
{ | { | ||||
Wire.beginTransmission(port.ADDR); | Wire.beginTransmission(port.ADDR); | ||||
Wire.write(configurationByteCommand); | Wire.write(configurationByteCommand); | ||||
Does not reset the other pins because LEDs could be using some of the pins. | Does not reset the other pins because LEDs could be using some of the pins. | ||||
Syntax is similar to Arduino DigitalWrite(). | Syntax is similar to Arduino DigitalWrite(). | ||||
*/ | */ | ||||
void StrobePort_PCA9655E::write(const uint8_t pin, const bool value) | |||||
void PortWrite_PCA9655E::write(const uint8_t pin, const bool value) | |||||
{ | { | ||||
if (value == LOW) //if active low | if (value == LOW) //if active low | ||||
{ | { |
#ifndef STROBEPORT_PCA9655E_H | |||||
#define STROBEPORT_PCA9655E_H | |||||
#ifndef PORTWRITE_PCA9655E_H | |||||
#define PORTWRITE_PCA9655E_H | |||||
#include <Arduino.h> | #include <Arduino.h> | ||||
#include <inttypes.h> | #include <inttypes.h> | ||||
#include <Wire.h> | #include <Wire.h> | ||||
#include <StrobePort.h> | |||||
#include "IOEPort.h" | |||||
#include <PortWrite.h> | |||||
#include "PortIOE.h" | |||||
/* One PCA9655E I/O expander port connected to matrix rows. | /* One PCA9655E I/O expander port connected to matrix rows. | ||||
begin() configures column port's configuration and output. | begin() configures column port's configuration and output. | ||||
This should normally be called only once. | This should normally be called only once. | ||||
If PortRead_PCA9655E is instantiated on the same port, do not use PortWrite_PCA9655E::begin(). | |||||
Use PortRead_PCA9655E::begin() instead. Otherwise READ_PINS could be overwritten. | |||||
Instantiation | Instantiation | ||||
------------ | ------------ | ||||
Example instantiation for row port 0: | Example instantiation for row port 0: | ||||
IOEPort port0(0, 0); | |||||
StrobePort_PCA9655E rowPort0(port0); | |||||
PortIOE port0(0, 0); | |||||
PortWrite_PCA9655E rowPort0(port0); | |||||
Example instantiation for row port 1: | Example instantiation for row port 1: | ||||
IOEPort port1(1, 0); | |||||
StrobePort_PCA9655E rowPort1(port1); | |||||
PortIOE port1(1, 0); | |||||
PortWrite_PCA9655E rowPort1(port1); | |||||
Diode orientation | Diode orientation | ||||
---------------- | ---------------- | ||||
http://www.onsemi.com/pub_link/Collateral/PCA9655E-D.PDF | http://www.onsemi.com/pub_link/Collateral/PCA9655E-D.PDF | ||||
*/ | */ | ||||
class StrobePort_PCA9655E : public StrobePort | |||||
class PortWrite_PCA9655E : public PortWrite | |||||
{ | { | ||||
private: | private: | ||||
IOEPort& port; | |||||
PortIOE& port; | |||||
const uint8_t configurationByteCommand; | const uint8_t configurationByteCommand; | ||||
const uint8_t outputByteCommand; | const uint8_t outputByteCommand; | ||||
public: | public: | ||||
//The constructor initialization list is in .cpp | //The constructor initialization list is in .cpp | ||||
StrobePort_PCA9655E(IOEPort& port); | |||||
PortWrite_PCA9655E(PortIOE& port); | |||||
void begin(); | void begin(); | ||||
virtual void write(const uint8_t pin, const bool level); | virtual void write(const uint8_t pin, const bool level); |
uint8_t readState; | uint8_t readState; | ||||
//strobe row on | //strobe row on | ||||
refStrobePort.write(STROBE_PIN, STROBE_ON); | |||||
refPortWrite.write(STROBE_PIN, STROBE_ON); | |||||
delayMicroseconds(3); //time to stablize voltage | delayMicroseconds(3); //time to stablize voltage | ||||
//read the port pins | //read the port pins | ||||
readState = refReadPort.read(); | |||||
readState = refPortRead.read(); | |||||
//strobe row off | //strobe row off | ||||
refStrobePort.write(STROBE_PIN, STROBE_OFF); | |||||
refPortWrite.write(STROBE_PIN, STROBE_OFF); | |||||
//return refReadPort.getPortState(); | |||||
//return refPortRead.getPortState(); | |||||
return readState; | return readState; | ||||
} | } |
#define SCANNER_PORT_H | #define SCANNER_PORT_H | ||||
#include <Arduino.h> | #include <Arduino.h> | ||||
#include <inttypes.h> | #include <inttypes.h> | ||||
#include <StrobePort.h> | |||||
#include <ReadPort.h> | |||||
#include <PortWrite.h> | |||||
#include <PortRead.h> | |||||
/* Scanner_Port uses bit manipulation to read all pins of one port. | /* 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. | The maximum keys per row is 8, because ports have a maximum of 8 pins each. | ||||
private: | private: | ||||
static const bool STROBE_ON; //HIGH or LOW logic level of strobe on, active state | 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 | static const bool STROBE_OFF; //logic level of strobe off, complement of STROBE_ON | ||||
StrobePort& refStrobePort; //this row's IC port | |||||
PortWrite& refPortWrite; //this row's IC port | |||||
const uint8_t STROBE_PIN; //bitwise, 1 indicates IC pin connected to this row | const uint8_t STROBE_PIN; //bitwise, 1 indicates IC pin connected to this row | ||||
ReadPort& refReadPort; | |||||
PortRead& refPortRead; | |||||
public: | public: | ||||
Scanner_Port(StrobePort &refStrobePort, const uint8_t STROBE_PIN, ReadPort& refReadPort) | |||||
: refStrobePort(refStrobePort), STROBE_PIN(STROBE_PIN), refReadPort(refReadPort) {} | |||||
Scanner_Port(PortWrite &refPortWrite, const uint8_t STROBE_PIN, PortRead& refPortRead) | |||||
: refPortWrite(refPortWrite), STROBE_PIN(STROBE_PIN), refPortRead(refPortRead) {} | |||||
uint8_t scan(); | uint8_t scan(); | ||||
}; | }; | ||||
#endif | #endif |
#include <inttypes.h> | #include <inttypes.h> | ||||
#include <config_keybrd.h> | #include <config_keybrd.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <StrobePort.h> | |||||
#include <ReadPort.h> | |||||
#include <PortWrite.h> | |||||
#include <PortRead.h> | |||||
/* Scanner_ShiftRegs74HC165 reads shift registers. | /* Scanner_ShiftRegs74HC165 reads shift registers. | ||||
shift registers 74HC165 is Parallel-In-Serial-Out (PISO) | shift registers 74HC165 is Parallel-In-Serial-Out (PISO) |
#include <Arduino.h> | #include <Arduino.h> | ||||
#include <inttypes.h> | #include <inttypes.h> | ||||
#include <config_keybrd.h> | #include <config_keybrd.h> | ||||
#include <StrobePort.h> | |||||
#include <ReadPort.h> | |||||
#include <PortWrite.h> | |||||
#include <PortRead.h> | |||||
/* Scanner_uC class uses Arduino pin numbers (not port pin numbers). | /* Scanner_uC class uses Arduino pin numbers (not port pin numbers). | ||||
Constructor is in Scanner_uC.cpp | Constructor is in Scanner_uC.cpp |