combined PortWrite_MCP23S17 and PortRead_MCP23S17 into Port_MCP23S17
This commit is contained in:
parent
7a9228e7dc
commit
59565dacb4
@ -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,7 +4,7 @@
|
||||
#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_*??
|
||||
@ -12,11 +12,11 @@ Input/Ouput Direction configuration are set to ouput in PortWrite_*.begin() and
|
||||
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
|
Binary file not shown.
@ -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();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user