#include <Scanner_uC.h> | #include <Scanner_uC.h> | ||||
//right matrix | //right matrix | ||||
#include <Port_MCP23018.h> | |||||
#include <Port_MCP23017.h> | |||||
//#include <Port_MCP23018.h> | |||||
#include <Scanner_IOE.h> | #include <Scanner_IOE.h> | ||||
// ============ SPEED CONFIGURATION ============ | // ============ SPEED CONFIGURATION ============ | ||||
// =============== RIGHT SCANNER =============== | // =============== RIGHT SCANNER =============== | ||||
const uint8_t IOE_ADDR = 0x20; //MCP23018 ADDR pin grounded | const uint8_t IOE_ADDR = 0x20; //MCP23018 ADDR pin grounded | ||||
Port_MCP23018 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //read pins 0, 1 | |||||
Port_MCP23018 portB(IOE_ADDR, 1, 0); | |||||
Port_MCP23017 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //read pins 0, 1 | |||||
Port_MCP23017 portB(IOE_ADDR, 1, 0); | |||||
Scanner_IOE scanner_R(LOW, portB, portA); | Scanner_IOE scanner_R(LOW, portB, portA); | ||||
// ================= RIGHT LED ================= | // ================= RIGHT LED ================= |
#include "Port_MCP23018.h" | |||||
#include "Port_MCP23017.h" | |||||
/* beginProtocol() is called from Scanner_IOE::begin(). Initiates I2C bus. | /* beginProtocol() is called from Scanner_IOE::begin(). Initiates I2C bus. | ||||
MCP23018 supports I2C SCL Clock Frequencies: 100 kHz, 400 kHz, 1000 kHz (Datasheet page 1 & 6) | |||||
MCP23017 supports I2C SCL Clock Frequencies: 100 kHz, 400 kHz, 1000 kHz (Datasheet page 1 & 6) | |||||
The electrical limitation to bus speed is bus capacitance and the length of the wires involved. | The electrical limitation to bus speed is bus capacitance and the length of the wires involved. | ||||
Longer wires require lower clock speeds. | Longer wires require lower clock speeds. | ||||
http://playground.arduino.cc/Main/WireLibraryDetailedReference > Wire.setclock() | http://playground.arduino.cc/Main/WireLibraryDetailedReference > Wire.setclock() | ||||
*/ | */ | ||||
void Port_MCP23018::beginProtocol() | |||||
void Port_MCP23017::beginProtocol() | |||||
{ | { | ||||
Wire.begin(); //initiate I2C bus to 100 kHz | Wire.begin(); //initiate I2C bus to 100 kHz | ||||
} | } | ||||
/* begin() is called from Scanner_IOE::begin(). | /* begin() is called from Scanner_IOE::begin(). | ||||
Configures port's IODIR and GPPU. | Configures port's IODIR and GPPU. | ||||
*/ | */ | ||||
void Port_MCP23018::begin(const uint8_t activeState) | |||||
void Port_MCP23017::begin(const uint8_t activeState) | |||||
{ | { | ||||
uint8_t pullUp; //bits, GPPU 0=pull-up disabled, 1=pull-up enabled | uint8_t pullUp; //bits, GPPU 0=pull-up disabled, 1=pull-up enabled | ||||
/* writeLow() sets pin output LOW. | /* writeLow() sets pin output LOW. | ||||
pin is bit pattern, where pin being set is 1. | pin is bit pattern, where pin being set is 1. | ||||
*/ | */ | ||||
void Port_MCP23018::writeLow(const uint8_t pin) | |||||
void Port_MCP23017::writeLow(const uint8_t pin) | |||||
{ | { | ||||
outputVal &= ~pin; //set pin output to low | outputVal &= ~pin; //set pin output to low | ||||
/* writeHigh() sets pin output HIGH. | /* writeHigh() sets pin output HIGH. | ||||
pin is bit pattern, where pin being set is 1. | pin is bit pattern, where pin being set is 1. | ||||
*/ | */ | ||||
void Port_MCP23018::writeHigh(const uint8_t pin) | |||||
void Port_MCP23017::writeHigh(const uint8_t pin) | |||||
{ | { | ||||
outputVal |= pin; //set pin output to high | outputVal |= pin; //set pin output to high | ||||
/* read() returns portState. | /* read() returns portState. | ||||
Only portState bits of readPins are valid. | Only portState bits of readPins are valid. | ||||
*/ | */ | ||||
uint8_t Port_MCP23018::read() | |||||
uint8_t Port_MCP23017::read() | |||||
{ | { | ||||
Wire.beginTransmission(deviceAddr); | Wire.beginTransmission(deviceAddr); | ||||
Wire.write(portNum + 0x12); //GPIO | Wire.write(portNum + 0x12); //GPIO | ||||
Wire.endTransmission(false); //MCP23018 needs false to send a restart ??really? | |||||
Wire.endTransmission(false); //MCP23017 needs false to send a restart ??todo really? | |||||
Wire.requestFrom(deviceAddr, 1u); //request one byte from input port | Wire.requestFrom(deviceAddr, 1u); //request one byte from input port | ||||
#ifndef PORT_MCP23017_H | |||||
#define PORT_MCP23017_H | |||||
#include <Arduino.h> | |||||
#include <inttypes.h> | |||||
#include <Wire.h> | |||||
#include <PortInterface.h> | |||||
/* | |||||
write pins are connected to matrix Row (strobe pin) or LED. | |||||
readPins are connected to matrix column to read which keys are pressed. | |||||
Instantiation | |||||
------------ | |||||
Example instantiation: | |||||
const uint8_t IOE_ADDR = 0x20; //all three MCP23017 ADDR pins pins grounded | |||||
Port_MCP23017 portB(IOE_ADDR, 1, 0); //all pins are set to output for strobes and LEDs | |||||
Port_MCP23017 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //pin 0 and pin 1 are set to input for reading, | |||||
//remaining pins can be used for LEDs | |||||
Diode orientation | |||||
---------------- | |||||
Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation | |||||
*/ | |||||
class Port_MCP23017 : public PortInterface | |||||
{ | |||||
private: | |||||
const uint8_t deviceAddr; | |||||
const uint8_t portNum; //port identification number, 0=A, 1=B | |||||
uint8_t outputVal; //bit pattern for strobe and LEDs | |||||
const uint8_t readPins; //bit pattern, IODIR 0=output, 1=input | |||||
public: | |||||
Port_MCP23017(const uint8_t deviceAddr, const uint8_t portNum, const uint8_t readPins) | |||||
: deviceAddr(deviceAddr), portNum(portNum), outputVal(0), readPins(readPins) {} | |||||
void beginProtocol(); | |||||
void begin(const uint8_t activeState); | |||||
virtual void writeLow(const uint8_t pin); | |||||
virtual void writeHigh(const uint8_t pin); | |||||
virtual uint8_t read(); | |||||
}; | |||||
#endif |
#ifndef PORT_MCP23018_H | |||||
#define PORT_MCP23018_H | |||||
#include <Arduino.h> | |||||
#include <inttypes.h> | |||||
#include <Wire.h> | |||||
#include <PortInterface.h> | |||||
/* | |||||
write pins are connected to matrix Row (strobe pin) or LED. | |||||
readPins are connected to matrix column to read which keys are pressed. | |||||
Port_MCP23018 can only be active low (Scanner_IOE::activeState = LOW). | |||||
Open-drain active high would not work because pull down resistors have no effect on sink. | |||||
https://en.wikipedia.org/wiki/Open_collector | |||||
Use LED_PortOpenDrain class for indicator LEDs. | |||||
Instantiation | |||||
------------ | |||||
Example instantiation: | |||||
const uint8_t IOE_ADDR = 0x20; //MCP23018 address pin grounded | |||||
Port_MCP23018 portB(IOE_ADDR, 1, 0); //all pins are set to output for strobes and LEDs | |||||
Port_MCP23018 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //pin 0 and pin 1 are set to input for reading, | |||||
//remaining pins can be used for LEDs | |||||
Diode orientation | |||||
---------------- | |||||
Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation | |||||
MCP23018 data sheet | |||||
---------------- | |||||
http://ww1.microchip.com/downloads/en/DeviceDoc/22103a.pdf | |||||
*/ | |||||
class Port_MCP23018 : public PortInterface | |||||
{ | |||||
private: | |||||
const uint8_t deviceAddr; | |||||
const uint8_t portNum; //port identification number, 0=A, 1=B | |||||
uint8_t outputVal; //bit pattern for strobe and LEDs | |||||
const uint8_t readPins; //bit pattern, IODIR 0=output, 1=input | |||||
public: | |||||
Port_MCP23018(const uint8_t deviceAddr, const uint8_t portNum, const uint8_t readPins) | |||||
: deviceAddr(deviceAddr), portNum(portNum), outputVal(0), readPins(readPins) {} | |||||
void beginProtocol(); | |||||
void begin(const uint8_t activeState); | |||||
virtual void writeLow(const uint8_t pin); | |||||
virtual void writeHigh(const uint8_t pin); | |||||
virtual uint8_t read(); | |||||
}; | |||||
#endif | |||||
#ifndef PORT_MCP23018_H | |||||
#define PORT_MCP23018_H | |||||
#include "Port_MCP23017.h" | |||||
/* | |||||
write pins are connected to matrix Row (strobe pin) or LED. | |||||
readPins are connected to matrix column to read which keys are pressed. | |||||
Port_MCP23018 can only be active low (Scanner_IOE::activeState = LOW). | |||||
Open-drain active high would not work because pull down resistors have no effect on sink. | |||||
https://en.wikipedia.org/wiki/Open_collector | |||||
Use LED_PortOpenDrain class for indicator LEDs. | |||||
Example instantiation: | |||||
const uint8_t IOE_ADDR = 0x20; //MCP23018 address pin grounded | |||||
Port_MCP23018 portB(IOE_ADDR, 1, 0); //all pins are set to output for strobes and LEDs | |||||
Port_MCP23018 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //pin 0 and pin 1 are set to input for reading, | |||||
//remaining pins can be used for LEDs | |||||
Diode orientation | |||||
---------------- | |||||
Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation | |||||
*/ | |||||
class Port_MCP23018 : public Port_MCP23017 | |||||
{ | |||||
public: | |||||
Port_MCP23018(const uint8_t deviceAddr, const uint8_t portNum, const uint8_t readPins) | |||||
: Port_MCP23017(deviceAddr, portNum, readPins) {} | |||||
}; | |||||
#endif |