aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/i2c_driver.md48
-rw-r--r--platforms/avr/drivers/i2c_master.c56
-rw-r--r--platforms/avr/drivers/i2c_master.h2
-rw-r--r--platforms/chibios/drivers/i2c_master.c25
-rw-r--r--platforms/chibios/drivers/i2c_master.h2
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
190Writes to a register on the I2C device. 190Writes 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
213Writes 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
213Reads from a register on the I2C device. 236Reads 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
257Reads 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
234Stop the current I2C transaction. 278Stop 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
205i2c_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
205i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { 224i2c_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
257i2c_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
288error:
289 i2c_stop();
290
291 return (status < 0) ? status : I2C_STATUS_SUCCESS;
292}
293
238void i2c_stop(void) { 294void 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);
39i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); 39i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
40i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); 40i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
41i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); 41i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
42i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
42i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 43i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
44i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
43void i2c_stop(void); 45void 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
114i2c_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
114i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { 129i2c_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
136i2c_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), &register_packet, 2, data, length, TIME_MS2I(timeout));
141 return chibios_to_qmk(&status);
142}
143
121void i2c_stop(void) { i2cStop(&I2C_DRIVER); } 144void 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);
96i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); 96i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
97i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); 97i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
98i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); 98i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
99i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
99i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 100i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
101i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
100void i2c_stop(void); 102void i2c_stop(void);