mirror of
https://github.com/esphome/esphome.git
synced 2025-09-10 23:32:23 +01:00
ESP-IDF support and generic target platforms (#2303)
* Socket refactor and SSL * esp-idf temp * Fixes * Echo component and noise * Add noise API transport support * Updates * ESP-IDF * Complete * Fixes * Fixes * Versions update * New i2c APIs * Complete i2c refactor * SPI migration * Revert ESP Preferences migration, too complex for now * OTA support * Remove echo again * Remove ssl again * GPIOFlags updates * Rename esphal and ICACHE_RAM_ATTR * Make ESP32 arduino compilable again * Fix GPIO flags * Complete pin registry refactor and fixes * Fixes to make test1 compile * Remove sdkconfig file * Ignore sdkconfig file * Fixes in reviewing * Make test2 compile * Make test4 compile * Make test5 compile * Run clang-format * Fix lint errors * Use esp-idf APIs instead of btStart * Another round of fixes * Start implementing ESP8266 * Make test3 compile * Guard esp8266 code * Lint * Reformat * Fixes * Fixes v2 * more fixes * ESP-IDF tidy target * Convert ARDUINO_ARCH_ESPxx * Update WiFiSignalSensor * Update time ifdefs * OTA needs millis from hal * RestartSwitch needs delay from hal * ESP-IDF Uart * Fix OTA blank password * Allow setting sdkconfig * Fix idf partitions and allow setting sdkconfig from yaml * Re-add read/write compat APIs and fix esp8266 uart * Fix esp8266 store log strings in flash * Fix ESP32 arduino preferences not initialized * Update ifdefs * Change how sdkconfig change is detected * Add checks to ci-custom and fix them * Run clang-format * Add esp-idf clang-tidy target and fix errors * Fixes from clang-tidy idf round 2 * Fixes from compiling tests with esp-idf * Run clang-format * Switch test5.yaml to esp-idf * Implement ESP8266 Preferences * Lint * Re-do PIO package version selection a bit * Fix arduinoespressif32 package version * Fix unit tests * Lint * Lint fixes * Fix readv/writev not defined * Fix graphing component * Re-add all old options from core/config.py Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
@@ -1,303 +1,40 @@
|
||||
#include "i2c.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include <memory>
|
||||
|
||||
namespace esphome {
|
||||
namespace i2c {
|
||||
|
||||
static const char *const TAG = "i2c";
|
||||
|
||||
I2CComponent::I2CComponent() {
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
static uint8_t next_i2c_bus_num = 0;
|
||||
if (next_i2c_bus_num == 0)
|
||||
this->wire_ = &Wire;
|
||||
else
|
||||
this->wire_ = new TwoWire(next_i2c_bus_num); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
next_i2c_bus_num++;
|
||||
#else
|
||||
this->wire_ = &Wire; // NOLINT(cppcoreguidelines-prefer-member-initializer)
|
||||
#endif
|
||||
bool I2CDevice::write_bytes_16(uint8_t a_register, const uint16_t *data, uint8_t len) {
|
||||
// we have to copy in order to be able to change byte order
|
||||
std::unique_ptr<uint16_t[]> temp{new uint16_t[len]};
|
||||
for (size_t i = 0; i < len; i++)
|
||||
temp[i] = htoi2cs(data[i]);
|
||||
return write_register(a_register, reinterpret_cast<const uint8_t *>(data), len * 2) == ERROR_OK;
|
||||
}
|
||||
|
||||
void I2CComponent::setup() {
|
||||
this->wire_->begin(this->sda_pin_, this->scl_pin_);
|
||||
this->wire_->setClock(this->frequency_);
|
||||
}
|
||||
void I2CComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "I2C Bus:");
|
||||
ESP_LOGCONFIG(TAG, " SDA Pin: GPIO%u", this->sda_pin_);
|
||||
ESP_LOGCONFIG(TAG, " SCL Pin: GPIO%u", this->scl_pin_);
|
||||
ESP_LOGCONFIG(TAG, " Frequency: %u Hz", this->frequency_);
|
||||
if (this->scan_) {
|
||||
ESP_LOGI(TAG, "Scanning i2c bus for active devices...");
|
||||
uint8_t found = 0;
|
||||
for (uint8_t address = 1; address < 120; address++) {
|
||||
this->wire_->beginTransmission(address);
|
||||
uint8_t error = this->wire_->endTransmission();
|
||||
|
||||
if (error == 0) {
|
||||
ESP_LOGI(TAG, "Found i2c device at address 0x%02X", address);
|
||||
found++;
|
||||
} else if (error == 4) {
|
||||
ESP_LOGI(TAG, "Unknown error at address 0x%02X", address);
|
||||
}
|
||||
|
||||
delay(1);
|
||||
}
|
||||
if (found == 0) {
|
||||
ESP_LOGI(TAG, "Found no i2c devices!");
|
||||
}
|
||||
}
|
||||
}
|
||||
float I2CComponent::get_setup_priority() const { return setup_priority::BUS; }
|
||||
|
||||
void I2CComponent::raw_begin_transmission(uint8_t address) {
|
||||
ESP_LOGVV(TAG, "Beginning Transmission to 0x%02X:", address);
|
||||
this->wire_->beginTransmission(address);
|
||||
}
|
||||
bool I2CComponent::raw_end_transmission(uint8_t address, bool send_stop) {
|
||||
uint8_t status = this->wire_->endTransmission(send_stop);
|
||||
ESP_LOGVV(TAG, " Transmission ended. Status code: 0x%02X", status);
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
ESP_LOGW(TAG, "Too much data to fit in transmitter buffer for address 0x%02X", address);
|
||||
break;
|
||||
case 2:
|
||||
ESP_LOGW(TAG, "Received NACK on transmit of address 0x%02X", address);
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGW(TAG, "Received NACK on transmit of data for address 0x%02X", address);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "Unknown transmit error %u for address 0x%02X", status, address);
|
||||
break;
|
||||
}
|
||||
|
||||
return status == 0;
|
||||
}
|
||||
bool I2CComponent::raw_request_from(uint8_t address, uint8_t len) {
|
||||
ESP_LOGVV(TAG, "Requesting %u bytes from 0x%02X:", len, address);
|
||||
uint8_t ret = this->wire_->requestFrom(address, len);
|
||||
if (ret != len) {
|
||||
ESP_LOGW(TAG, "Requesting %u bytes from 0x%02X failed!", len, address);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void HOT I2CComponent::raw_write(uint8_t address, const uint8_t *data, uint8_t len) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
ESP_LOGVV(TAG, " Writing 0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(data[i]), data[i]);
|
||||
this->wire_->write(data[i]);
|
||||
App.feed_wdt();
|
||||
}
|
||||
}
|
||||
void HOT I2CComponent::raw_write_16(uint8_t address, const uint16_t *data, uint8_t len) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
ESP_LOGVV(TAG, " Writing 0b" BYTE_TO_BINARY_PATTERN BYTE_TO_BINARY_PATTERN " (0x%04X)",
|
||||
BYTE_TO_BINARY(data[i] >> 8), BYTE_TO_BINARY(data[i]), data[i]);
|
||||
this->wire_->write(data[i] >> 8);
|
||||
this->wire_->write(data[i]);
|
||||
App.feed_wdt();
|
||||
}
|
||||
}
|
||||
|
||||
bool I2CComponent::raw_receive(uint8_t address, uint8_t *data, uint8_t len) {
|
||||
if (!this->raw_request_from(address, len))
|
||||
return false;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
data[i] = this->wire_->read();
|
||||
ESP_LOGVV(TAG, " Received 0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(data[i]), data[i]);
|
||||
App.feed_wdt();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool I2CComponent::raw_receive_16(uint8_t address, uint16_t *data, uint8_t len) {
|
||||
if (!this->raw_request_from(address, len * 2))
|
||||
return false;
|
||||
auto *data_8 = reinterpret_cast<uint8_t *>(data);
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
data_8[i * 2 + 1] = this->wire_->read();
|
||||
data_8[i * 2] = this->wire_->read();
|
||||
ESP_LOGVV(TAG, " Received 0b" BYTE_TO_BINARY_PATTERN BYTE_TO_BINARY_PATTERN " (0x%04X)",
|
||||
BYTE_TO_BINARY(data_8[i * 2 + 1]), BYTE_TO_BINARY(data_8[i * 2]), data[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool I2CComponent::read_bytes(uint8_t address, uint8_t a_register, uint8_t *data, uint8_t len, uint32_t conversion) {
|
||||
if (!this->write_bytes(address, a_register, nullptr, 0))
|
||||
return false;
|
||||
|
||||
if (conversion > 0)
|
||||
delay(conversion);
|
||||
return this->raw_receive(address, data, len);
|
||||
}
|
||||
bool I2CComponent::read_bytes_raw(uint8_t address, uint8_t *data, uint8_t len) {
|
||||
return this->raw_receive(address, data, len);
|
||||
}
|
||||
bool I2CComponent::read_bytes_16(uint8_t address, uint8_t a_register, uint16_t *data, uint8_t len,
|
||||
uint32_t conversion) {
|
||||
if (!this->write_bytes(address, a_register, nullptr, 0))
|
||||
return false;
|
||||
|
||||
if (conversion > 0)
|
||||
delay(conversion);
|
||||
return this->raw_receive_16(address, data, len);
|
||||
}
|
||||
bool I2CComponent::read_byte(uint8_t address, uint8_t a_register, uint8_t *data, uint32_t conversion) {
|
||||
return this->read_bytes(address, a_register, data, 1, conversion);
|
||||
}
|
||||
bool I2CComponent::read_byte_16(uint8_t address, uint8_t a_register, uint16_t *data, uint32_t conversion) {
|
||||
return this->read_bytes_16(address, a_register, data, 1, conversion);
|
||||
}
|
||||
bool I2CComponent::write_bytes(uint8_t address, uint8_t a_register, const uint8_t *data, uint8_t len) {
|
||||
this->raw_begin_transmission(address);
|
||||
this->raw_write(address, &a_register, 1);
|
||||
this->raw_write(address, data, len);
|
||||
return this->raw_end_transmission(address);
|
||||
}
|
||||
bool I2CComponent::write_bytes_raw(uint8_t address, const uint8_t *data, uint8_t len) {
|
||||
this->raw_begin_transmission(address);
|
||||
this->raw_write(address, data, len);
|
||||
return this->raw_end_transmission(address);
|
||||
}
|
||||
bool I2CComponent::write_bytes_16(uint8_t address, uint8_t a_register, const uint16_t *data, uint8_t len) {
|
||||
this->raw_begin_transmission(address);
|
||||
this->raw_write(address, &a_register, 1);
|
||||
this->raw_write_16(address, data, len);
|
||||
return this->raw_end_transmission(address);
|
||||
}
|
||||
bool I2CComponent::write_byte(uint8_t address, uint8_t a_register, uint8_t data) {
|
||||
return this->write_bytes(address, a_register, &data, 1);
|
||||
}
|
||||
bool I2CComponent::write_byte_16(uint8_t address, uint8_t a_register, uint16_t data) {
|
||||
return this->write_bytes_16(address, a_register, &data, 1);
|
||||
}
|
||||
|
||||
void I2CDevice::set_i2c_address(uint8_t address) { this->address_ = address; }
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
void I2CDevice::set_i2c_multiplexer(I2CMultiplexer *multiplexer, uint8_t channel) {
|
||||
ESP_LOGVV(TAG, " Setting Multiplexer %p for channel %d", multiplexer, channel);
|
||||
this->multiplexer_ = multiplexer;
|
||||
this->channel_ = channel;
|
||||
}
|
||||
|
||||
void I2CDevice::check_multiplexer_() {
|
||||
if (this->multiplexer_ != nullptr) {
|
||||
ESP_LOGVV(TAG, "Multiplexer setting channel to %d", this->channel_);
|
||||
this->multiplexer_->set_channel(this->channel_);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void I2CDevice::raw_begin_transmission() { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
this->parent_->raw_begin_transmission(this->address_);
|
||||
}
|
||||
bool I2CDevice::raw_end_transmission(bool send_stop) { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
return this->parent_->raw_end_transmission(this->address_, send_stop);
|
||||
}
|
||||
void I2CDevice::raw_write(const uint8_t *data, uint8_t len) { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
this->parent_->raw_write(this->address_, data, len);
|
||||
}
|
||||
bool I2CDevice::read_bytes(uint8_t a_register, uint8_t *data, uint8_t len, uint32_t conversion) { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
return this->parent_->read_bytes(this->address_, a_register, data, len, conversion);
|
||||
}
|
||||
bool I2CDevice::read_bytes_raw(uint8_t *data, uint8_t len) { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
return this->parent_->read_bytes_raw(this->address_, data, len);
|
||||
}
|
||||
bool I2CDevice::read_byte(uint8_t a_register, uint8_t *data, uint32_t conversion) { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
return this->parent_->read_byte(this->address_, a_register, data, conversion);
|
||||
}
|
||||
bool I2CDevice::write_bytes(uint8_t a_register, const uint8_t *data, uint8_t len) { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
return this->parent_->write_bytes(this->address_, a_register, data, len);
|
||||
}
|
||||
bool I2CDevice::write_bytes_raw(const uint8_t *data, uint8_t len) { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
return this->parent_->write_bytes_raw(this->address_, data, len);
|
||||
}
|
||||
bool I2CDevice::write_byte(uint8_t a_register, uint8_t data) { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
return this->parent_->write_byte(this->address_, a_register, data);
|
||||
}
|
||||
bool I2CDevice::read_bytes_16(uint8_t a_register, uint16_t *data, uint8_t len, uint32_t conversion) { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
return this->parent_->read_bytes_16(this->address_, a_register, data, len, conversion);
|
||||
}
|
||||
bool I2CDevice::read_byte_16(uint8_t a_register, uint16_t *data, uint32_t conversion) { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
return this->parent_->read_byte_16(this->address_, a_register, data, conversion);
|
||||
}
|
||||
bool I2CDevice::write_bytes_16(uint8_t a_register, const uint16_t *data, uint8_t len) { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
return this->parent_->write_bytes_16(this->address_, a_register, data, len);
|
||||
}
|
||||
bool I2CDevice::write_byte_16(uint8_t a_register, uint16_t data) { // NOLINT
|
||||
#ifdef USE_I2C_MULTIPLEXER
|
||||
this->check_multiplexer_();
|
||||
#endif
|
||||
return this->parent_->write_byte_16(this->address_, a_register, data);
|
||||
}
|
||||
void I2CDevice::set_i2c_parent(I2CComponent *parent) { this->parent_ = parent; }
|
||||
|
||||
I2CRegister &I2CRegister::operator=(uint8_t value) {
|
||||
this->parent_->write_byte(this->register_, value);
|
||||
this->parent_->write_register(this->register_, &value, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
I2CRegister &I2CRegister::operator&=(uint8_t value) {
|
||||
this->parent_->write_byte(this->register_, this->get() & value);
|
||||
value &= get();
|
||||
this->parent_->write_register(this->register_, &value, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
I2CRegister &I2CRegister::operator|=(uint8_t value) {
|
||||
this->parent_->write_byte(this->register_, this->get() | value);
|
||||
value |= get();
|
||||
this->parent_->write_register(this->register_, &value, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint8_t I2CRegister::get() {
|
||||
uint8_t I2CRegister::get() const {
|
||||
uint8_t value = 0x00;
|
||||
this->parent_->read_byte(this->register_, &value);
|
||||
this->parent_->read_register(this->register_, &value, 1);
|
||||
return value;
|
||||
}
|
||||
I2CRegister &I2CRegister::operator=(const std::vector<uint8_t> &value) {
|
||||
this->parent_->write_bytes(this->register_, value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace i2c
|
||||
} // namespace esphome
|
||||
|
Reference in New Issue
Block a user