Archived
1
0
This commit is contained in:
wolfv6 2016-09-11 15:23:47 -06:00
parent 4b1b53a76a
commit c2c0c02208
12 changed files with 89 additions and 105 deletions

View File

@ -6,7 +6,7 @@
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.
One port's outputVal can be shared by strobe pins and multiple LED pins.
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.
@ -32,7 +32,7 @@ struct PortIOE
const uint8_t num; //port number
uint8_t outputVal; //bitwise value of output register for LEDs
PortIOE(const uint8_t portNumber, uint8_t outputVal)
: num(portNumber), outputVal(outputVal) {}
PortIOE(const uint8_t portNumber)
: num(portNumber), outputVal(0) {}
};
#endif

View File

@ -1,7 +1,7 @@
#include "PortRead_MCP23S17.h"
/*
begin() is called from Scanner_IOE::begin().
/* begin() is called from Scanner_IOE::begin().
Configures port to to read (input with pullup enabled).
*/
void PortRead_MCP23S17::begin(const uint8_t strobeOn)
{
@ -14,16 +14,6 @@ void PortRead_MCP23S17::begin(const uint8_t strobeOn)
pullUp = 0;
}
Keyboard.print("\npullUp=");//todo
Keyboard.print(pullUp);
/*
//todo these 4 lines are duplicated in PortWrite_MCP23S17::begin(), which is called first
pinMode(SS, OUTPUT); //configure controller's Slave Select pin to output
digitalWrite(SS, HIGH); //disable Slave Select
SPI.begin();
SPI.beginTransaction(SPISettings (SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE0)); //control SPI bus todo is slow clock needed?
//SPI.endTransaction() not called to release SPI bus because keyboard only has one SPI device.
*/
digitalWrite(SS, LOW); //enable Slave Select
SPI.transfer(port.DEVICE_ADDR << 1); //write command
SPI.transfer(port.num); //configure IODIR
@ -37,15 +27,15 @@ Keyboard.print(pullUp);
digitalWrite(SS, HIGH); //disable Slave Select
}
/*
read() returns portState.
/* read() returns portState.
Only portState bits of readPins are valid.
*/
uint8_t PortRead_MCP23S17::read()
{
uint8_t portState; //bit wise
digitalWrite(SS, LOW); //enable Slave Select
SPI.transfer(port.DEVICE_ADDR << 1 | 1); //read command
SPI.transfer( (port.DEVICE_ADDR << 1) | 1); //read command
SPI.transfer(port.num + 0x12); //GPIO register address to read data from
portState = SPI.transfer(0); //save the data (0 is dummy data to send)
digitalWrite(SS, HIGH); //disable Slave Select

View File

@ -9,21 +9,28 @@
/* One MCP23S17 I/O expander port connected to matrix columns.
Instantiation todo
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 bitwise pin configuration
1=configure as input (for pins connected to column)
0=configure as output (for LED or not connected to a column)
Example instantiation for column port 0, with pins 2 and 3 connected to columns:
PortIOE port0(0, 0);
PortRead_MCP23S17 colPort0(port0, 2<<0 | 1<<3 );
Example instantiation for column port 1, with pins 2 and 3 connected to columns:
PortIOE port1(1, 0);
PortRead_MCP23S17 colPort1(port1, 2<<0 | 1<<3 );
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
{

View File

@ -1,17 +1,18 @@
#include "PortRead_PCA9655E.h"
/*
/* begin() is called from Scanner_IOE::begin().
Configures port to to read (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=configure as output (for LED), 1=configure as input (for read)
Wire.write(readPins); //0=output (for LED), 1=input (for read)
Wire.endTransmission();
}
/*
returns port value
/* read() returns portState.
Only portState bits of readPins are valid.
*/
uint8_t PortRead_PCA9655E::read()
{

View File

@ -14,16 +14,20 @@ Instantiation
readPins parameter is port's bitwise pin configuration
1=configure as input (for pins connected to column)
0=configure as output (for LED or not connected to a column)
Example instantiation for column port 0, with pins 2 and 3 connected to columns:
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:
PortIOE port1(1, 0);
PortRead_PCA9655E colPort1(port1, 2<<0 | 1<<3 );
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
{

View File

@ -1,47 +1,46 @@
#include "PortWrite_MCP23S17.h"
/* writePort() sets registerAddr to data.
/* push() writes data to registerAddr.
*/
void PortWrite_MCP23S17::writePort(const uint8_t registerAddr, const uint8_t data)
void PortWrite_MCP23S17::push(const uint8_t registerAddr, const uint8_t data)
{
digitalWrite(SS, LOW); //enable Slave Select
SPI.transfer(port.DEVICE_ADDR << 1); //write command
SPI.transfer(registerAddr); //register address to write data to
SPI.transfer(data); //data
SPI.transfer(data); //write the data
digitalWrite(SS, HIGH); //disable Slave Select
}
/* begin() is called from Scanner_IOE::begin(). Initiates SPI bus and configures write pins.
PortRead_MCP23S17 and PortWrite_MCP23S17 should be on seperate ports on the same MCP23S17.
Output pins can be used for strobe pins and LEDs.
/* begin() is called from Scanner_IOE::begin().
Initiates SPI bus and configures write pins to output.
MCP23S17 SPI interface is 10 MHz max.
*/
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 (SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE0)); //control SPI bus todo is slow clock needed?
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.
writePort(port.num, 0); //configure port direction (port.num) to output (0)
push(port.num, 0); //configure port direction (port.num) to output (0)
}
/*
strobePin is bitwise, where pin being strobed is 1.
pinLogicLevel is HIGH or LOW.
port.outputVal can be shared by LEDs.
The function does not reset the other pins so that they can be used for LEDs.
/* write() sets pin output to logicLevel.
pin is bitwise, 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 strobePin, const bool pinLogicLevel)
void PortWrite_MCP23S17::write(const uint8_t pin, const bool logicLevel)
{
if (pinLogicLevel == LOW)
if (logicLevel == LOW)
{
port.outputVal &= ~strobePin; //set strobePin output to low
port.outputVal &= ~pin; //set pin output to low
}
else
{
port.outputVal |= strobePin; //set strobePin output to high
port.outputVal |= pin; //set pin output to high
}
writePort(port.num + 0x12, port.outputVal); //set GPIO port pins for strobe and LEDs
push(port.num + 0x12, port.outputVal); //set GPIO port pin to outputVal
}

View File

@ -7,42 +7,35 @@
#include "PortIOE.h"
/* One MCP23S17 I/O expander port connected to matrix rows.
MCP23S17 does not have internal pull-up resistors (PCA9535E does).
write() can output logiclevel to strobePin, one LED pin, or multiple pins.
begin() configures column port's configuration and output.
This should normally be called once in sketch's setup().
If PortRead_MCP23S17 is instantiated on the same port, do NOT use PortWrite_MCP23S17::begin().
Otherwise readPins could be overwritten.
This class has Slave Select hardcoded to Arduino Pin 10.
Arduino Pin 10 avoids the speed penalty of digitalWrite.
Instantiation
------------
Example instantiation for row port 0:
PortIOE port0(0, 0);
PortWrite_MCP23S17 rowPort0(port0);
Example instantiation for row port 1:
PortIOE port1(1, 0);
PortWrite_MCP23S17 rowPort1(port1);
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
WARNING: This class hardcodes Slave Select to Arduino Pin 10 to avoid the speed penalty of digitalWrite
*/
class PortWrite_MCP23S17 : public PortWriteInterface
{
private:
PortIOE& port;
void writePort(const uint8_t registerAddr, const uint8_t data);
void push(const uint8_t registerAddr, const uint8_t data);
public:
PortWrite_MCP23S17(PortIOE& port) : port(port) {}
void begin();
virtual void write(const uint8_t pin, const bool pinLogicLevel);
virtual void write(const uint8_t pin, const bool logicLevel);
};
#endif

View File

@ -1,8 +1,7 @@
#include "PortWrite_PCA9655E.h"
/*
If PortRead_PCA9655E is instantiated on the same port, do NOT use PortWrite_PCA9655E::begin().
Otherwise readPins could be overwritten.
/* begin() is called from Scanner_IOE::begin().
Configures write pins to output.
*/
void PortWrite_PCA9655E::begin()
{
@ -10,25 +9,24 @@ void PortWrite_PCA9655E::begin()
Wire.beginTransmission(port.DEVICE_ADDR);
Wire.write(port.num + 6); //configuration byte command
Wire.write(0); //0=configure as output (for strobe pins and LED)
Wire.write(0); //configure all pins as output
Wire.endTransmission();
}
/*
strobePin is bitwise, where pin being strobed is 1.
pinLogicLevel is HIGH or LOW.
Does not reset the other pins because LEDs could be using some of the pins.
Syntax is similar to Arduino DigitalWrite().
/* write() sets pin output to logicLevel.
pin is bitwise, 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 strobePin, const bool pinLogicLevel)
void PortWrite_PCA9655E::write(const uint8_t pin, const bool logicLevel)
{
if (pinLogicLevel == LOW) //if strobePin low
if (logicLevel == LOW) //if pin low
{
port.outputVal &= ~strobePin; //set pin output to low
port.outputVal &= ~pin; //set pin output to low
}
else //if strobestrobe high
{
port.outputVal |= strobePin; //set pin output to high
port.outputVal |= pin; //set pin output to high
}
Wire.beginTransmission(port.DEVICE_ADDR);

View File

@ -7,23 +7,15 @@
#include "PortIOE.h"
/* One PCA9655E I/O expander port connected to matrix rows.
PCA9655E does not have internal pull-up resistors (PCA9535E does).
begin() configures column port's configuration and output.
This should normally be called once in sketch's setup().
If PortRead_PCA9655E is instantiated on the same port, do NOT use PortWrite_PCA9655E::begin().
Otherwise readPins could be overwritten.
write() can output logiclevel to strobePin, one LED pin, or multiple pins.
Instantiation
------------
Example instantiation for row port 0:
PortIOE port0(0, 0);
Example instantiation:
const uint8_t PortIOE::DEVICE_ADDR = 0x20; //PCA9655E address, all 3 ADDR pins are grounded
PortIOE port0(0);
PortWrite_PCA9655E rowPort0(port0);
Example instantiation for row port 1:
PortIOE port1(1, 0);
PortWrite_PCA9655E rowPort1(port1);
Diode orientation
----------------
Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation
@ -41,6 +33,6 @@ class PortWrite_PCA9655E : public PortWriteInterface
PortWrite_PCA9655E(PortIOE& port) : port(port) {}
void begin();
virtual void write(const uint8_t strobePin, const bool pinLogicLevel);
virtual void write(const uint8_t pin, const bool logicLevel);
};
#endif

View File

@ -11,7 +11,7 @@ void Scanner_IOE::init(const uint8_t strobePin)
*/
void Scanner_IOE::begin()
{
refPortWrite.begin(); //configures SPI bus
refPortWrite.begin(); //configure SPI bus
refPortRead.begin(strobeOn);
}

View File

@ -8,9 +8,10 @@
#include <PortReadInterface.h>
/* Scanner_IOE uses bit manipulation to read all pins of one port.
The ports are normally from an I/O Expander, but could also be ports from an AVR uC.
The maximum keys per row is 8, because ports have a maximum of 8 pins each.
begin() should be called once from sketch setup().
keybrd_library_developer_guide.md has instructions for ## Active state and diode orientation
*/
class Scanner_IOE : public ScannerInterface

View File

@ -32,10 +32,10 @@ Scanner_uC scanner_L(LOW, readPins, readPinCount);
// =============== RIGHT SCANNER ===============
const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded
PortIOE port_A(0, 0);
PortIOE port_A(0);
PortRead_MCP23S17 portRead_A(port_A, 1<<0 | 1<<1 );
PortIOE port_B(1, 0);
PortIOE port_B(1);
//PortWrite_MCP23S17 portWrite_B(port_B); //for LEDs
PortWrite_MCP23S17 portWrite_B(port_B);
@ -92,5 +92,4 @@ void loop()
scanDelay.delay();
//debug.print_scans_per_second();
//debug.print_microseconds_per_scan();
delay(100); //todo
}