@@ -187,6 +187,13 @@ Hardware items to check: | |||
* Diode orientation | |||
* To validate keyboard hardware, modify the simple [keybrd_1_breadboard.ino](../tutorials/keybrd_1_breadboard/keybrd_1_breadboard.ino) sketch. | |||
Debugging: | |||
Arduino doesn't have a debugger. You can print values like this: | |||
Keyboard.print(" var="); Keyboard.print(var); | |||
Keyboard.print(" bitPattern="); Keyboard.println(bitPattern, BIN); | |||
delay(200); | |||
The delay is so prints in a loop don't print too fast. | |||
Keybrd nomenclature | |||
------------------- | |||
**[scancode](http://en.wikipedia.org/wiki/Scancode)** - |
@@ -4,19 +4,19 @@ | |||
#include <inttypes.h> | |||
#include <Wire.h> | |||
#include <LED.h> | |||
#include <PortWriteInterface.h> | |||
#include <PortInterface.h> | |||
/* A LED_IOE object is an I/O expander pin that is connected to an LED indicator light. | |||
Input/Ouput Direction configuration are set to ouput in PortWrite_*.begin() and PortRead_*.begin(). todo PortRead_*?? | |||
*/ | |||
class LED_IOE: public LED | |||
class LED_IOE : public LED | |||
{ | |||
private: | |||
PortWriteInterface& refPort; | |||
PortInterface& refPort; | |||
const uint8_t pin; //bit pattern, 1 is IOE pin to LED | |||
public: | |||
LED_IOE(PortWriteInterface& refPort, const uint8_t pin) | |||
LED_IOE(PortInterface& refPort, const uint8_t pin) | |||
: refPort(refPort), pin(pin) {} | |||
virtual void on(); | |||
virtual void off(); |
@@ -1,11 +0,0 @@ | |||
#include "LED_PCA9655E.h" | |||
void LED_PCA9655E::on() | |||
{ | |||
refPort.write(pin, HIGH); | |||
} | |||
void LED_PCA9655E::off() | |||
{ | |||
refPort.write(pin, LOW); | |||
} |
@@ -1,27 +0,0 @@ | |||
#ifndef LED_PCA9655E_H | |||
#define LED_PCA9655E_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <Wire.h> | |||
#include <LED.h> | |||
#include <PortWrite_PCA9655E.h> | |||
/* 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 PortWrite_PCA9655E.begin() and PortRead_PCA9655E.begin(). | |||
*/ | |||
class LED_PCA9655E: public LED | |||
{ | |||
private: | |||
//PortIOE& port; | |||
//const uint8_t outputByteCommand; //General Purpose Input/Ouput register address | |||
PortWrite_PCA9655E& refPort; | |||
const uint8_t pin; //bit pattern, IOE pin to LED | |||
public: | |||
LED_PCA9655E(PortWrite_PCA9655E& refPort, const uint8_t pin) | |||
: refPort(refPort), pin(pin) {} | |||
virtual void on(); | |||
virtual void off(); | |||
}; | |||
#endif |
@@ -1,15 +1,16 @@ | |||
#ifndef PORTREADINTERFACE_H | |||
#define PORTREADINTERFACE_H | |||
#ifndef PORTINTERFACE_H | |||
#define PORTINTERFACE_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
/* | |||
Port classes are the keybrd library's interface to microcontroller ports or I/O expander ports. | |||
*/ | |||
class PortReadInterface | |||
class PortInterface | |||
{ | |||
public: | |||
virtual void begin(const uint8_t strobeOn)=0; | |||
virtual void write(const uint8_t strobePin, const bool pinLogicLevel)=0; | |||
virtual uint8_t read()=0; | |||
}; | |||
#endif |
@@ -14,3 +14,71 @@ uint8_t PortMCP23S17::transfer(const uint8_t command, const uint8_t registerAddr | |||
return portState; | |||
} | |||
/* begin() is called from Scanner_IOE::begin(). | |||
Initiates SPI bus and configures I/O pins for read and write. | |||
strobeOn is logic level of strobe on, HIGH or LOW | |||
MCP23S17 SPI interface is 10 MHz max. | |||
The electrical limitation to bus speed is bus capacitance and the length of the wires involved. | |||
Longer wires require lower clock speeds. | |||
*/ | |||
void PortMCP23S17::begin(const uint8_t strobeOn) | |||
{ | |||
uint8_t pullUp; //bits, GPPU 0=pull-up disabled, 1=pull-up enabled | |||
pinMode(SS, OUTPUT); //configure controller's Slave Select pin to output | |||
digitalWrite(SS, HIGH); //disable Slave Select | |||
SPI.begin(); | |||
SPI.beginTransaction(SPISettings (5000000, MSBFIRST, SPI_MODE0)); //control SPI bus, 5 MHz | |||
//SPI.endTransaction() not called to release SPI bus because keyboard only has one SPI device | |||
if (strobeOn == LOW) //if active low, use internal pull-up resistors | |||
{ | |||
pullUp = readPins; | |||
} | |||
else //active high requires external pull-down resistors | |||
{ | |||
pullUp = 0; | |||
} | |||
//todo | |||
Keyboard.print(" strobeOn="); Keyboard.print(strobeOn); | |||
Keyboard.print(" readPins="); Keyboard.print(readPins, BIN); | |||
Keyboard.print(" pullUp="); Keyboard.println(pullUp, BIN); | |||
transfer(port.DEVICE_ADDR << 1, port.num, readPins); //configure IODIR | |||
transfer(port.DEVICE_ADDR << 1, port.num + 0x0C, pullUp); //configure GPPU | |||
} | |||
/* write() sets pin output to logicLevel (useful for strobePin, one LED pin, or multiple pins). | |||
pin is bit pattern, where pin being set is 1. | |||
logicLevel is HIGH or LOW. | |||
write() does not overwrite the other pins. | |||
*/ | |||
void PortMCP23S17::write(const uint8_t pin, const bool logicLevel) | |||
{ | |||
if (logicLevel == LOW) | |||
{ | |||
port.outputVal &= ~pin; //set pin output to low | |||
} | |||
else | |||
{ | |||
port.outputVal |= pin; //set pin output to high | |||
} | |||
//todo | |||
//Keyboard.print(" readPins="); Keyboard.print(readPins, BIN); | |||
Keyboard.print(" pin="); Keyboard.print(pin, BIN); | |||
Keyboard.print(" logicLevel="); Keyboard.print(logicLevel); | |||
Keyboard.print(" outputVal="); Keyboard.println(port.outputVal, BIN); | |||
//Keyboard.print(" ="); Keyboard.print(); | |||
//delay(200); | |||
transfer(port.DEVICE_ADDR << 1, port.num + 0x12, port.outputVal); //set GPIO port to outputVal | |||
} | |||
/* read() returns portState. Only portState pins with pull resistors are valid. | |||
*/ | |||
uint8_t PortMCP23S17::read() | |||
{ | |||
return transfer( (port.DEVICE_ADDR << 1) | 1, port.num + 0x12, 0); //read from GPIO | |||
} |
@@ -3,10 +3,47 @@ | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <SPI.h> | |||
#include <PortIOE.h> | |||
#include <PortInterface.h> | |||
class PortMCP23S17 | |||
/* | |||
readPins are connected to matrix col | |||
write pin is connected to matrix Row (strobe pin) or LED. | |||
Slave Select is hardcoded to Arduino Pin 10. | |||
Arduino Pin 10 avoids the speed penalty of digitalWrite. | |||
Instantiation | |||
------------ | |||
readPins parameter is configures port's pins. | |||
Example instantiation: | |||
const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded | |||
PortIOE port_B(1); | |||
Port_MCP23S17 portWrite_B(port_B, 0); //all pins are set to output for strobes and LEDs | |||
PortIOE port_A(0); | |||
Port_MCP23S17 portRead_A(port_A, 1<<0 | 1<<1 ); //pins 0,1 are set to input for reading, | |||
//remaining pins can be used for LEDs | |||
Diode orientation | |||
---------------- | |||
Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation | |||
MCP23S17 data sheet | |||
------------------ | |||
http://www.onsemi.com/pub_link/Collateral/MCP23S17-D.PDF | |||
*/ | |||
class PortMCP23S17 : public PortInterface | |||
{ | |||
protected: | |||
private: | |||
PortIOE& port; | |||
const uint8_t readPins; //bits, IODIR 0=output, 1=input | |||
uint8_t transfer(const uint8_t command, const uint8_t registerAddr, const uint8_t data); | |||
public: | |||
PortMCP23S17(PortIOE& port, const uint8_t readPins) : port(port), readPins(readPins) {} | |||
void begin(const uint8_t strobeOn); | |||
virtual void write(const uint8_t pin, const bool logicLevel); | |||
virtual uint8_t read(); | |||
}; | |||
#endif |
@@ -1,27 +0,0 @@ | |||
#include "PortRead_MCP23S17.h" | |||
/* begin() is called from Scanner_IOE::begin(). | |||
Configures read pins to input with pullup enabled. | |||
*/ | |||
void PortRead_MCP23S17::begin(const uint8_t strobeOn) | |||
{ | |||
if (strobeOn == LOW) //if active low, use internal pull-up resistors | |||
{ | |||
pullUp = readPins; | |||
} | |||
else //active high requires external pull-down resistors | |||
{ | |||
pullUp = 0; | |||
} | |||
transfer(port.DEVICE_ADDR << 1, port.num, readPins); //write, configure IODIR, 0=output, 1=input | |||
transfer(port.DEVICE_ADDR << 1, port.num + 0x0C, pullUp); //write, configure GPPU, | |||
//0=pull-up disabled, 1=pull-up enabled | |||
} | |||
/* read() returns portState. Only portState pins with pull resistors are valid. | |||
*/ | |||
uint8_t PortRead_MCP23S17::read() | |||
{ | |||
return transfer( (port.DEVICE_ADDR << 1) | 1, port.num + 0x12, 0); //read from GPIO | |||
} |
@@ -1,48 +0,0 @@ | |||
#ifndef PORTREAD_MCP23S17_H | |||
#define PORTREAD_MCP23S17_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <SPI.h> | |||
#include <PortReadInterface.h> | |||
#include "PortMCP23S17.h" | |||
#include "PortIOE.h" | |||
#include "Scanner_IOE.h" | |||
/* One MCP23S17 I/O expander port connected to matrix columns. | |||
This class has Slave Select hardcoded to Arduino Pin 10. | |||
Arduino Pin 10 avoids the speed penalty of digitalWrite. | |||
Instantiation | |||
------------ | |||
readPins parameter is port's bit pattern pin configuration | |||
1=configure as input (for read pins connected to column) | |||
0=configure as output (for LED or not connected to a column) | |||
readPins are read from pin 0 on up. | |||
Example instantiation with port-A pins 0 and 1 connected to Scanner_IOE columns: | |||
const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded | |||
PortIOE port_A(0); | |||
PortRead_MCP23S17 portRead_A(port_A, 1<<0 | 1<<1 ); | |||
Diode orientation | |||
---------------- | |||
Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation | |||
MCP23S17 data sheet | |||
------------------ | |||
http://www.onsemi.com/pub_link/Collateral/MCP23S17-D.PDF | |||
*/ | |||
class PortRead_MCP23S17 : public PortReadInterface, public PortMCP23S17 | |||
{ | |||
private: | |||
PortIOE& port; | |||
uint8_t pullUp; //bits, 1 means internal pull-up resistor enabled | |||
const uint8_t readPins; //bits, 1 means internal pull-up resistor enabled | |||
public: | |||
PortRead_MCP23S17(PortIOE& port, const uint8_t readPins) | |||
: port(port), readPins(readPins) {} | |||
void begin(const uint8_t strobeOn); | |||
virtual uint8_t read(); | |||
}; | |||
#endif |
@@ -1,26 +0,0 @@ | |||
#include "PortRead_PCA9655E.h" | |||
/* begin() is called from Scanner_IOE::begin(). | |||
Configures read pins to input. | |||
*/ | |||
void PortRead_PCA9655E::begin(const uint8_t strobeOn) | |||
{ | |||
Wire.beginTransmission(port.DEVICE_ADDR); | |||
Wire.write(port.num + 6); //configuration byte command | |||
Wire.write(readPins); //0=output (for LED), 1=input (for read) | |||
Wire.endTransmission(); | |||
} | |||
/* read() returns portState. | |||
Only portState bits of readPins are valid. | |||
*/ | |||
uint8_t PortRead_PCA9655E::read() | |||
{ | |||
Wire.beginTransmission(port.DEVICE_ADDR); | |||
Wire.write(port.num); //input byte command | |||
Wire.endTransmission(false); //PCA9655E needs false to send a restart | |||
Wire.requestFrom(port.DEVICE_ADDR, 1u); //request one byte from input port | |||
return Wire.read(); | |||
} |
@@ -1,43 +0,0 @@ | |||
#ifndef PORTREAD_PCA9655E_H | |||
#define PORTREAD_PCA9655E_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <Wire.h> | |||
#include <PortReadInterface.h> | |||
#include "PortIOE.h" | |||
/* One PCA9655E I/O expander port connected to matrix columns. | |||
PCA9655E does not have internal pull-up resistors (PCA9535E does). | |||
Instantiation | |||
------------ | |||
readPins parameter is bit pattern for port's pin configuration | |||
1=configure as input (for pins connected to column) | |||
0=configure as output (for LED or not connected to a column) | |||
readPins are read from pin 0 on up. | |||
Example instantiation for column port 1, with pins 2 and 3 connected to columns: | |||
const uint8_t PortIOE::DEVICE_ADDR = 0x20; //PCA9655E address, all 3 ADDR pins are grounded | |||
PortIOE port1(1); | |||
PortRead_PCA9655E colPort1(port1, 1<<2 | 1<<3 ); | |||
Diode orientation | |||
---------------- | |||
Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation | |||
PCA9655E data sheet | |||
---------------- | |||
http://www.onsemi.com/pub_link/Collateral/PCA9655E-D.PDF | |||
*/ | |||
class PortRead_PCA9655E : public PortReadInterface | |||
{ | |||
private: | |||
PortIOE& port; | |||
const uint8_t readPins; //bit pattern, pin configuration, 1 means read pin | |||
public: | |||
PortRead_PCA9655E (PortIOE& port, const uint8_t readPins) | |||
: port(port), readPins(readPins) {} | |||
void begin(const uint8_t strobeOn); | |||
virtual uint8_t read(); | |||
}; | |||
#endif |
@@ -1,15 +0,0 @@ | |||
#ifndef PORTWRITEINTERFACE_H | |||
#define PORTWRITEINTERFACE_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
/* | |||
Port classes are the keybrd library's interface to microcontroller ports or I/O expander ports. | |||
*/ | |||
class PortWriteInterface | |||
{ | |||
public: | |||
virtual void begin()=0; | |||
virtual void write(const uint8_t strobePin, const bool pinLogicLevel)=0; | |||
}; | |||
#endif |
@@ -1,37 +0,0 @@ | |||
#include "PortWrite_MCP23S17.h" | |||
/* begin() is called from Scanner_IOE::begin(). | |||
Initiates SPI bus and configures port pins to output. | |||
MCP23S17 SPI interface is 10 MHz max. | |||
The electrical limitation to bus speed is bus capacitance and the length of the wires involved. | |||
Longer wires require lower clock speeds. | |||
*/ | |||
void PortWrite_MCP23S17::begin() | |||
{ | |||
pinMode(SS, OUTPUT); //configure controller's Slave Select pin to output | |||
digitalWrite(SS, HIGH); //disable Slave Select | |||
SPI.begin(); | |||
SPI.beginTransaction(SPISettings (5000000, MSBFIRST, SPI_MODE0)); //control SPI bus, 5 MHz | |||
//SPI.endTransaction() not called to release SPI bus because keyboard only has one SPI device. | |||
transfer(port.DEVICE_ADDR << 1, port.num, 0); //configure port direction (port.num) to output (0) | |||
} | |||
/* write() sets pin output to logicLevel. | |||
pin is bit pattern, where pin being set is 1. | |||
logicLevel is HIGH or LOW. | |||
write() does not overwrite the other pins. | |||
*/ | |||
void PortWrite_MCP23S17::write(const uint8_t pin, const bool logicLevel) | |||
{ | |||
if (logicLevel == LOW) | |||
{ | |||
port.outputVal &= ~pin; //set pin output to low | |||
} | |||
else | |||
{ | |||
port.outputVal |= pin; //set pin output to high | |||
} | |||
transfer(port.DEVICE_ADDR << 1, port.num + 0x12, port.outputVal); //set GPIO port to outputVal | |||
} |
@@ -1,41 +0,0 @@ | |||
#ifndef PORTWRITE_MCP23S17_H | |||
#define PORTWRITE_MCP23S17_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <SPI.h> | |||
#include <PortWriteInterface.h> | |||
#include "PortMCP23S17.h" | |||
#include "PortIOE.h" | |||
/* One MCP23S17 I/O expander port connected to matrix rows. | |||
write() can output logiclevel to strobePin, one LED pin, or multiple pins. | |||
This class has Slave Select hardcoded to Arduino Pin 10. | |||
Arduino Pin 10 avoids the speed penalty of digitalWrite. | |||
Instantiation | |||
------------ | |||
Example instantiation: | |||
const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded | |||
PortIOE port_B(1); | |||
PortWrite_MCP23S17 portWrite_B(port_B); | |||
Diode orientation | |||
---------------- | |||
Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation | |||
MCP23S17 data sheet | |||
------------------ | |||
http://www.onsemi.com/pub_link/Collateral/MCP23S17-D.PDF | |||
*/ | |||
class PortWrite_MCP23S17 : public PortWriteInterface, public PortMCP23S17 | |||
{ | |||
private: | |||
PortIOE& port; | |||
public: | |||
PortWrite_MCP23S17(PortIOE& port) : port(port) {} | |||
void begin(); | |||
virtual void write(const uint8_t pin, const bool logicLevel); | |||
}; | |||
#endif |
@@ -1,41 +0,0 @@ | |||
#include "PortWrite_PCA9655E.h" | |||
/* begin() is called from Scanner_IOE::begin(). | |||
Initiates I2C bus and configures port pins to output. | |||
PCA9655E supports I2C SCL Clock Frequencies: 100 kHz, 400 kHz, 1000 kHz (Datasheet page 1 & 6) | |||
The electrical limitation to bus speed is bus capacitance and the length of the wires involved. | |||
Longer wires require lower clock speeds. | |||
http://playground.arduino.cc/Main/WireLibraryDetailedReference > Wire.setclock() | |||
*/ | |||
void PortWrite_PCA9655E::begin() | |||
{ | |||
Wire.begin(); //initiate I2C bus to 100 kHz | |||
//Wire.setClock(400000L); //set I2C bus to 400 kHz (have not tested 400 kHz) | |||
Wire.beginTransmission(port.DEVICE_ADDR); | |||
Wire.write(port.num + 6); //configuration byte command | |||
Wire.write(0); //configure all pins as output | |||
Wire.endTransmission(); | |||
} | |||
/* write() sets pin output to logicLevel. | |||
pin is bit pattern, where pin being strobed is 1. | |||
logicLevel is HIGH or LOW. | |||
write() does not overwrite the other pins. | |||
*/ | |||
void PortWrite_PCA9655E::write(const uint8_t pin, const bool logicLevel) | |||
{ | |||
if (logicLevel == LOW) //if pin low | |||
{ | |||
port.outputVal &= ~pin; //set pin output to low | |||
} | |||
else //if strobestrobe high | |||
{ | |||
port.outputVal |= pin; //set pin output to high | |||
} | |||
Wire.beginTransmission(port.DEVICE_ADDR); | |||
Wire.write(port.num + 2); //output Byte command | |||
Wire.write(port.outputVal); | |||
Wire.endTransmission(); | |||
} |
@@ -1,38 +0,0 @@ | |||
#ifndef PORTWRITE_PCA9655E_H | |||
#define PORTWRITE_PCA9655E_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <Wire.h> | |||
#include <PortWriteInterface.h> | |||
#include "PortIOE.h" | |||
/* One PCA9655E I/O expander port connected to matrix rows. | |||
write() can output logiclevel to strobePin, one LED pin, or multiple pins. | |||
Instantiation | |||
------------ | |||
Example instantiation: | |||
const uint8_t PortIOE::DEVICE_ADDR = 0x20; //PCA9655E address, all 3 ADDR pins are grounded | |||
PortIOE port0(0); | |||
PortWrite_PCA9655E rowPort0(port0); | |||
Diode orientation | |||
---------------- | |||
Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation | |||
PCA9655E data sheet | |||
---------------- | |||
http://www.onsemi.com/pub_link/Collateral/PCA9655E-D.PDF | |||
*/ | |||
class PortWrite_PCA9655E : public PortWriteInterface | |||
{ | |||
private: | |||
PortIOE& port; | |||
public: | |||
PortWrite_PCA9655E(PortIOE& port) : port(port) {} | |||
void begin(); | |||
virtual void write(const uint8_t pin, const bool logicLevel); | |||
}; | |||
#endif |
@@ -12,7 +12,6 @@ Initiates communication protocal and configs ports. | |||
*/ | |||
void Scanner_IOE::begin() | |||
{ | |||
refPortWrite.begin(); | |||
refPortRead.begin(strobeOn); | |||
} | |||
@@ -24,11 +23,13 @@ read_pins_t Scanner_IOE::scan(const uint8_t strobePin) | |||
{ | |||
uint8_t readState; //bits, 1 means key is pressed, 0 means released | |||
delay(2000);//todo | |||
//strobe on | |||
refPortWrite.write(strobePin, strobeOn); | |||
delayMicroseconds(3); //time to stabilize voltage | |||
//delayMicroseconds(300); //todo | |||
delay(2000); | |||
//read the port pins | |||
readState = refPortRead.read(); | |||
@@ -4,8 +4,7 @@ | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <ScannerInterface.h> | |||
#include <PortWriteInterface.h> | |||
#include <PortReadInterface.h> | |||
#include <PortInterface.h> | |||
/* Scanner_IOE 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. | |||
@@ -19,11 +18,11 @@ class Scanner_IOE : public ScannerInterface | |||
private: | |||
const bool strobeOn; //logic level of strobe on, HIGH or LOW | |||
const bool strobeOff; //logic level of strobe off, complement of strobeOn | |||
PortWriteInterface& refPortWrite; //the IC port containing the strobePin | |||
PortReadInterface& refPortRead; //the IC's read port | |||
PortInterface& refPortWrite; //the IC port containing the strobePin | |||
PortInterface& refPortRead; //the IC's read port | |||
public: | |||
Scanner_IOE(const bool strobeOn, | |||
PortWriteInterface &refPortWrite, PortReadInterface& refPortRead) | |||
PortInterface &refPortWrite, PortInterface& refPortRead) | |||
: strobeOn(strobeOn), strobeOff(!strobeOn), | |||
refPortWrite(refPortWrite), refPortRead(refPortRead) {} | |||
void init(const uint8_t strobePin); |
@@ -1,51 +0,0 @@ | |||
#include "Scanner_ShiftRegsPISOMultiRow.h" | |||
/* constructor | |||
*/ | |||
Scanner_ShiftRegsPISOMultiRow::Scanner_ShiftRegsPISOMultiRow(const bool strobeOn, | |||
const uint8_t slaveSelect, const uint8_t byte_count) | |||
: strobeOn(strobeOn), strobeOff(!strobeOn), | |||
slaveSelect(slaveSelect), byte_count(byte_count) | |||
{ | |||
pinMode(slaveSelect, OUTPUT); | |||
} | |||
/* init() is called once for each row from Row constructor. | |||
Configures controller to communicate with shift register matrix. | |||
*/ | |||
void Scanner_ShiftRegsPISOMultiRow::init(const uint8_t strobePin) | |||
{ | |||
pinMode(strobePin, OUTPUT); | |||
} | |||
/* begin() should be called once from sketch setup(). | |||
Initializes shift register's shift/load pin. | |||
*/ | |||
void Scanner_ShiftRegsPISOMultiRow::begin() | |||
{ | |||
digitalWrite(slaveSelect, HIGH); | |||
} | |||
/* scan() strobes the row's strobePin and returns state of the shift register's input pins. | |||
strobePin is Arduino pin number connected to this row. | |||
Bit patterns are 1 bit per key. | |||
*/ | |||
read_pins_t Scanner_ShiftRegsPISOMultiRow::scan(const uint8_t strobePin) | |||
{ | |||
read_pins_t readState = 0; //bits, 1 means key is pressed, 0 means released | |||
//strobe row on | |||
digitalWrite(strobePin, strobeOn); | |||
delayMicroseconds(3); //time to stablize voltage | |||
//read all the column pins | |||
digitalWrite(slaveSelect, LOW); //load parallel inputs to the register | |||
digitalWrite(slaveSelect, HIGH); //shift the data toward a serial output | |||
SPI.transfer(&readState, byte_count); | |||
//strobe row off | |||
digitalWrite(strobePin, strobeOff); | |||
return readState; | |||
} | |||
@@ -1,58 +0,0 @@ | |||
#ifndef ROWSCANNER_SHIFTREGSPISOMULTIROW_H | |||
#define ROWSCANNER_SHIFTREGSPISOMULTIROW_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <config_keybrd.h> | |||
#include <SPI.h> | |||
#include <ScannerInterface.h> | |||
#include <PortWriteInterface.h> | |||
#include <PortReadInterface.h> | |||
/* Scanner_ShiftRegsPISOMultiRow reads shift registers. | |||
This was tested on 74HC165 shift registers, which are Parallel-In-Serial-Out (PISO). | |||
Upto 4 shift registers can be in a daisy chained for a total of 32 read pins. | |||
Example instantiation: | |||
Scanner_ShiftRegsPISOMultiRow scanner_R(HIGH, SS, 4); | |||
There are three Scanner_ShiftRegsPISOMultiRow parameters. | |||
"strobeOn" paramter is active state HIGH or LOW. | |||
"slaveSelect" paramter can be any controller pin connected to shift register's SHIFT-LOAD pin. | |||
slaveSelect pin SS (Arduino pin 10) has the fastest scan. | |||
"byte_count" is the number of bytes to read from shift registers (1 to 4). | |||
byte_count should cover all the row's keys: | |||
byte_count*8 >= row's keyCount | |||
Hardware setup: | |||
Each row needs to be connected to a strobe pin from the controller. | |||
Switche and diode in series are connected to shift-register parallel-input pins and strobed row. | |||
For active low: | |||
Shift-register parallel-input pins need 10k Ohm pull-up resistors powered. | |||
Orient diodes with cathode (banded end) towards the write pins (row) | |||
Controller's MISO pin is connected to shift register's complementary serial output (/QH) pin | |||
For active high: | |||
Shift-register parallel-input pins need 10k pull-down resistors grounded. | |||
Orient diodes with cathode (banded end) towards the read pins. | |||
Controller's MISO pin is connected to shift register's serial output (QH) pin | |||
*/ | |||
class Scanner_ShiftRegsPISOMultiRow : public ScannerInterface | |||
{ | |||
private: | |||
const bool strobeOn; //logic level of strobe on, active state HIGH or LOW | |||
const bool strobeOff; //logic level of strobe off, complement of strobeOn | |||
const uint8_t slaveSelect; //controller's pin number that is | |||
// connected to shift register's SHIFT-LOAD pin | |||
const uint8_t byte_count; //number of bytes to read from shift registers | |||
public: | |||
Scanner_ShiftRegsPISOMultiRow(const bool strobeOn, | |||
const uint8_t slaveSelect, const uint8_t byte_count); | |||
virtual void init(const uint8_t strobePin); | |||
virtual void begin(); | |||
virtual read_pins_t scan(const uint8_t strobePin); | |||
}; | |||
#endif |
@@ -1,43 +0,0 @@ | |||
#include "Scanner_ShiftRegsPISOSingleRow.h" | |||
/* constructor | |||
*/ | |||
Scanner_ShiftRegsPISOSingleRow::Scanner_ShiftRegsPISOSingleRow(const bool strobeOn, | |||
const uint8_t slaveSelect, const uint8_t byte_count) | |||
: slaveSelect(slaveSelect), byte_count(byte_count) | |||
{ | |||
pinMode(slaveSelect, OUTPUT); | |||
} | |||
/* init() is called once for each row from Row constructor. | |||
*/ | |||
void Scanner_ShiftRegsPISOSingleRow::init(const uint8_t strobePin) | |||
{ | |||
//empty function | |||
} | |||
/* begin() should be called once from sketch setup(). | |||
Initializes shift register's shift/load pin. | |||
*/ | |||
void Scanner_ShiftRegsPISOSingleRow::begin() | |||
{ | |||
SPI.begin(); | |||
digitalWrite(slaveSelect, HIGH); | |||
} | |||
/* scan() returns state of the shift register's input pins. | |||
No strobe pin is needed, the shift register is wired so the strobe is effectivley always "on". | |||
Bit patterns are 1 bit per key. | |||
*/ | |||
read_pins_t Scanner_ShiftRegsPISOSingleRow::scan(const uint8_t strobePin) | |||
{ | |||
read_pins_t readState = 0; //bits, 1 means key is pressed, 0 means released | |||
//read all the column pins | |||
digitalWrite(slaveSelect, LOW); //load parallel inputs to the register | |||
digitalWrite(slaveSelect, HIGH); //shift the data toward a serial output | |||
SPI.transfer(&readState, byte_count); | |||
return readState; | |||
} | |||
@@ -1,60 +0,0 @@ | |||
#ifndef ROWSCANNER_SHIFTREGSPISOSINGLEROW_H | |||
#define ROWSCANNER_SHIFTREGSPISOSINGLEROW_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <config_keybrd.h> | |||
#include <SPI.h> | |||
#include <ScannerInterface.h> | |||
#include <PortWriteInterface.h> | |||
#include <PortReadInterface.h> | |||
/* Scanner_ShiftRegsPISOSingleRow reads shift registers. | |||
This was tested on 74HC165 shift registers, which are Parallel-In-Serial-Out (PISO). | |||
Upto 4 shift registers can be in a daisy chained for a total of 32 read pins. | |||
Example instantiation: | |||
Row row_R0(scanner_R, 0, ptrsKeys_R0, sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0)); | |||
Scanner_ShiftRegsPISOSingleRow scanner_R(HIGH, SS, 4); | |||
The Row "strobePin" parameter is ignored. | |||
In the above example, the "strobePin" argument is 0, but it doesn't matter what value is given. | |||
There are three Scanner_ShiftRegsPISOSingleRow parameters. | |||
"strobeOn" paramter is ignored, but should be active state HIGH or LOW required by ScannerInterface. | |||
"slaveSelect" paramter can be any controller pin connected to shift register's SHIFT-LOAD pin. | |||
slaveSelect pin SS (Arduino pin 10) has the fastest scan. | |||
"byte_count" is the number of bytes to read from shift registers (1 to 4). | |||
byte_count should cover all the row's keys: | |||
byte_count*8 >= row's keyCount | |||
Hardware setup: | |||
There is only one row, and it is permanently active. | |||
Switches are connected to shift-register parallel-input pins (diodes are not needed) and row. | |||
For active low: | |||
Shift-register parallel-input pins need 10k Ohm pull-up resistors powered. | |||
Switches connect powered row to parallel-input pins. | |||
Controller's MISO pin is connected to shift register's complementary serial output (/QH) pin | |||
For active high: | |||
Shift-register parallel-input pins need 10k pull-down resistors grounded. | |||
Switches connect grouned row to parallel-input pins. | |||
Controller's MISO pin is connected to shift register's serial output (QH) pin | |||
*/ | |||
class Scanner_ShiftRegsPISOSingleRow : public ScannerInterface | |||
{ | |||
private: | |||
const uint8_t slaveSelect; //controller's pin number that is | |||
// connected to shift register's SHIFT-LOAD pin | |||
const uint8_t byte_count; //number of bytes to read from shift registers | |||
public: | |||
Scanner_ShiftRegsPISOSingleRow(const bool strobeOn, | |||
const uint8_t slaveSelect, const uint8_t byte_count); | |||
void init(const uint8_t strobePin); | |||
void begin(); | |||
virtual read_pins_t scan(const uint8_t strobePin); | |||
}; | |||
#endif |
@@ -24,8 +24,7 @@ This layout table shows left and right matrices: | |||
//right matrix | |||
#include <PortIOE.h> | |||
#include <PortWrite_MCP23S17.h> | |||
#include <PortRead_MCP23S17.h> | |||
#include <PortMCP23S17.h> | |||
#include <Scanner_IOE.h> | |||
#include <LED_IOE.h> | |||
@@ -42,20 +41,15 @@ Scanner_uC scanner_L(LOW, readPins, READPIN_COUNT); | |||
const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address with all 3 ADDR pins are grounded | |||
PortIOE port_A(0); | |||
PortRead_MCP23S17 portRead(port_A, 1<<0 | 1<<1 ); | |||
PortWrite_MCP23S17 portWriteA(port_A); //for LED | |||
//todo portWriteA(port_A) instantiation would not be needed if PortRead_MCP23S17 had write() | |||
// consider moving PortWrite_MCP23S17::write to Port_MCP23S17 (parent) | |||
// and passing portRead to LED_IOE | |||
// same for PCA9655E | |||
PortMCP23S17 portRead(port_A, 1<<0 | 1<<1 ); | |||
PortIOE port_B(1); | |||
PortWrite_MCP23S17 portWrite(port_B); | |||
PortMCP23S17 portWrite(port_B, 0); | |||
Scanner_IOE scanner_R(LOW, portWrite, portRead); | |||
// ================ RIGHT LEDs ================= | |||
LED_IOE LED_CapsLck(portWriteA, 1<<6); //tested LED on port A (read) | |||
//LED_IOE LED_CapsLck(portRead, 1<<6); //tested LED on port A (read) | |||
//LED_IOE LED_CapsLck(portWrite, 1<<6);//tested LED on port B (write) | |||
// =================== CODES =================== | |||
@@ -68,7 +62,8 @@ Code_Sc s_1(KEY_1); | |||
Code_Sc s_2(KEY_2); | |||
Code_Sc s_3(KEY_3); | |||
Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED_CapsLck); | |||
Code_Sc o_capsLock(KEY_4); | |||
//Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED_CapsLck); | |||
// =================== ROWS ==================== | |||
// ---------------- LEFT ROWS ------------------ | |||
@@ -93,6 +88,7 @@ Row row_R1(scanner_R, 1<<1, ptrsKeys_R1, KEY_COUNT_R1); | |||
void setup() | |||
{ | |||
Keyboard.begin(); | |||
delay(7000); | |||
scanner_R.begin(); | |||
} | |||