32#include "../SensorCommBase.hpp"
34#if !defined(ARDUINO) && defined(ESP_PLATFORM)
37#include "freertos/FreeRTOS.h"
38#include "esp_idf_version.h"
40#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API))
41#include "driver/i2c_master.h"
43#include "driver/i2c.h"
44#define SENSORLIB_USE_I2C_LEGACY 1
47#define SENSORLIB_I2C_MASTER_TIMEOUT_MS 1000
48#define SENSORLIB_I2C_MASTER_SPEED 400000
54#if defined(SENSORLIB_USE_I2C_LEGACY)
55 SensorCommI2C(i2c_port_t i2c_num, uint8_t addr,
int sda,
int scl,
SensorHal *ptr =
nullptr) :
56 addr(addr), sda(sda), scl(scl), _i2cNum(i2c_num), sendStopFlag(true)
59 SensorCommI2C(i2c_master_bus_handle_t handle, uint8_t addr,
SensorHal *ptr =
nullptr) :
60 addr(addr), _busHandle(handle), _i2cDevice(nullptr), sendStopFlag(true) {}
65#if defined(SENSORLIB_USE_I2C_LEGACY)
74#ifndef SENSORLIB_USE_I2C_LEGACY
77 i2c_master_bus_rm_device(_i2cDevice);
84 size_t totalLength =
sizeof(uint8_t) + len;
85 uint8_t *write_buffer = (uint8_t *)malloc(totalLength);
89 write_buffer[0] = reg;
91 memcpy(write_buffer + 1,
buf, len);
101#if defined(SENSORLIB_USE_I2C_LEGACY)
102 if (ESP_OK == i2c_master_write_to_device(_i2cNum, addr, buffer, len,
103 SENSORLIB_I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS)) {
107 if (ESP_OK == i2c_master_transmit(_i2cDevice, buffer, len, -1)) {
117#if defined(SENSORLIB_USE_I2C_LEGACY)
118 if (ESP_OK == i2c_master_write_read_device(_i2cNum, addr, NULL, 0,
buf, len,
119 SENSORLIB_I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS)) {
123 if (ESP_OK == i2c_master_transmit_receive(_i2cDevice, NULL, 0,
buf, len, -1)) {
132#if defined(SENSORLIB_USE_I2C_LEGACY)
133 if (ESP_OK == i2c_master_write_read_device(_i2cNum, addr, (uint8_t *)®, 1,
buf, len,
134 SENSORLIB_I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS)) {
138 if (ESP_OK == i2c_master_transmit_receive(_i2cDevice, (
const uint8_t *)®, 1,
buf, len, -1)) {
145 int writeThenRead(
const uint8_t *write_buffer,
size_t write_len, uint8_t *read_buffer,
size_t read_len)
override
147#if defined(SENSORLIB_USE_I2C_LEGACY)
148 if (ESP_OK == i2c_master_write_read_device(
155 SENSORLIB_I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS)) {
159 if (ESP_OK == i2c_master_transmit_receive(
174#if defined(__cpp_rtti)
175 const auto pdat =
dynamic_cast<const I2CParam *
>(¶ms);
177 const auto pdat =
static_cast<const I2CParam *
>(¶ms);
179 uint8_t type = pdat->
getType();
182 addr = pdat->getParams();
185 sendStopFlag = pdat->getParams();
191#if !defined(SENSORLIB_USE_I2C_LEGACY)
201#if defined(SENSORLIB_USE_I2C_LEGACY)
205 if (sda == -1 || scl == -1) {
208 i2c_config_t i2c_conf;
209 memset(&i2c_conf, 0,
sizeof(i2c_conf));
210 i2c_conf.mode = I2C_MODE_MASTER;
211 i2c_conf.sda_io_num = sda;
212 i2c_conf.scl_io_num = scl;
213 i2c_conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
214 i2c_conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
215 i2c_conf.master.clk_speed = SENSORLIB_I2C_MASTER_SPEED;
225 i2c_param_config(_i2cNum, &i2c_conf);
226 if (ESP_OK != i2c_driver_install(_i2cNum, i2c_conf.mode, 0, 0, 0)) {
241 i2c_device_config_t devConf;
242 if (_busHandle == NULL)
return false;
243 devConf.dev_addr_length = I2C_ADDR_BIT_LEN_7;
244 devConf.device_address = addr;
245 devConf.scl_speed_hz = SENSORLIB_I2C_MASTER_SPEED;
247#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,3,0))
248#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,4,0))
250 devConf.scl_wait_us = 0;
252 devConf.flags.disable_ack_check = 0;
255 if (ESP_OK != i2c_master_bus_add_device(_busHandle, &devConf, &_i2cDevice)) {
260 SENSORLIB_LOG_I(
"Added Device Address : 0x%X New Dev Address: %p Speed :%" PRIu32
" ", addr, _i2cDevice, devConf.scl_speed_hz);
266#if defined(SENSORLIB_USE_I2C_LEGACY)
271 i2c_master_bus_handle_t _busHandle;
272 i2c_master_dev_handle_t _i2cDevice;
#define SENSORLIB_LOG_I(...)
Abstract base for all communication parameter objects.
I2C communication parameters.
uint8_t getType() const
Retrieve the parameter type.
@ I2C_SET_ADDR
Set device address.
@ I2C_SET_FLAG
Set a generic flag (interpretation depends on driver)
Abstract base class for low‑level sensor communication.
virtual int writeThenRead(const uint8_t *write_buffer, size_t write_len, uint8_t *read_buffer, size_t read_len)=0
Perform a write followed by a read (e.g., for register‑based sensors).
virtual int readBuffer(uint8_t *buf, size_t len)=0
Read bytes directly from the device (no register address sent).
virtual int writeBuffer(uint8_t *buffer, size_t len)=0
Write a buffer directly to the device (no register address).
virtual void setParams(const CommParamsBase ¶ms)=0
Apply communication parameters (e.g., I2C address, SPI settings).
virtual int readRegister(const uint8_t reg)
Read a single byte from a register.
virtual void deinit()=0
Deinitialise the communication interface (close device, etc.).
virtual bool init()=0
Initialise the communication interface (open device, etc.).
virtual int writeRegister(const uint8_t reg, uint8_t val)
Write a single byte to a register.
void setError(SENSOR_ERROR_CODE e)
Abstract hardware abstraction layer.