Browse Source

combined PortWrite_MCP23S17 and PortRead_MCP23S17 into Port_MCP23S17

tags/v0.6.0
wolfv6 7 years ago
parent
commit
59565dacb4

+ 7
- 0
doc/keybrd_library_user_guide.md View File

@@ -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
- 4
src/LED_IOE.h View File

@@ -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();

+ 0
- 11
src/LED_PCA9655E.cpp View File

@@ -1,11 +0,0 @@
#include "LED_PCA9655E.h"

void LED_PCA9655E::on()
{
refPort.write(pin, HIGH);
}

void LED_PCA9655E::off()
{
refPort.write(pin, LOW);
}

+ 0
- 27
src/LED_PCA9655E.h View File

@@ -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

src/PortReadInterface.h → src/PortInterface.h View File

@@ -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

+ 68
- 0
src/PortMCP23S17.cpp View File

@@ -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
}

+ 39
- 2
src/PortMCP23S17.h View File

@@ -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

+ 0
- 27
src/PortRead_MCP23S17.cpp View File

@@ -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
}

+ 0
- 48
src/PortRead_MCP23S17.h View File

@@ -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

+ 0
- 26
src/PortRead_PCA9655E.cpp View File

@@ -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();
}

+ 0
- 43
src/PortRead_PCA9655E.h View File

@@ -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

+ 0
- 15
src/PortWriteInterface.h View File

@@ -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

+ 0
- 37
src/PortWrite_MCP23S17.cpp View File

@@ -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
}

+ 0
- 41
src/PortWrite_MCP23S17.h View File

@@ -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

+ 0
- 41
src/PortWrite_PCA9655E.cpp View File

@@ -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();
}

+ 0
- 38
src/PortWrite_PCA9655E.h View File

@@ -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

+ 2
- 1
src/Scanner_IOE.cpp View File

@@ -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
- 5
src/Scanner_IOE.h View File

@@ -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);

+ 0
- 51
src/Scanner_ShiftRegsPISOMultiRow.cpp View File

@@ -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;
}


+ 0
- 58
src/Scanner_ShiftRegsPISOMultiRow.h View File

@@ -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

+ 0
- 43
src/Scanner_ShiftRegsPISOSingleRow.cpp View File

@@ -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;
}


+ 0
- 60
src/Scanner_ShiftRegsPISOSingleRow.h View File

@@ -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

BIN
tutorials/breadboard_keyboard_supplies.ods View File


+ 7
- 11
tutorials/keybrd_5b_LED_on_IOE/keybrd_5b_LED_on_IOE.ino View File

@@ -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();
}