Device driver for TCA9554A, which is I2C GPIO expander IC.

Dependents:   AKDP-RevD7_014

Revision:
0:402147fa55f6
Child:
2:0d772298e874
--- /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), &regAddr, 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;
+}
+