mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-12-07 08:04:57 +08:00
* feat: adds a transmit and receive i2c method * fix: address the i2c transmit and receive length on u16 * Add AVR/LUFA implementation Didn't add a progmem version, since that would only apply to receive. Figured it wasn't worth it, but can add. * Rearrange order of functions * Add docs * Fix doc gen error * Fix lint issues * fix more lint issues
157 lines
7.1 KiB
C
157 lines
7.1 KiB
C
// Copyright 2025 QMK
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
|
|
/**
|
|
* \file
|
|
*
|
|
* \defgroup i2c_master I2C Master API
|
|
*
|
|
* \brief API to communicate with I2C devices.
|
|
* \{
|
|
*/
|
|
|
|
typedef int16_t i2c_status_t;
|
|
|
|
#define I2C_STATUS_SUCCESS (0)
|
|
#define I2C_STATUS_ERROR (-1)
|
|
#define I2C_STATUS_TIMEOUT (-2)
|
|
|
|
#define I2C_TIMEOUT_IMMEDIATE (0)
|
|
#define I2C_TIMEOUT_INFINITE (0xFFFF)
|
|
|
|
/**
|
|
* \brief Initialize the I2C driver. This function must be called only once, before any of the below functions can be called.
|
|
*
|
|
* This function is weakly defined, meaning it can be overridden if necessary for your particular use case.
|
|
*/
|
|
void i2c_init(void);
|
|
|
|
/**
|
|
* \brief Send multiple bytes to the selected I2C device.
|
|
*
|
|
* \param address The 7-bit I2C address of the device.
|
|
* \param data A pointer to the data to transmit.
|
|
* \param length The number of bytes to write. Take care not to overrun the length of `data`.
|
|
* \param timeout The time in milliseconds to wait for a response from the target device.
|
|
*
|
|
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
|
*/
|
|
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
|
|
|
|
#if defined(__AVR__) || defined(__DOXYGEN__)
|
|
/**
|
|
* \brief Send multiple bytes from PROGMEM to the selected I2C device.
|
|
*
|
|
* On ARM devices, this function is simply an alias for i2c_transmit(address, data, length, timeout).
|
|
*
|
|
* \param address The 7-bit I2C address of the device.
|
|
* \param data A pointer to the data to transmit.
|
|
* \param length The number of bytes to write. Take care not to overrun the length of `data`.
|
|
* \param timeout The time in milliseconds to wait for a response from the target device.
|
|
*
|
|
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
|
*/
|
|
i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
|
|
#else
|
|
# define i2c_transmit_P(address, data, length, timeout) i2c_transmit(address, data, length, timeout)
|
|
#endif
|
|
|
|
/**
|
|
* \brief Receive multiple bytes from the selected I2C device.
|
|
*
|
|
* \param address The 7-bit I2C address of the device.
|
|
* \param data A pointer to a buffer to read into.
|
|
* \param length The number of bytes to read. Take care not to overrun the length of `data`.
|
|
* \param timeout The time in milliseconds to wait for a response from the target device.
|
|
*
|
|
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
|
*/
|
|
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
|
|
|
|
/**
|
|
* \brief Send multiple bytes and then receive multiple bytes from the selected I2C device.
|
|
*
|
|
* \param address The 7-bit I2C address of the device.
|
|
* \param tx_data A pointer to the data to transmit.
|
|
* \param tx_length The number of bytes to write. Take care not to overrun the length of `tx_data`.
|
|
* \param rx_data A pointer to a buffer to read into.
|
|
* \param rx_length The number of bytes to read. Take care not to overrun the length of `rx_data`.
|
|
* \param timeout The time in milliseconds to wait for a response from the target device.
|
|
*
|
|
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
|
*/
|
|
|
|
i2c_status_t i2c_transmit_and_receive(uint8_t address, const uint8_t* tx_data, uint16_t tx_length, uint8_t* rx_data, uint16_t rx_length, uint16_t timeout);
|
|
|
|
/**
|
|
* \brief Write to a register with an 8-bit address on the I2C device.
|
|
*
|
|
* \param devaddr The 7-bit I2C address of the device.
|
|
* \param regaddr The register address to write to.
|
|
* \param data A pointer to the data to transmit.
|
|
* \param length The number of bytes to write. Take care not to overrun the length of `data`.
|
|
* \param timeout The time in milliseconds to wait for a response from the target device.
|
|
*
|
|
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
|
*/
|
|
i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
|
|
|
/**
|
|
* \brief Write to a register with a 16-bit address (big endian) on the I2C device.
|
|
*
|
|
* \param devaddr The 7-bit I2C address of the device.
|
|
* \param regaddr The register address to write to.
|
|
* \param data A pointer to the data to transmit.
|
|
* \param length The number of bytes to write. Take care not to overrun the length of `data`.
|
|
* \param timeout The time in milliseconds to wait for a response from the target device.
|
|
*
|
|
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
|
*/
|
|
i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
|
|
|
/**
|
|
* \brief Read from a register with an 8-bit address on the I2C device.
|
|
*
|
|
* \param devaddr The 7-bit I2C address of the device.
|
|
* \param regaddr The register address to read from.
|
|
* \param data A pointer to a buffer to read into.
|
|
* \param length The number of bytes to read. Take care not to overrun the length of `data`.
|
|
* \param timeout The time in milliseconds to wait for a response from the target device.
|
|
*
|
|
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
|
*/
|
|
i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
|
|
|
/**
|
|
* \brief Read from a register with a 16-bit address (big endian) on the I2C device.
|
|
*
|
|
* \param devaddr The 7-bit I2C address of the device.
|
|
* \param regaddr The register address to read from.
|
|
* \param data A pointer to a buffer to read into.
|
|
* \param length The number of bytes to read. Take care not to overrun the length of `data`.
|
|
* \param timeout The time in milliseconds to wait for a response from the target device.
|
|
*
|
|
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
|
*/
|
|
i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
|
|
|
/**
|
|
* \brief Ping the I2C bus for a specific address.
|
|
*
|
|
* 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).
|
|
*
|
|
* This function is weakly defined, meaning it can be overridden if necessary for your particular use case.
|
|
*
|
|
* \param address The 7-bit I2C address of the device.
|
|
* \param timeout The time in milliseconds to wait for a response from the target device.
|
|
*
|
|
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
|
*/
|
|
i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);
|
|
|
|
/** \} */
|