PortWrite_PCA9655E portWrite_R1(port_R1); | PortWrite_PCA9655E portWrite_R1(port_R1); | ||||
PortIOE port_R0(0, 0); | PortIOE port_R0(0, 0); | ||||
//PortWrite_PCA9655E portWrite_R0(port_R0); for LEDs | |||||
//PortWrite_PCA9655E portWrite_R0(port_R0); //for LEDs | |||||
PortRead_PCA9655E portRead_R0(port_R0, 1<<0 | 1<<1 ); | PortRead_PCA9655E portRead_R0(port_R0, 1<<0 | 1<<1 ); | ||||
Scanner_IOE scanner_R(HIGH, portWrite_R1, portRead_R0); | Scanner_IOE scanner_R(HIGH, portWrite_R1, portRead_R0); |
http://playground.arduino.cc/Main/WireLibraryDetailedReference | http://playground.arduino.cc/Main/WireLibraryDetailedReference | ||||
The PCA9655E data sheet is on http://www.onsemi.com/pub_link/Collateral/PCA9655E-D.PDF | The PCA9655E data sheet is on http://www.onsemi.com/pub_link/Collateral/PCA9655E-D.PDF | ||||
portNumber: If the I/O expander uses port letters, use 0 instead of A, use 1 instead of B. | |||||
outputVal: For pins that are connected to active low rows, set outputVal bit to 1. | |||||
Set all other outputVal bits to 0. | |||||
Example instantiation for port0 with active low rows on all pins: | |||||
PortIOE port0(0, ~0); | |||||
Example instantiation for portA with active low rows on pins 0,1,2: | |||||
PortIOE portA(0, 1<<0 | 1<<1 | 1<<2 ); | |||||
Example instantiation for portB with active high rows on pins 0,1,2: | |||||
PortIOE portB(1, 0); | |||||
portNumber: If the I/O expander uses port letters, use 0 inplace of A, use 1 inplace of B. | |||||
*/ | */ | ||||
struct PortIOE | struct PortIOE | ||||
{ | { | ||||
static const uint8_t DEVICE_ADDR; | static const uint8_t DEVICE_ADDR; | ||||
const uint8_t num; //port number | const uint8_t num; //port number | ||||
uint8_t outputVal; //bitwise value of output register | |||||
uint8_t outputVal; //bitwise value of output register for LEDs | |||||
PortIOE(const uint8_t portNumber, uint8_t outputVal) | PortIOE(const uint8_t portNumber, uint8_t outputVal) | ||||
: num(portNumber), outputVal(outputVal) {} | : num(portNumber), outputVal(outputVal) {} |
class PortReadInterface | class PortReadInterface | ||||
{ | { | ||||
public: | public: | ||||
virtual void begin()=0; | |||||
virtual void begin(const uint8_t strobeOn)=0; | |||||
virtual uint8_t read()=0; | virtual uint8_t read()=0; | ||||
}; | }; | ||||
#endif | #endif |
#include "PortRead_MCP23S17.h" | #include "PortRead_MCP23S17.h" | ||||
/* | /* | ||||
SPI bus is configured in PortWrite_MCP23S17::begin(). | |||||
begin() is called from Scanner_IOE::begin(). | |||||
*/ | */ | ||||
void PortRead_MCP23S17::begin(const uint8_t strobeOn) | void PortRead_MCP23S17::begin(const uint8_t strobeOn) | ||||
{ | { | ||||
uint8_t pullUp; //bitwise, 1 means internal pull-up resistor enabled | |||||
if (strobeOn == LOW) //if active low | if (strobeOn == LOW) //if active low | ||||
{ | { | ||||
pullUp = readPins; | pullUp = readPins; | ||||
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 | 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 (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 | ||||
SPI.transfer(readPins); //0=output (for LED), 1=input (for read) | SPI.transfer(readPins); //0=output (for LED), 1=input (for read) | ||||
digitalWrite(SS, LOW); //enable Slave Select | |||||
digitalWrite(SS, HIGH); //enable Slave Select | |||||
digitalWrite(SS, HIGH); //disable Slave Select | |||||
SPI.transfer(port.DEVICE_ADDR << 1); //write command | |||||
digitalWrite(SS, LOW); //disable Slave Select | |||||
SPI.transfer(port.DEVICE_ADDR << 1); //write command | |||||
SPI.transfer(port.num + 0x0C); //configure GPPU | SPI.transfer(port.num + 0x0C); //configure GPPU | ||||
SPI.transfer(pullUp); //0=pull-up disabled (for LED), 1=pull-up enabled (for read) | SPI.transfer(pullUp); //0=pull-up disabled (for LED), 1=pull-up enabled (for read) | ||||
digitalWrite(SS, HIGH); //disable Slave Select | digitalWrite(SS, HIGH); //disable Slave Select | ||||
//SPI.endTransaction() is not called to release the SPI bus | |||||
// because keyboard only has one SPI device. | |||||
} | } | ||||
/* | /* | ||||
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 |
{ | { | ||||
private: | private: | ||||
PortIOE& port; | PortIOE& port; | ||||
uint8_t pullUp; //bitwise, 1 means internal pull-up resistor enabled | |||||
const uint8_t readPins; //bitwise, 1 means internal pull-up resistor enabled | const uint8_t readPins; //bitwise, 1 means internal pull-up resistor enabled | ||||
public: | public: | ||||
PortRead_MCP23S17(PortIOE& port, const uint8_t readPins) : port(port), readPins(readPins) {} | |||||
PortRead_MCP23S17(PortIOE& port, const uint8_t readPins) | |||||
: port(port), readPins(readPins) {} | |||||
void begin(const uint8_t strobeOn); | void begin(const uint8_t strobeOn); | ||||
virtual uint8_t read(); | virtual uint8_t read(); | ||||
}; | }; |
#include "PortRead_PCA9655E.h" | #include "PortRead_PCA9655E.h" | ||||
void PortRead_PCA9655E::begin() | |||||
/* | |||||
*/ | |||||
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 |
public: | public: | ||||
PortRead_PCA9655E (PortIOE& port, const uint8_t readPins) | PortRead_PCA9655E (PortIOE& port, const uint8_t readPins) | ||||
: port(port), readPins(readPins) {} | : port(port), readPins(readPins) {} | ||||
void begin(); | |||||
void begin(const uint8_t strobeOn); | |||||
virtual uint8_t read(); | virtual uint8_t read(); | ||||
}; | }; | ||||
#endif | #endif |
{ | { | ||||
public: | public: | ||||
virtual void begin()=0; | virtual void begin()=0; | ||||
virtual void write(const uint8_t pin, const bool level)=0; | |||||
virtual void write(const uint8_t strobePin, const bool pinLogicLevel)=0; | |||||
}; | }; | ||||
#endif | #endif |
void PortWrite_MCP23S17::writePort(const uint8_t registerAddr, const uint8_t data) | void PortWrite_MCP23S17::writePort(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); //data | ||||
digitalWrite(SS, HIGH); //disable Slave Select | digitalWrite(SS, HIGH); //disable Slave Select | ||||
} | } | ||||
/* begin() should be called once from sketch in setup(). | |||||
/* 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. | PortRead_MCP23S17 and PortWrite_MCP23S17 should be on seperate ports on the same MCP23S17. | ||||
Output pins can be used for strobe pins and LEDs. | Output pins can be used for strobe pins and LEDs. | ||||
*/ | */ | ||||
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 (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. | |||||
writePort(port.num, 0); //configure port direction (port.num) to output (0) | writePort(port.num, 0); //configure port direction (port.num) to output (0) | ||||
//SPI.endTransaction() is not called to release the SPI bus | |||||
// because keyboard only has one SPI device. | |||||
} | } | ||||
/* | /* | ||||
strobePin is bitwise, where pin being strobed is 1. | strobePin is bitwise, where pin being strobed is 1. | ||||
pinLogicLevel is HIGH or LOW. | pinLogicLevel is HIGH or LOW. | ||||
port.outputVal can be shared by LEDs. | port.outputVal can be shared by LEDs. | ||||
The functions does not reset the other pins so that they can be used for LEDs. | |||||
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 uint8_t pinLogicLevel) | |||||
void PortWrite_MCP23S17::write(const uint8_t strobePin, const bool pinLogicLevel) | |||||
{ | { | ||||
if (pinLogicLevel == LOW) | if (pinLogicLevel == LOW) | ||||
{ | { | ||||
port.outputVal |= strobePin; //set strobePin output to high | port.outputVal |= strobePin; //set strobePin output to high | ||||
} | } | ||||
writePort(port.num + 0x12, port.outputVal); //set GPIO port pins for stobe and LEDs | |||||
writePort(port.num + 0x12, port.outputVal); //set GPIO port pins for strobe and LEDs | |||||
} | } |
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 uint8_t level); | |||||
virtual void write(const uint8_t pin, const bool pinLogicLevel); | |||||
}; | }; | ||||
#endif | #endif |
*/ | */ | ||||
void PortWrite_PCA9655E::begin() | void PortWrite_PCA9655E::begin() | ||||
{ | { | ||||
Wire.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); //0=configure as output (for strobe pins and LED) | ||||
} | } | ||||
/* | /* | ||||
pin is bitwise, where pin being strobed is 1. | |||||
value is HIGH or LOW. | |||||
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. | Does not reset the other pins because LEDs could be using some of the pins. | ||||
Syntax is similar to Arduino DigitalWrite(). | Syntax is similar to Arduino DigitalWrite(). | ||||
*/ | */ | ||||
void PortWrite_PCA9655E::write(const uint8_t pin, const bool value) | |||||
void PortWrite_PCA9655E::write(const uint8_t strobePin, const bool pinLogicLevel) | |||||
{ | { | ||||
if (value == LOW) //if active low | |||||
if (pinLogicLevel == LOW) //if strobePin low | |||||
{ | { | ||||
port.outputVal &= ~pin; //set pin output to low | |||||
port.outputVal &= ~strobePin; //set pin output to low | |||||
} | } | ||||
else //if active high | |||||
else //if strobestrobe high | |||||
{ | { | ||||
port.outputVal |= pin; //set pin output to high | |||||
port.outputVal |= strobePin; //set pin output to high | |||||
} | } | ||||
Wire.beginTransmission(port.DEVICE_ADDR); | Wire.beginTransmission(port.DEVICE_ADDR); |
PortWrite_PCA9655E(PortIOE& port) : port(port) {} | PortWrite_PCA9655E(PortIOE& port) : port(port) {} | ||||
void begin(); | void begin(); | ||||
virtual void write(const uint8_t pin, const bool level); | |||||
virtual void write(const uint8_t strobePin, const bool pinLogicLevel); | |||||
}; | }; | ||||
#endif | #endif |
#include "Scanner_IOE.h" | #include "Scanner_IOE.h" | ||||
/* Row constructor calls every Scanner's init(). | |||||
/* init() is called once for each row from Row constructor. | |||||
*/ | */ | ||||
void Scanner_IOE::init(const uint8_t strobePin) | void Scanner_IOE::init(const uint8_t strobePin) | ||||
{ | { | ||||
//emty function | |||||
//empty | |||||
} | } | ||||
/* begin() should be called once from sketch setup(). | /* begin() should be called once from sketch setup(). | ||||
*/ | */ | ||||
void Scanner_IOE::begin() | void Scanner_IOE::begin() | ||||
{ | { | ||||
Wire.begin(); | |||||
refPortWrite.begin(); | |||||
refPortRead.begin(); | |||||
refPortWrite.begin(); //configures SPI bus | |||||
refPortRead.begin(strobeOn); | |||||
} | } | ||||
/* scan() strobes the row's strobePin and retuns state of port's input pins. | |||||
/* scan() is called on every iteration of sketch loop(). | |||||
scan() strobes the row's strobePin and retuns state of port's input pins. | |||||
Bitwise variables are 1 bit per key. | Bitwise variables are 1 bit per key. | ||||
*/ | */ | ||||
read_pins_t Scanner_IOE::scan(const uint8_t strobePin) | read_pins_t Scanner_IOE::scan(const uint8_t strobePin) | ||||
//strobe off | //strobe off | ||||
refPortWrite.write(strobePin, strobeOff); | refPortWrite.write(strobePin, strobeOff); | ||||
if (strobeOn == LOW) //if active low | |||||
{ | |||||
readState = ~readState; | |||||
} | |||||
return readState; | return readState; | ||||
} | } |
#include <Arduino.h> | #include <Arduino.h> | ||||
#include <inttypes.h> | #include <inttypes.h> | ||||
#include <Wire.h> | |||||
#include <ScannerInterface.h> | #include <ScannerInterface.h> | ||||
#include <PortWriteInterface.h> | #include <PortWriteInterface.h> | ||||
#include <PortReadInterface.h> | #include <PortReadInterface.h> |
In the above example, the "strobePin" argument is 0, but it doesn't matter what value is given. | In the above example, the "strobePin" argument is 0, but it doesn't matter what value is given. | ||||
There are three Scanner_ShiftRegsPISOSingleRow parameters. | There are three Scanner_ShiftRegsPISOSingleRow parameters. | ||||
"strobeOn" paramter is active state HIGH or LOW. | |||||
"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" paramter can be any controller pin connected to shift register's SHIFT-LOAD pin. | ||||
slaveSelect pin SS (Arduino pin 10) has the fastest scan. | slaveSelect pin SS (Arduino pin 10) has the fastest scan. |
pinMode(strobePin, OUTPUT); | pinMode(strobePin, OUTPUT); | ||||
} | } | ||||
/* scan() strobes the row's strobePin and retuns state of readPins. | |||||
/* scan() is called on every iteration of sketch loop(). | |||||
scan() strobes the row's strobePin and retuns state of readPins. | |||||
Bitwise variables are 1 bit per key. | Bitwise variables are 1 bit per key. | ||||
*/ | */ | ||||
read_pins_t Scanner_uC::scan(const uint8_t strobePin) | read_pins_t Scanner_uC::scan(const uint8_t strobePin) |
For Scanner_ShiftRegs74HC165, Scanner_ShiftRegs74HC165::readPinCount | For Scanner_ShiftRegs74HC165, Scanner_ShiftRegs74HC165::readPinCount | ||||
For Scanner_IOE, cover the last 1 bit in Scanner_IOE::strobePin | For Scanner_IOE, cover the last 1 bit in Scanner_IOE::strobePin | ||||
*/ | */ | ||||
typedef uint8_t read_pins_t; | |||||
//typedef uint8_t read_pins_t; | |||||
//typedef uint16_t read_pins_t; | //typedef uint16_t read_pins_t; | ||||
//typedef uint32_t read_pins_t; | |||||
typedef uint32_t read_pins_t; | |||||
/* SAMPLE_COUNT_MACRO is used in Debouncer_Samples.h | /* SAMPLE_COUNT_MACRO is used in Debouncer_Samples.h | ||||
SAMPLE_COUNT_MACRO = 4 is very reliable for a keyboard. | SAMPLE_COUNT_MACRO = 4 is very reliable for a keyboard. |
| Left | **0** | **1** | | Right | **0** | **1** | | | Left | **0** | **1** | | Right | **0** | **1** | | ||||
|:-----:|-------|-------| |:-----:|-------|-------| | |:-----:|-------|-------| |:-----:|-------|-------| | ||||
| **0** | a | b | | **0** | 1 | 2 | | |||||
| **1** | shift | c | | **1** | 3 | shift | | |||||
| Left | **0** | **1** | | Right | **0** | **1** | todo | |||||
|:-----:|-------|-------| |:-----:|-------|-------| | |||||
| **1** | 1 | 2 | | **1** | 3 | 4 | | | **1** | 1 | 2 | | **1** | 3 | 4 | | ||||
| **0** | a | b | | **0** | c | d | | | **0** | a | b | | **0** | c | d | | ||||
*/ | */ | ||||
// ================= INCLUDES ================== | // ================= INCLUDES ================== | ||||
#include <ScanDelay.h> | #include <ScanDelay.h> | ||||
#include <Code_Sc.h> | #include <Code_Sc.h> | ||||
#include <Row.h> | |||||
//left matrix | //left matrix | ||||
#include <Row_uC.h> | |||||
#include <Scanner_uC.h> | |||||
//right matrix | //right matrix | ||||
#include <Row_IOE.h> | |||||
#include <PortIOE.h> | #include <PortIOE.h> | ||||
#include <PortWrite_MCP23S17.h> | #include <PortWrite_MCP23S17.h> | ||||
#include <PortRead_MCP23S17.h> | #include <PortRead_MCP23S17.h> | ||||
#include <Scanner_IOE.h> | |||||
// ============ SPEED CONFIGURATION ============ | // ============ SPEED CONFIGURATION ============ | ||||
ScanDelay scanDelay(9000); | ScanDelay scanDelay(9000); | ||||
// ================ LEFT MATRIX ================ | |||||
// ---------------- ACTIVE STATE --------------- | |||||
const bool Scanner_uC::STROBE_ON = LOW; //active low | |||||
const bool Scanner_uC::STROBE_OFF = HIGH; | |||||
// ------------------- PINS -------------------- | |||||
// ================ LEFT SCANNER =============== | |||||
uint8_t readPins[] = {14, 15}; | uint8_t readPins[] = {14, 15}; | ||||
uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins); | |||||
// ================ RIGHT MATRIX =============== | |||||
const bool Scanner_Port::STROBE_ON = HIGH; //active high | |||||
const bool Scanner_Port::STROBE_OFF = LOW; | |||||
Scanner_uC scanner_L(LOW, readPins, readPinCount); | |||||
const uint8_t PortIOE::DEVICE_ADDR = 0x18; | |||||
// =============== RIGHT SCANNER =============== | |||||
const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded | |||||
// ------------------ PORT 1 ------------------- | |||||
PortIOE port1_R(1, 0); | |||||
PortWrite_MCP23S17 portWrite1_R(port1_R); | |||||
PortIOE port_A(0, 0); | |||||
PortRead_MCP23S17 portRead_A(port_A, 1<<0 | 1<<1 ); | |||||
// ------------------ PORT 0 ------------------- | |||||
PortIOE port0_R(0, 0); | |||||
PortWrite_MCP23S17 portWrite0_R(port0_R); | |||||
PortRead_MCP23S17 portRead0_R(port0_R, 1<<0 | 1<<1 ); | |||||
PortIOE port_B(1, 0); | |||||
//PortWrite_MCP23S17 portWrite_B(port_B); //for LEDs | |||||
PortWrite_MCP23S17 portWrite_B(port_B); | |||||
// =================== CODES =================== | |||||
Code_Sc s_shiftL(MODIFIERKEY_LEFT_SHIFT); | |||||
Code_Sc s_shiftR(MODIFIERKEY_RIGHT_SHIFT); | |||||
Scanner_IOE scanner_R(LOW, portWrite_B, portRead_A); | |||||
// =================== CODES =================== | |||||
Code_Sc s_a(KEY_A); | Code_Sc s_a(KEY_A); | ||||
Code_Sc s_b(KEY_B); | Code_Sc s_b(KEY_B); | ||||
Code_Sc s_c(KEY_C); | Code_Sc s_c(KEY_C); | ||||
Code_Sc s_d(KEY_D); | |||||
Code_Sc s_1(KEY_1); | Code_Sc s_1(KEY_1); | ||||
Code_Sc s_2(KEY_2); | Code_Sc s_2(KEY_2); | ||||
Code_Sc s_3(KEY_3); | Code_Sc s_3(KEY_3); | ||||
Code_Sc s_4(KEY_4); | |||||
// =================== ROWS ==================== | // =================== ROWS ==================== | ||||
// ---------------- LEFT ROWS ------------------ | // ---------------- LEFT ROWS ------------------ | ||||
Key* ptrsKeys_L0[] = { &s_a, &s_b }; | |||||
Key* ptrsKeys_L0[] = { &s_1, &s_2 }; | |||||
const uint8_t KEY_COUNT_L0 = sizeof(ptrsKeys_L0)/sizeof(*ptrsKeys_L0); | const uint8_t KEY_COUNT_L0 = sizeof(ptrsKeys_L0)/sizeof(*ptrsKeys_L0); | ||||
Row_uC row_L0(0, readPins, KEY_COUNT_L0, ptrsKeys_L0); | |||||
Row row_L0(scanner_L, 0, ptrsKeys_L0, KEY_COUNT_L0); | |||||
Key* ptrsKeys_L1[] = { &s_c, &s_shiftL }; | |||||
Key* ptrsKeys_L1[] = { &s_a, &s_b }; | |||||
const uint8_t KEY_COUNT_L1 = sizeof(ptrsKeys_L1)/sizeof(*ptrsKeys_L1); | const uint8_t KEY_COUNT_L1 = sizeof(ptrsKeys_L1)/sizeof(*ptrsKeys_L1); | ||||
Row_uC row_L1(1, readPins, KEY_COUNT_L1, ptrsKeys_L1); | |||||
Row row_L1(scanner_L, 1, ptrsKeys_L1, KEY_COUNT_L1); | |||||
// ---------------- RIGHT ROWS ----------------- | // ---------------- RIGHT ROWS ----------------- | ||||
Key* ptrsKeys_R0[] = { &s_1, &s_2 }; | |||||
Key* ptrsKeys_R0[] = { &s_3, &s_4 }; | |||||
const uint8_t KEY_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); | const uint8_t KEY_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); | ||||
Row_IOE row_R0(portWrite1_R, 1<<0, portRead0_R, KEY_COUNT_R0, ptrsKeys_R0); | |||||
Row row_R0(scanner_R, 1<<0, ptrsKeys_R0, KEY_COUNT_R0); | |||||
Key* ptrsKeys_R1[] = { &s_3, &s_shiftR }; | |||||
Key* ptrsKeys_R1[] = { &s_c, &s_d }; | |||||
const uint8_t KEY_COUNT_R1 = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1); | const uint8_t KEY_COUNT_R1 = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1); | ||||
Row_IOE row_R1(portWrite1_R, 1<<1, portRead0_R, KEY_COUNT_R1, ptrsKeys_R1); | |||||
Row row_R1(scanner_R, 1<<1, ptrsKeys_R1, KEY_COUNT_R1); | |||||
// ################### MAIN #################### | // ################### MAIN #################### | ||||
void setup() | void setup() | ||||
{ | { | ||||
delay(7000); //todo | |||||
Keyboard.begin(); | Keyboard.begin(); | ||||
Wire.begin(); //Wire.begin() must be called before port begin() | |||||
portWrite1_R.begin(); | |||||
portRead0_R.begin(); | |||||
scanner_R.begin(); | |||||
} | } | ||||
void loop() | 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 | |||||
} | } |
/* unit test for PortRead_MCP23S17 | /* unit test for PortRead_MCP23S17 | ||||
Picture of hardware is in unit_tests/PortRead_MCP23S17/PortRead_MCP23S17_bb.JPG | |||||
The setup is an MCP23S17 I/O expander on a Teensy LC controller. | The setup is an MCP23S17 I/O expander on a Teensy LC controller. | ||||
MCP23S17 port-B pins are alternately grounded and energized. | MCP23S17 port-B pins are alternately grounded and energized. | ||||
portBState is a bitwise reading of port B. | portBState is a bitwise reading of port B. | ||||
output is: 10101010 | output is: 10101010 | ||||
posted on http://arduino.stackexchange.com/questions/tagged/spi | |||||
http://arduino.stackexchange.com/questions/28792/reading-an-mcp23s17-i-o-expander-port-with-the-arduino-spi-library | |||||
*/ | */ | ||||
#include "PortIOE.h" | #include "PortIOE.h" | ||||
#include "PortRead_MCP23S17.h" | #include "PortRead_MCP23S17.h" | ||||
#include "Scanner_Port.h" | |||||
const bool Scanner_Port::STROBE_ON = LOW; | |||||
const bool Scanner_Port::STROBE_OFF = HIGH; | |||||
#include "Scanner_IOE.h" | |||||
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 portB(1, 0); | PortIOE portB(1, 0); | ||||
uint8_t portBState; //bit wise | uint8_t portBState; //bit wise | ||||
delay(6000); | delay(6000); | ||||
portBRead.begin(); | |||||
portBRead.begin(LOW); | |||||
portBState = portBRead.read(); | portBState = portBRead.read(); | ||||
Keyboard.print("portBState = "); | Keyboard.print("portBState = "); |
/* unit test for PortRead_MCP23S17 | |||||
/* unit test for PortWrite_MCP23S17 | |||||
Picture of hardware is in unit_tests/PortRead_MCP23S17/PortRead_MCP23S17_bb.JPG | |||||
The setup is an MCP23S17 I/O expander on a Teensy LC controller. | The setup is an MCP23S17 I/O expander on a Teensy LC controller. | ||||
MCP23S17 port-A GPIO pins are not connected to anything. | MCP23S17 port-A GPIO pins are not connected to anything. | ||||
Port-A GPIO-pin ouputs alternate between 0 and 3.3 volts. | Port-A GPIO-pin ouputs alternate between 0 and 3.3 volts. | ||||
Use a volt meter to measure port-A GPIO-pin ouputs. | |||||
Use a volt meter to measure port-A GPIO-pin outputs. | |||||
MCP23S17 on 3.3v does not output enough power to reliable light LEDs | MCP23S17 on 3.3v does not output enough power to reliable light LEDs | ||||
LED lights w/o resistor | LED lights w/o resistor | ||||
LED not light with 56 ohm resistor | LED not light with 56 ohm resistor | ||||
PortWrite_MCP23S17 portAWrite(portA); //PortAWrite needed for begin() | PortWrite_MCP23S17 portAWrite(portA); //PortAWrite needed for begin() | ||||
const uint8_t GPIOA = 0x12; //LEDs are on port A | |||||
//const uint8_t GPIOA = 0x12; //LEDs are on port A | |||||
void setup() | void setup() | ||||
{ | { |