/* keybrd_PCA9655E.ino | |||||
Teensy 2.0 controller PCA9655E I/O expander | |||||
| Left | **0** | **1** | | Right | **0** | **1** | | |||||
|:-----:|-------|-------| |:-----:|-------|-------| | |||||
| **1** | 1 | 2 | | **1** | 3 | 4 | | |||||
| **0** | a | b | | **0** | c | d | | |||||
*/ | |||||
// ################## GLOBAL ################### | |||||
// ================= INCLUDES ================== | |||||
#include <ScanDelay.h> | |||||
#include <Code_Sc.h> | |||||
//left matrix | |||||
#include <Row_uC.h> | |||||
//right matrix | |||||
#include <Row_IOE.h> | |||||
#include <PortIOE.h> | |||||
#include <PortWrite_PCA9655E.h> | |||||
#include <PortRead_PCA9655E.h> | |||||
// ============ SPEED CONFIGURATION ============ | |||||
ScanDelay scanDelay(9000); | |||||
// =============== LEFT uC MATRIX ============== | |||||
const bool Scanner_uC::STROBE_ON = HIGH; //active high | |||||
const bool Scanner_uC::STROBE_OFF = LOW; | |||||
uint8_t readPins_L[] = {0, 1}; | |||||
// ============== RIGHT IOE MATRIX ============= | |||||
const bool Scanner_Port::STROBE_ON = HIGH; //active high | |||||
const bool Scanner_Port::STROBE_OFF = LOW; | |||||
const uint8_t PortIOE::DEVICE_ADDR = 0x18; | |||||
// ------------------ PORT 1 ------------------- | |||||
PortIOE port1_R(1, 0); | |||||
PortWrite_PCA9655E portWrite1_R(port1_R); | |||||
// ------------------ PORT 0 ------------------- | |||||
PortIOE port0_R(0, 0); | |||||
PortWrite_PCA9655E portWrite0_R(port0_R); | |||||
PortRead_PCA9655E portRead0_R(port0_R, 1<<0 | 1<<1 ); | |||||
// =================== CODES =================== | |||||
Code_Sc s_a(KEY_A); | |||||
Code_Sc s_b(KEY_B); | |||||
Code_Sc s_c(KEY_C); | |||||
Code_Sc s_d(KEY_D); | |||||
Code_Sc s_1(KEY_1); | |||||
Code_Sc s_2(KEY_2); | |||||
Code_Sc s_3(KEY_3); | |||||
Code_Sc s_4(KEY_4); | |||||
// =================== ROWS ==================== | |||||
// ---------------- LEFT ROWS ------------------ | |||||
Key* ptrsKeys_L0[] = { &s_1, &s_2 }; | |||||
uint8_t KEY_COUNT_L0 = sizeof(ptrsKeys_L0)/sizeof(*ptrsKeys_L0); | |||||
Row_uC row_L0(21, readPins_L, KEY_COUNT_L0, ptrsKeys_L0); | |||||
Key* ptrsKeys_L1[] = { &s_a, &s_b }; | |||||
uint8_t KEY_COUNT_L1 = sizeof(ptrsKeys_L1)/sizeof(*ptrsKeys_L1); | |||||
Row_uC row_L1(20, readPins_L, KEY_COUNT_L1, ptrsKeys_L1); | |||||
// ---------------- RIGHT ROWS ----------------- | |||||
Key* ptrsKeys_R0[] = { &s_3, &s_4 }; | |||||
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); | |||||
Key* ptrsKeys_R1[] = { &s_c, &s_d }; | |||||
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); | |||||
// ################### MAIN #################### | |||||
void setup() | |||||
{ | |||||
Keyboard.begin(); | |||||
Wire.begin(); //Wire.begin() must be called before port begin() | |||||
portWrite1_R.begin(); | |||||
portRead0_R.begin(); | |||||
} | |||||
void loop() | |||||
{ | |||||
//left matrix | |||||
row_L0.process(); | |||||
row_L1.process(); | |||||
//right matrix | |||||
row_R0.process(); | |||||
row_R1.process(); | |||||
scanDelay.delay(); | |||||
//debug.print_scans_per_second(); | |||||
//debug.print_microseconds_per_scan(); | |||||
} |
class PortWriteInterface; | class PortWriteInterface; | ||||
class PortReadInterface; | class PortReadInterface; | ||||
/* Row_IOE is a row connected to an Input/Output Expander. | |||||
Configuration and Instantiation instructions are in keybrd/src/Row_IOE.h | |||||
/* Row_IOE is a row connected to an I/O Expander. | |||||
Configuration and Instantiation instructions are in keybrd/src/Row_uC.h | |||||
*/ | */ | ||||
class Row_IOE : public Row | class Row_IOE : public Row | ||||
{ | { | ||||
private: | private: | ||||
Scanner_Port scanner; | Scanner_Port scanner; | ||||
Debouncer_Samples debouncer; | Debouncer_Samples debouncer; | ||||
const uint8_t readPinCount; //number of read pins | |||||
const uint8_t readPinCount; | |||||
public: | public: | ||||
Row_IOE(PortWriteInterface& refPortWrite, const uint8_t strobePin, | Row_IOE(PortWriteInterface& refPortWrite, const uint8_t strobePin, | ||||
PortReadInterface& refPortRead, const uint8_t readPinCount, Key *const ptrsKeys[]) | PortReadInterface& refPortRead, const uint8_t readPinCount, Key *const ptrsKeys[]) |
/* keybrd_4c_split_with_IOE_annotated.ino | |||||
/* keybrd_4c_split_with_IOE.ino | |||||
| Left | **0** | **1** | | Right | **0** | **1** | | | Left | **0** | **1** | | Right | **0** | **1** | | ||||
|:-----:|-------|-------| |:-----:|-------|-------| | |:-----:|-------|-------| |:-----:|-------|-------| |
/* this works | |||||
The setup is an MCP23S17 I/O expander on a Teensy LC controller. | |||||
MCP23S17 port B pins are alternately grounded and energized. | |||||
portBState is a bitwise reading of port B. | |||||
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 <SPI.h> | |||||
const uint8_t ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded | |||||
const uint8_t OPCODE_READ = (ADDR << 1 | 0x01); //MCP23S17 opcode read has LSB set | |||||
const uint8_t IODIRB = 0x01; | |||||
const uint8_t GPIOB = 0x13; | |||||
uint8_t portBState = 0; //bit wise | |||||
void setup() | |||||
{ | |||||
Serial.begin(9600); | |||||
delay(1000); | |||||
pinMode(SS, OUTPUT); //configure controller's Slave Select pin to output | |||||
digitalWrite(SS, HIGH); //disable Slave Select | |||||
SPI.begin(); | |||||
//IODIRB register is already configured to input by default | |||||
SPI.beginTransaction(SPISettings (SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE0)); //gain control of SPI bus | |||||
digitalWrite(SS, LOW); //enable Slave Select | |||||
SPI.transfer(OPCODE_READ); //read command | |||||
SPI.transfer(GPIOB); //register address to read data from | |||||
portBState = SPI.transfer(0); //save the data (0 is dummy data to send) | |||||
digitalWrite(SS, HIGH); //disable Slave Select | |||||
SPI.endTransaction(); //release the SPI bus | |||||
Serial.println(portBState, BIN); //should print 10101010 | |||||
} | |||||
void loop() { } |
/* this works with volt meter (MCP23S17 on 3.3v does not output enough power for LEDs) | |||||
LED lights w/o resistor, not light with 56 ohm resistor | |||||
blink LED on MCP23S17 port A pin | |||||
from Example 41.1 - Microchip MCP23017 with Arduino | |||||
http://tronixstuff.com/tutorials > chapter 41 | |||||
http://tronixstuff.com/2011/08/26/tutorial-maximising-your-arduinos-io-ports/ | |||||
John Boxall | CC by-sa-nc | |||||
from http://69.5.26.215/forum/?id=10945&page=3 #35 | |||||
modified to test MCP23S17 (SPI) using syntax from | |||||
http://arduino.stackexchange.com/questions/16348/how-do-you-use-spi-on-an-arduino | |||||
> | |||||
SPISettings from http://arduino.stackexchange.com/questions/14191/mcp23s17-programming-iodirx-register-works-in-loop-but-not-in-setup | |||||
*/ | |||||
#include <SPI.h> | |||||
const uint8_t ADDR = 0x20; //MCP23S17 address, all ADDR pins are grounded | |||||
const uint8_t OPCODE_WRITE = (ADDR << 1); //MCP23S17 opcode write has LSB clear | |||||
const uint8_t IODIRA = 0x00; //LEDs are on port A | |||||
const uint8_t GPIOA = 0x12; | |||||
uint8_t LED_state = 0; //bit wise | |||||
void IOEWrite(const uint8_t registerAddr, const uint8_t data) | |||||
{ | |||||
SPI.beginTransaction(SPISettings (SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE0)); //slower clock | |||||
digitalWrite(SS, LOW); //enable Slave Select | |||||
SPI.transfer(OPCODE_WRITE); //write command | |||||
SPI.transfer(registerAddr); //register address to write data to | |||||
SPI.transfer(data); //data | |||||
digitalWrite(SS, HIGH); //disable Slave Select | |||||
SPI.endTransaction(); //release the SPI bus | |||||
} | |||||
void setup() | |||||
{ | |||||
Serial.begin(9600); | |||||
pinMode(SS, OUTPUT); //configure controller's Slave Select pin to output | |||||
digitalWrite(SS, HIGH); //disable Slave Select | |||||
SPI.begin(); | |||||
IOEWrite(IODIRA, 0x00); //configure IODIRA register to output | |||||
} | |||||
void loop() | |||||
{ | |||||
IOEWrite(GPIOA, LED_state); //set all GPIOA pins | |||||
delay(2000); | |||||
//Serial.println(LED_state, BIN); //prints alternating 0 and 11111111 | |||||
LED_state = ~LED_state; //toggle LED on/off | |||||
} |