GY-63_MS5611/libraries/TCA9555/TCA9555.cpp
2021-06-11 10:31:59 +02:00

359 lines
6.9 KiB
C++

//
// FILE: TCA9555.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.1
// PURPOSE: Arduino library for I2C TCA9555 16 channel port expander
// DATE: 2021-06-09
// URL: https://github.com/RobTillaart/TCA9555
//
// HISTORY:
// 0.1.0 2021-06-09 initial version
// 0.1.1 2021-06-10 add 16 bit interface
#include "TCA9555.h"
// REGISTERS
#define TCA9555_INPUT_PORT_REGISTER_0 0x00 // read()
#define TCA9555_INPUT_PORT_REGISTER_1 0x01
#define TCA9555_OUTPUT_PORT_REGISTER_0 0x02 // write()
#define TCA9555_OUTPUT_PORT_REGISTER_1 0x03
#define TCA9555_POLARITY_REGISTER_0 0x04 // get/setPolarity
#define TCA9555_POLARITY_REGISTER_1 0x05
#define TCA9555_CONFIGURATION_PORT_0 0x06 // pinMode
#define TCA9555_CONFIGURATION_PORT_1 0x07
TCA9555::TCA9555(uint8_t address, TwoWire *wire)
{
_address = address;
_wire = wire;
_error = TCA9555_OK;
}
#if defined(ESP8266) || defined(ESP32)
bool TCA9555::begin(const uint8_t dataPin, const uint8_t clockPin)
{
_wire = &Wire;
_wire->begin(dataPin, clockPin);
if (! isConnected()) return false;
return true;
}
#endif
bool TCA9555::begin()
{
_wire->begin();
if (! isConnected()) return false;
return true;
}
bool TCA9555::isConnected()
{
_wire->beginTransmission(_address);
return (_wire->endTransmission() == 0);
}
//////////////////////////////////////////////////////////
//
// 1 PIN INTERFACE
//
bool TCA9555::pinMode(uint8_t pin, uint8_t mode)
{
if (pin > 15)
{
_error = TCA9555_PIN_ERROR;
return false;
}
if ( (mode != INPUT) && (mode != OUTPUT) )
{
_error = TCA9555_VALUE_ERROR;
return false;
}
uint8_t CONFREG = TCA9555_CONFIGURATION_PORT_0;
if (pin > 7)
{
CONFREG = TCA9555_CONFIGURATION_PORT_1;
pin -= 8;
}
uint8_t val = readRegister(CONFREG);
uint8_t mask = 1 << pin;
if (mode == INPUT) val |= mask;
if (mode == OUTPUT) val &= ~mask;
writeRegister(CONFREG, val);
_error = TCA9555_OK;
return true;
}
bool TCA9555::digitalWrite(uint8_t pin, uint8_t value) // pin = 0..15
{
if (pin > 15)
{
_error = TCA9555_PIN_ERROR;
return false;
}
uint8_t OPR = TCA9555_OUTPUT_PORT_REGISTER_0;
if (pin > 7)
{
OPR = TCA9555_OUTPUT_PORT_REGISTER_1;
pin -= 8;
}
uint8_t val = readRegister(OPR);
uint8_t mask = 1 << pin;
if (value) val |= mask;
else val &= ~mask;
writeRegister(OPR, val);
_error = TCA9555_OK;
return true;
}
uint8_t TCA9555::digitalRead(uint8_t pin)
{
if (pin > 15)
{
_error = TCA9555_PIN_ERROR;
return TCA9555_INVALID_READ;
}
uint8_t IPR = TCA9555_INPUT_PORT_REGISTER_0;
if (pin > 7)
{
IPR = TCA9555_INPUT_PORT_REGISTER_1;
pin -= 8;
}
uint8_t val = readRegister(IPR);
uint8_t mask = 1 << pin;
_error = TCA9555_OK;
if (val & mask) return HIGH;
return LOW;
}
bool TCA9555::setPolarity(uint8_t pin, uint8_t value) // pin = 0..15
{
if (pin > 15)
{
_error = TCA9555_PIN_ERROR;
return false;
}
uint8_t POLREG = TCA9555_POLARITY_REGISTER_0;
if (pin > 7)
{
POLREG = TCA9555_POLARITY_REGISTER_1;
pin -= 8;
}
uint8_t val = readRegister(POLREG);
uint8_t mask = 1 << pin;
if (value == HIGH) val |= mask;
if (value == LOW) val &= ~mask;
writeRegister(POLREG, val);
_error = TCA9555_OK;
return true;
}
uint8_t TCA9555::getPolarity(uint8_t pin)
{
if (pin > 15)
{
_error = TCA9555_PIN_ERROR;
return false;
}
uint8_t POLREG = TCA9555_POLARITY_REGISTER_0;
if (pin > 7) POLREG = TCA9555_POLARITY_REGISTER_1;
_error = TCA9555_OK;
uint8_t mask = readRegister(POLREG);
return (mask >> pin) == 0x01;
}
//////////////////////////////////////////////////////////
//
// 8 PIN INTERFACE
//
bool TCA9555::pinMode8(uint8_t port, uint8_t mask)
{
if (port > 1)
{
_error = TCA9555_PORT_ERROR;
return false;
}
_error = TCA9555_OK;
if (port == 0) return writeRegister(TCA9555_CONFIGURATION_PORT_0, mask);
if (port == 1) return writeRegister(TCA9555_CONFIGURATION_PORT_1, mask);
return false;
}
bool TCA9555::write8(uint8_t port, uint8_t mask) // port = 0..1
{
if (port > 1)
{
_error = TCA9555_PORT_ERROR;
return false;
}
_error = TCA9555_OK;
if (port == 0) return writeRegister(TCA9555_OUTPUT_PORT_REGISTER_0, mask);
if (port == 1) return writeRegister(TCA9555_OUTPUT_PORT_REGISTER_1, mask);
return false;
}
int TCA9555::read8(uint8_t port)
{
if (port > 1)
{
_error = TCA9555_PORT_ERROR;
return TCA9555_INVALID_READ;
}
_error = TCA9555_OK;
if (port == 0) return readRegister(TCA9555_INPUT_PORT_REGISTER_0);
if (port == 1) return readRegister(TCA9555_INPUT_PORT_REGISTER_1);
return 0; // keeps compiler happy
}
bool TCA9555::setPolarity8(uint8_t port, uint8_t mask)
{
if (port > 1)
{
_error = TCA9555_PORT_ERROR;
return false;
}
_error = TCA9555_OK;
if (port == 0) return writeRegister(TCA9555_POLARITY_REGISTER_0, mask);
if (port == 1) return writeRegister(TCA9555_POLARITY_REGISTER_1, mask);
return false;
}
uint8_t TCA9555::getPolarity8(uint8_t port)
{
if (port > 1)
{
_error = TCA9555_PORT_ERROR;
return false;
}
_error = TCA9555_OK;
if (port == 0) return readRegister(TCA9555_POLARITY_REGISTER_0);
if (port == 1) return readRegister(TCA9555_POLARITY_REGISTER_1);
return 0; // keeps compiler happy
}
//////////////////////////////////////////////////////////
//
// 16 PIN INTERFACE
//
bool TCA9555::pinMode16(uint16_t mask)
{
bool b = true;
b &= pinMode8(0, mask & 0xFF);
b &= pinMode8(1, mask >> 8);
return b;
}
bool TCA9555::write16(uint16_t mask)
{
bool b = true;
b &= write8(0, mask & 0xFF);
b &= write8(1, mask >> 8);
return b;
}
uint16_t TCA9555::read16()
{
uint16_t rv = 0;
rv |= (read8(1) << 8);
rv |= read8(0);
return rv;
}
bool TCA9555::setPolarity16(uint16_t mask)
{
bool b = true;
b &= setPolarity8(0, mask & 0xFF);
b &= setPolarity8(1, mask >> 8);
return b;
}
uint8_t TCA9555::getPolarity16()
{
uint16_t rv = 0;
rv |= (getPolarity8(1) << 8);
rv |= getPolarity8(0);
return rv;
}
int TCA9555::lastError()
{
int e = _error;
_error = TCA9555_OK; // reset error after read.
return e;
}
////////////////////////////////////////////////////
//
// PRIVATE
//
bool TCA9555::writeRegister(uint8_t reg, uint8_t value)
{
_wire->beginTransmission(_address);
_wire->write(reg);
_wire->write(value);
if (_wire->endTransmission() != 0)
{
_error = TCA9555_I2C_ERROR;
return false;
}
_error = TCA9555_OK;
return true;
}
uint8_t TCA9555::readRegister(uint8_t reg)
{
_wire->beginTransmission(_address);
_wire->write(reg);
int rv = _wire->endTransmission();
if (rv != 0)
{
_error = TCA9555_I2C_ERROR;
return rv;
}
else
{
_error = TCA9555_OK;
}
_wire->requestFrom(_address, (uint8_t)1);
return _wire->read();
}
/////////////////////////////////////////////////////////////////////////////
//
// TCA9535
//
TCA9535::TCA9535(uint8_t address, TwoWire *wire)
:TCA9555(address, wire)
{
}
// -- END OF FILE --