13static const char *
const TAG =
"i2c.arduino";
19 static uint8_t next_bus_num = 0;
20 if (next_bus_num == 0) {
23 wire_ =
new TwoWire(next_bus_num);
25 this->
port_ = next_bus_num;
27#elif defined(USE_ESP8266)
28 wire_ =
new TwoWire();
29#elif defined(USE_RP2040)
30 static bool first =
true;
39 this->set_pins_and_clock_();
43 ESP_LOGV(TAG,
"Scanning bus for active devices");
48void ArduinoI2CBus::set_pins_and_clock_() {
60#elif defined(USE_ESP8266)
63#elif defined(USE_RP2040)
72 ESP_LOGCONFIG(TAG,
"I2C Bus:");
80 ESP_LOGCONFIG(TAG,
" Timeout: %u ms", this->
timeout_ / 1000);
81#elif defined(USE_ESP8266)
82 ESP_LOGCONFIG(TAG,
" Timeout: %u us", this->
timeout_);
83#elif defined(USE_RP2040)
84 ESP_LOGCONFIG(TAG,
" Timeout: %u ms", this->
timeout_ / 1000);
87 switch (this->recovery_result_) {
89 ESP_LOGCONFIG(TAG,
" Recovery: bus successfully recovered");
92 ESP_LOGCONFIG(TAG,
" Recovery: failed, SCL is held low on the bus");
95 ESP_LOGCONFIG(TAG,
" Recovery: failed, SDA is held low on the bus");
99 ESP_LOGI(TAG,
"Results from bus scan:");
101 ESP_LOGI(TAG,
"Found no devices");
105 ESP_LOGI(TAG,
"Found device at address 0x%02X", s.first);
107 ESP_LOGE(TAG,
"Unknown error at address 0x%02X", s.first);
115 uint8_t *read_buffer,
size_t read_count) {
116#if defined(USE_ESP8266)
117 this->set_pins_and_clock_();
120 ESP_LOGD(TAG,
"i2c bus not initialized!");
127 if (write_count != 0 || read_count == 0) {
129 size_t ret =
wire_->write(write_buffer, write_count);
130 if (ret != write_count) {
131 ESP_LOGV(TAG,
"TX failed");
136 if (
status == 0 && read_count != 0) {
137 size_t ret2 =
wire_->requestFrom(
address, read_count,
true);
138 if (ret2 != read_count) {
139 ESP_LOGVV(TAG,
"RX %u from %02X failed with error %u", read_count,
address, ret2);
142 for (
size_t j = 0; j != read_count; j++)
143 read_buffer[j] =
wire_->read();
150 ESP_LOGVV(TAG,
"TX failed: buffer not large enough");
154 ESP_LOGVV(TAG,
"TX failed: not acknowledged: %d",
status);
157 ESP_LOGVV(TAG,
"TX failed: timeout");
161 ESP_LOGVV(TAG,
"TX failed: unknown error %u",
status);
169void ArduinoI2CBus::recover_() {
170 ESP_LOGI(TAG,
"Performing bus recovery");
176 const auto half_period_usec = 1000000 / 100000 / 2;
186 ESP_LOGE(TAG,
"Recovery failed: SCL is held LOW on the bus");
204 for (
auto i = 0; i < 9; i++) {
223 while (wait-- && digitalRead(
scl_pin_) == LOW) {
228 ESP_LOGE(TAG,
"Recovery failed: SCL is held LOW during clock pulse cycle");
243 ESP_LOGE(TAG,
"Recovery failed: SDA is held LOW after clock pulse cycle");
void feed_wdt(uint32_t time=0)
void dump_config() override
ErrorCode write_readv(uint8_t address, const uint8_t *write_buffer, size_t write_count, uint8_t *read_buffer, size_t read_count) override
bool scan_
Should we scan ? Can be set in the yaml.
std::vector< std::pair< uint8_t, bool > > scan_results_
array containing scan results
ErrorCode
Error codes returned by I2CBus and I2CDevice methods.
@ ERROR_TIMEOUT
timeout while waiting to receive bytes
@ ERROR_NOT_ACKNOWLEDGED
I2C bus acknowledgment not received.
@ ERROR_NOT_INITIALIZED
call method to a not initialized bus
@ ERROR_UNKNOWN
miscellaneous I2C error during execution
@ RECOVERY_FAILED_SDA_LOW
@ RECOVERY_FAILED_SCL_LOW
Providing packet encoding functions for exchanging data with a remote host.
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
std::string format_hex_pretty(const uint8_t *data, size_t length, char separator, bool show_length)
Format a byte array in pretty-printed, human-readable hex format.
Application App
Global storage of Application pointer - only one Application can exist.