diff --git a/components/ads1x15/example/CMakeLists.txt b/components/ads1x15/example/CMakeLists.txt index c26e719a0..d2eca9e43 100644 --- a/components/ads1x15/example/CMakeLists.txt +++ b/components/ads1x15/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver ads1x15 adc task controller" + "main esptool_py ads1x15 i2c task" CACHE STRING "List of components to include" ) diff --git a/components/ads1x15/example/main/Kconfig.projbuild b/components/ads1x15/example/main/Kconfig.projbuild new file mode 100644 index 000000000..dfc846b7d --- /dev/null +++ b/components/ads1x15/example/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_QTPYPICO + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_QTPYPICO + depends on IDF_TARGET_ESP32 + bool "Qt Py PICO" + + config EXAMPLE_HARDWARE_QTPYS3 + depends on IDF_TARGET_ESP32S3 + bool "Qt Py S3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 19 if EXAMPLE_HARDWARE_QTPYPICO + default 40 if EXAMPLE_HARDWARE_QTPYS3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 22 if EXAMPLE_HARDWARE_QTPYPICO + default 41 if EXAMPLE_HARDWARE_QTPYS3 + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/ads1x15/example/main/ads1x15_example.cpp b/components/ads1x15/example/main/ads1x15_example.cpp index 2d034e7e7..255ad24ed 100644 --- a/components/ads1x15/example/main/ads1x15_example.cpp +++ b/components/ads1x15/example/main/ads1x15_example.cpp @@ -1,20 +1,14 @@ #include +#include #include -#include "driver/i2c.h" - #include "ads1x15.hpp" +#include "i2c.hpp" #include "logger.hpp" #include "task.hpp" using namespace std::chrono_literals; -static constexpr auto I2C_NUM = (I2C_NUM_1); -static constexpr auto I2C_SCL_IO = (GPIO_NUM_19); -static constexpr auto I2C_SDA_IO = (GPIO_NUM_22); -static constexpr auto I2C_FREQ_HZ = (400 * 1000); -static constexpr auto I2C_TIMEOUT_MS = 10; - extern "C" void app_main(void) { static espp::Logger logger({.tag = "ads1015 example", .level = espp::Logger::Verbosity::INFO}); // This example shows using the i2c adc (ads1x15) @@ -22,35 +16,18 @@ extern "C" void app_main(void) { logger.info("Running i2c adc example!"); //! [ads1x15 example] // make the I2C that we'll use to communicate - i2c_config_t i2c_cfg; - logger.info("initializing i2c driver..."); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; // pin 3 on the joybonnet - i2c_cfg.scl_io_num = I2C_SCL_IO; // pin 5 on the joybonnet - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) - logger.error("config i2c failed"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) - logger.error("install i2c driver failed"); - // make some lambda functions we'll use to read/write to the i2c adc - auto ads_write = [](uint8_t dev_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_to_device(I2C_NUM, dev_addr, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; - auto ads_read = [](uint8_t dev_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_read_from_device(I2C_NUM, dev_addr, - data, data_len, I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; + espp::I2c i2c({ + .port = I2C_NUM_1, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, // pin 3 on the joybonnet + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, // pin 5 on the joybonnet + }); // make the actual ads class espp::Ads1x15 ads(espp::Ads1x15::Ads1015Config{ - .device_address = espp::Ads1x15::DEFAULT_ADDRESS, .write = ads_write, .read = ads_read}); + .device_address = espp::Ads1x15::DEFAULT_ADDRESS, + .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3)}); // make the task which will get the raw data from the I2C ADC auto ads_read_task_fn = [&ads](std::mutex &m, std::condition_variable &cv) { static auto start = std::chrono::high_resolution_clock::now(); @@ -89,9 +66,6 @@ extern "C" void app_main(void) { std::this_thread::sleep_for(100ms); } } - // now clean up the i2c driver (by now the task will have stopped, because we - // left its scope. - i2c_driver_delete(I2C_NUM); logger.info("ADS1x15 example complete!"); diff --git a/components/ads7138/example/CMakeLists.txt b/components/ads7138/example/CMakeLists.txt index 1036a1142..54394db72 100644 --- a/components/ads7138/example/CMakeLists.txt +++ b/components/ads7138/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver ads7138 adc task controller" + "main esptool_py driver ads7138 i2c task" CACHE STRING "List of components to include" ) diff --git a/components/ads7138/example/main/Kconfig.projbuild b/components/ads7138/example/main/Kconfig.projbuild new file mode 100644 index 000000000..9fb91cf07 --- /dev/null +++ b/components/ads7138/example/main/Kconfig.projbuild @@ -0,0 +1,46 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_QTPYS3 + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_QTPYPICO + depends on IDF_TARGET_ESP32 + bool "Qt Py PICO" + + config EXAMPLE_HARDWARE_QTPYS3 + depends on IDF_TARGET_ESP32S3 + bool "Qt Py S3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_ALERT_GPIO + int "Alert GPIO Num" + range 0 50 + default 18 + help + GPIO number for alert pin. + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 19 if EXAMPLE_HARDWARE_QTPYPICO + default 40 if EXAMPLE_HARDWARE_QTPYS3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 22 if EXAMPLE_HARDWARE_QTPYPICO + default 41 if EXAMPLE_HARDWARE_QTPYS3 + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/ads7138/example/main/ads7138_example.cpp b/components/ads7138/example/main/ads7138_example.cpp index f3812540b..9d820a22e 100644 --- a/components/ads7138/example/main/ads7138_example.cpp +++ b/components/ads7138/example/main/ads7138_example.cpp @@ -1,10 +1,11 @@ #include +#include #include #include "driver/gpio.h" -#include "driver/i2c.h" #include "ads7138.hpp" +#include "i2c.hpp" #include "logger.hpp" #include "task.hpp" @@ -64,13 +65,6 @@ using namespace std::chrono_literals; // active low, so when we set the digital output to 1, the LED should turn off, // and when we set the digital output to 0, the LED should turn on. We can // change the digital output value by pressing the button on the joystick. -static constexpr auto ALERT_PIN = (GPIO_NUM_18); -static constexpr auto I2C_NUM = (I2C_NUM_1); -static constexpr auto I2C_SCL_IO = (GPIO_NUM_40); -static constexpr auto I2C_SDA_IO = (GPIO_NUM_41); -static constexpr auto I2C_FREQ_HZ = (400 * 1000); -static constexpr auto I2C_TIMEOUT_MS = (10); - static QueueHandle_t gpio_evt_queue; static void gpio_isr_handler(void *arg) { @@ -85,34 +79,13 @@ extern "C" void app_main(void) { logger.info("Starting example!"); //! [ads7138 example] + static constexpr gpio_num_t ALERT_PIN = (gpio_num_t)CONFIG_EXAMPLE_ALERT_GPIO; // make the I2C that we'll use to communicate - i2c_config_t i2c_cfg; - logger.info("initializing i2c driver..."); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; - i2c_cfg.scl_io_num = I2C_SCL_IO; - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_DISABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_DISABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) - logger.error("config i2c failed"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) - logger.error("install i2c driver failed"); - - // make some lambda functions we'll use to read/write to the i2c adc - auto ads_write = [](uint8_t dev_addr, uint8_t *data, size_t data_len) -> bool { - auto err = i2c_master_write_to_device(I2C_NUM, dev_addr, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; - auto ads_read = [](uint8_t dev_addr, uint8_t *data, size_t data_len) -> bool { - auto err = i2c_master_read_from_device(I2C_NUM, dev_addr, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; + espp::I2c i2c({ + .port = I2C_NUM_1, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, + }); // make the actual ads class static int select_bit_mask = (1 << 5); @@ -127,8 +100,10 @@ extern "C" void app_main(void) { .digital_output_values = {{espp::Ads7138::Channel::CH7, 1}}, // start the LED off // enable oversampling / averaging .oversampling_ratio = espp::Ads7138::OversamplingRatio::OSR_32, - .write = ads_write, - .read = ads_read, + .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), .log_level = espp::Logger::Verbosity::WARN, }); @@ -277,9 +252,6 @@ extern "C" void app_main(void) { std::this_thread::sleep_for(100ms); } } - // now clean up the i2c driver (by now the task will have stopped, because we - // left its scope. - i2c_driver_delete(I2C_NUM); logger.info("ADS7138 example complete!"); diff --git a/components/as5600/example/CMakeLists.txt b/components/as5600/example/CMakeLists.txt index eb1ed2683..b828b54ae 100644 --- a/components/as5600/example/CMakeLists.txt +++ b/components/as5600/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py filters driver task as5600" + "main esptool_py filters i2c task as5600" CACHE STRING "List of components to include" ) diff --git a/components/as5600/example/main/Kconfig.projbuild b/components/as5600/example/main/Kconfig.projbuild new file mode 100644 index 000000000..926929e92 --- /dev/null +++ b/components/as5600/example/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_QTPYS3 + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_QTPYPICO + depends on IDF_TARGET_ESP32 + bool "Qt Py PICO" + + config EXAMPLE_HARDWARE_QTPYS3 + depends on IDF_TARGET_ESP32S3 + bool "Qt Py S3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 19 if EXAMPLE_HARDWARE_QTPYPICO + default 40 if EXAMPLE_HARDWARE_QTPYS3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 22 if EXAMPLE_HARDWARE_QTPYPICO + default 41 if EXAMPLE_HARDWARE_QTPYS3 + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/as5600/example/main/as5600_example.cpp b/components/as5600/example/main/as5600_example.cpp index 827568361..e4f34b4ea 100644 --- a/components/as5600/example/main/as5600_example.cpp +++ b/components/as5600/example/main/as5600_example.cpp @@ -1,53 +1,26 @@ #include +#include #include -#include "driver/i2c.h" - #include "as5600.hpp" #include "butterworth_filter.hpp" +#include "i2c.hpp" #include "task.hpp" using namespace std::chrono_literals; -#define I2C_NUM (I2C_NUM_1) -#define I2C_SCL_IO (GPIO_NUM_40) -#define I2C_SDA_IO (GPIO_NUM_41) -#define I2C_FREQ_HZ (400 * 1000) -#define I2C_TIMEOUT_MS (10) - extern "C" void app_main(void) { { std::atomic quit_test = false; fmt::print("Starting as5600 example, rotate to -720 degrees to quit!\n"); //! [as5600 example] // make the I2C that we'll use to communicate - i2c_config_t i2c_cfg; - fmt::print("initializing i2c driver...\n"); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; - i2c_cfg.scl_io_num = I2C_SCL_IO; - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) - printf("config i2c failed\n"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) - printf("install i2c driver failed\n"); - // make some lambda functions we'll use to read/write to the as5600 - auto as5600_write = [](uint8_t dev_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_to_device(I2C_NUM, dev_addr, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; + espp::I2c i2c({ + .port = I2C_NUM_1, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, + }); - auto as5600_read = [](uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_read_device(I2C_NUM, dev_addr, ®_addr, 1, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; // make the velocity filter static constexpr float filter_cutoff_hz = 4.0f; static constexpr float encoder_update_period = 0.01f; // seconds @@ -56,12 +29,17 @@ extern "C" void app_main(void) { // NOTE: we could just as easily disable filtering by simply returning the // raw value from this function auto filter_fn = [&filter](float raw) -> float { return filter.update(raw); }; + // now make the as5600 which decodes the data - espp::As5600 as5600({.write = as5600_write, - .read = as5600_read, - .velocity_filter = filter_fn, - .update_period = std::chrono::duration(encoder_update_period), - .log_level = espp::Logger::Verbosity::WARN}); + espp::As5600 as5600( + {.write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read_at_register, &i2c, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + .velocity_filter = filter_fn, + .update_period = std::chrono::duration(encoder_update_period), + .log_level = espp::Logger::Verbosity::WARN}); + // and finally, make the task to periodically poll the as5600 and print the // state. NOTE: the As5600 runs its own task to maintain state, so we're // just polling the current state. @@ -94,8 +72,6 @@ extern "C" void app_main(void) { while (!quit_test) { std::this_thread::sleep_for(100ms); } - // now clean up the i2c driver - i2c_driver_delete(I2C_NUM); } fmt::print("As5600 example complete!\n"); diff --git a/components/aw9523/example/CMakeLists.txt b/components/aw9523/example/CMakeLists.txt index c7d365a4d..273c7926e 100644 --- a/components/aw9523/example/CMakeLists.txt +++ b/components/aw9523/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver task aw9523" + "main esptool_py task i2c aw9523" CACHE STRING "List of components to include" ) diff --git a/components/aw9523/example/main/Kconfig.projbuild b/components/aw9523/example/main/Kconfig.projbuild new file mode 100644 index 000000000..dfc846b7d --- /dev/null +++ b/components/aw9523/example/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_QTPYPICO + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_QTPYPICO + depends on IDF_TARGET_ESP32 + bool "Qt Py PICO" + + config EXAMPLE_HARDWARE_QTPYS3 + depends on IDF_TARGET_ESP32S3 + bool "Qt Py S3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 19 if EXAMPLE_HARDWARE_QTPYPICO + default 40 if EXAMPLE_HARDWARE_QTPYS3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 22 if EXAMPLE_HARDWARE_QTPYPICO + default 41 if EXAMPLE_HARDWARE_QTPYS3 + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/aw9523/example/main/aw9523_example.cpp b/components/aw9523/example/main/aw9523_example.cpp index d11ae0828..408dab408 100644 --- a/components/aw9523/example/main/aw9523_example.cpp +++ b/components/aw9523/example/main/aw9523_example.cpp @@ -1,19 +1,13 @@ #include +#include #include -#include "driver/i2c.h" - #include "aw9523.hpp" +#include "i2c.hpp" #include "task.hpp" using namespace std::chrono_literals; -static constexpr auto I2C_NUM = I2C_NUM_1; -static constexpr auto I2C_SCL_IO = GPIO_NUM_19; -static constexpr auto I2C_SDA_IO = GPIO_NUM_22; -static constexpr auto I2C_FREQ_HZ = (400 * 1000); -static constexpr auto I2C_TIMEOUT_MS = 10; - extern "C" void app_main(void) { fmt::print("Starting aw9523 example, controls:\n" @@ -26,45 +20,25 @@ extern "C" void app_main(void) { "\n"); //! [aw9523 example] // make the I2C that we'll use to communicate - i2c_config_t i2c_cfg; - fmt::print("initializing i2c driver...\n"); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; - i2c_cfg.scl_io_num = I2C_SCL_IO; - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) - printf("config i2c failed\n"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) - printf("install i2c driver failed\n"); - // make some lambda functions we'll use to read/write to the aw9523 - auto aw9523_write = [](uint8_t dev_addr, uint8_t *data, size_t data_len) -> bool { - auto err = i2c_master_write_to_device(I2C_NUM, dev_addr, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; - - auto aw9523_read = [](uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, - size_t data_len) -> bool { - auto err = i2c_master_write_read_device(I2C_NUM, dev_addr, ®_addr, 1, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; + espp::I2c i2c({ + .port = I2C_NUM_1, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, + }); // now make the aw9523 which handles GPIO - espp::Aw9523 aw9523({// since this uses LEDs, both of the address pins are pulled up in - // hardware to have the LEDs default to off - .device_address = espp::Aw9523::DEFAULT_ADDRESS | 0b11, - // set P0_0 - P0_5 to be inputs - .port_0_direction_mask = 0b00111111, - // set P1_0 - P1_1 to be inputs - .port_1_direction_mask = 0b00000011, - .write = aw9523_write, - .read = aw9523_read, - .log_level = espp::Logger::Verbosity::WARN}); + espp::Aw9523 aw9523( + {// since this uses LEDs, both of the address pins are pulled up in + // hardware to have the LEDs default to off + .device_address = espp::Aw9523::DEFAULT_ADDRESS | 0b11, + // set P0_0 - P0_5 to be inputs + .port_0_direction_mask = 0b00111111, + // set P1_0 - P1_1 to be inputs + .port_1_direction_mask = 0b00000011, + .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read_at_register, &i2c, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + .log_level = espp::Logger::Verbosity::WARN}); std::error_code ec; aw9523.initialize(ec); // Initialized separately from the constructor. if (ec) { @@ -153,8 +127,6 @@ extern "C" void app_main(void) { while (true) { std::this_thread::sleep_for(100ms); } - // now clean up the i2c driver - i2c_driver_delete(I2C_NUM); fmt::print("Aw9523 example complete!\n"); diff --git a/components/bldc_haptics/example/CMakeLists.txt b/components/bldc_haptics/example/CMakeLists.txt index 9ab603863..a8f5b9724 100644 --- a/components/bldc_haptics/example/CMakeLists.txt +++ b/components/bldc_haptics/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py filters task monitor mt6701 bldc_motor bldc_driver bldc_haptics" + "main esptool_py filters task monitor mt6701 bldc_motor bldc_driver bldc_haptics i2c" CACHE STRING "List of components to include" ) diff --git a/components/bldc_haptics/example/main/Kconfig.projbuild b/components/bldc_haptics/example/main/Kconfig.projbuild new file mode 100644 index 000000000..eaedcec09 --- /dev/null +++ b/components/bldc_haptics/example/main/Kconfig.projbuild @@ -0,0 +1,33 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_TEST_STAND + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_TEST_STAND + depends on IDF_TARGET_ESP32S3 + bool "BLDC Motor Test Stand (TinyS3)" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 9 if EXAMPLE_HARDWARE_TEST_STAND + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 8 if EXAMPLE_HARDWARE_TEST_STAND + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/bldc_haptics/example/main/bldc_haptics_example.cpp b/components/bldc_haptics/example/main/bldc_haptics_example.cpp index dd546a70e..0d6e2071e 100644 --- a/components/bldc_haptics/example/main/bldc_haptics_example.cpp +++ b/components/bldc_haptics/example/main/bldc_haptics_example.cpp @@ -1,25 +1,18 @@ #include +#include #include -#include "driver/i2c.h" - #include "bldc_driver.hpp" #include "bldc_haptics.hpp" #include "bldc_motor.hpp" #include "butterworth_filter.hpp" +#include "i2c.hpp" #include "lowpass_filter.hpp" #include "mt6701.hpp" #include "task.hpp" using namespace std::chrono_literals; -// pins for the bldc motor test stand with the TinyS3 -static constexpr auto I2C_NUM = (I2C_NUM_1); -static constexpr auto I2C_SCL_IO = (GPIO_NUM_9); -static constexpr auto I2C_SDA_IO = (GPIO_NUM_8); -static constexpr int I2C_FREQ_HZ = (400 * 1000); -static constexpr int I2C_TIMEOUT_MS = (10); - extern "C" void app_main(void) { espp::Logger logger({.tag = "BLDC Haptics Example", .level = espp::Logger::Verbosity::DEBUG}); constexpr int num_seconds_to_run = 20; @@ -27,33 +20,12 @@ extern "C" void app_main(void) { logger.info("Running BLDC Haptics example for {} seconds!", num_seconds_to_run); // make the I2C that we'll use to communicate with the mt6701 (magnetic encoder) - i2c_config_t i2c_cfg; logger.info("initializing i2c driver..."); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; - i2c_cfg.scl_io_num = I2C_SCL_IO; - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) - logger.error("config i2c failed"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) - logger.error("install i2c driver failed"); - // make some lambda functions we'll use to read/write to the mt6701 - auto i2c_write = [](uint8_t dev_addr, uint8_t *data, size_t len) { - auto err = i2c_master_write_to_device(I2C_NUM, dev_addr, data, len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; - - auto i2c_read = [](uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, size_t len) { - auto err = i2c_master_write_read_device(I2C_NUM, dev_addr, ®_addr, 1, data, len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; + espp::I2c i2c({ + .port = I2C_NUM_1, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, + }); // make the velocity filter static constexpr float core_update_period = 0.001f; // seconds @@ -78,12 +50,14 @@ extern "C" void app_main(void) { }; // now make the mt6701 which decodes the data - std::shared_ptr mt6701 = std::make_shared( - espp::Mt6701::Config{.write = i2c_write, - .read = i2c_read, - .velocity_filter = filter_fn, - .update_period = std::chrono::duration(core_update_period), - .log_level = espp::Logger::Verbosity::WARN}); + std::shared_ptr mt6701 = std::make_shared(espp::Mt6701::Config{ + .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read_at_register, &i2c, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + .velocity_filter = filter_fn, + .update_period = std::chrono::duration(core_update_period), + .log_level = espp::Logger::Verbosity::WARN}); // now make the bldc driver std::shared_ptr driver = @@ -228,8 +202,6 @@ extern "C" void app_main(void) { driver->disable(); } - // now clean up the i2c driver - i2c_driver_delete(I2C_NUM); logger.info("BLDC Haptics example complete!"); diff --git a/components/bldc_motor/example/CMakeLists.txt b/components/bldc_motor/example/CMakeLists.txt index cc7c9ccaf..7161e1888 100644 --- a/components/bldc_motor/example/CMakeLists.txt +++ b/components/bldc_motor/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py filters task monitor mt6701 bldc_motor bldc_driver" + "main esptool_py filters task monitor mt6701 bldc_motor bldc_driver i2c" CACHE STRING "List of components to include" ) diff --git a/components/bldc_motor/example/main/Kconfig.projbuild b/components/bldc_motor/example/main/Kconfig.projbuild new file mode 100644 index 000000000..eaedcec09 --- /dev/null +++ b/components/bldc_motor/example/main/Kconfig.projbuild @@ -0,0 +1,33 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_TEST_STAND + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_TEST_STAND + depends on IDF_TARGET_ESP32S3 + bool "BLDC Motor Test Stand (TinyS3)" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 9 if EXAMPLE_HARDWARE_TEST_STAND + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 8 if EXAMPLE_HARDWARE_TEST_STAND + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/bldc_motor/example/main/bldc_motor_example.cpp b/components/bldc_motor/example/main/bldc_motor_example.cpp index 6a9ecfb7a..c3a8ab2fa 100644 --- a/components/bldc_motor/example/main/bldc_motor_example.cpp +++ b/components/bldc_motor/example/main/bldc_motor_example.cpp @@ -1,11 +1,11 @@ #include +#include #include -#include "driver/i2c.h" - #include "bldc_driver.hpp" #include "bldc_motor.hpp" #include "butterworth_filter.hpp" +#include "i2c.hpp" #include "logger.hpp" #include "lowpass_filter.hpp" #include "mt6701.hpp" @@ -14,13 +14,6 @@ using namespace std::chrono_literals; -// pins for the bldc motor test stand with the TinyS3 -static constexpr auto I2C_NUM = (I2C_NUM_1); -static constexpr auto I2C_SCL_IO = (GPIO_NUM_9); -static constexpr auto I2C_SDA_IO = (GPIO_NUM_8); -static constexpr int I2C_FREQ_HZ = (400 * 1000); -static constexpr int I2C_TIMEOUT_MS = (10); - extern "C" void app_main(void) { espp::Logger logger({.tag = "BLDC Motor example", .level = espp::Logger::Verbosity::DEBUG}); constexpr int num_seconds_to_run = 120; @@ -28,33 +21,12 @@ extern "C" void app_main(void) { logger.info("Running BLDC Motor (FOC) example for {} seconds!", num_seconds_to_run); // make the I2C that we'll use to communicate with the mt6701 (magnetic encoder) - i2c_config_t i2c_cfg; logger.info("initializing i2c driver..."); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; - i2c_cfg.scl_io_num = I2C_SCL_IO; - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) - logger.error("config i2c failed"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) - logger.error("install i2c driver failed"); - // make some lambda functions we'll use to read/write to the mt6701 - auto mt6701_write = [](uint8_t dev_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_to_device(I2C_NUM, dev_addr, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; - - auto mt6701_read = [](uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_read_device(I2C_NUM, dev_addr, ®_addr, 1, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; + espp::I2c i2c({ + .port = I2C_NUM_1, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, + }); // make the velocity filter static constexpr float core_update_period = 0.001f; // seconds @@ -79,12 +51,14 @@ extern "C" void app_main(void) { //! [bldc_motor example] // now make the mt6701 which decodes the data - std::shared_ptr mt6701 = std::make_shared( - espp::Mt6701::Config{.write = mt6701_write, - .read = mt6701_read, - .velocity_filter = filter_fn, - .update_period = std::chrono::duration(core_update_period), - .log_level = espp::Logger::Verbosity::WARN}); + std::shared_ptr mt6701 = std::make_shared(espp::Mt6701::Config{ + .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read_at_register, &i2c, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + .velocity_filter = filter_fn, + .update_period = std::chrono::duration(core_update_period), + .log_level = espp::Logger::Verbosity::WARN}); // now make the bldc driver std::shared_ptr driver = @@ -292,8 +266,6 @@ extern "C" void app_main(void) { std::this_thread::sleep_for(500ms); } } - // now clean up the i2c driver - i2c_driver_delete(I2C_NUM); logger.info("BLDC Motor (FOC) example complete!"); diff --git a/components/bm8563/example/CMakeLists.txt b/components/bm8563/example/CMakeLists.txt index b3ccd506b..bff00d68a 100644 --- a/components/bm8563/example/CMakeLists.txt +++ b/components/bm8563/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver task bm8563 i2c" + "main esptool_py task bm8563 i2c" CACHE STRING "List of components to include" ) diff --git a/components/bm8563/example/main/Kconfig.projbuild b/components/bm8563/example/main/Kconfig.projbuild new file mode 100644 index 000000000..93cf4ee39 --- /dev/null +++ b/components/bm8563/example/main/Kconfig.projbuild @@ -0,0 +1,33 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_TIMERCAM + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_TIMERCAM + depends on IDF_TARGET_ESP32 + bool "ESP32 TimerCam + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 14 if EXAMPLE_HARDWARE_TIMERCAM + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 12 if EXAMPLE_HARDWARE_TIMERCAM + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/bm8563/example/main/bm8563_example.cpp b/components/bm8563/example/main/bm8563_example.cpp index 4ba2527a6..32b89af54 100644 --- a/components/bm8563/example/main/bm8563_example.cpp +++ b/components/bm8563/example/main/bm8563_example.cpp @@ -1,9 +1,10 @@ #include +#include #include +#include "bm8563.hpp" #include "i2c.hpp" #include "task.hpp" -#include "bm8563.hpp" using namespace std::chrono_literals; @@ -15,33 +16,30 @@ extern "C" void app_main(void) { // make the I2C that we'll use to communicate espp::I2c i2c({ .port = I2C_NUM_0, - .sda_io_num = GPIO_NUM_12, - .scl_io_num = GPIO_NUM_14, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, }); // now make the bm8563 auto bm8563 = espp::Bm8563({ - .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), - .read = std::bind(&espp::I2c::read_at_register, &i2c, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read_at_register, &i2c, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), }); std::error_code ec; // set the time - espp::Bm8563::DateTime date_time = { - .date = { - .year = 2023, - .month = 11, - .weekday = 4, - .day = 23, - }, - .time = { - .hour = 8, - .minute = 15, - .second = 30 - } - }; + espp::Bm8563::DateTime date_time = {.date = + { + .year = 2023, + .month = 11, + .weekday = 4, + .day = 23, + }, + .time = {.hour = 8, .minute = 15, .second = 30}}; bm8563.set_date_time(date_time, ec); if (ec) { fmt::print("Error setting date time: {}\n", ec.message()); diff --git a/components/controller/example/CMakeLists.txt b/components/controller/example/CMakeLists.txt index c965d8fe2..47c66a204 100644 --- a/components/controller/example/CMakeLists.txt +++ b/components/controller/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver ads1x15 adc task controller" + "main esptool_py ads1x15 adc task controller" CACHE STRING "List of components to include" ) diff --git a/components/controller/example/main/Kconfig.projbuild b/components/controller/example/main/Kconfig.projbuild new file mode 100644 index 000000000..926929e92 --- /dev/null +++ b/components/controller/example/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_QTPYS3 + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_QTPYPICO + depends on IDF_TARGET_ESP32 + bool "Qt Py PICO" + + config EXAMPLE_HARDWARE_QTPYS3 + depends on IDF_TARGET_ESP32S3 + bool "Qt Py S3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 19 if EXAMPLE_HARDWARE_QTPYPICO + default 40 if EXAMPLE_HARDWARE_QTPYS3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 22 if EXAMPLE_HARDWARE_QTPYPICO + default 41 if EXAMPLE_HARDWARE_QTPYS3 + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/controller/example/main/controller_example.cpp b/components/controller/example/main/controller_example.cpp index 9fc013866..c10d280e1 100644 --- a/components/controller/example/main/controller_example.cpp +++ b/components/controller/example/main/controller_example.cpp @@ -1,21 +1,15 @@ #include +#include #include -#include "driver/i2c.h" - #include "ads1x15.hpp" #include "controller.hpp" +#include "i2c.hpp" #include "oneshot_adc.hpp" #include "task.hpp" using namespace std::chrono_literals; -#define I2C_NUM (I2C_NUM_1) -#define I2C_SCL_IO (GPIO_NUM_40) -#define I2C_SDA_IO (GPIO_NUM_41) -#define I2C_FREQ_HZ (400 * 1000) -#define I2C_TIMEOUT_MS (10) - extern "C" void app_main(void) { // This example shows creating a digital controller without specifying all the // pins @@ -177,34 +171,17 @@ extern "C" void app_main(void) { "Starting i2c adc joystick controller example, press start & select together to quit!\n"); //! [i2c analog controller example] // make the I2C that we'll use to communicate - i2c_config_t i2c_cfg; - fmt::print("initializing i2c driver...\n"); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; // pin 3 on the joybonnet - i2c_cfg.scl_io_num = I2C_SCL_IO; // pin 5 on the joybonnet - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) - printf("config i2c failed\n"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) - printf("install i2c driver failed\n"); - // make some lambda functions we'll use to read/write to the i2c adc - auto ads_write = [](uint8_t dev_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_to_device(I2C_NUM, dev_addr, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; - auto ads_read = [](uint8_t dev_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_read_from_device(I2C_NUM, dev_addr, - data, data_len, I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; + espp::I2c i2c({ + .port = I2C_NUM_1, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, + }); // make the actual ads class - espp::Ads1x15 ads(espp::Ads1x15::Ads1015Config{.write = ads_write, .read = ads_read}); + espp::Ads1x15 ads(espp::Ads1x15::Ads1015Config{ + .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3)}); // make the task which will get the raw data from the I2C ADC and convert to // uncalibrated [-1,1] std::atomic joystick_x{0}; @@ -308,9 +285,6 @@ extern "C" void app_main(void) { std::this_thread::sleep_for(100ms); } } - // now clean up the i2c driver (by now the task will have stopped, because we - // left its scope. - i2c_driver_delete(I2C_NUM); fmt::print("Controller example complete!\n"); diff --git a/components/drv2605/example/CMakeLists.txt b/components/drv2605/example/CMakeLists.txt index 315518800..927b17d84 100644 --- a/components/drv2605/example/CMakeLists.txt +++ b/components/drv2605/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver drv2605 logger task" + "main esptool_py drv2605 i2c logger task" CACHE STRING "List of components to include" ) diff --git a/components/drv2605/example/main/Kconfig.projbuild b/components/drv2605/example/main/Kconfig.projbuild new file mode 100644 index 000000000..dfc846b7d --- /dev/null +++ b/components/drv2605/example/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_QTPYPICO + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_QTPYPICO + depends on IDF_TARGET_ESP32 + bool "Qt Py PICO" + + config EXAMPLE_HARDWARE_QTPYS3 + depends on IDF_TARGET_ESP32S3 + bool "Qt Py S3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 19 if EXAMPLE_HARDWARE_QTPYPICO + default 40 if EXAMPLE_HARDWARE_QTPYS3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 22 if EXAMPLE_HARDWARE_QTPYPICO + default 41 if EXAMPLE_HARDWARE_QTPYS3 + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/drv2605/example/main/drv2605_example.cpp b/components/drv2605/example/main/drv2605_example.cpp index d3c2fa16c..6a7bd44e2 100644 --- a/components/drv2605/example/main/drv2605_example.cpp +++ b/components/drv2605/example/main/drv2605_example.cpp @@ -1,20 +1,14 @@ #include +#include #include -#include "driver/i2c.h" - #include "drv2605.hpp" +#include "i2c.hpp" #include "logger.hpp" #include "task.hpp" using namespace std::chrono_literals; -#define I2C_NUM (I2C_NUM_1) -#define I2C_SCL_IO (GPIO_NUM_19) -#define I2C_SDA_IO (GPIO_NUM_22) -#define I2C_FREQ_HZ (400 * 1000) -#define I2C_TIMEOUT_MS (10) - extern "C" void app_main(void) { static espp::Logger logger({.tag = "drv2605 example", .level = espp::Logger::Verbosity::INFO}); // This example shows using the i2c haptic motor driver (drv2605) @@ -22,38 +16,19 @@ extern "C" void app_main(void) { logger.info("Running i2c adc example!"); //! [drv2605 example] // make the I2C that we'll use to communicate - i2c_config_t i2c_cfg; - logger.info("initializing i2c driver..."); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; - i2c_cfg.scl_io_num = I2C_SCL_IO; - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) - logger.error("config i2c failed"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) - logger.error("install i2c driver failed"); - // make some lambda functions we'll use to read/write to the i2c adc - auto i2c_write = [](uint8_t dev_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_to_device(I2C_NUM, dev_addr, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; - auto i2c_read = [](uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_read_device(I2C_NUM, dev_addr, ®_addr, - 1, // size of addr - data, data_len, I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; + espp::I2c i2c({ + .port = I2C_NUM_1, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, + }); // make the actual drv2605 class - espp::Drv2605 drv2605(espp::Drv2605::Config{.device_address = espp::Drv2605::DEFAULT_ADDRESS, - .write = i2c_write, - .read = i2c_read, - .motor_type = espp::Drv2605::MotorType::LRA}); + espp::Drv2605 drv2605(espp::Drv2605::Config{ + .device_address = espp::Drv2605::DEFAULT_ADDRESS, + .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read_at_register, &i2c, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + .motor_type = espp::Drv2605::MotorType::LRA}); std::error_code ec; // we're using an ERM motor, so select an ERM library (1-5). // drv2605.select_library(1, ec); @@ -110,9 +85,6 @@ extern "C" void app_main(void) { std::this_thread::sleep_for(100ms); } } - // now clean up the i2c driver (by now the task will have stopped, because we - // left its scope. - i2c_driver_delete(I2C_NUM); logger.info("Drv2605 example complete!"); diff --git a/components/ft5x06/example/CMakeLists.txt b/components/ft5x06/example/CMakeLists.txt index 05583cf61..6c3085642 100644 --- a/components/ft5x06/example/CMakeLists.txt +++ b/components/ft5x06/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver task ft5x06 i2c" + "main esptool_py task ft5x06 i2c" CACHE STRING "List of components to include" ) diff --git a/components/ft5x06/example/main/Kconfig.projbuild b/components/ft5x06/example/main/Kconfig.projbuild new file mode 100644 index 000000000..83e7e6d4f --- /dev/null +++ b/components/ft5x06/example/main/Kconfig.projbuild @@ -0,0 +1,33 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_BOX + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_BOX + depends on IDF_TARGET_ESP32S3 + bool "ESP32-S3 Box" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 18 if EXAMPLE_HARDWARE_BOX + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 8 if EXAMPLE_HARDWARE_BOX + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/ft5x06/example/main/ft5x06_example.cpp b/components/ft5x06/example/main/ft5x06_example.cpp index c76b6a1e0..b0a9b935e 100644 --- a/components/ft5x06/example/main/ft5x06_example.cpp +++ b/components/ft5x06/example/main/ft5x06_example.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "ft5x06.hpp" @@ -15,8 +16,8 @@ extern "C" void app_main(void) { // make the I2C that we'll use to communicate espp::I2c i2c({ .port = I2C_NUM_0, - .sda_io_num = GPIO_NUM_8, - .scl_io_num = GPIO_NUM_18, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, }); diff --git a/components/gt911/example/CMakeLists.txt b/components/gt911/example/CMakeLists.txt index c244449e1..91a938848 100644 --- a/components/gt911/example/CMakeLists.txt +++ b/components/gt911/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver task gt911 i2c" + "main esptool_py task gt911 i2c" CACHE STRING "List of components to include" ) diff --git a/components/gt911/example/main/Kconfig.projbuild b/components/gt911/example/main/Kconfig.projbuild new file mode 100644 index 000000000..e029564b2 --- /dev/null +++ b/components/gt911/example/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_TDECK + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_TDECK + depends on IDF_TARGET_ESP32S3 + bool "LilyGO T-Deck" + + config EXAMPLE_HARDWARE_BOX_3 + depends on IDF_TARGET_ESP32S3 + bool "ESP32-S3 BOX-3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 8 if EXAMPLE_HARDWARE_TDECK + default 18 if EXAMPLE_HARDWARE_BOX_3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 18 if EXAMPLE_HARDWARE_TDECK + default 8 if EXAMPLE_HARDWARE_BOX_3 + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/gt911/example/main/gt911_example.cpp b/components/gt911/example/main/gt911_example.cpp index 12ea9a088..de2906b8f 100644 --- a/components/gt911/example/main/gt911_example.cpp +++ b/components/gt911/example/main/gt911_example.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "gt911.hpp" @@ -15,8 +16,8 @@ extern "C" void app_main(void) { // make the I2C that we'll use to communicate espp::I2c i2c({ .port = I2C_NUM_0, - .sda_io_num = GPIO_NUM_18, - .scl_io_num = GPIO_NUM_8, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, }); // now make the gt911 which decodes the data espp::Gt911 gt911({.write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, diff --git a/components/i2c/example/CMakeLists.txt b/components/i2c/example/CMakeLists.txt index 23e9ac108..a27b5a87e 100644 --- a/components/i2c/example/CMakeLists.txt +++ b/components/i2c/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver task i2c" + "main esptool_py task i2c" CACHE STRING "List of components to include" ) diff --git a/components/i2c/example/main/Kconfig.projbuild b/components/i2c/example/main/Kconfig.projbuild new file mode 100644 index 000000000..dfc846b7d --- /dev/null +++ b/components/i2c/example/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_QTPYPICO + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_QTPYPICO + depends on IDF_TARGET_ESP32 + bool "Qt Py PICO" + + config EXAMPLE_HARDWARE_QTPYS3 + depends on IDF_TARGET_ESP32S3 + bool "Qt Py S3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 19 if EXAMPLE_HARDWARE_QTPYPICO + default 40 if EXAMPLE_HARDWARE_QTPYS3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 22 if EXAMPLE_HARDWARE_QTPYPICO + default 41 if EXAMPLE_HARDWARE_QTPYS3 + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/i2c/example/main/i2c_example.cpp b/components/i2c/example/main/i2c_example.cpp index 766f7dfcf..df85bf831 100644 --- a/components/i2c/example/main/i2c_example.cpp +++ b/components/i2c/example/main/i2c_example.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "i2c.hpp" @@ -13,19 +14,25 @@ extern "C" void app_main(void) { //! [i2c example] espp::I2c i2c({ .port = I2C_NUM_0, - .sda_io_num = GPIO_NUM_22, // qwiic sda on the qtpy - .scl_io_num = GPIO_NUM_19, // qwiic scl on the qtpy + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, }); // finally, make the task to periodically query the bus auto task_fn = [&i2c](std::mutex &m, std::condition_variable &cv) { static constexpr uint8_t device_address = 0x58; static constexpr uint8_t register_address = 0x58; uint8_t read_data[1]; - bool success = i2c.read_at_register(device_address, register_address, read_data, 1); - if (success) { - fmt::print("read data: {:#04x}\n", read_data[0]); + bool device_found = i2c.probe_device(device_address); + if (device_found) { + fmt::print("Found device with address 0x{:#02x}\n", device_address); + bool success = i2c.read_at_register(device_address, register_address, read_data, 1); + if (success) { + fmt::print("read data: {:#04x}\n", read_data[0]); + } else { + fmt::print("read failed\n"); + } } else { - fmt::print("read failed\n"); + fmt::print("Could not find device with address 0x{:#02x}\n", device_address); } // NOTE: sleeping in this way allows the sleep to exit early when the // task is being stopped / destroyed diff --git a/components/mcp23x17/example/CMakeLists.txt b/components/mcp23x17/example/CMakeLists.txt index d20613627..c06fe42a3 100644 --- a/components/mcp23x17/example/CMakeLists.txt +++ b/components/mcp23x17/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver task mcp23x17" + "main esptool_py i2c task mcp23x17" CACHE STRING "List of components to include" ) diff --git a/components/mcp23x17/example/main/Kconfig.projbuild b/components/mcp23x17/example/main/Kconfig.projbuild new file mode 100644 index 000000000..926929e92 --- /dev/null +++ b/components/mcp23x17/example/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_QTPYS3 + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_QTPYPICO + depends on IDF_TARGET_ESP32 + bool "Qt Py PICO" + + config EXAMPLE_HARDWARE_QTPYS3 + depends on IDF_TARGET_ESP32S3 + bool "Qt Py S3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 19 if EXAMPLE_HARDWARE_QTPYPICO + default 40 if EXAMPLE_HARDWARE_QTPYS3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 22 if EXAMPLE_HARDWARE_QTPYPICO + default 41 if EXAMPLE_HARDWARE_QTPYS3 + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/mcp23x17/example/main/mcp23x17_example.cpp b/components/mcp23x17/example/main/mcp23x17_example.cpp index 095f72069..2001245fb 100644 --- a/components/mcp23x17/example/main/mcp23x17_example.cpp +++ b/components/mcp23x17/example/main/mcp23x17_example.cpp @@ -1,60 +1,35 @@ #include +#include #include -#include "driver/i2c.h" - +#include "i2c.hpp" #include "mcp23x17.hpp" #include "task.hpp" using namespace std::chrono_literals; -#define I2C_NUM (I2C_NUM_1) -#define I2C_SCL_IO (GPIO_NUM_40) -#define I2C_SDA_IO (GPIO_NUM_41) -#define I2C_FREQ_HZ (400 * 1000) -#define I2C_TIMEOUT_MS (10) - extern "C" void app_main(void) { { std::atomic quit_test = false; fmt::print("Starting mcp23x17 example, press button on B7 quit!\n"); //! [mcp23x17 example] // make the I2C that we'll use to communicate - i2c_config_t i2c_cfg; - fmt::print("initializing i2c driver...\n"); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; - i2c_cfg.scl_io_num = I2C_SCL_IO; - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) - printf("config i2c failed\n"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) - printf("install i2c driver failed\n"); - // make some lambda functions we'll use to read/write to the mcp23x17 - auto mcp23x17_write = [](uint8_t dev_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_to_device(I2C_NUM, dev_addr, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; - - auto mcp23x17_read = [](uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_read_device(I2C_NUM, dev_addr, ®_addr, 1, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; + espp::I2c i2c({ + .port = I2C_NUM_0, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, + }); // now make the mcp23x17 which handles GPIO - espp::Mcp23x17 mcp23x17({.port_0_direction_mask = (1 << 0), // input on A0 - .port_0_interrupt_mask = (1 << 0), // interrupt on A0 - .port_1_direction_mask = (1 << 7), // input on B7 - .port_1_interrupt_mask = (1 << 7), // interrupt on B7 - .write = mcp23x17_write, - .read = mcp23x17_read, - .log_level = espp::Logger::Verbosity::WARN}); + espp::Mcp23x17 mcp23x17( + {.port_0_direction_mask = (1 << 0), // input on A0 + .port_0_interrupt_mask = (1 << 0), // interrupt on A0 + .port_1_direction_mask = (1 << 7), // input on B7 + .port_1_interrupt_mask = (1 << 7), // interrupt on B7 + .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read_at_register, &i2c, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + .log_level = espp::Logger::Verbosity::WARN}); // set pull up on the input pins std::error_code ec; mcp23x17.set_pull_up(espp::Mcp23x17::Port::PORT0, (1 << 0), ec); @@ -115,8 +90,6 @@ extern "C" void app_main(void) { while (!quit_test) { std::this_thread::sleep_for(100ms); } - // now clean up the i2c driver - i2c_driver_delete(I2C_NUM); } fmt::print("Mcp23x17 example complete!\n"); diff --git a/components/mt6701/example/CMakeLists.txt b/components/mt6701/example/CMakeLists.txt index 2125cae00..a88b78eba 100644 --- a/components/mt6701/example/CMakeLists.txt +++ b/components/mt6701/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py filters driver task mt6701" + "main esptool_py filters i2c task mt6701" CACHE STRING "List of components to include" ) diff --git a/components/mt6701/example/main/Kconfig.projbuild b/components/mt6701/example/main/Kconfig.projbuild new file mode 100644 index 000000000..926929e92 --- /dev/null +++ b/components/mt6701/example/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_QTPYS3 + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_QTPYPICO + depends on IDF_TARGET_ESP32 + bool "Qt Py PICO" + + config EXAMPLE_HARDWARE_QTPYS3 + depends on IDF_TARGET_ESP32S3 + bool "Qt Py S3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 19 if EXAMPLE_HARDWARE_QTPYPICO + default 40 if EXAMPLE_HARDWARE_QTPYS3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 22 if EXAMPLE_HARDWARE_QTPYPICO + default 41 if EXAMPLE_HARDWARE_QTPYS3 + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/mt6701/example/main/mt6701_example.cpp b/components/mt6701/example/main/mt6701_example.cpp index 78e4ca750..47661ee02 100644 --- a/components/mt6701/example/main/mt6701_example.cpp +++ b/components/mt6701/example/main/mt6701_example.cpp @@ -1,53 +1,25 @@ #include +#include #include -#include "driver/i2c.h" - #include "butterworth_filter.hpp" +#include "i2c.hpp" #include "mt6701.hpp" #include "task.hpp" using namespace std::chrono_literals; -#define I2C_NUM (I2C_NUM_1) -#define I2C_SCL_IO (GPIO_NUM_40) -#define I2C_SDA_IO (GPIO_NUM_41) -#define I2C_FREQ_HZ (400 * 1000) -#define I2C_TIMEOUT_MS (10) - extern "C" void app_main(void) { { std::atomic quit_test = false; fmt::print("Starting mt6701 example, rotate to -720 degrees to quit!\n"); //! [mt6701 example] // make the I2C that we'll use to communicate - i2c_config_t i2c_cfg; - fmt::print("initializing i2c driver...\n"); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; - i2c_cfg.scl_io_num = I2C_SCL_IO; - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) - printf("config i2c failed\n"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) - printf("install i2c driver failed\n"); - // make some lambda functions we'll use to read/write to the mt6701 - auto mt6701_write = [](uint8_t dev_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_to_device(I2C_NUM, dev_addr, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; - - auto mt6701_read = [](uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_read_device(I2C_NUM, dev_addr, ®_addr, 1, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; + espp::I2c i2c({ + .port = I2C_NUM_0, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, + }); // make the velocity filter static constexpr float filter_cutoff_hz = 4.0f; static constexpr float encoder_update_period = 0.01f; // seconds @@ -55,11 +27,14 @@ extern "C" void app_main(void) { {.normalized_cutoff_frequency = 2.0f * filter_cutoff_hz * encoder_update_period}); auto filter_fn = [&filter](float raw) -> float { return filter.update(raw); }; // now make the mt6701 which decodes the data - espp::Mt6701 mt6701({.write = mt6701_write, - .read = mt6701_read, - .velocity_filter = filter_fn, - .update_period = std::chrono::duration(encoder_update_period), - .log_level = espp::Logger::Verbosity::WARN}); + espp::Mt6701 mt6701( + {.write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read_at_register, &i2c, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + .velocity_filter = filter_fn, + .update_period = std::chrono::duration(encoder_update_period), + .log_level = espp::Logger::Verbosity::WARN}); // and finally, make the task to periodically poll the mt6701 and print the // state. NOTE: the Mt6701 runs its own task to maintain state, so we're // just polling the current state. @@ -92,8 +67,6 @@ extern "C" void app_main(void) { while (!quit_test) { std::this_thread::sleep_for(100ms); } - // now clean up the i2c driver - i2c_driver_delete(I2C_NUM); } fmt::print("Mt6701 example complete!\n"); diff --git a/components/qwiicnes/example/CMakeLists.txt b/components/qwiicnes/example/CMakeLists.txt index 752dd85d4..b33bf1272 100644 --- a/components/qwiicnes/example/CMakeLists.txt +++ b/components/qwiicnes/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver task qwiicnes i2c" + "main esptool_py task qwiicnes i2c" CACHE STRING "List of components to include" ) diff --git a/components/qwiicnes/example/main/Kconfig.projbuild b/components/qwiicnes/example/main/Kconfig.projbuild new file mode 100644 index 000000000..dfc846b7d --- /dev/null +++ b/components/qwiicnes/example/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_QTPYPICO + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_QTPYPICO + depends on IDF_TARGET_ESP32 + bool "Qt Py PICO" + + config EXAMPLE_HARDWARE_QTPYS3 + depends on IDF_TARGET_ESP32S3 + bool "Qt Py S3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 19 if EXAMPLE_HARDWARE_QTPYPICO + default 40 if EXAMPLE_HARDWARE_QTPYS3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 22 if EXAMPLE_HARDWARE_QTPYPICO + default 41 if EXAMPLE_HARDWARE_QTPYS3 + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/qwiicnes/example/main/qwiicnes_example.cpp b/components/qwiicnes/example/main/qwiicnes_example.cpp index ee01c1e00..2d6cfbd0b 100644 --- a/components/qwiicnes/example/main/qwiicnes_example.cpp +++ b/components/qwiicnes/example/main/qwiicnes_example.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "i2c.hpp" @@ -15,8 +16,8 @@ extern "C" void app_main(void) { // make the I2C that we'll use to communicate espp::I2c i2c({ .port = I2C_NUM_0, - .sda_io_num = GPIO_NUM_22, - .scl_io_num = GPIO_NUM_19, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, }); // now make the qwiicnes which decodes the data espp::QwiicNes qwiicnes({.write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, diff --git a/components/st25dv/example/CMakeLists.txt b/components/st25dv/example/CMakeLists.txt index c04b9f97f..d06460957 100644 --- a/components/st25dv/example/CMakeLists.txt +++ b/components/st25dv/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py bt nvs_flash filters driver task st25dv" + "main esptool_py bt nvs_flash filters i2c task st25dv" CACHE STRING "List of components to include" ) diff --git a/components/st25dv/example/main/Kconfig.projbuild b/components/st25dv/example/main/Kconfig.projbuild index 5c470af18..926929e92 100644 --- a/components/st25dv/example/main/Kconfig.projbuild +++ b/components/st25dv/example/main/Kconfig.projbuild @@ -1,15 +1,39 @@ -menu "NFC WiFi Configuration" +menu "Example Configuration" - config ESP_WIFI_SSID - string "WiFi SSID" - default "myssid" + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_QTPYS3 help - SSID (network name) for the NFC to provide configuration for. + Select the hardware to run this example on. - config ESP_WIFI_PASSWORD - string "WiFi Password" - default "mypassword" + config EXAMPLE_HARDWARE_QTPYPICO + depends on IDF_TARGET_ESP32 + bool "Qt Py PICO" + + config EXAMPLE_HARDWARE_QTPYS3 + depends on IDF_TARGET_ESP32S3 + bool "Qt Py S3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 19 if EXAMPLE_HARDWARE_QTPYPICO + default 40 if EXAMPLE_HARDWARE_QTPYS3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 22 if EXAMPLE_HARDWARE_QTPYPICO + default 41 if EXAMPLE_HARDWARE_QTPYS3 + default 22 if EXAMPLE_HARDWARE_CUSTOM help - WiFi password (WPA or WPA2) for the NFC to provide configuration for. + GPIO number for I2C Master data line. endmenu diff --git a/components/st25dv/example/main/st25dv_example.cpp b/components/st25dv/example/main/st25dv_example.cpp index 646c1fa9e..70609035b 100644 --- a/components/st25dv/example/main/st25dv_example.cpp +++ b/components/st25dv/example/main/st25dv_example.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -17,19 +18,12 @@ #endif #include -#include - +#include "i2c.hpp" #include "st25dv.hpp" #include "task.hpp" using namespace std::chrono_literals; -static constexpr auto I2C_NUM = I2C_NUM_1; -static constexpr auto I2C_SCL_IO = GPIO_NUM_40; -static constexpr auto I2C_SDA_IO = GPIO_NUM_41; -static constexpr auto I2C_FREQ_HZ = (400 * 1000); -static constexpr auto I2C_TIMEOUT_MS = 10; - static constexpr auto HIDD_IDLE_MODE = 0x00; static constexpr auto HIDD_BLE_MODE = 0x01; static constexpr auto HIDD_BT_MODE = 0x02; @@ -70,37 +64,18 @@ extern "C" void app_main(void) { "quit!\n"); //! [st25dv example] // make the I2C that we'll use to communicate - i2c_config_t i2c_cfg; - fmt::print("initializing i2c driver...\n"); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; - i2c_cfg.scl_io_num = I2C_SCL_IO; - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) - printf("config i2c failed\n"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) - printf("install i2c driver failed\n"); - // make some lambda functions we'll use to read/write to the st25dv - auto st25dv_write = [](uint8_t addr, uint8_t *data, uint8_t length) { - auto err = i2c_master_write_to_device(I2C_NUM, addr, data, length, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; - - auto st25dv_read = [](uint8_t addr, uint16_t reg_addr, uint8_t *data, uint8_t length) { - uint8_t reg[2] = {(uint8_t)(reg_addr >> 8), (uint8_t)(reg_addr & 0xFF)}; - auto err = i2c_master_write_read_device(I2C_NUM, addr, reg, 2, data, length, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; + espp::I2c i2c({ + .port = I2C_NUM_0, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, + }); // now make the st25dv which decodes the data espp::St25dv st25dv( - {.write = st25dv_write, .read = st25dv_read, .log_level = espp::Logger::Verbosity::DEBUG}); + {.write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read_at_register, &i2c, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + .log_level = espp::Logger::Verbosity::DEBUG}); std::array programmed_data; std::error_code ec; @@ -180,8 +155,6 @@ extern "C" void app_main(void) { while (!quit_test) { std::this_thread::sleep_for(100ms); } - // now clean up the i2c driver - i2c_driver_delete(I2C_NUM); } fmt::print("St25dv example complete!\n"); diff --git a/components/t_keyboard/example/main/Kconfig.projbuild b/components/t_keyboard/example/main/Kconfig.projbuild new file mode 100644 index 000000000..c51f034d2 --- /dev/null +++ b/components/t_keyboard/example/main/Kconfig.projbuild @@ -0,0 +1,33 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_TDECK + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_TDECK + depends on IDF_TARGET_ESP32S3 + bool "LilyGO T-Deck" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 8 if EXAMPLE_HARDWARE_TDECK + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 18 if EXAMPLE_HARDWARE_TDECK + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/t_keyboard/example/main/t_keyboard_example.cpp b/components/t_keyboard/example/main/t_keyboard_example.cpp index 24274e510..a7f6f2ce2 100644 --- a/components/t_keyboard/example/main/t_keyboard_example.cpp +++ b/components/t_keyboard/example/main/t_keyboard_example.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -16,8 +17,8 @@ extern "C" void app_main(void) { // make the I2C that we'll use to communicate espp::I2c i2c({ .port = I2C_NUM_0, - .sda_io_num = GPIO_NUM_18, - .scl_io_num = GPIO_NUM_8, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, }); // now make the tkeyboard which decodes the data espp::TKeyboard tkeyboard( diff --git a/components/tla2528/example/CMakeLists.txt b/components/tla2528/example/CMakeLists.txt index fdd87ea4c..15a078fe9 100644 --- a/components/tla2528/example/CMakeLists.txt +++ b/components/tla2528/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver tla2528 adc task controller" + "main esptool_py i2c task tla2528" CACHE STRING "List of components to include" ) diff --git a/components/tla2528/example/main/Kconfig.projbuild b/components/tla2528/example/main/Kconfig.projbuild new file mode 100644 index 000000000..dfc846b7d --- /dev/null +++ b/components/tla2528/example/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_QTPYPICO + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_QTPYPICO + depends on IDF_TARGET_ESP32 + bool "Qt Py PICO" + + config EXAMPLE_HARDWARE_QTPYS3 + depends on IDF_TARGET_ESP32S3 + bool "Qt Py S3" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 19 if EXAMPLE_HARDWARE_QTPYPICO + default 40 if EXAMPLE_HARDWARE_QTPYS3 + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 22 if EXAMPLE_HARDWARE_QTPYPICO + default 41 if EXAMPLE_HARDWARE_QTPYS3 + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/tla2528/example/main/tla2528_example.cpp b/components/tla2528/example/main/tla2528_example.cpp index 70e29cd23..dcb09a425 100644 --- a/components/tla2528/example/main/tla2528_example.cpp +++ b/components/tla2528/example/main/tla2528_example.cpp @@ -1,22 +1,14 @@ #include +#include #include -#include "driver/gpio.h" -#include "driver/i2c.h" - +#include "i2c.hpp" #include "logger.hpp" #include "task.hpp" #include "tla2528.hpp" using namespace std::chrono_literals; -// This example is designed to be run on a QtPy ESP32 -static constexpr auto I2C_NUM = (I2C_NUM_1); -static constexpr auto I2C_SCL_IO = (GPIO_NUM_19); -static constexpr auto I2C_SDA_IO = (GPIO_NUM_22); -static constexpr auto I2C_FREQ_HZ = (400 * 1000); -static constexpr auto I2C_TIMEOUT_MS = (10); - extern "C" void app_main(void) { static espp::Logger logger({.tag = "tla2528 example", .level = espp::Logger::Verbosity::INFO}); // This example shows using the i2c adc (tla2528) @@ -25,33 +17,11 @@ extern "C" void app_main(void) { //! [tla2528 example] // make the I2C that we'll use to communicate - i2c_config_t i2c_cfg; - logger.info("initializing i2c driver..."); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; - i2c_cfg.scl_io_num = I2C_SCL_IO; - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_DISABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_DISABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) - logger.error("config i2c failed"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) - logger.error("install i2c driver failed"); - - // make some lambda functions we'll use to read/write to the i2c adc - auto tla_write = [](uint8_t dev_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_write_to_device(I2C_NUM, dev_addr, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; - auto tla_read = [](uint8_t dev_addr, uint8_t *data, size_t data_len) { - auto err = i2c_master_read_from_device(I2C_NUM, dev_addr, data, data_len, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return err == ESP_OK; - }; + espp::I2c i2c({ + .port = I2C_NUM_0, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, + }); static auto NTC_CHANNEL = espp::Tla2528::Channel::CH1; static auto X_CHANNEL = espp::Tla2528::Channel::CH6; @@ -68,8 +38,10 @@ extern "C" void app_main(void) { .digital_outputs = {}, // enable oversampling / averaging .oversampling_ratio = espp::Tla2528::OversamplingRatio::NONE, - .write = tla_write, - .read = tla_read, + .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .read = std::bind(&espp::I2c::read, &i2c, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), .log_level = espp::Logger::Verbosity::WARN, }); @@ -130,9 +102,6 @@ extern "C" void app_main(void) { std::this_thread::sleep_for(100ms); } } - // now clean up the i2c driver (by now the task will have stopped, because we - // left its scope. - i2c_driver_delete(I2C_NUM); logger.info("TLA2528 example complete!"); diff --git a/components/tt21100/example/CMakeLists.txt b/components/tt21100/example/CMakeLists.txt index 3606100dd..ec790c781 100644 --- a/components/tt21100/example/CMakeLists.txt +++ b/components/tt21100/example/CMakeLists.txt @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS set( COMPONENTS - "main esptool_py driver task tt21100 i2c" + "main esptool_py task tt21100 i2c" CACHE STRING "List of components to include" ) diff --git a/components/tt21100/example/main/Kconfig.projbuild b/components/tt21100/example/main/Kconfig.projbuild new file mode 100644 index 000000000..a9d2edc52 --- /dev/null +++ b/components/tt21100/example/main/Kconfig.projbuild @@ -0,0 +1,33 @@ +menu "Example Configuration" + + choice EXAMPLE_HARDWARE + prompt "Hardware" + default EXAMPLE_HARDWARE_BOX + help + Select the hardware to run this example on. + + config EXAMPLE_HARDWARE_BOX + depends on IDF_TARGET_ESP32S3 + bool "ESP32-S3 BOX" + + config EXAMPLE_HARDWARE_CUSTOM + bool "Custom" + endchoice + + config EXAMPLE_I2C_SCL_GPIO + int "SCL GPIO Num" + range 0 50 + default 18 if EXAMPLE_HARDWARE_BOX + default 19 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_SDA_GPIO + int "SDA GPIO Num" + range 0 50 + default 8 if EXAMPLE_HARDWARE_BOX + default 22 if EXAMPLE_HARDWARE_CUSTOM + help + GPIO number for I2C Master data line. + +endmenu diff --git a/components/tt21100/example/main/tt21100_example.cpp b/components/tt21100/example/main/tt21100_example.cpp index e52a7a93c..6dfd48e6b 100644 --- a/components/tt21100/example/main/tt21100_example.cpp +++ b/components/tt21100/example/main/tt21100_example.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "i2c.hpp" @@ -15,8 +16,8 @@ extern "C" void app_main(void) { // make the I2C that we'll use to communicate espp::I2c i2c({ .port = I2C_NUM_0, - .sda_io_num = GPIO_NUM_8, - .scl_io_num = GPIO_NUM_18, + .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, + .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, });