diff options
-rw-r--r-- | docs/i2c_driver.md | 48 | ||||
-rw-r--r-- | platforms/avr/drivers/i2c_master.c | 56 | ||||
-rw-r--r-- | platforms/avr/drivers/i2c_master.h | 2 | ||||
-rw-r--r-- | platforms/chibios/drivers/i2c_master.c | 25 | ||||
-rw-r--r-- | platforms/chibios/drivers/i2c_master.h | 2 |
5 files changed, 130 insertions, 3 deletions
diff --git a/docs/i2c_driver.md b/docs/i2c_driver.md index 9017b44ed..95c588af4 100644 --- a/docs/i2c_driver.md +++ b/docs/i2c_driver.md | |||
@@ -187,7 +187,7 @@ Receive multiple bytes from the selected SPI device. | |||
187 | 187 | ||
188 | ### `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` | 188 | ### `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` |
189 | 189 | ||
190 | Writes to a register on the I2C device. | 190 | Writes to a register with an 8-bit address on the I2C device. |
191 | 191 | ||
192 | #### Arguments | 192 | #### Arguments |
193 | 193 | ||
@@ -208,9 +208,32 @@ Writes to a register on the I2C device. | |||
208 | 208 | ||
209 | --- | 209 | --- |
210 | 210 | ||
211 | ### `i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` | ||
212 | |||
213 | Writes to a register with a 16-bit address (big endian) on the I2C device. | ||
214 | |||
215 | #### Arguments | ||
216 | |||
217 | - `uint8_t devaddr` | ||
218 | The 7-bit I2C address of the device. | ||
219 | - `uint16_t regaddr` | ||
220 | The register address to write to. | ||
221 | - `uint8_t *data` | ||
222 | A pointer to the data to transmit. | ||
223 | - `uint16_t length` | ||
224 | The number of bytes to write. Take care not to overrun the length of `data`. | ||
225 | - `uint16_t timeout` | ||
226 | The time in milliseconds to wait for a response from the target device. | ||
227 | |||
228 | #### Return Value | ||
229 | |||
230 | `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`. | ||
231 | |||
232 | --- | ||
233 | |||
211 | ### `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` | 234 | ### `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` |
212 | 235 | ||
213 | Reads from a register on the I2C device. | 236 | Reads from a register with an 8-bit address on the I2C device. |
214 | 237 | ||
215 | #### Arguments | 238 | #### Arguments |
216 | 239 | ||
@@ -229,6 +252,27 @@ Reads from a register on the I2C device. | |||
229 | 252 | ||
230 | --- | 253 | --- |
231 | 254 | ||
255 | ### `i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` | ||
256 | |||
257 | Reads from a register with a 16-bit address (big endian) on the I2C device. | ||
258 | |||
259 | #### Arguments | ||
260 | |||
261 | - `uint8_t devaddr` | ||
262 | The 7-bit I2C address of the device. | ||
263 | - `uint16_t regaddr` | ||
264 | The register address to read from. | ||
265 | - `uint16_t length` | ||
266 | The number of bytes to read. Take care not to overrun the length of `data`. | ||
267 | - `uint16_t timeout` | ||
268 | The time in milliseconds to wait for a response from the target device. | ||
269 | |||
270 | #### Return Value | ||
271 | |||
272 | `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`. | ||
273 | |||
274 | --- | ||
275 | |||
232 | ### `i2c_status_t i2c_stop(void)` | 276 | ### `i2c_status_t i2c_stop(void)` |
233 | 277 | ||
234 | Stop the current I2C transaction. | 278 | Stop the current I2C transaction. |
diff --git a/platforms/avr/drivers/i2c_master.c b/platforms/avr/drivers/i2c_master.c index 2773e0077..111b55d6b 100644 --- a/platforms/avr/drivers/i2c_master.c +++ b/platforms/avr/drivers/i2c_master.c | |||
@@ -202,6 +202,25 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, | |||
202 | return status; | 202 | return status; |
203 | } | 203 | } |
204 | 204 | ||
205 | i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { | ||
206 | i2c_status_t status = i2c_start(devaddr | 0x00, timeout); | ||
207 | if (status >= 0) { | ||
208 | status = i2c_write(regaddr >> 8, timeout); | ||
209 | |||
210 | if (status >= 0) { | ||
211 | status = i2c_write(regaddr & 0xFF, timeout); | ||
212 | |||
213 | for (uint16_t i = 0; i < length && status >= 0; i++) { | ||
214 | status = i2c_write(data[i], timeout); | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | |||
219 | i2c_stop(); | ||
220 | |||
221 | return status; | ||
222 | } | ||
223 | |||
205 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { | 224 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { |
206 | i2c_status_t status = i2c_start(devaddr, timeout); | 225 | i2c_status_t status = i2c_start(devaddr, timeout); |
207 | if (status < 0) { | 226 | if (status < 0) { |
@@ -235,6 +254,43 @@ error: | |||
235 | return (status < 0) ? status : I2C_STATUS_SUCCESS; | 254 | return (status < 0) ? status : I2C_STATUS_SUCCESS; |
236 | } | 255 | } |
237 | 256 | ||
257 | i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { | ||
258 | i2c_status_t status = i2c_start(devaddr, timeout); | ||
259 | if (status < 0) { | ||
260 | goto error; | ||
261 | } | ||
262 | |||
263 | status = i2c_write(regaddr >> 8, timeout); | ||
264 | if (status < 0) { | ||
265 | goto error; | ||
266 | } | ||
267 | status = i2c_write(regaddr & 0xFF, timeout); | ||
268 | if (status < 0) { | ||
269 | goto error; | ||
270 | } | ||
271 | |||
272 | status = i2c_start(devaddr | 0x01, timeout); | ||
273 | |||
274 | for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { | ||
275 | status = i2c_read_ack(timeout); | ||
276 | if (status >= 0) { | ||
277 | data[i] = status; | ||
278 | } | ||
279 | } | ||
280 | |||
281 | if (status >= 0) { | ||
282 | status = i2c_read_nack(timeout); | ||
283 | if (status >= 0) { | ||
284 | data[(length - 1)] = status; | ||
285 | } | ||
286 | } | ||
287 | |||
288 | error: | ||
289 | i2c_stop(); | ||
290 | |||
291 | return (status < 0) ? status : I2C_STATUS_SUCCESS; | ||
292 | } | ||
293 | |||
238 | void i2c_stop(void) { | 294 | void i2c_stop(void) { |
239 | // transmit STOP condition | 295 | // transmit STOP condition |
240 | TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); | 296 | TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); |
diff --git a/platforms/avr/drivers/i2c_master.h b/platforms/avr/drivers/i2c_master.h index e5af73364..2d95846db 100644 --- a/platforms/avr/drivers/i2c_master.h +++ b/platforms/avr/drivers/i2c_master.h | |||
@@ -39,5 +39,7 @@ int16_t i2c_read_nack(uint16_t timeout); | |||
39 | i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); | 39 | i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); |
40 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); | 40 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); |
41 | i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); | 41 | i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); |
42 | i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
42 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | 43 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); |
44 | i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | ||
43 | void i2c_stop(void); | 45 | void i2c_stop(void); |
diff --git a/platforms/chibios/drivers/i2c_master.c b/platforms/chibios/drivers/i2c_master.c index 981f6fa06..312b4c7d0 100644 --- a/platforms/chibios/drivers/i2c_master.c +++ b/platforms/chibios/drivers/i2c_master.c | |||
@@ -102,7 +102,7 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, | |||
102 | i2cStart(&I2C_DRIVER, &i2cconfig); | 102 | i2cStart(&I2C_DRIVER, &i2cconfig); |
103 | 103 | ||
104 | uint8_t complete_packet[length + 1]; | 104 | uint8_t complete_packet[length + 1]; |
105 | for (uint8_t i = 0; i < length; i++) { | 105 | for (uint16_t i = 0; i < length; i++) { |
106 | complete_packet[i + 1] = data[i]; | 106 | complete_packet[i + 1] = data[i]; |
107 | } | 107 | } |
108 | complete_packet[0] = regaddr; | 108 | complete_packet[0] = regaddr; |
@@ -111,6 +111,21 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, | |||
111 | return chibios_to_qmk(&status); | 111 | return chibios_to_qmk(&status); |
112 | } | 112 | } |
113 | 113 | ||
114 | i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { | ||
115 | i2c_address = devaddr; | ||
116 | i2cStart(&I2C_DRIVER, &i2cconfig); | ||
117 | |||
118 | uint8_t complete_packet[length + 2]; | ||
119 | for (uint16_t i = 0; i < length; i++) { | ||
120 | complete_packet[i + 2] = data[i]; | ||
121 | } | ||
122 | complete_packet[0] = regaddr >> 8; | ||
123 | complete_packet[1] = regaddr & 0xFF; | ||
124 | |||
125 | msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout)); | ||
126 | return chibios_to_qmk(&status); | ||
127 | } | ||
128 | |||
114 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { | 129 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { |
115 | i2c_address = devaddr; | 130 | i2c_address = devaddr; |
116 | i2cStart(&I2C_DRIVER, &i2cconfig); | 131 | i2cStart(&I2C_DRIVER, &i2cconfig); |
@@ -118,4 +133,12 @@ i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16 | |||
118 | return chibios_to_qmk(&status); | 133 | return chibios_to_qmk(&status); |
119 | } | 134 | } |
120 | 135 | ||
136 | i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { | ||
137 | i2c_address = devaddr; | ||
138 | i2cStart(&I2C_DRIVER, &i2cconfig); | ||
139 | uint8_t register_packet[2] = {regaddr >> 8, regaddr & 0xFF}; | ||
140 | msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), ®ister_packet, 2, data, length, TIME_MS2I(timeout)); | ||
141 | return chibios_to_qmk(&status); | ||
142 | } | ||
143 | |||
121 | void i2c_stop(void) { i2cStop(&I2C_DRIVER); } | 144 | void i2c_stop(void) { i2cStop(&I2C_DRIVER); } |
diff --git a/platforms/chibios/drivers/i2c_master.h b/platforms/chibios/drivers/i2c_master.h index ce32fd245..5f082e9d1 100644 --- a/platforms/chibios/drivers/i2c_master.h +++ b/platforms/chibios/drivers/i2c_master.h | |||
@@ -96,5 +96,7 @@ i2c_status_t i2c_start(uint8_t address); | |||
96 | i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); | 96 | i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); |
97 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); | 97 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); |
98 | i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); | 98 | i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); |
99 | i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
99 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | 100 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); |
101 | i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | ||
100 | void i2c_stop(void); | 102 | void i2c_stop(void); |