Device driver for TCA9554A, which is I2C GPIO expander IC.
tca9554a.h@2:0d772298e874, 2016-05-26 (annotated)
- 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?
User | Revision | Line number | New 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 |