amiro-os / components / bus / i2c / mux / pca9544.tpp @ 58fe0e0b
History | View | Annotate | Download (2.469 KB)
| 1 |
#include <chdebug.h> |
|---|---|
| 2 |
|
| 3 |
namespace amiro {
|
| 4 |
|
| 5 |
template <bool ignore_deselect> |
| 6 |
PCA9544<ignore_deselect>:: |
| 7 |
PCA9544(I2CDriver *driver, const uint8_t master_id) : |
| 8 |
I2CMultiplexer(driver), |
| 9 |
master_id(master_id), |
| 10 |
selected(-1) {
|
| 11 |
|
| 12 |
chDbgCheck(master_id <= 0x07u, "PCA9544 ctor master_id"); |
| 13 |
this->tx_params.addr = (PCA9544::SLA | this->master_id); |
| 14 |
this->rx_params.addr = (PCA9544::SLA | this->master_id); |
| 15 |
|
| 16 |
} |
| 17 |
|
| 18 |
template <bool ignore_deselect> |
| 19 |
msg_t |
| 20 |
PCA9544<ignore_deselect>:: |
| 21 |
select(const uint8_t bus_id) {
|
| 22 |
|
| 23 |
chDbgCheck(bus_id <= 0x03u, "PCA9544 select bus_id"); |
| 24 |
|
| 25 |
uint8_t tmp = PCA9544::BUS_ON | bus_id; |
| 26 |
|
| 27 |
if (bus_id == this->selected) |
| 28 |
return RDY_OK; |
| 29 |
|
| 30 |
this->selected = bus_id; |
| 31 |
|
| 32 |
this->tx_params.txbuf = &tmp; |
| 33 |
this->tx_params.txbytes = 1; |
| 34 |
this->tx_params.rxbytes = 0; |
| 35 |
return this->masterTransmit(&this->tx_params); // TODO select timeout |
| 36 |
|
| 37 |
} |
| 38 |
|
| 39 |
template <> |
| 40 |
inline msg_t |
| 41 |
PCA9544<true>:: |
| 42 |
deselect() {
|
| 43 |
|
| 44 |
return RDY_OK; |
| 45 |
|
| 46 |
} |
| 47 |
|
| 48 |
template <> |
| 49 |
inline msg_t |
| 50 |
PCA9544<false>:: |
| 51 |
deselect() {
|
| 52 |
|
| 53 |
uint8_t tmp = PCA9544::BUS_OFF; |
| 54 |
|
| 55 |
this->selected = -1; |
| 56 |
this->tx_params.txbuf = &tmp; |
| 57 |
this->tx_params.txbytes = 1; |
| 58 |
this->tx_params.rxbytes = 0; |
| 59 |
return this->masterTransmit(&this->tx_params); // TODO select timeout |
| 60 |
|
| 61 |
} |
| 62 |
|
| 63 |
template <bool ignore_deselect> |
| 64 |
uint8_t |
| 65 |
PCA9544<ignore_deselect>:: |
| 66 |
getInterruptSource() {
|
| 67 |
|
| 68 |
uint8_t tmp; |
| 69 |
this->rx_params.rxbuf = &tmp; |
| 70 |
this->rx_params.rxbytes = 1; |
| 71 |
this->masterReceive(&this->rx_params); // TODO select timeout |
| 72 |
return tmp; |
| 73 |
|
| 74 |
} |
| 75 |
|
| 76 |
template <bool ignore_deselect> |
| 77 |
uint8_t |
| 78 |
PCA9544<ignore_deselect>:: |
| 79 |
getCheck(void) {
|
| 80 |
|
| 81 |
const int8_t rxBufferMask = 0x07; /** We are only intrested in the first three bits*/ |
| 82 |
int8_t txBuffer, resTx, resRx; |
| 83 |
uint8_t rxBuffer[2]; |
| 84 |
|
| 85 |
// Copy the data, because some virtual driver can write into it |
| 86 |
I2CTxParams tx_params = this->tx_params; |
| 87 |
I2CRxParams rx_params = this->rx_params; |
| 88 |
|
| 89 |
tx_params.txbuf = (uint8_t*) &txBuffer; |
| 90 |
tx_params.txbytes = 1; |
| 91 |
tx_params.rxbytes = 0; |
| 92 |
rx_params.rxbuf = rxBuffer; |
| 93 |
rx_params.rxbytes = 2; /** This is a bug workaround: 1 byte is impossible to read*/ |
| 94 |
|
| 95 |
for (txBuffer = rxBufferMask; txBuffer >= 0x00; txBuffer--) {
|
| 96 |
this->acquireBus(); |
| 97 |
resTx = this->masterTransmit(&tx_params); |
| 98 |
resRx = this->masterReceive(&rx_params); |
| 99 |
this->releaseBus(); |
| 100 |
// Failed to transmit |
| 101 |
if (resTx != RDY_OK || resRx != RDY_OK) {
|
| 102 |
break; |
| 103 |
} |
| 104 |
// Check data written to MUX register |
| 105 |
if (txBuffer != (rxBuffer[0] & rxBufferMask)) {
|
| 106 |
break; |
| 107 |
} |
| 108 |
} |
| 109 |
|
| 110 |
// Data analysis |
| 111 |
if (txBuffer != -1) {
|
| 112 |
return PCA9544::CHECK_FAIL; |
| 113 |
} else {
|
| 114 |
return PCA9544::CHECK_OK; |
| 115 |
} |
| 116 |
} |
| 117 |
|
| 118 |
} /* amiro */ |