PortIOE | PortIOE | ||||
PortWriteInterface | |||||
/ \ | |||||
PortWrite_PCA9655E PortWrite_MCP23S17 (one PortWrite class for each IOE type) | |||||
PortInterface | |||||
/ \ | |||||
Port_PCA9655E Port_MCP23S17 (one Port class for each IOE type) | |||||
PortReadInterface | |||||
/ \ | |||||
PortRead_PCA9655E PortRead_MCP23S17 (one PortRead class for each IOE type) | |||||
_ LED _ | |||||
LEDInterface | |||||
/ \ | / \ | ||||
LED_uC LED_PCA9655E | |||||
LED_uC LED_IOE | |||||
DebouncerInterface | DebouncerInterface |
#include "PortMCP23S17.h" | |||||
#include "Port_MCP23S17.h" | |||||
/* transfer() writes data to registerAddr, reads portSate from registerAddr, and returns portState. | /* transfer() writes data to registerAddr, reads portSate from registerAddr, and returns portState. | ||||
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. | ||||
*/ | */ | ||||
uint8_t PortMCP23S17::transfer(const uint8_t command, const uint8_t registerAddr, | |||||
uint8_t Port_MCP23S17::transfer(const uint8_t command, const uint8_t registerAddr, | |||||
const uint8_t data) | const uint8_t data) | ||||
{ | { | ||||
uint8_t portState; //bit pattern | uint8_t portState; //bit pattern | ||||
/* begin() is called from Scanner_IOE::begin(). Initiates SPI bus. | /* begin() is called from Scanner_IOE::begin(). Initiates SPI bus. | ||||
*/ | */ | ||||
void PortMCP23S17::beginProtocol() | |||||
void Port_MCP23S17::beginProtocol() | |||||
{ | { | ||||
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 | ||||
strobeOn is logic level of strobe on, HIGH or LOW | strobeOn is logic level of strobe on, HIGH or LOW | ||||
configure IODIR and GPPU. | configure IODIR and GPPU. | ||||
*/ | */ | ||||
void PortMCP23S17::begin(const uint8_t strobeOn) | |||||
void Port_MCP23S17::begin(const uint8_t strobeOn) | |||||
{ | { | ||||
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 | ||||
logicLevel is HIGH or LOW. | logicLevel is HIGH or LOW. | ||||
write() does not overwrite the other pins. | write() does not overwrite the other pins. | ||||
*/ | */ | ||||
void PortMCP23S17::write(const uint8_t pin, const bool logicLevel) | |||||
void Port_MCP23S17::write(const uint8_t pin, const bool logicLevel) | |||||
{ | { | ||||
if (logicLevel == LOW) | if (logicLevel == LOW) | ||||
{ | { | ||||
/* read() returns portState. Only portState pins with pull resistors are valid. | /* read() returns portState. Only portState pins with pull resistors are valid. | ||||
*/ | */ | ||||
uint8_t PortMCP23S17::read() | |||||
uint8_t Port_MCP23S17::read() | |||||
{ | { | ||||
return transfer( (deviceAddr << 1) | 1, portNum + 0x12, 0); //read from GPIO | return transfer( (deviceAddr << 1) | 1, portNum + 0x12, 0); //read from GPIO | ||||
} | } |
#ifndef PORTMCP23S17_H | |||||
#define PORTMCP23S17_H | |||||
#ifndef PORT_MCP23S17_H | |||||
#define PORT_MCP23S17_H | |||||
#include <Arduino.h> | #include <Arduino.h> | ||||
#include <inttypes.h> | #include <inttypes.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
Instantiation | Instantiation | ||||
------------ | ------------ | ||||
MCP23S17 datasheet identifies ports by letters, while class PortMCP23S17 uses portNum | |||||
MCP23S17 datasheet identifies ports by letters, while class Port_MCP23S17 uses portNum | |||||
for port A, use portNum=0 | for port A, use portNum=0 | ||||
for port B, use portNum=1 | for port B, use portNum=1 | ||||
readPins parameter configures port's pins. | readPins parameter configures port's pins. | ||||
------------------ | ------------------ | ||||
http://www.onsemi.com/pub_link/Collateral/MCP23S17-D.PDF | http://www.onsemi.com/pub_link/Collateral/MCP23S17-D.PDF | ||||
*/ | */ | ||||
class PortMCP23S17 : public PortInterface | |||||
class Port_MCP23S17 : public PortInterface | |||||
{ | { | ||||
private: | private: | ||||
const uint8_t deviceAddr; | const uint8_t deviceAddr; | ||||
const uint8_t readPins; //bit pattern, 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); | uint8_t transfer(const uint8_t command, const uint8_t registerAddr, const uint8_t data); | ||||
public: | public: | ||||
PortMCP23S17(const uint8_t deviceAddr, const uint8_t portNum, const uint8_t readPins) | |||||
Port_MCP23S17(const uint8_t deviceAddr, const uint8_t portNum, const uint8_t readPins) | |||||
: deviceAddr(deviceAddr), portNum(portNum), outputVal(0), readPins(readPins) {} | : deviceAddr(deviceAddr), portNum(portNum), outputVal(0), readPins(readPins) {} | ||||
void beginProtocol(); | void beginProtocol(); | ||||
void begin(const uint8_t strobeOn); | void begin(const uint8_t strobeOn); |
#include "PortPCA9655E.h" | |||||
#include "Port_PCA9655E.h" | |||||
/* begin() is called from Scanner_IOE::begin(). Initiates I2C bus. | /* begin() is called from Scanner_IOE::begin(). Initiates I2C bus. | ||||
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 PortPCA9655E::beginProtocol() | |||||
void Port_PCA9655E::beginProtocol() | |||||
{ | { | ||||
Wire.begin(); //initiate I2C bus to 100 kHz | Wire.begin(); //initiate I2C bus to 100 kHz | ||||
//Wire.setClock(400000L); //set I2C bus to 400 kHz (have not tested 400 kHz) | //Wire.setClock(400000L); //set I2C bus to 400 kHz (have not tested 400 kHz) | ||||
Configures read pins to input. | Configures read pins to input. | ||||
strobeOn is not used because PCA9655E has no pull-up resistors. | strobeOn is not used because PCA9655E has no pull-up resistors. | ||||
*/ | */ | ||||
void PortPCA9655E::begin(const uint8_t strobeOn) | |||||
void Port_PCA9655E::begin(const uint8_t strobeOn) | |||||
{ | { | ||||
Wire.beginTransmission(deviceAddr); | Wire.beginTransmission(deviceAddr); | ||||
Wire.write(portNum + 6); //configuration byte command | Wire.write(portNum + 6); //configuration byte command | ||||
logicLevel is HIGH or LOW. | logicLevel is HIGH or LOW. | ||||
write() does not overwrite the other pins. | write() does not overwrite the other pins. | ||||
*/ | */ | ||||
void PortPCA9655E::write(const uint8_t pin, const bool logicLevel) | |||||
void Port_PCA9655E::write(const uint8_t pin, const bool logicLevel) | |||||
{ | { | ||||
if (logicLevel == LOW) | if (logicLevel == LOW) | ||||
{ | { | ||||
/* read() returns portState. | /* read() returns portState. | ||||
Only portState bits of readPins are valid. | Only portState bits of readPins are valid. | ||||
*/ | */ | ||||
uint8_t PortPCA9655E::read() | |||||
uint8_t Port_PCA9655E::read() | |||||
{ | { | ||||
Wire.beginTransmission(deviceAddr); | Wire.beginTransmission(deviceAddr); | ||||
Wire.write(portNum); //input byte command | Wire.write(portNum); //input byte command |
#ifndef PORTPCA9655E_H | |||||
#define PORTPCA9655E_H | |||||
#ifndef PORT_PCA9655E_H | |||||
#define PORT_PCA9655E_H | |||||
#include <Arduino.h> | #include <Arduino.h> | ||||
#include <inttypes.h> | #include <inttypes.h> | ||||
#include <Wire.h> | #include <Wire.h> | ||||
------------ | ------------ | ||||
Example instantiation: | Example instantiation: | ||||
const uint8_t IOE_ADDR = 0x20; //PCA9655E address, all 3 ADDR pins are grounded | const uint8_t IOE_ADDR = 0x20; //PCA9655E address, all 3 ADDR pins are grounded | ||||
PortPCA9655E portB(IOE_ADDR, 1, 0); //all pins are set to output for strobes and LEDs | |||||
PortPCA9655E portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //first two pins are set to input for reading, | |||||
Port_PCA9655E portB(IOE_ADDR, 1, 0); //all pins are set to output for strobes and LEDs | |||||
Port_PCA9655E portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //first two pins are set to input for reading, | |||||
//remaining pins can be used for LEDs | //remaining pins can be used for LEDs | ||||
Diode orientation | Diode orientation | ||||
http://www.onsemi.com/pub_link/Collateral/PCA9655E-D.PDF | http://www.onsemi.com/pub_link/Collateral/PCA9655E-D.PDF | ||||
*/ | */ | ||||
class PortPCA9655E : public PortInterface | |||||
class Port_PCA9655E : public PortInterface | |||||
{ | { | ||||
private: | private: | ||||
const uint8_t deviceAddr; | const uint8_t deviceAddr; | ||||
uint8_t outputVal; //bit pattern for strobe and LEDs | uint8_t outputVal; //bit pattern for strobe and LEDs | ||||
const uint8_t readPins; //bit pattern, IODIR 0=output, 1=input | const uint8_t readPins; //bit pattern, IODIR 0=output, 1=input | ||||
public: | public: | ||||
PortPCA9655E(const uint8_t deviceAddr, const uint8_t portNum, const uint8_t readPins) | |||||
Port_PCA9655E(const uint8_t deviceAddr, const uint8_t portNum, const uint8_t readPins) | |||||
: deviceAddr(deviceAddr), portNum(portNum), outputVal(0), readPins(readPins) {} | : deviceAddr(deviceAddr), portNum(portNum), outputVal(0), readPins(readPins) {} | ||||
void beginProtocol(); | void beginProtocol(); | ||||
void begin(const uint8_t strobeOn); | void begin(const uint8_t strobeOn); |