@@ -1,36 +1,34 @@ | |||
#include "PortMCP23S17.h" | |||
/* transfer() writes data to registerAddr, reads portSate from registerAddr, and returns portState. | |||
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. | |||
*/ | |||
uint8_t PortMCP23S17::transfer(const uint8_t command, const uint8_t registerAddr, | |||
const uint8_t data) | |||
{ | |||
uint8_t portState; //bit pattern | |||
SPI.beginTransaction( SPISettings(5000000, MSBFIRST, SPI_MODE0) ); //control SPI bus, 5 MHz | |||
digitalWrite(SS, LOW); //enable Slave Select | |||
SPI.transfer(command); //write or read command | |||
SPI.transfer(registerAddr); //register address to write data to | |||
portState = SPI.transfer(data); //write data, read portState | |||
digitalWrite(SS, HIGH); //disable Slave Select | |||
SPI.endTransaction(); | |||
return portState; | |||
} | |||
/* begin() is called from Scanner_IOE::begin(). | |||
Initiates SPI bus and configures I/O pins for read and write. | |||
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. | |||
/* begin() is called from Scanner_IOE::begin(). Initiates SPI bus. | |||
*/ | |||
void PortMCP23S17::beginProtocol() | |||
{ | |||
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 two IOEs are used, move beginTransaction() endTransaction() to write() read() functions | |||
} | |||
/* begin() is called from Scanner_IOE::begin(). |
@@ -6,8 +6,8 @@ | |||
#include <PortInterface.h> | |||
/* | |||
readPins are connected to matrix col | |||
write pin is connected to matrix Row (strobe pin) or LED. | |||
write pins are connected to matrix Row (strobe pin) or LED. | |||
readPins are connected to matrix column to read which keys are pressed. | |||
Slave Select is hardcoded to Arduino Pin 10. | |||
Arduino Pin 10 avoids the speed penalty of digitalWrite. | |||
@@ -20,9 +20,9 @@ MCP23S17 datasheet identifies ports by letters, while class PortMCP23S17 uses po | |||
readPins parameter configures port's pins. | |||
Example instantiation: | |||
const uint8_t Port_MCP23S17::DEVICE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins grounded | |||
Port_MCP23S17 portB(1, 0); //all pins are set to output for strobes and LEDs | |||
Port_MCP23S17 portA(0, 1<<0 | 1<<1 ); //1 pins are set to input for reading, | |||
const uint8_t IOE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded | |||
Port_MCP23S17 portB(IOE_ADDR, 1, 0); //all pins are set to output for strobes and LEDs | |||
Port_MCP23S17 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //first two pins are set to input for reading, | |||
//remaining pins can be used for LEDs | |||
Diode orientation | |||
@@ -39,7 +39,7 @@ class PortMCP23S17 : public PortInterface | |||
const uint8_t deviceAddr; | |||
const uint8_t portNum; //port identification number | |||
uint8_t outputVal; //bit pattern for strobe and LEDs | |||
const uint8_t readPins; //bits, IODIR 0=output, 1=input | |||
const uint8_t readPins; //bit pattern, IODIR 0=output, 1=input | |||
uint8_t transfer(const uint8_t command, const uint8_t registerAddr, const uint8_t data); | |||
public: | |||
PortMCP23S17(const uint8_t deviceAddr, const uint8_t portNum, const uint8_t readPins) |
@@ -21,9 +21,7 @@ This layout table shows left and right matrices: | |||
#include <Scanner_uC.h> | |||
//right matrix | |||
#include <PortIOE.h> | |||
#include <PortWrite_MCP23S17.h> | |||
#include <PortRead_MCP23S17.h> | |||
#include <PortMCP23S17.h> | |||
#include <Scanner_IOE.h> | |||
// ============ SPEED CONFIGURATION ============ | |||
@@ -33,37 +31,28 @@ ScanDelay scanDelay(9000); | |||
Left matrix rows work the same as the ones in keybrd_2_single-layer.ino | |||
*/ | |||
uint8_t readPins[] = {14, 15}; | |||
const uint8_t READPIN_COUNT = sizeof(readPins)/sizeof(*readPins); | |||
const uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins); | |||
Scanner_uC scanner_L(LOW, readPins, READPIN_COUNT); | |||
Scanner_uC scanner_L(LOW, readPins, readPinCount); | |||
/* =============== RIGHT SCANNER =============== | |||
The right matrix is scanned by an I/O expander. | |||
The I/O expander device address is configured by hardware pins. | |||
DEVICE_ADDR is a static variable of class PortIOE. | |||
The MCP23S17 address is set by grounding or powering pins. | |||
*/ | |||
const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address with all 3 ADDR pins are grounded | |||
const uint8_t IOE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded | |||
/* | |||
port_B stobes the row while port_A reads the colums. | |||
port_A is assigned port identification number 0. | |||
port_A is assigned to portRead, which reads port_A pins 0 and 1. | |||
Normally all strobe pins are on one port, and all the read pins are on the other port. | |||
In this example, portB stobes the row while portA reads the colums. | |||
PortMCP23S17 constructor parameters are: deviceAddr, portNum, readPins | |||
readPins is a bit pattern, where 0=output, 1=input. | |||
In portA, the first two pins are set to input for reading. | |||
"<<" (bit shift left) and "|" (OR) are bitwise operators. | |||
Pin numbers to be read are to the right of "1<<" and delimited by "|". | |||
*/ | |||
PortIOE port_A(0); | |||
PortRead_MCP23S17 portRead(port_A, 1<<0 | 1<<1 ); | |||
/* | |||
port_B is assigned port identification number 1. | |||
port_B is assigned to portWrite. | |||
*/ | |||
PortIOE port_B(1); | |||
PortWrite_MCP23S17 portWrite(port_B); | |||
Scanner_IOE scanner_R(LOW, portWrite, portRead); | |||
PortMCP23S17 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); | |||
PortMCP23S17 portB(IOE_ADDR, 1, 0); | |||
Scanner_IOE scanner_R(LOW, portB, portA); | |||
// =================== CODES =================== | |||
Code_Sc s_a(KEY_A); |
@@ -34,7 +34,7 @@ This layout table shows left and right matrices: | |||
// ============ SPEED CONFIGURATION ============ | |||
ScanDelay scanDelay(9000); | |||
// ================ LEFT =============== | |||
// ================= LEFT PINS ================= | |||
// ---------------- LEFT SCANNER --------------- | |||
uint8_t readPins[] = {14, 15}; | |||
const uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins); | |||
@@ -44,7 +44,7 @@ Scanner_uC scanner_L(LOW, readPins, readPinCount); | |||
// ----------------- LEFT LEDs ----------------- | |||
LED_uC LED_CapsLck(21); | |||
// =============== RIGHT =============== | |||
// ================ RIGHT PINS ================= | |||
// --------------- RIGHT SCANNER --------------- | |||
const uint8_t IOE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded | |||
PortMCP23S17 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //for read and LED |
@@ -35,7 +35,8 @@ The MCP23S17 with all address pins grounded has an device address of 0x20. | |||
The MCP23S17's /RESET pin is connected to VDD. | |||
The MCP23S17 I/O expander has two ports. Each port has eight pins. | |||
Port B is connected to the matrix's rows. Port A is connected to the matrix's columns. | |||
Port B is connected to the matrix's rows. | |||
Port A is connected to the matrix's columns. | |||
Building a split keyboard with I/O Expander | |||
------------------------------------------- |