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