From 0ea485e518680e20bec831f27c164f8d0265a828 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 3 Feb 2022 14:06:12 -0300 Subject: [PATCH 1/8] Touch Sensor IDF Refactoring (#6194) Summary Touch Sensor refactoring to be based on IDF 4.4. Adds support to ESP32S2 and future ESP32S3. Adds some new APIs: For all chips: void touchAttachInterruptArg(uint8_t pin, void (*userFunc)(void*), void *arg, uint32_t threshold); This function allows the user to add and pass a void* parameter to the ISR user callback. void touchDetachInterrupt(uint8_t pin); This function detaches ISR call back for the touch pad pin. Only ESP32 chip void touchInterruptSetThresholdDirection(bool mustbeLower); This function allows the user to set if the ISR callback will be activated when the touch sensor readings are lower or higher than the threshold defined. See example TouchButton.ino. Only ESP32-S2 and ESP32-S3 chips bool touchInterruptGetLastStatus(uint8_t pin); This function reports if the touch pad pin is touched or untouched. It can be used with ISR to identify when it is touched and untouched (released). See example TouchButtonV2.ino. Impact None. ll original APIs and examples now run on ESP32 and ESP32-S2. Related links Fix #6095 Fix #6034 Fix #5799 Fix #5745 Fix #5527 Fix #5493 Fix #4321 Fix #4044 Fix #2722 Fix #2625 --- cores/esp32/esp32-hal-touch.c | 342 ++++++++++-------- cores/esp32/esp32-hal-touch.h | 52 ++- .../examples/Touch/TouchButton/.skip.esp32c3 | 0 .../examples/Touch/TouchButton/.skip.esp32s2 | 0 .../examples/Touch/TouchButton/.skip.esp32s3 | 0 .../Touch/TouchButton/TouchButton.ino | 46 +++ .../examples/Touch/TouchButtonV2/.skip.esp32 | 0 .../Touch/TouchButtonV2/.skip.esp32c3 | 0 .../Touch/TouchButtonV2/TouchButtonV2.ino | 53 +++ 9 files changed, 332 insertions(+), 161 deletions(-) create mode 100644 libraries/ESP32/examples/Touch/TouchButton/.skip.esp32c3 create mode 100644 libraries/ESP32/examples/Touch/TouchButton/.skip.esp32s2 create mode 100644 libraries/ESP32/examples/Touch/TouchButton/.skip.esp32s3 create mode 100644 libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino create mode 100644 libraries/ESP32/examples/Touch/TouchButtonV2/.skip.esp32 create mode 100644 libraries/ESP32/examples/Touch/TouchButtonV2/.skip.esp32c3 create mode 100644 libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino diff --git a/cores/esp32/esp32-hal-touch.c b/cores/esp32/esp32-hal-touch.c index 1492eff78a8..e5eaf497b5e 100644 --- a/cores/esp32/esp32-hal-touch.c +++ b/cores/esp32/esp32-hal-touch.c @@ -12,219 +12,251 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "esp32-hal-touch.h" -#ifndef CONFIG_IDF_TARGET_ESP32C3 -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_attr.h" -#include "soc/rtc_io_reg.h" -#include "soc/sens_reg.h" -#include "soc/sens_struct.h" -#include "soc/rtc_cntl_reg.h" +#include "soc/soc_caps.h" +#if SOC_TOUCH_SENSOR_NUM > 0 + #include "driver/touch_sensor.h" +#include "esp32-hal-touch.h" -#include "esp_system.h" -#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+ -#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 -#include "esp32/rom/ets_sys.h" -#include "esp_intr_alloc.h" -#elif CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/rom/ets_sys.h" -#include "esp_intr_alloc.h" -#include "soc/periph_defs.h" -#else -#error Target CONFIG_IDF_TARGET is not supported -#endif -#else // ESP32 Before IDF 4.0 -#include "rom/ets_sys.h" -#include "esp_intr.h" -#endif +/* + Internal Private Touch Data Structure and Functions +*/ +#if SOC_TOUCH_VERSION_1 // ESP32 static uint16_t __touchSleepCycles = 0x1000; static uint16_t __touchMeasureCycles = 0x1000; +#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 +static uint16_t __touchSleepCycles = TOUCH_PAD_SLEEP_CYCLE_DEFAULT; +static uint16_t __touchMeasureCycles = TOUCH_PAD_MEASURE_CYCLE_DEFAULT; +#endif typedef void (*voidFuncPtr)(void); -static voidFuncPtr __touchInterruptHandlers[10] = {0,}; -static intr_handle_t touch_intr_handle = NULL; +typedef void (*voidArgFuncPtr)(void *); + +typedef struct { + voidFuncPtr fn; + bool callWithArgs; + void* arg; +#if SOC_TOUCH_VERSION_2 // Only for ESP32S2 and ESP32S3 + bool lastStatusIsPressed; +#endif +} TouchInterruptHandle_t; + +static TouchInterruptHandle_t __touchInterruptHandlers[SOC_TOUCH_SENSOR_NUM] = {0,}; -void ARDUINO_ISR_ATTR __touchISR(void * arg) +static void ARDUINO_ISR_ATTR __touchISR(void * arg) { -#if CONFIG_IDF_TARGET_ESP32 - uint32_t pad_intr = READ_PERI_REG(SENS_SAR_TOUCH_CTRL2_REG) & 0x3ff; - uint32_t rtc_intr = READ_PERI_REG(RTC_CNTL_INT_ST_REG); - uint8_t i = 0; +#if SOC_TOUCH_VERSION_1 // ESP32 + uint32_t pad_intr = touch_pad_get_status(); //clear interrupt - WRITE_PERI_REG(RTC_CNTL_INT_CLR_REG, rtc_intr); - SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN_CLR); - - if (rtc_intr & RTC_CNTL_TOUCH_INT_ST) { - for (i = 0; i < 10; ++i) { - if ((pad_intr >> i) & 0x01) { - if(__touchInterruptHandlers[i]){ - __touchInterruptHandlers[i](); + touch_pad_clear_status(); + // call Pad ISR User callback + for (int i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) { + if ((pad_intr >> i) & 0x01) { + if(__touchInterruptHandlers[i].fn){ + // keeping backward compatibility with "void cb(void)" and with new "void cb(vooid *)" + if (__touchInterruptHandlers[i].callWithArgs) { + ((voidArgFuncPtr)__touchInterruptHandlers[i].fn)(__touchInterruptHandlers[i].arg); + } else { + __touchInterruptHandlers[i].fn(); } } } } +#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 + touch_pad_intr_mask_t evt = touch_pad_read_intr_status_mask(); + uint8_t pad_num = touch_pad_get_current_meas_channel(); + if (evt & TOUCH_PAD_INTR_MASK_ACTIVE) { + // touch has been pressed / touched + __touchInterruptHandlers[pad_num].lastStatusIsPressed = true; + } + if (evt & TOUCH_PAD_INTR_MASK_INACTIVE) { + // touch has been released / untouched + __touchInterruptHandlers[pad_num].lastStatusIsPressed = false; + } + if(__touchInterruptHandlers[pad_num].fn){ + // keeping backward compatibility with "void cb(void)" and with new "void cb(vooid *)" + if (__touchInterruptHandlers[pad_num].callWithArgs) { + ((voidArgFuncPtr)__touchInterruptHandlers[pad_num].fn)(__touchInterruptHandlers[pad_num].arg); + } else { + __touchInterruptHandlers[pad_num].fn(); + } + } #endif } -void __touchSetCycles(uint16_t measure, uint16_t sleep) + + +static void __touchSetCycles(uint16_t measure, uint16_t sleep) { __touchSleepCycles = sleep; __touchMeasureCycles = measure; -#if CONFIG_IDF_TARGET_ESP32 - //Touch pad SleepCycle Time - SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_SLEEP_CYCLES, __touchSleepCycles, SENS_TOUCH_SLEEP_CYCLES_S); - //Touch Pad Measure Time - SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_MEAS_DELAY, __touchMeasureCycles, SENS_TOUCH_MEAS_DELAY_S); -#else touch_pad_set_meas_time(sleep, measure); -#endif } -void __touchInit() + + +static void __touchInit() { static bool initialized = false; if(initialized){ return; } - initialized = true; -#if CONFIG_IDF_TARGET_ESP32 - SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS, 1, RTC_IO_TOUCH_XPD_BIAS_S); - SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN_CLR); - //clear touch enable - WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, 0x0); - SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_TOUCH_SLP_TIMER_EN); - __touchSetCycles(__touchMeasureCycles, __touchSleepCycles); - esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, __touchISR, NULL, &touch_intr_handle); -#else - touch_pad_init(); - touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V5); - touch_pad_set_idle_channel_connect(TOUCH_PAD_CONN_GND); - __touchSetCycles(__touchMeasureCycles, __touchSleepCycles); + + esp_err_t err = ESP_OK; + +#if SOC_TOUCH_VERSION_1 // ESP32 + err = touch_pad_init(); + if (err != ESP_OK) { + goto err; + } + // the next two lines will drive the touch reading values -- both will return ESP_OK + touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V); + touch_pad_set_meas_time(__touchMeasureCycles, __touchSleepCycles); + // Touch Sensor Timer initiated + touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); // returns ESP_OK + err = touch_pad_filter_start(10); + if (err != ESP_OK) { + goto err; + } + // Initial no Threshold and setup + for (int i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) { + __touchInterruptHandlers[i].fn = NULL; + touch_pad_config(i, SOC_TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK + } + // keep ISR activated - it can run all together (ISR + touchRead()) + err = touch_pad_isr_register(__touchISR, NULL); + if (err != ESP_OK) { + goto err; + } + touch_pad_intr_enable(); // returns ESP_OK +#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 + err = touch_pad_init(); + if (err != ESP_OK) { + goto err; + } + // the next lines will drive the touch reading values -- all os them return ESP_OK + touch_pad_set_meas_time(__touchSleepCycles, __touchMeasureCycles); + touch_pad_set_voltage(TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD); + touch_pad_set_idle_channel_connect(TOUCH_PAD_IDLE_CH_CONNECT_DEFAULT); touch_pad_denoise_t denoise = { .grade = TOUCH_PAD_DENOISE_BIT4, .cap_level = TOUCH_PAD_DENOISE_CAP_L4, }; touch_pad_denoise_set_config(&denoise); touch_pad_denoise_enable(); - touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); - touch_pad_fsm_start(); + // Touch Sensor Timer initiated + touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); // returns ESP_OK + touch_pad_fsm_start(); // returns ESP_OK + + // Initial no Threshold and setup - TOUCH0 is internal denoise channel + for (int i = 1; i < SOC_TOUCH_SENSOR_NUM; i++) { + __touchInterruptHandlers[i].fn = NULL; + touch_pad_config(i); // returns ESP_OK + } + // keep ISR activated - it can run all together (ISR + touchRead()) + err = touch_pad_isr_register(__touchISR, NULL, TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE); + if (err != ESP_OK) { + goto err; + } + touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE); // returns ESP_OK #endif + + initialized = true; + return; +err: + log_e(" Touch sensor initialization error."); + initialized = false; + return; } -uint16_t __touchRead(uint8_t pin) +static touch_value_t __touchRead(uint8_t pin) { int8_t pad = digitalPinToTouchChannel(pin); if(pad < 0){ return 0; } + __touchInit(); - pinMode(pin, ANALOG); + touch_value_t touch_value; + touch_pad_read_raw_data(pad, &touch_value); - __touchInit(); + return touch_value; +} -#if CONFIG_IDF_TARGET_ESP32 - uint32_t v0 = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG); - //Disable Intr & enable touch pad - WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, - (v0 & ~((1 << (pad + SENS_TOUCH_PAD_OUTEN2_S)) | (1 << (pad + SENS_TOUCH_PAD_OUTEN1_S)))) - | (1 << (pad + SENS_TOUCH_PAD_WORKEN_S))); +static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Args, touch_value_t threshold, bool callWithArgs) +{ + int8_t pad = digitalPinToTouchChannel(pin); + if(pad < 0){ + return; + } - SET_PERI_REG_MASK(SENS_SAR_TOUCH_ENABLE_REG, (1 << (pad + SENS_TOUCH_PAD_WORKEN_S))); + if (userFunc == NULL) { + // dettach ISR User Call + __touchInterruptHandlers[pad].fn = NULL; + threshold = SOC_TOUCH_PAD_THRESHOLD_MAX; // deactivate the ISR with SOC_TOUCH_PAD_THRESHOLD_MAX + } else { + // attach ISR User Call + __touchInit(); + __touchInterruptHandlers[pad].fn = userFunc; + __touchInterruptHandlers[pad].callWithArgs = callWithArgs; + __touchInterruptHandlers[pad].arg = Args; + } - uint32_t rtc_tio_reg = RTC_IO_TOUCH_PAD0_REG + pad * 4; - WRITE_PERI_REG(rtc_tio_reg, (READ_PERI_REG(rtc_tio_reg) - & ~(RTC_IO_TOUCH_PAD0_DAC_M)) - | (7 << RTC_IO_TOUCH_PAD0_DAC_S)//Touch Set Slope - | RTC_IO_TOUCH_PAD0_TIE_OPT_M //Enable Tie,Init Level - | RTC_IO_TOUCH_PAD0_START_M //Enable Touch Pad IO - | RTC_IO_TOUCH_PAD0_XPD_M); //Enable Touch Pad Power on +#if SOC_TOUCH_VERSION_1 // ESP32 + touch_pad_config(pad, threshold); +#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 + touch_pad_set_thresh(pad, threshold); +#endif +} - //force oneTime test start - SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M); +// it keeps backwards compatibility +static void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), touch_value_t threshold) +{ + __touchConfigInterrupt(pin, userFunc, NULL, threshold, false); +} - SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_XPD_WAIT, 10, SENS_TOUCH_XPD_WAIT_S); +// new additional version of the API with User Args +static void __touchAttachArgsInterrupt(uint8_t pin, void (*userFunc)(void), void *args, touch_value_t threshold) +{ + __touchConfigInterrupt(pin, userFunc, args, threshold, true); +} - while (GET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_DONE) == 0) {}; +// new additional API to dettach touch ISR +static void __touchDettachInterrupt(uint8_t pin) +{ + __touchConfigInterrupt(pin, NULL, NULL, 0, false); // userFunc as NULL acts as dettaching +} - uint16_t touch_value = READ_PERI_REG(SENS_SAR_TOUCH_OUT1_REG + (pad / 2) * 4) >> ((pad & 1) ? SENS_TOUCH_MEAS_OUT1_S : SENS_TOUCH_MEAS_OUT0_S); - //clear touch force ,select the Touch mode is Timer - CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M); +/* + External Public Touch API Functions +*/ - //restore previous value - WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, v0); - return touch_value; -#else - static uint32_t chan_mask = 0; - uint32_t value = 0; - if((chan_mask & (1 << pad)) == 0){ - if(touch_pad_set_thresh((touch_pad_t)pad, TOUCH_PAD_THRESHOLD_MAX) != ESP_OK){ - log_e("touch_pad_set_thresh failed"); - } else if(touch_pad_config((touch_pad_t)pad) != ESP_OK){ - log_e("touch_pad_config failed"); - } else { - chan_mask |= (1 << pad); - } - } - if((chan_mask & (1 << pad)) != 0) { - if(touch_pad_read_raw_data((touch_pad_t)pad, &value) != ESP_OK){ - log_e("touch_pad_read_raw_data failed"); - } +#if SOC_TOUCH_VERSION_1 // Only for ESP32 SoC +void touchInterruptSetThresholdDirection(bool mustbeLower) { + if (mustbeLower) { + touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW); + } else { + touch_pad_set_trigger_mode(TOUCH_TRIGGER_ABOVE); } - return value; -#endif } - -void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold) -{ +#elif SOC_TOUCH_VERSION_2 // Only for ESP32S2 and ESP32S3 +// returns true if touch pad has been and continues pressed and false otherwise +bool touchInterruptGetLastStatus(uint8_t pin) { int8_t pad = digitalPinToTouchChannel(pin); if(pad < 0){ - return; + return false; } - pinMode(pin, ANALOG); - - __touchInit(); - - __touchInterruptHandlers[pad] = userFunc; - -#if CONFIG_IDF_TARGET_ESP32 - //clear touch force ,select the Touch mode is Timer - CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M); - - //interrupt when touch value < threshold - CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_OUT_SEL); - //Intr will give ,when SET0 < threshold - SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_OUT_1EN); - //Enable Rtc Touch Module Intr,the Interrupt need Rtc out Enable - SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, RTC_CNTL_TOUCH_INT_ENA); - - //set threshold - uint8_t shift = (pad & 1) ? SENS_TOUCH_OUT_TH1_S : SENS_TOUCH_OUT_TH0_S; - SET_PERI_REG_BITS((SENS_SAR_TOUCH_THRES1_REG + (pad / 2) * 4), SENS_TOUCH_OUT_TH0, threshold, shift); - - uint32_t rtc_tio_reg = RTC_IO_TOUCH_PAD0_REG + pad * 4; - WRITE_PERI_REG(rtc_tio_reg, (READ_PERI_REG(rtc_tio_reg) - & ~(RTC_IO_TOUCH_PAD0_DAC_M)) - | (7 << RTC_IO_TOUCH_PAD0_DAC_S)//Touch Set Slope - | RTC_IO_TOUCH_PAD0_TIE_OPT_M //Enable Tie,Init Level - | RTC_IO_TOUCH_PAD0_START_M //Enable Touch Pad IO - | RTC_IO_TOUCH_PAD0_XPD_M); //Enable Touch Pad Power on - - //Enable Digital rtc control :work mode and out mode - SET_PERI_REG_MASK(SENS_SAR_TOUCH_ENABLE_REG, - (1 << (pad + SENS_TOUCH_PAD_WORKEN_S)) | \ - (1 << (pad + SENS_TOUCH_PAD_OUTEN2_S)) | \ - (1 << (pad + SENS_TOUCH_PAD_OUTEN1_S))); -#else - -#endif + return __touchInterruptHandlers[pad].lastStatusIsPressed; } - -extern uint16_t touchRead(uint8_t pin) __attribute__ ((weak, alias("__touchRead"))); -extern void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold) __attribute__ ((weak, alias("__touchAttachInterrupt"))); -extern void touchSetCycles(uint16_t measure, uint16_t sleep) __attribute__ ((weak, alias("__touchSetCycles"))); #endif + +extern touch_value_t touchRead(uint8_t) __attribute__ ((weak, alias("__touchRead"))); +extern void touchAttachInterrupt(uint8_t, voidFuncPtr, touch_value_t) __attribute__ ((weak, alias("__touchAttachInterrupt"))); +extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value_t) __attribute__ ((weak, alias("__touchAttachArgsInterrupt"))); +extern void touchDetachInterrupt(uint8_t) __attribute__ ((weak, alias("__touchDettachInterrupt"))); +extern void touchSetCycles(uint16_t, uint16_t) __attribute__ ((weak, alias("__touchSetCycles"))); + +#endif // #if SOC_TOUCH_SENSOR_NUM > 0 diff --git a/cores/esp32/esp32-hal-touch.h b/cores/esp32/esp32-hal-touch.h index 6f3b0fd0f7d..a8cda191c31 100644 --- a/cores/esp32/esp32-hal-touch.h +++ b/cores/esp32/esp32-hal-touch.h @@ -24,8 +24,21 @@ extern "C" { #endif +#include "soc/soc_caps.h" #include "esp32-hal.h" +#if SOC_TOUCH_SENSOR_NUM > 0 + +#if !defined(SOC_TOUCH_VERSION_1) && !defined(SOC_TOUCH_VERSION_2) +#error Touch IDF driver Not supported! +#endif + +#if SOC_TOUCH_VERSION_1 // ESP32 +typedef uint16_t touch_value_t; +#elif SOC_TOUCH_VERSION_2 // ESP32S2 ESP32S3 +typedef uint32_t touch_value_t; +#endif + /* * Set cycles that measurement operation takes * The result from touchRead, threshold and detection @@ -40,17 +53,44 @@ void touchSetCycles(uint16_t measure, uint16_t sleep); * You can use this method to chose a good threshold value * to use as value for touchAttachInterrupt * */ -uint16_t touchRead(uint8_t pin); +touch_value_t touchRead(uint8_t pin); /* - * Set function to be called if touch pad value falls - * below the given threshold. Use touchRead to determine - * a proper threshold between touched and untouched state + * Set function to be called if touch pad value falls (ESP32) + * below the given threshold / rises (ESP32-S2/S3) by given increment (threshold). + * Use touchRead to determine a proper threshold between touched and untouched state * */ -void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold); +void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), touch_value_t threshold); +void touchAttachInterruptArg(uint8_t pin, void (*userFunc)(void*), void *arg, touch_value_t threshold); +void touchDetachInterrupt(uint8_t pin); + +/* + * Specific functions to ESP32 + * Tells the driver if it shall activate the ISR if the sensor is Lower or Higher than the Threshold + * Default if Lower. + **/ + +#if SOC_TOUCH_VERSION_1 // Only for ESP32 SoC +void touchInterruptSetThresholdDirection(bool mustbeLower); +#endif + + +/* + * Specific functions to ESP32-S2 and ESP32-S3 + * Returns true when the latest ISR status for the Touchpad is that it is touched (Active) + * and false when the Touchpad is untoouched (Inactive) + * This function can be used in conjunction with ISR User callback in order to take action + * as soon as the touchpad is touched and/or released + **/ + +#if SOC_TOUCH_VERSION_2 // Only for ESP32S2 and ESP32S3 +// returns true if touch pad has been and continues pressed and false otherwise +bool touchInterruptGetLastStatus(uint8_t pin); +#endif + +#endif // SOC_TOUCH_SENSOR_NUM > 0 #ifdef __cplusplus } #endif - #endif /* MAIN_ESP32_HAL_TOUCH_H_ */ diff --git a/libraries/ESP32/examples/Touch/TouchButton/.skip.esp32c3 b/libraries/ESP32/examples/Touch/TouchButton/.skip.esp32c3 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/ESP32/examples/Touch/TouchButton/.skip.esp32s2 b/libraries/ESP32/examples/Touch/TouchButton/.skip.esp32s2 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/ESP32/examples/Touch/TouchButton/.skip.esp32s3 b/libraries/ESP32/examples/Touch/TouchButton/.skip.esp32s3 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino b/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino new file mode 100644 index 00000000000..b1dbc63fdcb --- /dev/null +++ b/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino @@ -0,0 +1,46 @@ +/* + +This is an example how to use Touch Intrrerupts +The sketh will tell when it is touched and then relesased as like a push-button + +This method based on touchInterruptSetThresholdDirection() is only available for ESP32 +*/ + +#include "Arduino.h" + +int threshold = 40; +bool touchActive = false; +bool lastTouchActive = false; +bool testingLower = true; + +void gotTouchEvent(){ + if (lastTouchActive != testingLower) { + touchActive = !touchActive; + testingLower = !testingLower; + // Touch ISR will be inverted: Lower <--> Higher than the Threshold after ISR event is noticed + touchInterruptSetThresholdDirection(testingLower); + } +} + +void setup() { + Serial.begin(115200); + delay(1000); // give me time to bring up serial monitor + Serial.println("ESP32 Touch Interrupt Test"); + touchAttachInterrupt(T2, gotTouchEvent, threshold); + + // Touch ISR will be activated when touchRead is lower than the Threshold + touchInterruptSetThresholdDirection(testingLower); +} + +void loop(){ + if(lastTouchActive != touchActive){ + lastTouchActive = touchActive; + if (touchActive) { + Serial.println(" ---- Touch was Pressed"); + } else { + Serial.println(" ---- Touch was Released"); + } + } + Serial.printf("T2 pin2 = %d \n", touchRead(T2)); + delay(125); +} diff --git a/libraries/ESP32/examples/Touch/TouchButtonV2/.skip.esp32 b/libraries/ESP32/examples/Touch/TouchButtonV2/.skip.esp32 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/ESP32/examples/Touch/TouchButtonV2/.skip.esp32c3 b/libraries/ESP32/examples/Touch/TouchButtonV2/.skip.esp32c3 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino b/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino new file mode 100644 index 00000000000..640fd2d3b59 --- /dev/null +++ b/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino @@ -0,0 +1,53 @@ +/* + +This is an example how to use Touch Intrrerupts +The sketh will tell when it is touched and then relesased as like a push-button + +This method based on touchInterruptGetLastStatus() is only available for ESP32 S2 and S3 +*/ + +#include "Arduino.h" + +int threshold = 1500; // ESP32S2 +bool touch1detected = false; +bool touch2detected = false; + +void gotTouch1() { + touch1detected = true; +} + +void gotTouch2() { + touch2detected = true; +} + +void setup() { + Serial.begin(115200); + delay(1000); // give me time to bring up serial monitor + + Serial.println("\n ESP32 Touch Interrupt Test\n"); + touchAttachInterrupt(T1, gotTouch1, threshold); + touchAttachInterrupt(T2, gotTouch2, threshold); +} + +void loop() { + static uint32_t count = 0; + + if (touch1detected) { + touch1detected = false; + if (touchInterruptGetLastStatus(T1)) { + Serial.println(" --- T1 Touched"); + } else { + Serial.println(" --- T1 Released"); + } + } + if (touch2detected) { + touch2detected = false; + if (touchInterruptGetLastStatus(T2)) { + Serial.println(" --- T2 Touched"); + } else { + Serial.println(" --- T2 Released"); + } + } + + delay(80); +} From 6591f5bd4cf4d3ef7c9c783680d8b06678d3c449 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 3 Feb 2022 19:07:34 +0100 Subject: [PATCH 2/8] Fix replace() failing (#6224) --- cores/esp32/WString.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cores/esp32/WString.cpp b/cores/esp32/WString.cpp index 4badf63d0fe..f69302a253f 100644 --- a/cores/esp32/WString.cpp +++ b/cores/esp32/WString.cpp @@ -774,9 +774,10 @@ void String::replace(const String& find, const String& replace) { } if(size == len()) return; - if(size > capacity() && !changeBuffer(size)) + if(size > capacity() && !changeBuffer(size)) { log_w("String.Replace() Insufficient space to replace string"); return; + } int index = len() - 1; while(index >= 0 && (index = lastIndexOf(find, index)) >= 0) { readFrom = wbuffer() + index + find.len(); From 1046f59f6bc3d60534171ae4e61bb4578247316a Mon Sep 17 00:00:00 2001 From: Dmitry Bondarenko Date: Thu, 3 Feb 2022 21:09:18 +0300 Subject: [PATCH 3/8] Upload to the component registry (#6203) Co-authored-by: Sergei Silnov --- .github/workflows/upload-idf-component.yml | 19 +++++++++++++++++++ idf_component.yml | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 .github/workflows/upload-idf-component.yml create mode 100644 idf_component.yml diff --git a/.github/workflows/upload-idf-component.yml b/.github/workflows/upload-idf-component.yml new file mode 100644 index 00000000000..d9e4032df08 --- /dev/null +++ b/.github/workflows/upload-idf-component.yml @@ -0,0 +1,19 @@ +name: Push components to https://components.espressif.com +on: + push: + tags: + - v* +jobs: + upload_components: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: "recursive" + + - name: Upload components to the component registry + uses: espressif/github-actions/upload_components@master + with: + name: arduino-esp32 + namespace: espressif + api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} diff --git a/idf_component.yml b/idf_component.yml new file mode 100644 index 00000000000..72e81d7b2a9 --- /dev/null +++ b/idf_component.yml @@ -0,0 +1,20 @@ +description: "Arduino core for ESP32, ESP32-S and ESP32-C series of SoCs" +url: "https://github.com/espressif/arduino-esp32" +targets: + - esp32 + - esp32s2 + - esp32c3 +tags: + - arduino +files: + include: + - "cores/**/*" + - "variants/esp32/**/*" + - "variants/esp32s2/**/*" + - "variants/esp32s3/**/*" + - "variants/esp32c3/**/*" + - "libraries/**/*" + - "CMakeLists.txt" + - "Kconfig.projbuild" + exclude: + - "**/*" \ No newline at end of file From bb4d9027dda9f1ac8a73217404294a3c06cb6607 Mon Sep 17 00:00:00 2001 From: "Limor \"Ladyada\" Fried" Date: Thu, 3 Feb 2022 13:10:54 -0500 Subject: [PATCH 4/8] add feather esp32 v2 and qtpy c3 board def (#6223) * add feather esp32 v2 and qtpy c3 board def update some pin names add variant.cpp's to auto-enable i2c, tft, neopixels on boot * add auto-enable for i2c! --- boards.txt | 278 ++++++++++++++++++ .../adafruit_feather_esp32_v2/pins_arduino.h | 73 +++++ .../adafruit_feather_esp32_v2/variant.cpp | 40 +++ .../adafruit_feather_esp32s2/pins_arduino.h | 1 + variants/adafruit_qtpy_esp32/pins_arduino.h | 8 +- variants/adafruit_qtpy_esp32/variant.cpp | 40 +++ variants/adafruit_qtpy_esp32c3/pins_arduino.h | 34 +++ variants/feather_esp32/pins_arduino.h | 3 +- 8 files changed, 471 insertions(+), 6 deletions(-) create mode 100644 variants/adafruit_feather_esp32_v2/pins_arduino.h create mode 100644 variants/adafruit_feather_esp32_v2/variant.cpp create mode 100644 variants/adafruit_qtpy_esp32/variant.cpp create mode 100644 variants/adafruit_qtpy_esp32c3/pins_arduino.h diff --git a/boards.txt b/boards.txt index 085c03e56d3..7517c647229 100755 --- a/boards.txt +++ b/boards.txt @@ -5088,6 +5088,284 @@ adafruit_qtpy_esp32s2.menu.DebugLevel.debug.build.code_debug=4 adafruit_qtpy_esp32s2.menu.DebugLevel.verbose=Verbose adafruit_qtpy_esp32s2.menu.DebugLevel.verbose.build.code_debug=5 +############################################################## + +adafruit_qtpy_esp32c3.name=Adafruit QT Py ESP32-C3 +adafruit_qtpy_esp32c3.vid.0=0x303a +adafruit_qtpy_esp32c3.pid.0=0x1001 + +adafruit_qtpy_esp32c3.upload.tool=esptool_py +adafruit_qtpy_esp32c3.upload.maximum_size=1310720 +adafruit_qtpy_esp32c3.upload.maximum_data_size=327680 +adafruit_qtpy_esp32c3.upload.flags= +adafruit_qtpy_esp32c3.upload.extra_flags= +adafruit_qtpy_esp32c3.upload.use_1200bps_touch=false +adafruit_qtpy_esp32c3.upload.wait_for_upload_port=false + +adafruit_qtpy_esp32c3.serial.disableDTR=false +adafruit_qtpy_esp32c3.serial.disableRTS=false + +adafruit_qtpy_esp32c3.build.tarch=riscv32 +adafruit_qtpy_esp32c3.build.target=esp +adafruit_qtpy_esp32c3.build.mcu=esp32c3 +adafruit_qtpy_esp32c3.build.core=esp32 +adafruit_qtpy_esp32c3.build.variant=adafruit_qtpy_esp32c3 +adafruit_qtpy_esp32c3.build.board=ADAFRUIT_QTPY_ESP32C3 +adafruit_qtpy_esp32c3.build.bootloader_addr=0x0 + +adafruit_qtpy_esp32c3.build.cdc_on_boot=0 +adafruit_qtpy_esp32c3.build.f_cpu=160000000L +adafruit_qtpy_esp32c3.build.flash_size=4MB +adafruit_qtpy_esp32c3.build.flash_freq=80m +adafruit_qtpy_esp32c3.build.flash_mode=dout +adafruit_qtpy_esp32c3.build.boot=dout +adafruit_qtpy_esp32c3.build.partitions=default +adafruit_qtpy_esp32c3.build.defines= + +adafruit_qtpy_esp32c3.menu.CDCOnBoot.cdc=Enabled +adafruit_qtpy_esp32c3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 +adafruit_qtpy_esp32c3.menu.CDCOnBoot.default=Disabled +adafruit_qtpy_esp32c3.menu.CDCOnBoot.default.build.cdc_on_boot=0 + +adafruit_qtpy_esp32c3.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +adafruit_qtpy_esp32c3.menu.PartitionScheme.default.build.partitions=default +adafruit_qtpy_esp32c3.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +adafruit_qtpy_esp32c3.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +adafruit_qtpy_esp32c3.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +adafruit_qtpy_esp32c3.menu.PartitionScheme.minimal.build.partitions=minimal +adafruit_qtpy_esp32c3.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +adafruit_qtpy_esp32c3.menu.PartitionScheme.no_ota.build.partitions=no_ota +adafruit_qtpy_esp32c3.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +adafruit_qtpy_esp32c3.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +adafruit_qtpy_esp32c3.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +adafruit_qtpy_esp32c3.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +adafruit_qtpy_esp32c3.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +adafruit_qtpy_esp32c3.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +adafruit_qtpy_esp32c3.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +adafruit_qtpy_esp32c3.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +adafruit_qtpy_esp32c3.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +adafruit_qtpy_esp32c3.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +adafruit_qtpy_esp32c3.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +adafruit_qtpy_esp32c3.menu.PartitionScheme.huge_app.build.partitions=huge_app +adafruit_qtpy_esp32c3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +adafruit_qtpy_esp32c3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +adafruit_qtpy_esp32c3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +adafruit_qtpy_esp32c3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 + +adafruit_qtpy_esp32c3.menu.CPUFreq.160=160MHz (WiFi) +adafruit_qtpy_esp32c3.menu.CPUFreq.160.build.f_cpu=160000000L +adafruit_qtpy_esp32c3.menu.CPUFreq.80=80MHz (WiFi) +adafruit_qtpy_esp32c3.menu.CPUFreq.80.build.f_cpu=80000000L +adafruit_qtpy_esp32c3.menu.CPUFreq.40=40MHz +adafruit_qtpy_esp32c3.menu.CPUFreq.40.build.f_cpu=40000000L +adafruit_qtpy_esp32c3.menu.CPUFreq.20=20MHz +adafruit_qtpy_esp32c3.menu.CPUFreq.20.build.f_cpu=20000000L +adafruit_qtpy_esp32c3.menu.CPUFreq.10=10MHz +adafruit_qtpy_esp32c3.menu.CPUFreq.10.build.f_cpu=10000000L + +adafruit_qtpy_esp32c3.menu.FlashMode.dout=DOUT +adafruit_qtpy_esp32c3.menu.FlashMode.dout.build.flash_mode=dout +adafruit_qtpy_esp32c3.menu.FlashMode.dout.build.boot=dout +adafruit_qtpy_esp32c3.menu.FlashMode.qio=QIO +adafruit_qtpy_esp32c3.menu.FlashMode.qio.build.flash_mode=dio +adafruit_qtpy_esp32c3.menu.FlashMode.qio.build.boot=qio +adafruit_qtpy_esp32c3.menu.FlashMode.dio=DIO +adafruit_qtpy_esp32c3.menu.FlashMode.dio.build.flash_mode=dio +adafruit_qtpy_esp32c3.menu.FlashMode.dio.build.boot=dio +adafruit_qtpy_esp32c3.menu.FlashMode.qout=QOUT +adafruit_qtpy_esp32c3.menu.FlashMode.qout.build.flash_mode=dout +adafruit_qtpy_esp32c3.menu.FlashMode.qout.build.boot=qout + +adafruit_qtpy_esp32c3.menu.FlashFreq.80=80MHz +adafruit_qtpy_esp32c3.menu.FlashFreq.80.build.flash_freq=80m +adafruit_qtpy_esp32c3.menu.FlashFreq.40=40MHz +adafruit_qtpy_esp32c3.menu.FlashFreq.40.build.flash_freq=40m + +adafruit_qtpy_esp32c3.menu.FlashSize.4M=4MB (32Mb) +adafruit_qtpy_esp32c3.menu.FlashSize.4M.build.flash_size=4MB +adafruit_qtpy_esp32c3.menu.FlashSize.2M=2MB (16Mb) +adafruit_qtpy_esp32c3.menu.FlashSize.2M.build.flash_size=2MB +adafruit_qtpy_esp32c3.menu.FlashSize.2M.build.partitions=minimal + +adafruit_qtpy_esp32c3.menu.UploadSpeed.115200=115200 +adafruit_qtpy_esp32c3.menu.UploadSpeed.115200.upload.speed=115200 +adafruit_qtpy_esp32c3.menu.UploadSpeed.921600=921600 +adafruit_qtpy_esp32c3.menu.UploadSpeed.921600.upload.speed=921600 +adafruit_qtpy_esp32c3.menu.UploadSpeed.921600=921600 +adafruit_qtpy_esp32c3.menu.UploadSpeed.921600.upload.speed=921600 +adafruit_qtpy_esp32c3.menu.UploadSpeed.115200=115200 +adafruit_qtpy_esp32c3.menu.UploadSpeed.115200.upload.speed=115200 +adafruit_qtpy_esp32c3.menu.UploadSpeed.256000.windows=256000 +adafruit_qtpy_esp32c3.menu.UploadSpeed.256000.upload.speed=256000 +adafruit_qtpy_esp32c3.menu.UploadSpeed.230400.windows.upload.speed=256000 +adafruit_qtpy_esp32c3.menu.UploadSpeed.230400=230400 +adafruit_qtpy_esp32c3.menu.UploadSpeed.230400.upload.speed=230400 +adafruit_qtpy_esp32c3.menu.UploadSpeed.460800.linux=460800 +adafruit_qtpy_esp32c3.menu.UploadSpeed.460800.macosx=460800 +adafruit_qtpy_esp32c3.menu.UploadSpeed.460800.upload.speed=460800 +adafruit_qtpy_esp32c3.menu.UploadSpeed.512000.windows=512000 +adafruit_qtpy_esp32c3.menu.UploadSpeed.512000.upload.speed=512000 + +adafruit_qtpy_esp32c3.menu.DebugLevel.none=None +adafruit_qtpy_esp32c3.menu.DebugLevel.none.build.code_debug=0 +adafruit_qtpy_esp32c3.menu.DebugLevel.error=Error +adafruit_qtpy_esp32c3.menu.DebugLevel.error.build.code_debug=1 +adafruit_qtpy_esp32c3.menu.DebugLevel.warn=Warn +adafruit_qtpy_esp32c3.menu.DebugLevel.warn.build.code_debug=2 +adafruit_qtpy_esp32c3.menu.DebugLevel.info=Info +adafruit_qtpy_esp32c3.menu.DebugLevel.info.build.code_debug=3 +adafruit_qtpy_esp32c3.menu.DebugLevel.debug=Debug +adafruit_qtpy_esp32c3.menu.DebugLevel.debug.build.code_debug=4 +adafruit_qtpy_esp32c3.menu.DebugLevel.verbose=Verbose +adafruit_qtpy_esp32c3.menu.DebugLevel.verbose.build.code_debug=5 + + +adafruit_qtpy_esp32_pico.name=Adafruit QT Py ESP32 Pico + +adafruit_qtpy_esp32_pico.upload.tool=esptool_py +adafruit_qtpy_esp32_pico.upload.maximum_size=1310720 +adafruit_qtpy_esp32_pico.upload.maximum_data_size=327680 +adafruit_qtpy_esp32_pico.upload.flags= +adafruit_qtpy_esp32_pico.upload.extra_flags= + +adafruit_qtpy_esp32_pico.serial.disableDTR=true +adafruit_qtpy_esp32_pico.serial.disableRTS=true + +adafruit_qtpy_esp32_pico.build.tarch=xtensa +adafruit_qtpy_esp32_pico.build.bootloader_addr=0x1000 +adafruit_qtpy_esp32_pico.build.target=esp32 +adafruit_qtpy_esp32_pico.build.mcu=esp32 +adafruit_qtpy_esp32_pico.build.core=esp32 +adafruit_qtpy_esp32_pico.build.variant=adafruit_qtpy_esp32 +adafruit_qtpy_esp32_pico.build.board=ADAFRUIT_QTPY_ESP32_PICO + +adafruit_qtpy_esp32_pico.build.f_cpu=240000000L +adafruit_qtpy_esp32_pico.build.flash_size=8MB +adafruit_qtpy_esp32_pico.build.flash_freq=80m +adafruit_qtpy_esp32_pico.build.flash_mode=dio +adafruit_qtpy_esp32_pico.build.boot=dio +adafruit_qtpy_esp32_pico.build.partitions=default +adafruit_qtpy_esp32_pico.build.defines= + +adafruit_qtpy_esp32_pico.menu.PartitionScheme.default=Default +adafruit_qtpy_esp32_pico.menu.PartitionScheme.default.build.partitions=default +adafruit_qtpy_esp32_pico.menu.PartitionScheme.no_ota=No OTA (Large APP) +adafruit_qtpy_esp32_pico.menu.PartitionScheme.no_ota.build.partitions=no_ota +adafruit_qtpy_esp32_pico.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +adafruit_qtpy_esp32_pico.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA) +adafruit_qtpy_esp32_pico.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +adafruit_qtpy_esp32_pico.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 + +adafruit_qtpy_esp32_pico.menu.UploadSpeed.921600=921600 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.921600.upload.speed=921600 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.115200=115200 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.115200.upload.speed=115200 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.256000.windows=256000 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.256000.upload.speed=256000 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.230400.windows.upload.speed=256000 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.230400=230400 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.230400.upload.speed=230400 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.460800.linux=460800 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.460800.macosx=460800 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.460800.upload.speed=460800 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.512000.windows=512000 +adafruit_qtpy_esp32_pico.menu.UploadSpeed.512000.upload.speed=512000 + +adafruit_qtpy_esp32_pico.menu.PSRAM.enabled=Enabled +adafruit_qtpy_esp32_pico.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw +adafruit_qtpy_esp32_pico.menu.PSRAM.enabled.build.extra_libs= +adafruit_qtpy_esp32_pico.menu.PSRAM.disabled=Disabled +adafruit_qtpy_esp32_pico.menu.PSRAM.disabled.build.defines= +adafruit_qtpy_esp32_pico.menu.PSRAM.disabled.build.extra_libs= + +adafruit_qtpy_esp32_pico.menu.DebugLevel.none=None +adafruit_qtpy_esp32_pico.menu.DebugLevel.none.build.code_debug=0 +adafruit_qtpy_esp32_pico.menu.DebugLevel.error=Error +adafruit_qtpy_esp32_pico.menu.DebugLevel.error.build.code_debug=1 +adafruit_qtpy_esp32_pico.menu.DebugLevel.warn=Warn +adafruit_qtpy_esp32_pico.menu.DebugLevel.warn.build.code_debug=2 +adafruit_qtpy_esp32_pico.menu.DebugLevel.info=Info +adafruit_qtpy_esp32_pico.menu.DebugLevel.info.build.code_debug=3 +adafruit_qtpy_esp32_pico.menu.DebugLevel.debug=Debug +adafruit_qtpy_esp32_pico.menu.DebugLevel.debug.build.code_debug=4 +adafruit_qtpy_esp32_pico.menu.DebugLevel.verbose=Verbose +adafruit_qtpy_esp32_pico.menu.DebugLevel.verbose.build.code_debug=5 + + + +adafruit_feather_esp32_v2.name=Adafruit Feather ESP32 V2 + +adafruit_feather_esp32_v2.upload.tool=esptool_py +adafruit_feather_esp32_v2.upload.maximum_size=1310720 +adafruit_feather_esp32_v2.upload.maximum_data_size=327680 +adafruit_feather_esp32_v2.upload.flags= +adafruit_feather_esp32_v2.upload.extra_flags= + +adafruit_feather_esp32_v2.serial.disableDTR=true +adafruit_feather_esp32_v2.serial.disableRTS=true + +adafruit_feather_esp32_v2.build.tarch=xtensa +adafruit_feather_esp32_v2.build.bootloader_addr=0x1000 +adafruit_feather_esp32_v2.build.target=esp32 +adafruit_feather_esp32_v2.build.mcu=esp32 +adafruit_feather_esp32_v2.build.core=esp32 +adafruit_feather_esp32_v2.build.variant=adafruit_feather_esp32_v2 +adafruit_feather_esp32_v2.build.board=ADAFRUIT_FEATHER_ESP32_V2 + +adafruit_feather_esp32_v2.build.f_cpu=240000000L +adafruit_feather_esp32_v2.build.flash_size=8MB +adafruit_feather_esp32_v2.build.flash_freq=80m +adafruit_feather_esp32_v2.build.flash_mode=dio +adafruit_feather_esp32_v2.build.boot=dio +adafruit_feather_esp32_v2.build.partitions=default +adafruit_feather_esp32_v2.build.defines= + +adafruit_feather_esp32_v2.menu.PartitionScheme.default=Default +adafruit_feather_esp32_v2.menu.PartitionScheme.default.build.partitions=default +adafruit_feather_esp32_v2.menu.PartitionScheme.no_ota=No OTA (Large APP) +adafruit_feather_esp32_v2.menu.PartitionScheme.no_ota.build.partitions=no_ota +adafruit_feather_esp32_v2.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +adafruit_feather_esp32_v2.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA) +adafruit_feather_esp32_v2.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +adafruit_feather_esp32_v2.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 + +adafruit_feather_esp32_v2.menu.UploadSpeed.921600=921600 +adafruit_feather_esp32_v2.menu.UploadSpeed.921600.upload.speed=921600 +adafruit_feather_esp32_v2.menu.UploadSpeed.115200=115200 +adafruit_feather_esp32_v2.menu.UploadSpeed.115200.upload.speed=115200 +adafruit_feather_esp32_v2.menu.UploadSpeed.256000.windows=256000 +adafruit_feather_esp32_v2.menu.UploadSpeed.256000.upload.speed=256000 +adafruit_feather_esp32_v2.menu.UploadSpeed.230400.windows.upload.speed=256000 +adafruit_feather_esp32_v2.menu.UploadSpeed.230400=230400 +adafruit_feather_esp32_v2.menu.UploadSpeed.230400.upload.speed=230400 +adafruit_feather_esp32_v2.menu.UploadSpeed.460800.linux=460800 +adafruit_feather_esp32_v2.menu.UploadSpeed.460800.macosx=460800 +adafruit_feather_esp32_v2.menu.UploadSpeed.460800.upload.speed=460800 +adafruit_feather_esp32_v2.menu.UploadSpeed.512000.windows=512000 +adafruit_feather_esp32_v2.menu.UploadSpeed.512000.upload.speed=512000 + +adafruit_feather_esp32_v2.menu.PSRAM.enabled=Enabled +adafruit_feather_esp32_v2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw +adafruit_feather_esp32_v2.menu.PSRAM.enabled.build.extra_libs= +adafruit_feather_esp32_v2.menu.PSRAM.disabled=Disabled +adafruit_feather_esp32_v2.menu.PSRAM.disabled.build.defines= +adafruit_feather_esp32_v2.menu.PSRAM.disabled.build.extra_libs= + +adafruit_feather_esp32_v2.menu.DebugLevel.none=None +adafruit_feather_esp32_v2.menu.DebugLevel.none.build.code_debug=0 +adafruit_feather_esp32_v2.menu.DebugLevel.error=Error +adafruit_feather_esp32_v2.menu.DebugLevel.error.build.code_debug=1 +adafruit_feather_esp32_v2.menu.DebugLevel.warn=Warn +adafruit_feather_esp32_v2.menu.DebugLevel.warn.build.code_debug=2 +adafruit_feather_esp32_v2.menu.DebugLevel.info=Info +adafruit_feather_esp32_v2.menu.DebugLevel.info.build.code_debug=3 +adafruit_feather_esp32_v2.menu.DebugLevel.debug=Debug +adafruit_feather_esp32_v2.menu.DebugLevel.debug.build.code_debug=4 +adafruit_feather_esp32_v2.menu.DebugLevel.verbose=Verbose +adafruit_feather_esp32_v2.menu.DebugLevel.verbose.build.code_debug=5 + + + ############################################################## nodemcu-32s.name=NodeMCU-32S diff --git a/variants/adafruit_feather_esp32_v2/pins_arduino.h b/variants/adafruit_feather_esp32_v2/pins_arduino.h new file mode 100644 index 00000000000..2bfaf63b7aa --- /dev/null +++ b/variants/adafruit_feather_esp32_v2/pins_arduino.h @@ -0,0 +1,73 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define EXTERNAL_NUM_INTERRUPTS 16 +#define NUM_DIGITAL_PINS 40 +#define NUM_ANALOG_INPUTS 16 + +#define analogInputToDigitalPin(p) (((p)<20)?(esp32_adc2gpio[(p)]):-1) +#define digitalPinToInterrupt(p) (((p)<40)?(p):-1) +#define digitalPinHasPWM(p) (p < 34) + +static const uint8_t LED_BUILTIN = 13; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN + +static const uint8_t TX = 7; +static const uint8_t RX = 8; +static const uint8_t TX1 = 7; +static const uint8_t RX1 = 8; + +static const uint8_t SDA = 22; +static const uint8_t SCL = 20; + +static const uint8_t SS = 33; +static const uint8_t MOSI = 19; +static const uint8_t MISO = 21; +static const uint8_t SCK = 5; + +// mapping to match other feathers and also in order +static const uint8_t A0 = 26; +static const uint8_t A1 = 25; +static const uint8_t A2 = 34; +static const uint8_t A3 = 39; +static const uint8_t A4 = 36; +static const uint8_t A5 = 4; +static const uint8_t A6 = 14; +static const uint8_t A7 = 32; +static const uint8_t A8 = 15; +static const uint8_t A9 = 33; +static const uint8_t A10 = 27; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; + +// vbat measure +static const uint8_t BATT_MONITOR = 35; +static const uint8_t A13 = 35; + +// internal switch +static const uint8_t BUTTON = 38; + +// Neopixel +static const uint8_t NEOPIXEL_PIN = 0; + +// Neopixel & I2C power +static const uint8_t NEOPIXEL_I2C_POWER = 2; + +static const uint8_t T0 = 4; +static const uint8_t T1 = 0; +static const uint8_t T2 = 2; +static const uint8_t T3 = 15; +static const uint8_t T4 = 13; +static const uint8_t T5 = 12; +static const uint8_t T6 = 14; +static const uint8_t T7 = 27; +static const uint8_t T8 = 33; +static const uint8_t T9 = 32; + +static const uint8_t DAC1 = 25; +static const uint8_t DAC2 = 26; + +#endif /* Pins_Arduino_h */ diff --git a/variants/adafruit_feather_esp32_v2/variant.cpp b/variants/adafruit_feather_esp32_v2/variant.cpp new file mode 100644 index 00000000000..9345f6058a6 --- /dev/null +++ b/variants/adafruit_feather_esp32_v2/variant.cpp @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Ha Thach (tinyusb.org) for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#include "esp32-hal-gpio.h" +#include "pins_arduino.h" + +extern "C" { + +// Initialize variant/board, called before setup() +void initVariant(void) +{ + // This board has a power control pin, and we must set it to output and high + // in order to enable the NeoPixels & I2C + pinMode(NEOPIXEL_I2C_POWER, OUTPUT); + digitalWrite(NEOPIXEL_I2C_POWER, HIGH); +} + +} diff --git a/variants/adafruit_feather_esp32s2/pins_arduino.h b/variants/adafruit_feather_esp32s2/pins_arduino.h index 4e5e13de6e2..bde8d973d8f 100644 --- a/variants/adafruit_feather_esp32s2/pins_arduino.h +++ b/variants/adafruit_feather_esp32s2/pins_arduino.h @@ -26,6 +26,7 @@ #define NEOPIXEL_POWER 21 // power pin #define NEOPIXEL_POWER_ON HIGH // power pin state when on #define I2C_POWER 7 // I2C power pin +#define PIN_I2C_POWER 7 // I2C power pin static const uint8_t SDA = 3; static const uint8_t SCL = 4; diff --git a/variants/adafruit_qtpy_esp32/pins_arduino.h b/variants/adafruit_qtpy_esp32/pins_arduino.h index 72a5606c5d6..091554a08dd 100644 --- a/variants/adafruit_qtpy_esp32/pins_arduino.h +++ b/variants/adafruit_qtpy_esp32/pins_arduino.h @@ -11,14 +11,14 @@ #define digitalPinToInterrupt(p) (((p)<40)?(p):-1) #define digitalPinHasPWM(p) (p < 34) -static const uint8_t NEOPIXEL = 5; +static const uint8_t PIN_NEOPIXEL = 5; static const uint8_t NEOPIXEL_POWER = 8; static const uint8_t TX = 32; static const uint8_t RX = 7; -static const uint8_t TX1 = 32; -static const uint8_t RX1 = 7; +#define TX1 32 +#define RX1 7 static const uint8_t SDA = 25; static const uint8_t SCL = 33; @@ -43,7 +43,7 @@ static const uint8_t A8 = 14; static const uint8_t A9 = 12; static const uint8_t A10 = 13; -static const uint8_t SWITCH = 0; +static const uint8_t BUTTON = 0; static const uint8_t T0 = 4; static const uint8_t T3 = 15; diff --git a/variants/adafruit_qtpy_esp32/variant.cpp b/variants/adafruit_qtpy_esp32/variant.cpp new file mode 100644 index 00000000000..726ec8fa483 --- /dev/null +++ b/variants/adafruit_qtpy_esp32/variant.cpp @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Ha Thach (tinyusb.org) for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#include "esp32-hal-gpio.h" +#include "pins_arduino.h" + +extern "C" { + +// Initialize variant/board, called before setup() +void initVariant(void) +{ + // This board has a power control pin, and we must set it to output and high + // in order to enable the NeoPixels. + pinMode(NEOPIXEL_POWER, OUTPUT); + digitalWrite(NEOPIXEL_POWER, HIGH); +} + +} diff --git a/variants/adafruit_qtpy_esp32c3/pins_arduino.h b/variants/adafruit_qtpy_esp32c3/pins_arduino.h new file mode 100644 index 00000000000..61d1f49492b --- /dev/null +++ b/variants/adafruit_qtpy_esp32c3/pins_arduino.h @@ -0,0 +1,34 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define EXTERNAL_NUM_INTERRUPTS 22 +#define NUM_DIGITAL_PINS 22 +#define NUM_ANALOG_INPUTS 6 + +#define analogInputToDigitalPin(p) (((p) Date: Thu, 3 Feb 2022 18:56:25 +0000 Subject: [PATCH 5/8] Added dual antenna for WiFi (based on the ESP32-WROOM-DA module) (#6226) * Added dual antenna for WiFi (based on the ESP32-WROOM-DA module) * Fixed build error * Fixed indentation and renamed function to setDualAntennaConfig * Added the RX and TX selection modes as configuration * Mode code optimization --- libraries/WiFi/src/WiFiGeneric.cpp | 88 ++++++++++++++++++++++++++++++ libraries/WiFi/src/WiFiGeneric.h | 14 +++++ 2 files changed, 102 insertions(+) diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index 3bcaececc7a..5dfdacdc05d 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -1192,6 +1192,94 @@ bool WiFiGenericClass::initiateFTM(uint8_t frm_count, uint16_t burst_period, uin return true; } +/** + * Configure Dual antenna. + * @param gpio_ant1 Configure the GPIO number for the antenna 1 connected to the RF switch (default GPIO2 on ESP32-WROOM-DA) + * @param gpio_ant2 Configure the GPIO number for the antenna 2 connected to the RF switch (default GPIO25 on ESP32-WROOM-DA) + * @param rx_mode Set the RX antenna mode. See wifi_rx_ant_t for the options. + * @param tx_mode Set the TX antenna mode. See wifi_tx_ant_t for the options. + * @return true on success + */ +bool WiFiGenericClass::setDualAntennaConfig(uint8_t gpio_ant1, uint8_t gpio_ant2, wifi_rx_ant_t rx_mode, wifi_tx_ant_t tx_mode) { + + wifi_ant_gpio_config_t wifi_ant_io; + + if (ESP_OK != esp_wifi_get_ant_gpio(&wifi_ant_io)) { + log_e("Failed to get antenna configuration"); + return false; + } + + wifi_ant_io.gpio_cfg[0].gpio_num = gpio_ant1; + wifi_ant_io.gpio_cfg[0].gpio_select = 1; + wifi_ant_io.gpio_cfg[1].gpio_num = gpio_ant2; + wifi_ant_io.gpio_cfg[1].gpio_select = 1; + + if (ESP_OK != esp_wifi_set_ant_gpio(&wifi_ant_io)) { + log_e("Failed to set antenna GPIO configuration"); + return false; + } + + // Set antenna default configuration + wifi_ant_config_t ant_config = { + .rx_ant_mode = WIFI_ANT_MODE_AUTO, + .tx_ant_mode = WIFI_ANT_MODE_AUTO, + .enabled_ant0 = 0, + .enabled_ant1 = 1, + }; + + switch (rx_mode) + { + case WIFI_RX_ANT0: + ant_config.rx_ant_mode = WIFI_ANT_MODE_ANT0; + break; + case WIFI_RX_ANT1: + ant_config.rx_ant_mode = WIFI_ANT_MODE_ANT1; + break; + case WIFI_RX_ANT_AUTO: + log_i("TX Antenna will be automatically selected"); + ant_config.rx_ant_default = WIFI_ANT_ANT0; + ant_config.rx_ant_mode = WIFI_ANT_MODE_AUTO; + // Force TX for AUTO if RX is AUTO + ant_config.tx_ant_mode = WIFI_ANT_MODE_AUTO; + goto set_ant; + break; + default: + log_e("Invalid default antenna! Falling back to AUTO"); + ant_config.rx_ant_mode = WIFI_ANT_MODE_AUTO; + break; + } + + switch (tx_mode) + { + case WIFI_TX_ANT0: + ant_config.tx_ant_mode = WIFI_ANT_MODE_ANT0; + break; + case WIFI_TX_ANT1: + ant_config.tx_ant_mode = WIFI_ANT_MODE_ANT1; + break; + case WIFI_TX_ANT_AUTO: + log_i("RX Antenna will be automatically selected"); + ant_config.rx_ant_default = WIFI_ANT_ANT0; + ant_config.tx_ant_mode = WIFI_ANT_MODE_AUTO; + // Force RX for AUTO if RX is AUTO + ant_config.rx_ant_mode = WIFI_ANT_MODE_AUTO; + break; + default: + log_e("Invalid default antenna! Falling back to AUTO"); + ant_config.rx_ant_default = WIFI_ANT_ANT0; + ant_config.tx_ant_mode = WIFI_ANT_MODE_AUTO; + break; + } + +set_ant: + if (ESP_OK != esp_wifi_set_ant(&ant_config)) { + log_e("Failed to set antenna configuration"); + return false; + } + + return true; +} + // ----------------------------------------------------------------------------------------------------------------------- // ------------------------------------------------ Generic Network function --------------------------------------------- // ----------------------------------------------------------------------------------------------------------------------- diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index 7079c032993..f8a1bb77d37 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -139,6 +139,18 @@ static const int WIFI_SCAN_DONE_BIT= BIT12; static const int WIFI_DNS_IDLE_BIT = BIT13; static const int WIFI_DNS_DONE_BIT = BIT14; +typedef enum { + WIFI_RX_ANT0 = 0, + WIFI_RX_ANT1, + WIFI_RX_ANT_AUTO +} wifi_rx_ant_t; + +typedef enum { + WIFI_TX_ANT0 = 0, + WIFI_TX_ANT1, + WIFI_TX_ANT_AUTO +} wifi_tx_ant_t; + class WiFiGenericClass { public: @@ -174,6 +186,8 @@ class WiFiGenericClass bool initiateFTM(uint8_t frm_count=16, uint16_t burst_period=2, uint8_t channel=1, const uint8_t * mac=NULL); + bool setDualAntennaConfig(uint8_t gpio_ant1, uint8_t gpio_ant2, wifi_rx_ant_t rx_mode, wifi_tx_ant_t tx_mode); + static const char * getHostname(); static bool setHostname(const char * hostname); static bool hostname(const String& aHostname) { return setHostname(aHostname.c_str()); } From 9dbc90878435b13645bbf4df91d2824206579c24 Mon Sep 17 00:00:00 2001 From: P-R-O-C-H-Y <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 4 Feb 2022 14:55:28 +0100 Subject: [PATCH 6/8] FIX ledc on ESP32C3 (#6229) --- cores/esp32/esp32-hal-ledc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cores/esp32/esp32-hal-ledc.c b/cores/esp32/esp32-hal-ledc.c index 997bb806b80..b6c55ecb570 100644 --- a/cores/esp32/esp32-hal-ledc.c +++ b/cores/esp32/esp32-hal-ledc.c @@ -169,7 +169,11 @@ void ledcAttachPin(uint8_t pin, uint8_t chan) }; ledc_channel_config(&ledc_channel); + //Making attachInterrupt to work. + //WILL BE REMOVED AFTER REFACTORING GPIO to use ESP-IDF API + #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 pinMode(pin,OUTPUT); + #endif } void ledcDetachPin(uint8_t pin) From 7eec41dcb52366210ab7eeb6ac4c88be5e1dcfd9 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sat, 5 Feb 2022 06:54:01 -0300 Subject: [PATCH 7/8] Fixes Touch Sensor for ESP32-S3 and any future SoC (#6234) * Fixes digitalPinToTouchChannel() for ESP32-S3 --- cores/esp32/esp32-hal-gpio.c | 26 ++++++++++++++++++++++++++ cores/esp32/esp32-hal-gpio.h | 3 ++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/cores/esp32/esp32-hal-gpio.c b/cores/esp32/esp32-hal-gpio.c index 552126b848d..2a8a8294e5e 100644 --- a/cores/esp32/esp32-hal-gpio.c +++ b/cores/esp32/esp32-hal-gpio.c @@ -52,6 +52,32 @@ #include "esp_intr.h" #endif +#include "soc/soc_caps.h" +// It fixes lack of pin definition for S3 and for any future SoC +// this function works for ESP32, ESP32-S2 and ESP32-S3 - including the C3, it will return -1 for any pin +#if SOC_TOUCH_SENSOR_NUM > 0 +#include "soc/touch_sensor_periph.h" +int8_t digitalPinToTouchChannel(uint8_t pin) +{ + int8_t ret = -1; + if (pin < SOC_GPIO_PIN_COUNT) { + for (uint8_t i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) { + if (touch_sensor_channel_io_map[i] == pin) { + ret = i; + break; + } + } + } + return ret; +} +#else +// No Touch Sensor available +int8_t digitalPinToTouchChannel(uint8_t pin) +{ + return -1; +} +#endif + #if CONFIG_IDF_TARGET_ESP32 const int8_t esp32_adc2gpio[20] = {36, 37, 38, 39, 32, 33, 34, 35, -1, -1, 4, 0, 2, 15, 13, 12, 14, 27, 25, 26}; #elif CONFIG_IDF_TARGET_ESP32S2 diff --git a/cores/esp32/esp32-hal-gpio.h b/cores/esp32/esp32-hal-gpio.h index d7618392619..9110a790777 100644 --- a/cores/esp32/esp32-hal-gpio.h +++ b/cores/esp32/esp32-hal-gpio.h @@ -82,7 +82,6 @@ extern const int8_t esp32_adc2gpio[20]; #define digitalPinCanOutput(pin) ((pin) < NUM_OUPUT_PINS && esp32_gpioMux[(pin)].reg) #define digitalPinToRtcPin(pin) (((pin) < SOC_GPIO_PIN_COUNT)?esp32_gpioMux[(pin)].rtc:-1) #define digitalPinToAnalogChannel(pin) (((pin) < SOC_GPIO_PIN_COUNT)?esp32_gpioMux[(pin)].adc:-1) -#define digitalPinToTouchChannel(pin) (((pin) < SOC_GPIO_PIN_COUNT)?esp32_gpioMux[(pin)].touch:-1) #define digitalPinToDacChannel(pin) (((pin) == PIN_DAC1)?0:((pin) == PIN_DAC2)?1:-1) void pinMode(uint8_t pin, uint8_t mode); @@ -93,6 +92,8 @@ void attachInterrupt(uint8_t pin, void (*)(void), int mode); void attachInterruptArg(uint8_t pin, void (*)(void*), void * arg, int mode); void detachInterrupt(uint8_t pin); +int8_t digitalPinToTouchChannel(uint8_t pin); + #ifdef __cplusplus } #endif From ab6e010c20518d871f4bf77be1141b510d194158 Mon Sep 17 00:00:00 2001 From: mattsches1 <96293675+mattsches1@users.noreply.github.com> Date: Sat, 5 Feb 2022 12:04:57 +0100 Subject: [PATCH 8/8] HttpClient: Add cookie support (cookie jar) (#6216) * Support concatenation of headers (as in https://github.com/esp8266/Arduino/commit/1de0c341b55ba8c0993fd3d2e0c5696935578751#diff-977435a9cc4619fa0b8b995085f6ae683485cf563722756bab57108b362da316 for ESP8266, fixes https://github.com/espressif/arduino-esp32/issues/4069) * Add support for receiving, storing and sending cookies (cookie jar) * Cookie support: Respect `secure` attribute when sending a request * Fix missing `_secure` flag * Comment out support concatenation of headers (not needed anymore when using cookie jar) --- libraries/HTTPClient/src/HTTPClient.cpp | 203 +++++++++++++++++++++++- libraries/HTTPClient/src/HTTPClient.h | 37 +++++ 2 files changed, 236 insertions(+), 4 deletions(-) diff --git a/libraries/HTTPClient/src/HTTPClient.cpp b/libraries/HTTPClient/src/HTTPClient.cpp index a7bf13e89f5..250a695e0fe 100644 --- a/libraries/HTTPClient/src/HTTPClient.cpp +++ b/libraries/HTTPClient/src/HTTPClient.cpp @@ -39,6 +39,9 @@ #include "HTTPClient.h" +/// Cookie jar support +#include + #ifdef HTTPCLIENT_1_1_COMPATIBLE class TransportTraits { @@ -157,6 +160,7 @@ bool HTTPClient::begin(WiFiClient &client, String url) { } _port = (protocol == "https" ? 443 : 80); + _secure = (protocol == "https"); return beginInternal(url, protocol.c_str()); } @@ -187,6 +191,7 @@ bool HTTPClient::begin(WiFiClient &client, String host, uint16_t port, String ur _port = port; _uri = uri; _protocol = (https ? "https" : "http"); + _secure = https; return true; } @@ -603,6 +608,12 @@ int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) addHeader(F("Content-Length"), String(size)); } + // add cookies to header, if present + String cookie_string; + if(generateCookieString(&cookie_string)) { + addHeader("Cookie", cookie_string); + } + // send Header if(!sendHeader(type)) { return returnError(HTTPC_ERROR_SEND_HEADER_FAILED); @@ -706,6 +717,12 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) addHeader("Content-Length", String(size)); } + // add cookies to header, if present + String cookie_string; + if(generateCookieString(&cookie_string)) { + addHeader("Cookie", cookie_string); + } + // send Header if(!sendHeader(type)) { return returnError(HTTPC_ERROR_SEND_HEADER_FAILED); @@ -1222,6 +1239,7 @@ int HTTPClient::handleHeaderResponse() _transferEncoding = HTTPC_TE_IDENTITY; unsigned long lastDataTime = millis(); bool firstLine = true; + String date; while(connected()) { size_t len = _client->available(); @@ -1234,7 +1252,7 @@ int HTTPClient::handleHeaderResponse() log_v("RX: '%s'", headerLine.c_str()); if(firstLine) { - firstLine = false; + firstLine = false; if(_canReuse && headerLine.startsWith("HTTP/1.")) { _canReuse = (headerLine[sizeof "HTTP/1." - 1] != '0'); } @@ -1245,6 +1263,10 @@ int HTTPClient::handleHeaderResponse() String headerValue = headerLine.substring(headerLine.indexOf(':') + 1); headerValue.trim(); + if(headerName.equalsIgnoreCase("Date")) { + date = headerValue; + } + if(headerName.equalsIgnoreCase("Content-Length")) { _size = headerValue.toInt(); } @@ -1263,12 +1285,24 @@ int HTTPClient::handleHeaderResponse() _location = headerValue; } - for(size_t i = 0; i < _headerKeysCount; i++) { - if(_currentHeaders[i].key.equalsIgnoreCase(headerName)) { + if (headerName.equalsIgnoreCase("Set-Cookie")) { + setCookie(date, headerValue); + } + + for (size_t i = 0; i < _headerKeysCount; i++) { + if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) { + // Uncomment the following lines if you need to add support for multiple headers with the same key: + // if (!_currentHeaders[i].value.isEmpty()) { + // // Existing value, append this one with a comma + // _currentHeaders[i].value += ','; + // _currentHeaders[i].value += headerValue; + // } else { _currentHeaders[i].value = headerValue; - break; + // } + break; // We found a match, stop looking } } + } if(headerLine == "") { @@ -1491,3 +1525,164 @@ const String &HTTPClient::getLocation(void) { return _location; } + +void HTTPClient::setCookieJar(CookieJar* cookieJar) +{ + _cookieJar = cookieJar; +} + +void HTTPClient::resetCookieJar() +{ + _cookieJar = nullptr; +} + +void HTTPClient::clearAllCookies() +{ + if (_cookieJar) _cookieJar->clear(); +} + +void HTTPClient::setCookie(String date, String headerValue) +{ + #define HTTP_TIME_PATTERN "%a, %d %b %Y %H:%M:%S" + + Cookie cookie; + String value; + int pos1, pos2; + + headerValue.toLowerCase(); + + struct tm tm; + strptime(date.c_str(), HTTP_TIME_PATTERN, &tm); + cookie.date = mktime(&tm); + + pos1 = headerValue.indexOf('='); + pos2 = headerValue.indexOf(';'); + + if (pos1 >= 0 && pos2 > pos1){ + cookie.name = headerValue.substring(0, pos1); + cookie.value = headerValue.substring(pos1 + 1, pos2); + } else { + return; // invalid cookie header + } + + // expires + if (headerValue.indexOf("expires=") >= 0){ + pos1 = headerValue.indexOf("expires=") + strlen("expires="); + pos2 = headerValue.indexOf(';', pos1); + + if (pos2 > pos1) + value = headerValue.substring(pos1, pos2); + else + value = headerValue.substring(pos1); + + strptime(value.c_str(), HTTP_TIME_PATTERN, &tm); + cookie.expires.date = mktime(&tm); + cookie.expires.valid = true; + } + + // max-age + if (headerValue.indexOf("max-age=") >= 0){ + pos1 = headerValue.indexOf("max-age=") + strlen("max-age="); + pos2 = headerValue.indexOf(';', pos1); + + if (pos2 > pos1) + value = headerValue.substring(pos1, pos2); + else + value = headerValue.substring(pos1); + + cookie.max_age.duration = value.toInt(); + cookie.max_age.valid = true; + } + + // domain + if (headerValue.indexOf("domain=") >= 0){ + pos1 = headerValue.indexOf("domain=") + strlen("domain="); + pos2 = headerValue.indexOf(';', pos1); + + if (pos2 > pos1) + value = headerValue.substring(pos1, pos2); + else + value = headerValue.substring(pos1); + + if (value.startsWith(".")) value.remove(0, 1); + + if (_host.indexOf(value) >= 0) { + cookie.domain = value; + } else { + return; // server tries to set a cookie on a different domain; ignore it + } + } else { + pos1 = _host.lastIndexOf('.', _host.lastIndexOf('.') - 1); + if (pos1 >= 0) + cookie.domain = _host.substring(pos1 + 1); + else + cookie.domain = _host; + } + + // path + if (headerValue.indexOf("path=") >= 0){ + pos1 = headerValue.indexOf("path=") + strlen("path="); + pos2 = headerValue.indexOf(';', pos1); + + if (pos2 > pos1) + cookie.path = headerValue.substring(pos1, pos2); + else + cookie.path = headerValue.substring(pos1); + } + + // HttpOnly + cookie.http_only = (headerValue.indexOf("httponly") >= 0); + + // secure + cookie.secure = (headerValue.indexOf("secure") >= 0); + + // overwrite or delete cookie in/from cookie jar + time_t now_local = time(NULL); + time_t now_gmt = mktime(gmtime(&now_local)); + + bool found = false; + + for (auto c = _cookieJar->begin(); c != _cookieJar->end(); ++c) { + if (c->domain == cookie.domain && c->name == cookie.name) { + // when evaluating, max-age takes precedence over expires if both are defined + if (cookie.max_age.valid && ((cookie.date + cookie.max_age.duration) < now_gmt || cookie.max_age.duration <= 0) + || (!cookie.max_age.valid && cookie.expires.valid && cookie.expires.date < now_gmt)) { + _cookieJar->erase(c); + c--; + } else { + *c = cookie; + } + found = true; + } + } + + // add cookie to jar + if (!found && !(cookie.max_age.valid && cookie.max_age.duration <= 0)) + _cookieJar->push_back(cookie); + +} + +bool HTTPClient::generateCookieString(String *cookieString) +{ + time_t now_local = time(NULL); + time_t now_gmt = mktime(gmtime(&now_local)); + + *cookieString = ""; + bool found = false; + + for (auto c = _cookieJar->begin(); c != _cookieJar->end(); ++c) { + if (c->max_age.valid && ((c->date + c->max_age.duration) < now_gmt) || (!c->max_age.valid && c->expires.valid && c->expires.date < now_gmt)) { + _cookieJar->erase(c); + c--; + } else if (_host.indexOf(c->domain) >= 0 && (!c->secure || _secure) ) { + if (*cookieString == "") + *cookieString = c->name + "=" + c->value; + else + *cookieString += " ;" + c->name + "=" + c->value; + found = true; + } + } + return found; +} + + diff --git a/libraries/HTTPClient/src/HTTPClient.h b/libraries/HTTPClient/src/HTTPClient.h index fb6a7d4db87..6fe25b79b24 100644 --- a/libraries/HTTPClient/src/HTTPClient.h +++ b/libraries/HTTPClient/src/HTTPClient.h @@ -36,6 +36,9 @@ #include #include +/// Cookie jar support +#include + #define HTTPCLIENT_DEFAULT_TCP_TIMEOUT (5000) /// HTTP client errors @@ -144,6 +147,28 @@ class TransportTraits; typedef std::unique_ptr TransportTraitsPtr; #endif +// cookie jar support +typedef struct { + String host; // host which tries to set the cookie + time_t date; // timestamp of the response that set the cookie + String name; + String value; + String domain; + String path = ""; + struct { + time_t date = 0; + bool valid = false; + } expires; + struct { + time_t duration = 0; + bool valid = false; + } max_age; + bool http_only = false; + bool secure = false; +} Cookie; +typedef std::vector CookieJar; + + class HTTPClient { public: @@ -217,6 +242,11 @@ class HTTPClient static String errorToString(int error); + /// Cookie jar support + void setCookieJar(CookieJar* cookieJar); + void resetCookieJar(); + void clearAllCookies(); + protected: struct RequestArgument { String key; @@ -232,6 +262,9 @@ class HTTPClient int handleHeaderResponse(); int writeToStreamDataBlock(Stream * stream, int len); + /// Cookie jar support + void setCookie(String date, String headerValue); + bool generateCookieString(String *cookieString); #ifdef HTTPCLIENT_1_1_COMPATIBLE TransportTraitsPtr _transportTraits; @@ -267,6 +300,10 @@ class HTTPClient uint16_t _redirectLimit = 10; String _location; transferEncoding_t _transferEncoding = HTTPC_TE_IDENTITY; + + /// Cookie jar support + CookieJar* _cookieJar = nullptr; + };