Progress
-
Oh lovely. The ESP32 line by Espressif (a fabless semiconductor company) is a line of MCU processors out of China that have 2 hardware I2C busses on them. Two. This is important. Well in previous versions of their development framework you'd simply tell it
I2C_NUM0
orI2C_NUM1
to indicate which bus you were going to send data on. It has been this way through 4 major versions of the framework, and it works similarly in Arduino, at least similarly enough to make code forking minimal if you want to support both platforms. Now Espressif has decided that's not good enough in 5.0+ Now you must configure a bus, and then get a handle for it, rather than using one of two fixed constants. It's unnecessary complexity. Furthermore, it makes supporting both Arduino and ESP-IDF platforms tricky, because there's no bus initialization required to reference an I2C bus with Arduino or ESP-IDF 4- To that end I made a stupid little lib called htcw_esp_i2c. The ugly code is at the end of the post. Now you can do for example to init bus index 1 on pins 21 and 22:static ft6336<320, 280> touch(esp_i2c<1,21,22>::instance);
static m5core2_power power(esp_i2c<1,21,22>::instance);which works on any ESP-IDF 4.0+ or Arduino platform. The issue with this is the code to facilitate it is ugly, and shouldn't need to exist. Was it Einstein? who said "something should be as simple as it can be, and no simpler" Well, code should be that way.
template
class esp_i2c {
public:
#ifdef ARDUINO
static TwoWire& get_instance() {
if(Port==1) {
Wire1.begin(SdaPin,SclPin);
return Wire1;
}
Wire.begin(SdaPin,SclPin);
return Wire;
}
static TwoWire& instance;
#else
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
static i2c_master_bus_handle_t get_instance() {
i2c_master_bus_config_t i2c_mst_config;
memset(&i2c_mst_config,0,sizeof(i2c_mst_config));
i2c_mst_config.clk_source = I2C_CLK_SRC_DEFAULT;
i2c_mst_config.i2c_port = Port==1?I2C_NUM_1:I2C_NUM_0;
i2c_mst_config.scl_io_num = (gpio_num_t)SclPin;
i2c_mst_config.sda_io_num = (gpio_num_t)SdaPin;
i2c_mst_config.glitch_ignore_cnt = 7;
i2c_mst_config.flags.enable_internal_pullup = true;
i2c_master_bus_handle_t bus_handle;
if(ESP_OK!=i2c_new_master_bus(&i2c_mst_config, &bus_handle)) { -
Oh lovely. The ESP32 line by Espressif (a fabless semiconductor company) is a line of MCU processors out of China that have 2 hardware I2C busses on them. Two. This is important. Well in previous versions of their development framework you'd simply tell it
I2C_NUM0
orI2C_NUM1
to indicate which bus you were going to send data on. It has been this way through 4 major versions of the framework, and it works similarly in Arduino, at least similarly enough to make code forking minimal if you want to support both platforms. Now Espressif has decided that's not good enough in 5.0+ Now you must configure a bus, and then get a handle for it, rather than using one of two fixed constants. It's unnecessary complexity. Furthermore, it makes supporting both Arduino and ESP-IDF platforms tricky, because there's no bus initialization required to reference an I2C bus with Arduino or ESP-IDF 4- To that end I made a stupid little lib called htcw_esp_i2c. The ugly code is at the end of the post. Now you can do for example to init bus index 1 on pins 21 and 22:static ft6336<320, 280> touch(esp_i2c<1,21,22>::instance);
static m5core2_power power(esp_i2c<1,21,22>::instance);which works on any ESP-IDF 4.0+ or Arduino platform. The issue with this is the code to facilitate it is ugly, and shouldn't need to exist. Was it Einstein? who said "something should be as simple as it can be, and no simpler" Well, code should be that way.
template
class esp_i2c {
public:
#ifdef ARDUINO
static TwoWire& get_instance() {
if(Port==1) {
Wire1.begin(SdaPin,SclPin);
return Wire1;
}
Wire.begin(SdaPin,SclPin);
return Wire;
}
static TwoWire& instance;
#else
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
static i2c_master_bus_handle_t get_instance() {
i2c_master_bus_config_t i2c_mst_config;
memset(&i2c_mst_config,0,sizeof(i2c_mst_config));
i2c_mst_config.clk_source = I2C_CLK_SRC_DEFAULT;
i2c_mst_config.i2c_port = Port==1?I2C_NUM_1:I2C_NUM_0;
i2c_mst_config.scl_io_num = (gpio_num_t)SclPin;
i2c_mst_config.sda_io_num = (gpio_num_t)SdaPin;
i2c_mst_config.glitch_ignore_cnt = 7;
i2c_mst_config.flags.enable_internal_pullup = true;
i2c_master_bus_handle_t bus_handle;
if(ESP_OK!=i2c_new_master_bus(&i2c_mst_config, &bus_handle)) {honey the codewitch wrote:
#if defined(ARDUINO) || ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
Several seal pups died from this line alone :-D I hate it when you are forced to that kind of ugliness #MaintainMyCode
-
honey the codewitch wrote:
#if defined(ARDUINO) || ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
Several seal pups died from this line alone :-D I hate it when you are forced to that kind of ugliness #MaintainMyCode
Fortunately in the latest revision that went away. What's still really ugly is that static template field initialization code. I hate that C++ makes you do it that way instead of putting the initializer inline. At least C++17 - maybe they've changed that since.
Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix