amiro-os / components / bus / i2c / mux / pca9544.tpp @ 8c99e03a
History | View | Annotate | Download (2.469 KB)
1 | 58fe0e0b | Thomas Schöpping | #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 */ |