diff options
| -rw-r--r-- | docs/drivers/i2c.md | 94 | ||||
| -rw-r--r-- | drivers/i2c_master.h | 141 | ||||
| -rw-r--r-- | platforms/avr/drivers/i2c_master.h | 41 | ||||
| -rw-r--r-- | platforms/chibios/drivers/i2c_master.c | 43 | ||||
| -rw-r--r-- | platforms/chibios/drivers/i2c_master.h | 42 |
5 files changed, 225 insertions, 136 deletions
diff --git a/docs/drivers/i2c.md b/docs/drivers/i2c.md index 2ef7afccc9..ad74d0e481 100644 --- a/docs/drivers/i2c.md +++ b/docs/drivers/i2c.md | |||
| @@ -16,17 +16,22 @@ You can then call the I2C API by including `i2c_master.h` in your code. | |||
| 16 | 16 | ||
| 17 | ## I2C Addressing {#note-on-i2c-addresses} | 17 | ## I2C Addressing {#note-on-i2c-addresses} |
| 18 | 18 | ||
| 19 | All of the addresses expected by this driver should be pushed to the upper 7 bits of the address byte. Setting | 19 | I2C addresses listed on datasheets and the internet are usually represented as a 7-bit value. The eighth bit (the least significant bit) controls whether the operation is a read or a write. |
| 20 | the lower bit (indicating read/write) will be done by the respective functions. Almost all I2C addresses listed | ||
| 21 | on datasheets and the internet will be represented as 7 bits occupying the lower 7 bits and will need to be | ||
| 22 | shifted to the left (more significant) by one bit. This is easy to do via the bitwise shift operator `<< 1`. | ||
| 23 | 20 | ||
| 24 | You can either do this on each call to the functions below, or once in your definition of the address. For example, if your device has an address of `0x18`: | 21 | All of the address parameters expected by the driver API should therefore be pushed to the upper 7 bits of the address byte; the driver will take care of setting the read/write bit as appropriate. |
| 22 | |||
| 23 | This is easy to do via the bitwise left shift operator. For example, if your device has an address of `0x18` you might create a define for convenience: | ||
| 25 | 24 | ||
| 26 | ```c | 25 | ```c |
| 27 | #define MY_I2C_ADDRESS (0x18 << 1) | 26 | #define MY_I2C_ADDRESS (0x18 << 1) |
| 28 | ``` | 27 | ``` |
| 29 | 28 | ||
| 29 | Or, you can shift the address ahead of time: | ||
| 30 | |||
| 31 | ```c | ||
| 32 | #define MY_I2C_ADDRESS 0x30 | ||
| 33 | ``` | ||
| 34 | |||
| 30 | See https://www.robot-electronics.co.uk/i2c-tutorial for more information about I2C addressing and other technical details. | 35 | See https://www.robot-electronics.co.uk/i2c-tutorial for more information about I2C addressing and other technical details. |
| 31 | 36 | ||
| 32 | ## AVR Configuration {#avr-configuration} | 37 | ## AVR Configuration {#avr-configuration} |
| @@ -39,12 +44,12 @@ The following defines can be used to configure the I2C master driver: | |||
| 39 | 44 | ||
| 40 | No further setup is required - just connect the `SDA` and `SCL` pins of your I2C devices to the matching pins on the MCU: | 45 | No further setup is required - just connect the `SDA` and `SCL` pins of your I2C devices to the matching pins on the MCU: |
| 41 | 46 | ||
| 42 | |MCU |`SCL`|`SDA`| | 47 | |MCU |`SCL`|`SDA`| |
| 43 | |------------------|-----|-----| | 48 | |-------------|-----|-----| |
| 44 | |ATmega16/32U4 |`D0` |`D1` | | 49 | |ATmega16/32U4|`D0` |`D1` | |
| 45 | |AT90USB64/128 |`D0` |`D1` | | 50 | |AT90USB64/128|`D0` |`D1` | |
| 46 | |ATmega32A |`C0` |`C1` | | 51 | |ATmega32A |`C0` |`C1` | |
| 47 | |ATmega328/P |`C5` |`C4` | | 52 | |ATmega328/P |`C5` |`C4` | |
| 48 | 53 | ||
| 49 | ::: tip | 54 | ::: tip |
| 50 | The ATmega16/32U2 does not possess I2C functionality, and so cannot use this driver. | 55 | The ATmega16/32U2 does not possess I2C functionality, and so cannot use this driver. |
| @@ -52,7 +57,7 @@ The ATmega16/32U2 does not possess I2C functionality, and so cannot use this dri | |||
| 52 | 57 | ||
| 53 | ## ChibiOS/ARM Configuration {#arm-configuration} | 58 | ## ChibiOS/ARM Configuration {#arm-configuration} |
| 54 | 59 | ||
| 55 | You'll need to determine which pins can be used for I2C -- a an example, STM32 parts generally have multiple I2C peripherals, labeled I2C1, I2C2, I2C3 etc. | 60 | You'll need to determine which pins can be used for I2C -- as an example, STM32 parts generally have multiple I2C peripherals, labeled I2C1, I2C2, I2C3 etc. |
| 56 | 61 | ||
| 57 | To enable I2C, modify your board's `halconf.h` to enable I2C, then modify your board's `mcuconf.h` to enable the peripheral you've chosen: | 62 | To enable I2C, modify your board's `halconf.h` to enable I2C, then modify your board's `mcuconf.h` to enable the peripheral you've chosen: |
| 58 | 63 | ||
| @@ -83,15 +88,19 @@ To enable I2C, modify your board's `halconf.h` to enable I2C, then modify your b | |||
| 83 | 88 | ||
| 84 | Configuration-wise, you'll need to set up the peripheral as per your MCU's datasheet -- the defaults match the pins for a Proton-C, i.e. STM32F303. | 89 | Configuration-wise, you'll need to set up the peripheral as per your MCU's datasheet -- the defaults match the pins for a Proton-C, i.e. STM32F303. |
| 85 | 90 | ||
| 86 | |`config.h` Overrride |Description |Default| | 91 | |`config.h` Override|Description |Default| |
| 87 | |------------------------|--------------------------------------------------------------|-------| | 92 | |-------------------|-------------------------------------------------------------|-------| |
| 88 | |`I2C_DRIVER` |I2C peripheral to use - I2C1 -> `I2CD1`, I2C2 -> `I2CD2` etc. |`I2CD1`| | 93 | |`I2C_DRIVER` |I2C peripheral to use - I2C1 -> `I2CD1`, I2C2 -> `I2CD2` etc.|`I2CD1`| |
| 89 | |`I2C1_SCL_PIN` |The pin definition for SCL |`B6` | | 94 | |`I2C1_SCL_PIN` |The pin to use for SCL |`B6` | |
| 90 | |`I2C1_SCL_PAL_MODE` |The alternate function mode for SCL |`4` | | 95 | |`I2C1_SCL_PAL_MODE`|The alternate function mode for SCL |`4` | |
| 91 | |`I2C1_SDA_PIN` |The pin definition for SDA |`B7` | | 96 | |`I2C1_SDA_PIN` |The pin to use for SDA |`B7` | |
| 92 | |`I2C1_SDA_PAL_MODE` |The alternate function mode for SDA |`4` | | 97 | |`I2C1_SDA_PAL_MODE`|The alternate function mode for SDA |`4` | |
| 98 | |||
| 99 | ::: tip | ||
| 100 | Currently only a single I2C peripheral is supported, therefore the `I2C1_*` defines are used for configuration regardless of the selected peripheral. | ||
| 101 | ::: | ||
| 93 | 102 | ||
| 94 | The following configuration values depend on the specific MCU in use. | 103 | The following configuration values are dependent on the ChibiOS I2C LLD, which is dictated by the microcontroller. |
| 95 | 104 | ||
| 96 | ### I2Cv1 {#arm-configuration-i2cv1} | 105 | ### I2Cv1 {#arm-configuration-i2cv1} |
| 97 | 106 | ||
| @@ -158,7 +167,7 @@ Send multiple bytes to the selected I2C device. | |||
| 158 | - `const uint8_t* data` | 167 | - `const uint8_t* data` |
| 159 | A pointer to the data to transmit. | 168 | A pointer to the data to transmit. |
| 160 | - `uint16_t length` | 169 | - `uint16_t length` |
| 161 | The number of bytes to write. Take care not to overrun the length of `data`. | 170 | The number of bytes to write. Take care not to overrun the length of `data`. |
| 162 | - `uint16_t timeout` | 171 | - `uint16_t timeout` |
| 163 | The time in milliseconds to wait for a response from the target device. | 172 | The time in milliseconds to wait for a response from the target device. |
| 164 | 173 | ||
| @@ -168,6 +177,29 @@ Send multiple bytes to the selected I2C device. | |||
| 168 | 177 | ||
| 169 | --- | 178 | --- |
| 170 | 179 | ||
| 180 | ### `i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout)` {#api-i2c-transmit-p} | ||
| 181 | |||
| 182 | Send multiple bytes from PROGMEM to the selected I2C device. | ||
| 183 | |||
| 184 | On ARM devices, this function is simply an alias for `i2c_transmit(address, data, length, timeout)`. | ||
| 185 | |||
| 186 | #### Arguments {#api-i2c-transmit-p-arguments} | ||
| 187 | |||
| 188 | - `uint8_t address` | ||
| 189 | The 7-bit I2C address of the device. | ||
| 190 | - `const uint8_t* data` | ||
| 191 | A pointer to the data to transmit. | ||
| 192 | - `uint16_t length` | ||
| 193 | The number of bytes to write. Take care not to overrun the length of `data`. | ||
| 194 | - `uint16_t timeout` | ||
| 195 | The time in milliseconds to wait for a response from the target device. | ||
| 196 | |||
| 197 | #### Return Value {#api-i2c-transmit-p-return} | ||
| 198 | |||
| 199 | `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`. | ||
| 200 | |||
| 201 | --- | ||
| 202 | |||
| 171 | ### `i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)` {#api-i2c-receive} | 203 | ### `i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)` {#api-i2c-receive} |
| 172 | 204 | ||
| 173 | Receive multiple bytes from the selected I2C device. | 205 | Receive multiple bytes from the selected I2C device. |
| @@ -177,9 +209,9 @@ Receive multiple bytes from the selected I2C device. | |||
| 177 | - `uint8_t address` | 209 | - `uint8_t address` |
| 178 | The 7-bit I2C address of the device. | 210 | The 7-bit I2C address of the device. |
| 179 | - `uint8_t* data` | 211 | - `uint8_t* data` |
| 180 | A pointer to the buffer to read into. | 212 | A pointer to a buffer to read into. |
| 181 | - `uint16_t length` | 213 | - `uint16_t length` |
| 182 | The number of bytes to read. Take care not to overrun the length of `data`. | 214 | The number of bytes to read. Take care not to overrun the length of `data`. |
| 183 | - `uint16_t timeout` | 215 | - `uint16_t timeout` |
| 184 | The time in milliseconds to wait for a response from the target device. | 216 | The time in milliseconds to wait for a response from the target device. |
| 185 | 217 | ||
| @@ -191,7 +223,7 @@ Receive multiple bytes from the selected I2C device. | |||
| 191 | 223 | ||
| 192 | ### `i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout)` {#api-i2c-write-register} | 224 | ### `i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout)` {#api-i2c-write-register} |
| 193 | 225 | ||
| 194 | Writes to a register with an 8-bit address on the I2C device. | 226 | Write to a register with an 8-bit address on the I2C device. |
| 195 | 227 | ||
| 196 | #### Arguments {#api-i2c-write-register-arguments} | 228 | #### Arguments {#api-i2c-write-register-arguments} |
| 197 | 229 | ||
| @@ -202,7 +234,7 @@ Writes to a register with an 8-bit address on the I2C device. | |||
| 202 | - `const uint8_t* data` | 234 | - `const uint8_t* data` |
| 203 | A pointer to the data to transmit. | 235 | A pointer to the data to transmit. |
| 204 | - `uint16_t length` | 236 | - `uint16_t length` |
| 205 | The number of bytes to write. Take care not to overrun the length of `data`. | 237 | The number of bytes to write. Take care not to overrun the length of `data`. |
| 206 | - `uint16_t timeout` | 238 | - `uint16_t timeout` |
| 207 | The time in milliseconds to wait for a response from the target device. | 239 | The time in milliseconds to wait for a response from the target device. |
| 208 | 240 | ||
| @@ -214,7 +246,7 @@ Writes to a register with an 8-bit address on the I2C device. | |||
| 214 | 246 | ||
| 215 | ### `i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout)` {#api-i2c-write-register16} | 247 | ### `i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout)` {#api-i2c-write-register16} |
| 216 | 248 | ||
| 217 | Writes to a register with a 16-bit address (big endian) on the I2C device. | 249 | Write to a register with a 16-bit address (big endian) on the I2C device. |
| 218 | 250 | ||
| 219 | #### Arguments {#api-i2c-write-register16-arguments} | 251 | #### Arguments {#api-i2c-write-register16-arguments} |
| 220 | 252 | ||
| @@ -237,7 +269,7 @@ Writes to a register with a 16-bit address (big endian) on the I2C device. | |||
| 237 | 269 | ||
| 238 | ### `i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` {#api-i2c-read-register} | 270 | ### `i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` {#api-i2c-read-register} |
| 239 | 271 | ||
| 240 | Reads from a register with an 8-bit address on the I2C device. | 272 | Read from a register with an 8-bit address on the I2C device. |
| 241 | 273 | ||
| 242 | #### Arguments {#api-i2c-read-register-arguments} | 274 | #### Arguments {#api-i2c-read-register-arguments} |
| 243 | 275 | ||
| @@ -260,7 +292,7 @@ Reads from a register with an 8-bit address on the I2C device. | |||
| 260 | 292 | ||
| 261 | ### `i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` {#api-i2c-read-register16} | 293 | ### `i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` {#api-i2c-read-register16} |
| 262 | 294 | ||
| 263 | Reads from a register with a 16-bit address (big endian) on the I2C device. | 295 | Read from a register with a 16-bit address (big endian) on the I2C device. |
| 264 | 296 | ||
| 265 | #### Arguments {#api-i2c-read-register16-arguments} | 297 | #### Arguments {#api-i2c-read-register16-arguments} |
| 266 | 298 | ||
| @@ -283,16 +315,16 @@ Reads from a register with a 16-bit address (big endian) on the I2C device. | |||
| 283 | 315 | ||
| 284 | ### `i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout)` {#api-i2c-ping-address} | 316 | ### `i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout)` {#api-i2c-ping-address} |
| 285 | 317 | ||
| 286 | Pings the I2C bus for a specific address. | 318 | Ping the I2C bus for a specific address. |
| 287 | 319 | ||
| 288 | On ChibiOS a "best effort" attempt is made by reading a single byte from register 0 at the requested address. This should generally work except for I2C devices that do not not respond to a register 0 read request, which will result in a false negative result (unsuccessful response to ping attempt). | 320 | On ChibiOS a "best effort" attempt is made by reading a single byte from register 0 at the given address. This should generally work except for I2C devices that do not not respond to a register 0 read request, which will result in a false negative result (unsuccessful response to ping attempt). |
| 289 | 321 | ||
| 290 | This function is weakly defined, meaning it can be overridden if necessary for your particular use case. | 322 | This function is weakly defined, meaning it can be overridden if necessary for your particular use case. |
| 291 | 323 | ||
| 292 | #### Arguments {#api-i2c-ping-address-arguments} | 324 | #### Arguments {#api-i2c-ping-address-arguments} |
| 293 | 325 | ||
| 294 | - `uint8_t address` | 326 | - `uint8_t address` |
| 295 | The 7-bit I2C address of the device (ie. without the read/write bit - this will be set automatically). | 327 | The 7-bit I2C address of the device. |
| 296 | - `uint16_t timeout` | 328 | - `uint16_t timeout` |
| 297 | The time in milliseconds to wait for a response from the target device. | 329 | The time in milliseconds to wait for a response from the target device. |
| 298 | 330 | ||
diff --git a/drivers/i2c_master.h b/drivers/i2c_master.h new file mode 100644 index 0000000000..dbe1cd42fa --- /dev/null +++ b/drivers/i2c_master.h | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | // Copyright 2025 QMK | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <stdint.h> | ||
| 7 | |||
| 8 | /** | ||
| 9 | * \file | ||
| 10 | * | ||
| 11 | * \defgroup i2c_master I2C Master API | ||
| 12 | * | ||
| 13 | * \brief API to communicate with I2C devices. | ||
| 14 | * \{ | ||
| 15 | */ | ||
| 16 | |||
| 17 | typedef int16_t i2c_status_t; | ||
| 18 | |||
| 19 | #define I2C_STATUS_SUCCESS (0) | ||
| 20 | #define I2C_STATUS_ERROR (-1) | ||
| 21 | #define I2C_STATUS_TIMEOUT (-2) | ||
| 22 | |||
| 23 | #define I2C_TIMEOUT_IMMEDIATE (0) | ||
| 24 | #define I2C_TIMEOUT_INFINITE (0xFFFF) | ||
| 25 | |||
| 26 | /** | ||
| 27 | * \brief Initialize the I2C driver. This function must be called only once, before any of the below functions can be called. | ||
| 28 | * | ||
| 29 | * This function is weakly defined, meaning it can be overridden if necessary for your particular use case. | ||
| 30 | */ | ||
| 31 | void i2c_init(void); | ||
| 32 | |||
| 33 | /** | ||
| 34 | * \brief Send multiple bytes to the selected I2C device. | ||
| 35 | * | ||
| 36 | * \param address The 7-bit I2C address of the device. | ||
| 37 | * \param data A pointer to the data to transmit. | ||
| 38 | * \param length The number of bytes to write. Take care not to overrun the length of `data`. | ||
| 39 | * \param timeout The time in milliseconds to wait for a response from the target device. | ||
| 40 | * | ||
| 41 | * \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`. | ||
| 42 | */ | ||
| 43 | i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 44 | |||
| 45 | #if defined(__AVR__) || defined(__DOXYGEN__) | ||
| 46 | /** | ||
| 47 | * \brief Send multiple bytes from PROGMEM to the selected I2C device. | ||
| 48 | * | ||
| 49 | * On ARM devices, this function is simply an alias for i2c_transmit(address, data, length, timeout). | ||
| 50 | * | ||
| 51 | * \param address The 7-bit I2C address of the device. | ||
| 52 | * \param data A pointer to the data to transmit. | ||
| 53 | * \param length The number of bytes to write. Take care not to overrun the length of `data`. | ||
| 54 | * \param timeout The time in milliseconds to wait for a response from the target device. | ||
| 55 | * | ||
| 56 | * \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`. | ||
| 57 | */ | ||
| 58 | i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 59 | #else | ||
| 60 | # define i2c_transmit_P(address, data, length, timeout) i2c_transmit(address, data, length, timeout) | ||
| 61 | #endif | ||
| 62 | |||
| 63 | /** | ||
| 64 | * \brief Receive multiple bytes from the selected I2C device. | ||
| 65 | * | ||
| 66 | * \param address The 7-bit I2C address of the device. | ||
| 67 | * \param data A pointer to a buffer to read into. | ||
| 68 | * \param length The number of bytes to read. Take care not to overrun the length of `data`. | ||
| 69 | * \param timeout The time in milliseconds to wait for a response from the target device. | ||
| 70 | * | ||
| 71 | * \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`. | ||
| 72 | */ | ||
| 73 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 74 | |||
| 75 | /** | ||
| 76 | * \brief Write to a register with an 8-bit address on the I2C device. | ||
| 77 | * | ||
| 78 | * \param devaddr The 7-bit I2C address of the device. | ||
| 79 | * \param regaddr The register address to write to. | ||
| 80 | * \param data A pointer to the data to transmit. | ||
| 81 | * \param length The number of bytes to write. Take care not to overrun the length of `data`. | ||
| 82 | * \param timeout The time in milliseconds to wait for a response from the target device. | ||
| 83 | * | ||
| 84 | * \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`. | ||
| 85 | */ | ||
| 86 | i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 87 | |||
| 88 | /** | ||
| 89 | * \brief Write to a register with a 16-bit address (big endian) on the I2C device. | ||
| 90 | * | ||
| 91 | * \param devaddr The 7-bit I2C address of the device. | ||
| 92 | * \param regaddr The register address to write to. | ||
| 93 | * \param data A pointer to the data to transmit. | ||
| 94 | * \param length The number of bytes to write. Take care not to overrun the length of `data`. | ||
| 95 | * \param timeout The time in milliseconds to wait for a response from the target device. | ||
| 96 | * | ||
| 97 | * \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`. | ||
| 98 | */ | ||
| 99 | i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 100 | |||
| 101 | /** | ||
| 102 | * \brief Read from a register with an 8-bit address on the I2C device. | ||
| 103 | * | ||
| 104 | * \param devaddr The 7-bit I2C address of the device. | ||
| 105 | * \param regaddr The register address to read from. | ||
| 106 | * \param data A pointer to a buffer to read into. | ||
| 107 | * \param length The number of bytes to read. Take care not to overrun the length of `data`. | ||
| 108 | * \param timeout The time in milliseconds to wait for a response from the target device. | ||
| 109 | * | ||
| 110 | * \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`. | ||
| 111 | */ | ||
| 112 | i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 113 | |||
| 114 | /** | ||
| 115 | * \brief Read from a register with a 16-bit address (big endian) on the I2C device. | ||
| 116 | * | ||
| 117 | * \param devaddr The 7-bit I2C address of the device. | ||
| 118 | * \param regaddr The register address to read from. | ||
| 119 | * \param data A pointer to a buffer to read into. | ||
| 120 | * \param length The number of bytes to read. Take care not to overrun the length of `data`. | ||
| 121 | * \param timeout The time in milliseconds to wait for a response from the target device. | ||
| 122 | * | ||
| 123 | * \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`. | ||
| 124 | */ | ||
| 125 | i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 126 | |||
| 127 | /** | ||
| 128 | * \brief Ping the I2C bus for a specific address. | ||
| 129 | * | ||
| 130 | * On ChibiOS a "best effort" attempt is made by reading a single byte from register 0 at the given address. This should generally work except for I2C devices that do not not respond to a register 0 read request, which will result in a false negative result (unsuccessful response to ping attempt). | ||
| 131 | * | ||
| 132 | * This function is weakly defined, meaning it can be overridden if necessary for your particular use case. | ||
| 133 | * | ||
| 134 | * \param address The 7-bit I2C address of the device. | ||
| 135 | * \param timeout The time in milliseconds to wait for a response from the target device. | ||
| 136 | * | ||
| 137 | * \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`. | ||
| 138 | */ | ||
| 139 | i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout); | ||
| 140 | |||
| 141 | /** \} */ | ||
diff --git a/platforms/avr/drivers/i2c_master.h b/platforms/avr/drivers/i2c_master.h deleted file mode 100644 index ad92caa55a..0000000000 --- a/platforms/avr/drivers/i2c_master.h +++ /dev/null | |||
| @@ -1,41 +0,0 @@ | |||
| 1 | /* Copyright (C) 2019 Elia Ritterbusch | ||
| 2 | + | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 3 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | /* Library made by: g4lvanix | ||
| 17 | * GitHub repository: https://github.com/g4lvanix/I2C-master-lib | ||
| 18 | */ | ||
| 19 | |||
| 20 | #pragma once | ||
| 21 | |||
| 22 | #include <stdint.h> | ||
| 23 | |||
| 24 | typedef int16_t i2c_status_t; | ||
| 25 | |||
| 26 | #define I2C_STATUS_SUCCESS (0) | ||
| 27 | #define I2C_STATUS_ERROR (-1) | ||
| 28 | #define I2C_STATUS_TIMEOUT (-2) | ||
| 29 | |||
| 30 | #define I2C_TIMEOUT_IMMEDIATE (0) | ||
| 31 | #define I2C_TIMEOUT_INFINITE (0xFFFF) | ||
| 32 | |||
| 33 | void i2c_init(void); | ||
| 34 | i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 35 | i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 36 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 37 | i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 38 | i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 39 | i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 40 | i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 41 | i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout); | ||
diff --git a/platforms/chibios/drivers/i2c_master.c b/platforms/chibios/drivers/i2c_master.c index 0d5fb1e985..1d7fe27633 100644 --- a/platforms/chibios/drivers/i2c_master.c +++ b/platforms/chibios/drivers/i2c_master.c | |||
| @@ -29,17 +29,37 @@ | |||
| 29 | #include "i2c_master.h" | 29 | #include "i2c_master.h" |
| 30 | #include "gpio.h" | 30 | #include "gpio.h" |
| 31 | #include "chibios_config.h" | 31 | #include "chibios_config.h" |
| 32 | #include <string.h> | ||
| 33 | #include <ch.h> | 32 | #include <ch.h> |
| 34 | #include <hal.h> | 33 | #include <hal.h> |
| 35 | 34 | ||
| 35 | #ifndef I2C_DRIVER | ||
| 36 | # define I2C_DRIVER I2CD1 | ||
| 37 | #endif | ||
| 38 | |||
| 36 | #ifndef I2C1_SCL_PIN | 39 | #ifndef I2C1_SCL_PIN |
| 37 | # define I2C1_SCL_PIN B6 | 40 | # define I2C1_SCL_PIN B6 |
| 38 | #endif | 41 | #endif |
| 42 | |||
| 43 | #ifndef I2C1_SCL_PAL_MODE | ||
| 44 | # ifdef USE_GPIOV1 | ||
| 45 | # define I2C1_SCL_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN | ||
| 46 | # else | ||
| 47 | # define I2C1_SCL_PAL_MODE 4 | ||
| 48 | # endif | ||
| 49 | #endif | ||
| 50 | |||
| 39 | #ifndef I2C1_SDA_PIN | 51 | #ifndef I2C1_SDA_PIN |
| 40 | # define I2C1_SDA_PIN B7 | 52 | # define I2C1_SDA_PIN B7 |
| 41 | #endif | 53 | #endif |
| 42 | 54 | ||
| 55 | #ifndef I2C1_SDA_PAL_MODE | ||
| 56 | # ifdef USE_GPIOV1 | ||
| 57 | # define I2C1_SDA_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN | ||
| 58 | # else | ||
| 59 | # define I2C1_SDA_PAL_MODE 4 | ||
| 60 | # endif | ||
| 61 | #endif | ||
| 62 | |||
| 43 | #ifdef USE_I2CV1 | 63 | #ifdef USE_I2CV1 |
| 44 | # ifndef I2C1_OPMODE | 64 | # ifndef I2C1_OPMODE |
| 45 | # define I2C1_OPMODE OPMODE_I2C | 65 | # define I2C1_OPMODE OPMODE_I2C |
| @@ -70,27 +90,6 @@ | |||
| 70 | # endif | 90 | # endif |
| 71 | #endif | 91 | #endif |
| 72 | 92 | ||
| 73 | #ifndef I2C_DRIVER | ||
| 74 | # define I2C_DRIVER I2CD1 | ||
| 75 | #endif | ||
| 76 | |||
| 77 | #ifdef USE_GPIOV1 | ||
| 78 | # ifndef I2C1_SCL_PAL_MODE | ||
| 79 | # define I2C1_SCL_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN | ||
| 80 | # endif | ||
| 81 | # ifndef I2C1_SDA_PAL_MODE | ||
| 82 | # define I2C1_SDA_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN | ||
| 83 | # endif | ||
| 84 | #else | ||
| 85 | // The default PAL alternate modes are used to signal that the pins are used for I2C | ||
| 86 | # ifndef I2C1_SCL_PAL_MODE | ||
| 87 | # define I2C1_SCL_PAL_MODE 4 | ||
| 88 | # endif | ||
| 89 | # ifndef I2C1_SDA_PAL_MODE | ||
| 90 | # define I2C1_SDA_PAL_MODE 4 | ||
| 91 | # endif | ||
| 92 | #endif | ||
| 93 | |||
| 94 | static const I2CConfig i2cconfig = { | 93 | static const I2CConfig i2cconfig = { |
| 95 | #if defined(USE_I2CV1_CONTRIB) | 94 | #if defined(USE_I2CV1_CONTRIB) |
| 96 | I2C1_CLOCK_SPEED, | 95 | I2C1_CLOCK_SPEED, |
diff --git a/platforms/chibios/drivers/i2c_master.h b/platforms/chibios/drivers/i2c_master.h deleted file mode 100644 index 2215f89ad2..0000000000 --- a/platforms/chibios/drivers/i2c_master.h +++ /dev/null | |||
| @@ -1,42 +0,0 @@ | |||
| 1 | /* Copyright 2018 Jack Humbert | ||
| 2 | * Copyright 2018 Yiancar | ||
| 3 | * | ||
| 4 | * This program is free software: you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation, either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | /* This library follows the convention of the AVR i2c_master library. | ||
| 19 | * As a result addresses are expected to be already shifted (addr << 1). | ||
| 20 | * I2CD1 is the default driver which corresponds to pins B6 and B7. This | ||
| 21 | * can be changed. | ||
| 22 | * Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that | ||
| 23 | * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file. | ||
| 24 | */ | ||
| 25 | #pragma once | ||
| 26 | |||
| 27 | #include <stdint.h> | ||
| 28 | |||
| 29 | typedef int16_t i2c_status_t; | ||
| 30 | |||
| 31 | #define I2C_STATUS_SUCCESS (0) | ||
| 32 | #define I2C_STATUS_ERROR (-1) | ||
| 33 | #define I2C_STATUS_TIMEOUT (-2) | ||
| 34 | |||
| 35 | void i2c_init(void); | ||
| 36 | i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 37 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 38 | i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 39 | i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 40 | i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 41 | i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | ||
| 42 | i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout); | ||
