Device driver for TCA9554A, which is I2C GPIO expander IC.
Diff: tca9554a.cpp
- Revision:
- 0:402147fa55f6
- Child:
- 2:0d772298e874
diff -r 000000000000 -r 402147fa55f6 tca9554a.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tca9554a.cpp Wed May 04 00:40:25 2016 +0000 @@ -0,0 +1,125 @@ +#include "tca9554a.h" + +#define LEN_ONE_BYTE 1 +#define LEN_TWO_BYTE 2 + +TCA9554A::TCA9554A(I2C *conn, SlaveAddress addr) { + connection = conn; + slaveAddress = addr; +} + +TCA9554A::Status TCA9554A::read(RegisterAddress addr, uint8_t *buf) { + char regAddr = (char)addr; + + // Sets the register address to be read. + if (connection->write((slaveAddress << 1), ®Addr, LEN_ONE_BYTE) != 0) { + return ERROR_I2C_WRITE; + } + + // Reads the register value. + char val = 0; + if (connection->read((slaveAddress << 1), &val, LEN_ONE_BYTE) != 0) { + return ERROR_I2C_READ; + } + + *buf = (uint8_t)val; + + return SUCCESS; +} + +TCA9554A::Status TCA9554A::write(RegisterAddress addr, uint8_t val) { + char buf[LEN_TWO_BYTE]; + + buf[0] = (char)addr; + buf[1] = (char)val; + + // Writes to the devices. + if (connection->write(slaveAddress, buf, LEN_TWO_BYTE) != 0) { + return ERROR_I2C_WRITE; + } + + return SUCCESS; +} + +TCA9554A::Status TCA9554A::configurePort(Port port, Direction dir, PolarityInversion pol) { + Status status; + uint8_t buf = 0; + + // Reads the current configuration register value. + if ((status=read(REG_ADDR_CONFIG, &buf)) != SUCCESS) { + return status; + } + + // Modifies the specified bit. + buf = (((~port) & buf) | dir); + + // Writes back to the configuration register. + if ((status=write(REG_ADDR_CONFIG, buf)) != SUCCESS) { + return status; + } + + // Reads the current polarity inversion register value. + if ((status=read(REG_ADDR_POLARITY, &buf)) != SUCCESS) { + return status; + } + + // Modifies the specified bit. + buf = (((~port) & buf) | pol); + + // Writes back to the polarity inversion register. + if ((status=write(REG_ADDR_POLARITY, buf)) != SUCCESS) { + return status; + } + + return status; +} + +TCA9554A::Status TCA9554A::getPortLevel(LogicLevel *val, Port port) { + Status status; + uint8_t buf = 0; + + // Reads the input register + if ((status=read(REG_ADDR_INPUT, &buf)) != SUCCESS) { + return status; + } + + *val = (((port & buf) > 0) ? HIGH : LOW); + + return status; +} + +TCA9554A::Status TCA9554A::setPortLevel(Port port, LogicLevel val) { + Status status; + + // Get the current register setting. + uint8_t buf = 0; + if ((status=read(REG_ADDR_OUTPUT, &buf)) != SUCCESS) { + return status; + } + + // Modify the specified bit by port. + buf = ((buf & (~port)) | val); + + // Write back the modified value to the register. + if ((status=write(REG_ADDR_OUTPUT, buf)) != SUCCESS) { + return status; + } + + return status; +} + +TCA9554A::Status TCA9554A::getPortDirection(Direction *dir, Port port) { + Status status; + + // Get the current register setting. + uint8_t buf = 0; + if ((status=read(REG_ADDR_OUTPUT, &buf)) != SUCCESS) { + return status; + } + + // Gets the value of the specified port. + *dir = ((buf & port) > 0) ? DIR_INPUT : DIR_OUTPUT; + + return status; +} +