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

Dependents:   AKDP-RevD7_014

Committer:
coisme
Date:
Thu May 26 21:04:28 2016 +0000
Revision:
2:0d772298e874
Parent:
0:402147fa55f6
Bug fixed. I2C write operation and bit calculation.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
coisme 0:402147fa55f6 1 #include "tca9554a.h"
coisme 0:402147fa55f6 2
coisme 0:402147fa55f6 3 #define LEN_ONE_BYTE 1
coisme 0:402147fa55f6 4 #define LEN_TWO_BYTE 2
coisme 0:402147fa55f6 5
coisme 0:402147fa55f6 6 TCA9554A::TCA9554A(I2C *conn, SlaveAddress addr) {
coisme 0:402147fa55f6 7 connection = conn;
coisme 0:402147fa55f6 8 slaveAddress = addr;
coisme 0:402147fa55f6 9 }
coisme 0:402147fa55f6 10
coisme 0:402147fa55f6 11 TCA9554A::Status TCA9554A::read(RegisterAddress addr, uint8_t *buf) {
coisme 0:402147fa55f6 12 char regAddr = (char)addr;
coisme 0:402147fa55f6 13
coisme 0:402147fa55f6 14 // Sets the register address to be read.
coisme 0:402147fa55f6 15 if (connection->write((slaveAddress << 1), &regAddr, LEN_ONE_BYTE) != 0) {
coisme 0:402147fa55f6 16 return ERROR_I2C_WRITE;
coisme 0:402147fa55f6 17 }
coisme 0:402147fa55f6 18
coisme 0:402147fa55f6 19 // Reads the register value.
coisme 0:402147fa55f6 20 char val = 0;
coisme 2:0d772298e874 21 if (connection->read(((slaveAddress << 1) | 0x01), &val, LEN_ONE_BYTE) != 0) {
coisme 0:402147fa55f6 22 return ERROR_I2C_READ;
coisme 0:402147fa55f6 23 }
coisme 0:402147fa55f6 24
coisme 0:402147fa55f6 25 *buf = (uint8_t)val;
coisme 0:402147fa55f6 26
coisme 0:402147fa55f6 27 return SUCCESS;
coisme 0:402147fa55f6 28 }
coisme 0:402147fa55f6 29
coisme 0:402147fa55f6 30 TCA9554A::Status TCA9554A::write(RegisterAddress addr, uint8_t val) {
coisme 0:402147fa55f6 31 char buf[LEN_TWO_BYTE];
coisme 0:402147fa55f6 32
coisme 0:402147fa55f6 33 buf[0] = (char)addr;
coisme 0:402147fa55f6 34 buf[1] = (char)val;
coisme 0:402147fa55f6 35
coisme 0:402147fa55f6 36 // Writes to the devices.
coisme 2:0d772298e874 37 if (connection->write((slaveAddress << 1), buf, LEN_TWO_BYTE) != 0) {
coisme 0:402147fa55f6 38 return ERROR_I2C_WRITE;
coisme 0:402147fa55f6 39 }
coisme 2:0d772298e874 40
coisme 0:402147fa55f6 41 return SUCCESS;
coisme 0:402147fa55f6 42 }
coisme 0:402147fa55f6 43
coisme 0:402147fa55f6 44 TCA9554A::Status TCA9554A::configurePort(Port port, Direction dir, PolarityInversion pol) {
coisme 0:402147fa55f6 45 Status status;
coisme 0:402147fa55f6 46 uint8_t buf = 0;
coisme 0:402147fa55f6 47
coisme 0:402147fa55f6 48 // Reads the current configuration register value.
coisme 0:402147fa55f6 49 if ((status=read(REG_ADDR_CONFIG, &buf)) != SUCCESS) {
coisme 0:402147fa55f6 50 return status;
coisme 0:402147fa55f6 51 }
coisme 0:402147fa55f6 52
coisme 0:402147fa55f6 53 // Modifies the specified bit.
coisme 0:402147fa55f6 54 buf = (((~port) & buf) | dir);
coisme 0:402147fa55f6 55
coisme 0:402147fa55f6 56 // Writes back to the configuration register.
coisme 0:402147fa55f6 57 if ((status=write(REG_ADDR_CONFIG, buf)) != SUCCESS) {
coisme 0:402147fa55f6 58 return status;
coisme 0:402147fa55f6 59 }
coisme 0:402147fa55f6 60
coisme 0:402147fa55f6 61 // Reads the current polarity inversion register value.
coisme 0:402147fa55f6 62 if ((status=read(REG_ADDR_POLARITY, &buf)) != SUCCESS) {
coisme 0:402147fa55f6 63 return status;
coisme 0:402147fa55f6 64 }
coisme 0:402147fa55f6 65
coisme 0:402147fa55f6 66 // Modifies the specified bit.
coisme 0:402147fa55f6 67 buf = (((~port) & buf) | pol);
coisme 0:402147fa55f6 68
coisme 0:402147fa55f6 69 // Writes back to the polarity inversion register.
coisme 0:402147fa55f6 70 if ((status=write(REG_ADDR_POLARITY, buf)) != SUCCESS) {
coisme 0:402147fa55f6 71 return status;
coisme 0:402147fa55f6 72 }
coisme 0:402147fa55f6 73
coisme 0:402147fa55f6 74 return status;
coisme 0:402147fa55f6 75 }
coisme 0:402147fa55f6 76
coisme 0:402147fa55f6 77 TCA9554A::Status TCA9554A::getPortLevel(LogicLevel *val, Port port) {
coisme 0:402147fa55f6 78 Status status;
coisme 0:402147fa55f6 79 uint8_t buf = 0;
coisme 0:402147fa55f6 80
coisme 0:402147fa55f6 81 // Reads the input register
coisme 0:402147fa55f6 82 if ((status=read(REG_ADDR_INPUT, &buf)) != SUCCESS) {
coisme 0:402147fa55f6 83 return status;
coisme 0:402147fa55f6 84 }
coisme 0:402147fa55f6 85
coisme 0:402147fa55f6 86 *val = (((port & buf) > 0) ? HIGH : LOW);
coisme 0:402147fa55f6 87
coisme 0:402147fa55f6 88 return status;
coisme 0:402147fa55f6 89 }
coisme 0:402147fa55f6 90
coisme 0:402147fa55f6 91 TCA9554A::Status TCA9554A::setPortLevel(Port port, LogicLevel val) {
coisme 0:402147fa55f6 92 Status status;
coisme 0:402147fa55f6 93
coisme 0:402147fa55f6 94 // Get the current register setting.
coisme 0:402147fa55f6 95 uint8_t buf = 0;
coisme 0:402147fa55f6 96 if ((status=read(REG_ADDR_OUTPUT, &buf)) != SUCCESS) {
coisme 0:402147fa55f6 97 return status;
coisme 0:402147fa55f6 98 }
coisme 0:402147fa55f6 99
coisme 0:402147fa55f6 100 // Modify the specified bit by port.
coisme 2:0d772298e874 101 buf = ((buf & (~port) | (port * val)));
coisme 0:402147fa55f6 102
coisme 0:402147fa55f6 103 // Write back the modified value to the register.
coisme 0:402147fa55f6 104 if ((status=write(REG_ADDR_OUTPUT, buf)) != SUCCESS) {
coisme 0:402147fa55f6 105 return status;
coisme 0:402147fa55f6 106 }
coisme 0:402147fa55f6 107
coisme 0:402147fa55f6 108 return status;
coisme 0:402147fa55f6 109 }
coisme 0:402147fa55f6 110
coisme 0:402147fa55f6 111 TCA9554A::Status TCA9554A::getPortDirection(Direction *dir, Port port) {
coisme 0:402147fa55f6 112 Status status;
coisme 0:402147fa55f6 113
coisme 0:402147fa55f6 114 // Get the current register setting.
coisme 0:402147fa55f6 115 uint8_t buf = 0;
coisme 0:402147fa55f6 116 if ((status=read(REG_ADDR_OUTPUT, &buf)) != SUCCESS) {
coisme 0:402147fa55f6 117 return status;
coisme 0:402147fa55f6 118 }
coisme 0:402147fa55f6 119
coisme 0:402147fa55f6 120 // Gets the value of the specified port.
coisme 0:402147fa55f6 121 *dir = ((buf & port) > 0) ? DIR_INPUT : DIR_OUTPUT;
coisme 0:402147fa55f6 122
coisme 0:402147fa55f6 123 return status;
coisme 0:402147fa55f6 124 }
coisme 0:402147fa55f6 125