mirror of
https://github.com/openstenoproject/qmk
synced 2024-11-12 19:44:43 +00:00
i2c_master: Add support for reading/writing to 16-bit registers (#14289)
This commit is contained in:
parent
875e44faac
commit
bc1f5ef381
5 changed files with 130 additions and 3 deletions
|
@ -187,7 +187,7 @@ Receive multiple bytes from the selected SPI device.
|
||||||
|
|
||||||
### `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
|
### `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
|
||||||
|
|
||||||
Writes to a register on the I2C device.
|
Writes to a register with an 8-bit address on the I2C device.
|
||||||
|
|
||||||
#### Arguments
|
#### Arguments
|
||||||
|
|
||||||
|
@ -208,9 +208,32 @@ Writes to a register on the I2C device.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### `i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
|
||||||
|
|
||||||
|
Writes to a register with a 16-bit address (big endian) on the I2C device.
|
||||||
|
|
||||||
|
#### Arguments
|
||||||
|
|
||||||
|
- `uint8_t devaddr`
|
||||||
|
The 7-bit I2C address of the device.
|
||||||
|
- `uint16_t regaddr`
|
||||||
|
The register address to write to.
|
||||||
|
- `uint8_t *data`
|
||||||
|
A pointer to the data to transmit.
|
||||||
|
- `uint16_t length`
|
||||||
|
The number of bytes to write. Take care not to overrun the length of `data`.
|
||||||
|
- `uint16_t timeout`
|
||||||
|
The time in milliseconds to wait for a response from the target device.
|
||||||
|
|
||||||
|
#### Return Value
|
||||||
|
|
||||||
|
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, 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)`
|
||||||
|
|
||||||
Reads from a register on the I2C device.
|
Reads from a register with an 8-bit address on the I2C device.
|
||||||
|
|
||||||
#### Arguments
|
#### Arguments
|
||||||
|
|
||||||
|
@ -229,6 +252,27 @@ Reads from a register on the I2C device.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### `i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
|
||||||
|
|
||||||
|
Reads from a register with a 16-bit address (big endian) on the I2C device.
|
||||||
|
|
||||||
|
#### Arguments
|
||||||
|
|
||||||
|
- `uint8_t devaddr`
|
||||||
|
The 7-bit I2C address of the device.
|
||||||
|
- `uint16_t regaddr`
|
||||||
|
The register address to read from.
|
||||||
|
- `uint16_t length`
|
||||||
|
The number of bytes to read. Take care not to overrun the length of `data`.
|
||||||
|
- `uint16_t timeout`
|
||||||
|
The time in milliseconds to wait for a response from the target device.
|
||||||
|
|
||||||
|
#### Return Value
|
||||||
|
|
||||||
|
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `i2c_status_t i2c_stop(void)`
|
### `i2c_status_t i2c_stop(void)`
|
||||||
|
|
||||||
Stop the current I2C transaction.
|
Stop the current I2C transaction.
|
||||||
|
|
|
@ -202,6 +202,25 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data,
|
||||||
return status;
|
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 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);
|
i2c_status_t status = i2c_start(devaddr, timeout);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
|
@ -235,6 +254,43 @@ error:
|
||||||
return (status < 0) ? status : I2C_STATUS_SUCCESS;
|
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) {
|
void i2c_stop(void) {
|
||||||
// transmit STOP condition
|
// transmit STOP condition
|
||||||
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
|
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
|
||||||
|
|
|
@ -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_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_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_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_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);
|
void i2c_stop(void);
|
||||||
|
|
|
@ -102,7 +102,7 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data,
|
||||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||||
|
|
||||||
uint8_t complete_packet[length + 1];
|
uint8_t complete_packet[length + 1];
|
||||||
for (uint8_t i = 0; i < length; i++) {
|
for (uint16_t i = 0; i < length; i++) {
|
||||||
complete_packet[i + 1] = data[i];
|
complete_packet[i + 1] = data[i];
|
||||||
}
|
}
|
||||||
complete_packet[0] = regaddr;
|
complete_packet[0] = regaddr;
|
||||||
|
@ -111,6 +111,21 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data,
|
||||||
return chibios_to_qmk(&status);
|
return chibios_to_qmk(&status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||||
|
i2c_address = devaddr;
|
||||||
|
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||||
|
|
||||||
|
uint8_t complete_packet[length + 2];
|
||||||
|
for (uint16_t i = 0; i < length; i++) {
|
||||||
|
complete_packet[i + 2] = data[i];
|
||||||
|
}
|
||||||
|
complete_packet[0] = regaddr >> 8;
|
||||||
|
complete_packet[1] = regaddr & 0xFF;
|
||||||
|
|
||||||
|
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout));
|
||||||
|
return chibios_to_qmk(&status);
|
||||||
|
}
|
||||||
|
|
||||||
i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, 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_address = devaddr;
|
i2c_address = devaddr;
|
||||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||||
|
@ -118,4 +133,12 @@ i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16
|
||||||
return chibios_to_qmk(&status);
|
return chibios_to_qmk(&status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||||
|
i2c_address = devaddr;
|
||||||
|
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||||
|
uint8_t register_packet[2] = {regaddr >> 8, regaddr & 0xFF};
|
||||||
|
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), ®ister_packet, 2, data, length, TIME_MS2I(timeout));
|
||||||
|
return chibios_to_qmk(&status);
|
||||||
|
}
|
||||||
|
|
||||||
void i2c_stop(void) { i2cStop(&I2C_DRIVER); }
|
void i2c_stop(void) { i2cStop(&I2C_DRIVER); }
|
||||||
|
|
|
@ -96,5 +96,7 @@ i2c_status_t i2c_start(uint8_t address);
|
||||||
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, 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_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_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_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);
|
void i2c_stop(void);
|
||||||
|
|
Loading…
Reference in a new issue