mirror of
				https://github.com/mfulz/qmk_firmware.git
				synced 2025-10-31 05:12:33 +01:00 
			
		
		
		
	i2c_master: Add support for reading/writing to 16-bit registers (#14289)
This commit is contained in:
		
							parent
							
								
									875e44faac
								
							
						
					
					
						commit
						bc1f5ef381
					
				| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Ryan
						Ryan