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. PortIOE contains outputVal, the value of a port's output register.
outputVal is used for port manipulation by classes PortWrite and LED. 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. PortIOE is only used by I/O expander port classes.
AVR port classes do not need a similar class because PORTx is global in the Arduino library. AVR port classes do not need a similar class because PORTx is global in the Arduino library.
@ -32,7 +32,7 @@ struct PortIOE
const uint8_t num; //port number const uint8_t num; //port number
uint8_t outputVal; //bitwise value of output register for LEDs uint8_t outputVal; //bitwise value of output register for LEDs
PortIOE(const uint8_t portNumber, uint8_t outputVal) PortIOE(const uint8_t portNumber)
: num(portNumber), outputVal(outputVal) {} : num(portNumber), outputVal(0) {}
}; };
#endif #endif

View File

@ -1,7 +1,7 @@
#include "PortRead_MCP23S17.h" #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) void PortRead_MCP23S17::begin(const uint8_t strobeOn)
{ {
@ -14,16 +14,6 @@ void PortRead_MCP23S17::begin(const uint8_t strobeOn)
pullUp = 0; 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 digitalWrite(SS, LOW); //enable Slave Select
SPI.transfer(port.DEVICE_ADDR << 1); //write command SPI.transfer(port.DEVICE_ADDR << 1); //write command
SPI.transfer(port.num); //configure IODIR SPI.transfer(port.num); //configure IODIR
@ -37,15 +27,15 @@ Keyboard.print(pullUp);
digitalWrite(SS, HIGH); //disable Slave Select 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 PortRead_MCP23S17::read()
{ {
uint8_t portState; //bit wise uint8_t portState; //bit wise
digitalWrite(SS, LOW); //enable Slave Select 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 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) portState = SPI.transfer(0); //save the data (0 is dummy data to send)
digitalWrite(SS, HIGH); //disable Slave Select digitalWrite(SS, HIGH); //disable Slave Select

View File

@ -9,21 +9,28 @@
/* One MCP23S17 I/O expander port connected to matrix columns. /* 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 readPins parameter is port's bitwise pin configuration
1=configure as input (for pins connected to column) 1=configure as input (for pins connected to column)
0=configure as output (for LED or not connected to a column) 0=configure as output (for LED or not connected to a column)
Example instantiation for column port 0, with pins 2 and 3 connected to columns:
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. 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 class PortRead_MCP23S17 : public PortReadInterface
{ {

View File

@ -1,17 +1,18 @@
#include "PortRead_PCA9655E.h" #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) void PortRead_PCA9655E::begin(const uint8_t strobeOn)
{ {
Wire.beginTransmission(port.DEVICE_ADDR); Wire.beginTransmission(port.DEVICE_ADDR);
Wire.write(port.num + 6); //configuration byte command 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(); Wire.endTransmission();
} }
/* /* read() returns portState.
returns port value Only portState bits of readPins are valid.
*/ */
uint8_t PortRead_PCA9655E::read() uint8_t PortRead_PCA9655E::read()
{ {

View File

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

View File

@ -1,47 +1,46 @@
#include "PortWrite_MCP23S17.h" #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 digitalWrite(SS, LOW); //enable Slave Select
SPI.transfer(port.DEVICE_ADDR << 1); //write command SPI.transfer(port.DEVICE_ADDR << 1); //write command
SPI.transfer(registerAddr); //register address to write data to 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 digitalWrite(SS, HIGH); //disable Slave Select
} }
/* begin() is called from Scanner_IOE::begin(). Initiates SPI bus and configures write pins. /* begin() is called from Scanner_IOE::begin().
PortRead_MCP23S17 and PortWrite_MCP23S17 should be on seperate ports on the same MCP23S17. Initiates SPI bus and configures write pins to output.
Output pins can be used for strobe pins and LEDs. MCP23S17 SPI interface is 10 MHz max.
*/ */
void PortWrite_MCP23S17::begin() void PortWrite_MCP23S17::begin()
{ {
pinMode(SS, OUTPUT); //configure controller's Slave Select pin to output pinMode(SS, OUTPUT); //configure controller's Slave Select pin to output
digitalWrite(SS, HIGH); //disable Slave Select digitalWrite(SS, HIGH); //disable Slave Select
SPI.begin(); 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. //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)
} }
/* /* write() sets pin output to logicLevel.
strobePin is bitwise, where pin being strobed is 1. pin is bitwise, where pin being set is 1.
pinLogicLevel is HIGH or LOW. logicLevel is HIGH or LOW.
port.outputVal can be shared by LEDs. write() does not overwrite the other pins.
The function does not reset the other pins so that they can be used for LEDs.
*/ */
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 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" #include "PortIOE.h"
/* One MCP23S17 I/O expander port connected to matrix rows. /* 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 class has Slave Select hardcoded to Arduino Pin 10.
This should normally be called once in sketch's setup(). Arduino Pin 10 avoids the speed penalty of digitalWrite.
If PortRead_MCP23S17 is instantiated on the same port, do NOT use PortWrite_MCP23S17::begin().
Otherwise readPins could be overwritten.
Instantiation Instantiation
------------ ------------
Example instantiation for row port 0: Example instantiation:
PortIOE port0(0, 0); const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded
PortWrite_MCP23S17 rowPort0(port0); PortIOE port_B(1);
PortWrite_MCP23S17 portWrite_B(port_B);
Example instantiation for row port 1:
PortIOE port1(1, 0);
PortWrite_MCP23S17 rowPort1(port1);
Diode orientation Diode orientation
---------------- ----------------
Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation
MCP23S17 data sheet MCP23S17 data sheet
---------------- ------------------
http://www.onsemi.com/pub_link/Collateral/MCP23S17-D.PDF 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 class PortWrite_MCP23S17 : public PortWriteInterface
{ {
private: private:
PortIOE& port; PortIOE& port;
void writePort(const uint8_t registerAddr, const uint8_t data); void push(const uint8_t registerAddr, const uint8_t data);
public: public:
PortWrite_MCP23S17(PortIOE& port) : port(port) {} PortWrite_MCP23S17(PortIOE& port) : port(port) {}
void begin(); void begin();
virtual void write(const uint8_t pin, const bool pinLogicLevel); virtual void write(const uint8_t pin, const bool logicLevel);
}; };
#endif #endif

View File

@ -1,8 +1,7 @@
#include "PortWrite_PCA9655E.h" #include "PortWrite_PCA9655E.h"
/* /* begin() is called from Scanner_IOE::begin().
If PortRead_PCA9655E is instantiated on the same port, do NOT use PortWrite_PCA9655E::begin(). Configures write pins to output.
Otherwise readPins could be overwritten.
*/ */
void PortWrite_PCA9655E::begin() void PortWrite_PCA9655E::begin()
{ {
@ -10,25 +9,24 @@ void PortWrite_PCA9655E::begin()
Wire.beginTransmission(port.DEVICE_ADDR); Wire.beginTransmission(port.DEVICE_ADDR);
Wire.write(port.num + 6); //configuration byte command 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(); Wire.endTransmission();
} }
/* /* write() sets pin output to logicLevel.
strobePin is bitwise, where pin being strobed is 1. pin is bitwise, where pin being strobed is 1.
pinLogicLevel is HIGH or LOW. logicLevel is HIGH or LOW.
Does not reset the other pins because LEDs could be using some of the pins. write() does not overwrite the other pins.
Syntax is similar to Arduino DigitalWrite().
*/ */
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 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); Wire.beginTransmission(port.DEVICE_ADDR);

View File

@ -7,23 +7,15 @@
#include "PortIOE.h" #include "PortIOE.h"
/* One PCA9655E I/O expander port connected to matrix rows. /* One PCA9655E I/O expander port connected to matrix rows.
PCA9655E 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_PCA9655E is instantiated on the same port, do NOT use PortWrite_PCA9655E::begin().
Otherwise readPins could be overwritten.
Instantiation Instantiation
------------ ------------
Example instantiation for row port 0: Example instantiation:
PortIOE port0(0, 0); const uint8_t PortIOE::DEVICE_ADDR = 0x20; //PCA9655E address, all 3 ADDR pins are grounded
PortIOE port0(0);
PortWrite_PCA9655E rowPort0(port0); PortWrite_PCA9655E rowPort0(port0);
Example instantiation for row port 1:
PortIOE port1(1, 0);
PortWrite_PCA9655E rowPort1(port1);
Diode orientation Diode orientation
---------------- ----------------
Diode orientation is explained in keybrd_library_user_guide.md > 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) {} PortWrite_PCA9655E(PortIOE& port) : port(port) {}
void begin(); void begin();
virtual void write(const uint8_t strobePin, const bool pinLogicLevel); virtual void write(const uint8_t pin, const bool logicLevel);
}; };
#endif #endif

View File

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

View File

@ -8,9 +8,10 @@
#include <PortReadInterface.h> #include <PortReadInterface.h>
/* Scanner_IOE uses bit manipulation to read all pins of one port. /* 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. 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 keybrd_library_developer_guide.md has instructions for ## Active state and diode orientation
*/ */
class Scanner_IOE : public ScannerInterface class Scanner_IOE : public ScannerInterface

View File

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