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:
1:e02d9e33b9f3
Bug fixed. I2C write operation and bit calculation.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
coisme 0:402147fa55f6 1 #ifndef __TCA9554A_H__
coisme 0:402147fa55f6 2 #define __TCA9554A_H__
coisme 0:402147fa55f6 3
coisme 0:402147fa55f6 4 #include "mbed.h"
coisme 0:402147fa55f6 5
coisme 1:e02d9e33b9f3 6 /**
coisme 1:e02d9e33b9f3 7 * Device driver for TCA9554A.
coisme 1:e02d9e33b9f3 8 * @note TCA9554A is a GPIO expander with I2C interface.
coisme 1:e02d9e33b9f3 9 * Example:
coisme 1:e02d9e33b9f3 10 * @code
coisme 1:e02d9e33b9f3 11 * #include "mbed.h"
coisme 1:e02d9e33b9f3 12 * #include "tca9554a.h"
coisme 1:e02d9e33b9f3 13 *
coisme 1:e02d9e33b9f3 14 * #define I2C_SPEED_100KHZ 100000
coisme 1:e02d9e33b9f3 15 * #define I2C_SPEED_400KHZ 400000
coisme 1:e02d9e33b9f3 16 *
coisme 1:e02d9e33b9f3 17 * int main(void) {
coisme 1:e02d9e33b9f3 18 * // Instanciate I2C
coisme 1:e02d9e33b9f3 19 * I2C i2c(I2C_SDA0, I2C_SCL0);
coisme 1:e02d9e33b9f3 20 * i2c.frequency(I2C_SPEED_400KHZ);
coisme 1:e02d9e33b9f3 21 *
coisme 1:e02d9e33b9f3 22 * // Instanciate TCA9554A
coisme 1:e02d9e33b9f3 23 * // Suppose that the slave address of TCA9554A on your board is 38H.
coisme 1:e02d9e33b9f3 24 * TCA9554A tca9554a(&i2c, TCA9554A::SLAVE_ADDRESS_38H);
coisme 1:e02d9e33b9f3 25 *
coisme 1:e02d9e33b9f3 26 * // Configure the GPIO ports.
coisme 1:e02d9e33b9f3 27 * // Default direction of the ports are input and polarity inversion is disabled.
coisme 1:e02d9e33b9f3 28 * // Here, sets port 3 to output and port 5 to input with polarity inversion.
coisme 1:e02d9e33b9f3 29 * if (tca9554a.configurePort(TCA9554A::PORT_3, TCA9554A::DIR_OUTPUT)!= TCA9554A::SUCCESS) {
coisme 1:e02d9e33b9f3 30 * // @TODO: error handling
coisme 1:e02d9e33b9f3 31 * }
coisme 1:e02d9e33b9f3 32 * if (tca9554a.configurePort(TCA9554A::PORT_5, TCA9554A::DIR_INPUT, TCA9554A::INVERTING) != TCA9554A::SUCCESS) {
coisme 1:e02d9e33b9f3 33 * // @TODO: error handling
coisme 1:e02d9e33b9f3 34 * }
coisme 1:e02d9e33b9f3 35 *
coisme 1:e02d9e33b9f3 36 * while(true) {
coisme 1:e02d9e33b9f3 37 * LogicLevel val = TCA9554A::LOW;
coisme 1:e02d9e33b9f3 38 * // Reads the value from port 5 and sets the read value to port 3.
coisme 1:e02d9e33b9f3 39 * // Note that the read value is inverted from the actual input level,
coisme 1:e02d9e33b9f3 40 * // because the port 5 is configured as INVERTING at the initialization process above.
coisme 1:e02d9e33b9f3 41 * if (tca9554a.getPortLevel(&val, TCA9554A::PORT_5) != SUCCESS) {
coisme 1:e02d9e33b9f3 42 * // @TODO: error handling
coisme 1:e02d9e33b9f3 43 * }
coisme 1:e02d9e33b9f3 44 * if (tca9554a.setPortLevel(TCA9554A::PORT_3, val) != SUCCESS) {
coisme 1:e02d9e33b9f3 45 * // @TODO: error handling
coisme 1:e02d9e33b9f3 46 * }
coisme 1:e02d9e33b9f3 47 * }
coisme 1:e02d9e33b9f3 48 * }
coisme 1:e02d9e33b9f3 49 * @endcode
coisme 1:e02d9e33b9f3 50 */
coisme 0:402147fa55f6 51 class TCA9554A
coisme 0:402147fa55f6 52 {
coisme 0:402147fa55f6 53 public:
coisme 0:402147fa55f6 54 /**
coisme 0:402147fa55f6 55 * Device's slave address.
coisme 0:402147fa55f6 56 */
coisme 0:402147fa55f6 57 typedef enum {
coisme 0:402147fa55f6 58 SLAVE_ADDRESS_38H = 0x38, /**< Slave address 0x38, when (A2)(A1)(A0) = 000. */
coisme 0:402147fa55f6 59 SLAVE_ADDRESS_39H = 0x39, /**< Slave address 0x39, when (A2)(A1)(A0) = 001. */
coisme 0:402147fa55f6 60 SLAVE_ADDRESS_3AH = 0x3A, /**< Slave address 0x3A, when (A2)(A1)(A0) = 010. */
coisme 0:402147fa55f6 61 SLAVE_ADDRESS_3BH = 0x3B, /**< Slave address 0x3B, when (A2)(A1)(A0) = 011. */
coisme 0:402147fa55f6 62 SLAVE_ADDRESS_3CH = 0x3C, /**< Slave address 0x3C, when (A2)(A1)(A0) = 100. */
coisme 0:402147fa55f6 63 SLAVE_ADDRESS_3DH = 0x3D, /**< Slave address 0x3D, when (A2)(A1)(A0) = 101. */
coisme 0:402147fa55f6 64 SLAVE_ADDRESS_3EH = 0x3E, /**< Slave address 0x3E, when (A2)(A1)(A0) = 110. */
coisme 0:402147fa55f6 65 SLAVE_ADDRESS_3FH = 0x3F, /**< Slave address 0x3F, when (A2)(A1)(A0) = 111. */
coisme 0:402147fa55f6 66 } SlaveAddress;
coisme 0:402147fa55f6 67
coisme 0:402147fa55f6 68 /**
coisme 1:e02d9e33b9f3 69 * Result status of function execution.
coisme 0:402147fa55f6 70 */
coisme 0:402147fa55f6 71 typedef enum {
coisme 0:402147fa55f6 72 SUCCESS, /**< The function processed successfully. */
coisme 0:402147fa55f6 73 ERROR_I2C_READ, /**< Error related to I2C read. */
coisme 0:402147fa55f6 74 ERROR_I2C_WRITE, /**< Error related to I2C write. */
coisme 0:402147fa55f6 75 ERROR, /**< General Error */
coisme 0:402147fa55f6 76 } Status;
coisme 0:402147fa55f6 77
coisme 0:402147fa55f6 78 /**
coisme 1:e02d9e33b9f3 79 * GPIO port number.
coisme 0:402147fa55f6 80 */
coisme 0:402147fa55f6 81 typedef enum {
coisme 0:402147fa55f6 82 PORT_0 = 0x01, /**< Port 0. */
coisme 0:402147fa55f6 83 PORT_1 = 0x02, /**< Port 1. */
coisme 0:402147fa55f6 84 PORT_2 = 0x04, /**< Port 2. */
coisme 0:402147fa55f6 85 PORT_3 = 0x08, /**< Port 3. */
coisme 0:402147fa55f6 86 PORT_4 = 0x10, /**< Port 4. */
coisme 0:402147fa55f6 87 PORT_5 = 0x20, /**< Port 5. */
coisme 0:402147fa55f6 88 PORT_6 = 0x40, /**< Port 6. */
coisme 0:402147fa55f6 89 PORT_7 = 0x80, /**< Port 7. */
coisme 0:402147fa55f6 90 } Port;
coisme 0:402147fa55f6 91
coisme 0:402147fa55f6 92 /**
coisme 0:402147fa55f6 93 * Port value.
coisme 0:402147fa55f6 94 */
coisme 0:402147fa55f6 95 typedef enum {
coisme 1:e02d9e33b9f3 96 LOW = 0, /**< Indicates low level. */
coisme 1:e02d9e33b9f3 97 HIGH = 1, /**< Indicates high level. */
coisme 0:402147fa55f6 98 } LogicLevel;
coisme 0:402147fa55f6 99
coisme 0:402147fa55f6 100 /**
coisme 0:402147fa55f6 101 * Direction of a port.
coisme 0:402147fa55f6 102 */
coisme 0:402147fa55f6 103 typedef enum {
coisme 1:e02d9e33b9f3 104 DIR_OUTPUT = 0x00, /**< Output. */
coisme 1:e02d9e33b9f3 105 DIR_INPUT = 0x01, /**< Input. */
coisme 0:402147fa55f6 106 } Direction;
coisme 0:402147fa55f6 107
coisme 0:402147fa55f6 108 /**
coisme 0:402147fa55f6 109 * Flag for enabling input polarity inversion.
coisme 0:402147fa55f6 110 */
coisme 0:402147fa55f6 111 typedef enum {
coisme 1:e02d9e33b9f3 112 NON_INVERTING = 0x00, /**< Input polarity is not inverted. */
coisme 1:e02d9e33b9f3 113 INVERTING = 0x01, /**< Input polarity is inverted. */
coisme 0:402147fa55f6 114 } PolarityInversion;
coisme 0:402147fa55f6 115
coisme 0:402147fa55f6 116 /**
coisme 0:402147fa55f6 117 * Constructor. In default, all the ports are set as input.
coisme 1:e02d9e33b9f3 118 * @param conn Pointer to an instance of I2C.
coisme 1:e02d9e33b9f3 119 * @param addr Slave address of this device.
coisme 0:402147fa55f6 120 */
coisme 0:402147fa55f6 121 TCA9554A(I2C *conn, SlaveAddress addr);
coisme 0:402147fa55f6 122
coisme 0:402147fa55f6 123
coisme 0:402147fa55f6 124 /**
coisme 0:402147fa55f6 125 * Sets port properties.
coisme 0:402147fa55f6 126 * @param port Port number to be configured.
coisme 0:402147fa55f6 127 * @param dir Direction to be set for the specified port.
coisme 0:402147fa55f6 128 * @param pol Polarity inversion to be set for the specified port.
coisme 0:402147fa55f6 129 * @return SUCCESS when succeeded. Other value will be returned when error.
coisme 0:402147fa55f6 130 */
coisme 0:402147fa55f6 131 Status configurePort(Port port, Direction dir, PolarityInversion pol = NON_INVERTING);
coisme 0:402147fa55f6 132
coisme 0:402147fa55f6 133 /**
coisme 0:402147fa55f6 134 * Gets the logic level from the specified port. If the polarity inversion is enabled at the port,
coisme 0:402147fa55f6 135 * this function returns the inverted value. For example, the input voltage of a port is high level
coisme 0:402147fa55f6 136 * and polarity inversion setting for the port is enabled, then LOW will be obtained from this function.
coisme 0:402147fa55f6 137 * @param val Logic level of the specified port.
coisme 0:402147fa55f6 138 * @param port Port to be read.
coisme 0:402147fa55f6 139 * @return SUCCESS when succeeded. Other value will be returned when error.
coisme 0:402147fa55f6 140 */
coisme 0:402147fa55f6 141 Status getPortLevel(LogicLevel *val, Port port);
coisme 0:402147fa55f6 142
coisme 0:402147fa55f6 143 /**
coisme 0:402147fa55f6 144 * Sets output level of the specified port. If the direction of the specified port is input,
coisme 0:402147fa55f6 145 * this operation has no effect.
coisme 0:402147fa55f6 146 * @param port Port to be set.
coisme 0:402147fa55f6 147 * @param val Logic level to be set.
coisme 0:402147fa55f6 148 * @return SUCCESS when succeeded. Other value will be returned when error.
coisme 0:402147fa55f6 149 */
coisme 0:402147fa55f6 150 Status setPortLevel(Port port, LogicLevel val);
coisme 0:402147fa55f6 151
coisme 0:402147fa55f6 152 /**
coisme 0:402147fa55f6 153 * Gets port direction of the specified port.
coisme 0:402147fa55f6 154 * @param dir Pointer to the buffer direction to be stored.
coisme 0:402147fa55f6 155 * @param port Port to be checked direction.
coisme 0:402147fa55f6 156 * @return SUCCESS when succeeded. Other value will be returned when error.
coisme 0:402147fa55f6 157 */
coisme 0:402147fa55f6 158 Status getPortDirection(Direction *dir, Port port);
coisme 0:402147fa55f6 159
coisme 0:402147fa55f6 160 private:
coisme 0:402147fa55f6 161 I2C *connection; /**< Pointer to an I2C object. */
coisme 0:402147fa55f6 162 uint8_t slaveAddress; /**< Holds the device's slave address. */
coisme 0:402147fa55f6 163
coisme 0:402147fa55f6 164 typedef enum {
coisme 0:402147fa55f6 165 REG_ADDR_INPUT = 0x00,
coisme 0:402147fa55f6 166 REG_ADDR_OUTPUT = 0x01,
coisme 0:402147fa55f6 167 REG_ADDR_POLARITY = 0x02,
coisme 0:402147fa55f6 168 REG_ADDR_CONFIG = 0x03,
coisme 0:402147fa55f6 169 } RegisterAddress;
coisme 0:402147fa55f6 170
coisme 0:402147fa55f6 171 /**
coisme 0:402147fa55f6 172 * Reads one byte from the specified register address.
coisme 0:402147fa55f6 173 * @param addr Register address to be read.
coisme 0:402147fa55f6 174 * @param buf Buffer to store the read value.
coisme 0:402147fa55f6 175 * @return SUCCESS when succeeded. Other value will be returned when error.
coisme 0:402147fa55f6 176 */
coisme 0:402147fa55f6 177 Status read(RegisterAddress addr, uint8_t *buf);
coisme 0:402147fa55f6 178
coisme 0:402147fa55f6 179 /**
coisme 0:402147fa55f6 180 * Write one byte to the specified register address.
coisme 0:402147fa55f6 181 * @param addr Register address to be read.
coisme 0:402147fa55f6 182 * @param buf Value to be written into the specified register.
coisme 0:402147fa55f6 183 * @return SUCCESS when succeeded. Other value will be returned when error.
coisme 0:402147fa55f6 184 */
coisme 0:402147fa55f6 185 Status write(RegisterAddress addr, uint8_t val);
coisme 0:402147fa55f6 186 };
coisme 0:402147fa55f6 187
coisme 0:402147fa55f6 188 #endif