diff options
author | Ryan <fauxpark@gmail.com> | 2021-10-07 10:29:35 +1100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-07 10:29:35 +1100 |
commit | bc1f5ef38172bc77a802fb779e5da60f800c231b (patch) | |
tree | 104a22b67c21e08c33a9d2ddedf04abc9710d5e4 /platforms/avr | |
parent | 875e44faac31e5985e764c7b117ad4938e2e6027 (diff) | |
download | qmk_firmware-bc1f5ef38172bc77a802fb779e5da60f800c231b.tar.gz qmk_firmware-bc1f5ef38172bc77a802fb779e5da60f800c231b.zip |
i2c_master: Add support for reading/writing to 16-bit registers (#14289)
Diffstat (limited to 'platforms/avr')
-rw-r--r-- | platforms/avr/drivers/i2c_master.c | 56 | ||||
-rw-r--r-- | platforms/avr/drivers/i2c_master.h | 2 |
2 files changed, 58 insertions, 0 deletions
diff --git a/platforms/avr/drivers/i2c_master.c b/platforms/avr/drivers/i2c_master.c index 2773e00778..111b55d6b0 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, return status; } +i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { + i2c_status_t status = i2c_start(devaddr | 0x00, timeout); + if (status >= 0) { + status = i2c_write(regaddr >> 8, timeout); + + if (status >= 0) { + status = i2c_write(regaddr & 0xFF, timeout); + + for (uint16_t i = 0; i < length && status >= 0; i++) { + status = i2c_write(data[i], timeout); + } + } + } + + i2c_stop(); + + return status; +} + i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { i2c_status_t status = i2c_start(devaddr, timeout); if (status < 0) { @@ -235,6 +254,43 @@ error: return (status < 0) ? status : I2C_STATUS_SUCCESS; } +i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { + i2c_status_t status = i2c_start(devaddr, timeout); + if (status < 0) { + goto error; + } + + status = i2c_write(regaddr >> 8, timeout); + if (status < 0) { + goto error; + } + status = i2c_write(regaddr & 0xFF, timeout); + if (status < 0) { + goto error; + } + + status = i2c_start(devaddr | 0x01, timeout); + + for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { + status = i2c_read_ack(timeout); + if (status >= 0) { + data[i] = status; + } + } + + if (status >= 0) { + status = i2c_read_nack(timeout); + if (status >= 0) { + data[(length - 1)] = status; + } + } + +error: + i2c_stop(); + + return (status < 0) ? status : I2C_STATUS_SUCCESS; +} + void i2c_stop(void) { // transmit STOP condition TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); diff --git a/platforms/avr/drivers/i2c_master.h b/platforms/avr/drivers/i2c_master.h index e5af73364b..2d95846db5 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); i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); +i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); +i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); void i2c_stop(void); |