diff --git a/.github/scripts/sketch_utils.sh b/.github/scripts/sketch_utils.sh index 01ceafe9af1..8beb70c548b 100755 --- a/.github/scripts/sketch_utils.sh +++ b/.github/scripts/sketch_utils.sh @@ -244,6 +244,14 @@ function build_sketch { # build_sketch [ext fi fi + # Install libraries from ci.json if they exist + install_libs -ai "$ide_path" -s "$sketchdir" + install_result=$? + if [ $install_result -ne 0 ]; then + echo "ERROR: Library installation failed for $sketchname" >&2 + exit $install_result + fi + ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp" if [ -n "$ARDUINO_BUILD_DIR" ]; then build_dir="$ARDUINO_BUILD_DIR" @@ -580,6 +588,160 @@ function build_sketches { # build_sketches &2 || printf '%s\n' "$out" >&2 + fi +} + +function install_libs { # install_libs [-v] + local ide_path="" + local sketchdir="" + local verbose=false + + while [ -n "$1" ]; do + case "$1" in + -ai ) shift; ide_path=$1 ;; + -s ) shift; sketchdir=$1 ;; + -v ) verbose=true ;; + * ) + echo "ERROR: Unknown argument: $1" >&2 + echo "USAGE: install_libs -ai -s [-v]" >&2 + return 1 + ;; + esac + shift + done + + if [ -z "$ide_path" ]; then + echo "ERROR: IDE path not provided" >&2 + echo "USAGE: install_libs -ai -s [-v]" >&2 + return 1 + fi + if [ -z "$sketchdir" ]; then + echo "ERROR: Sketch directory not provided" >&2 + echo "USAGE: install_libs -ai -s [-v]" >&2 + return 1 + fi + if [ ! -f "$ide_path/arduino-cli" ]; then + echo "ERROR: arduino-cli not found at $ide_path/arduino-cli" >&2 + return 1 + fi + + if [ ! -f "$sketchdir/ci.json" ]; then + [ "$verbose" = true ] && echo "No ci.json found in $sketchdir, skipping library installation" + return 0 + fi + if ! jq -e . "$sketchdir/ci.json" >/dev/null 2>&1; then + echo "ERROR: $sketchdir/ci.json is not valid JSON" >&2 + return 1 + fi + + local libs_type + libs_type=$(jq -r '.libs | type' "$sketchdir/ci.json" 2>/dev/null) + if [ -z "$libs_type" ] || [ "$libs_type" = "null" ]; then + [ "$verbose" = true ] && echo "No libs field found in ci.json, skipping library installation" + return 0 + elif [ "$libs_type" != "array" ]; then + echo "ERROR: libs field in ci.json must be an array, found: $libs_type" >&2 + return 1 + fi + + local libs_count + libs_count=$(jq -r '.libs | length' "$sketchdir/ci.json" 2>/dev/null) + if [ "$libs_count" -eq 0 ]; then + [ "$verbose" = true ] && echo "libs array is empty in ci.json, skipping library installation" + return 0 + fi + + echo "Installing $libs_count libraries from $sketchdir/ci.json" + + local needs_unsafe=false + local original_unsafe_setting="" + local libs + libs=$(jq -r '.libs[]? // empty' "$sketchdir/ci.json") + + # Detect any git-like URL (GitHub/GitLab/Bitbucket/self-hosted/ssh) + for lib in $libs; do + if is_git_like_url "$lib"; then + needs_unsafe=true + break + fi + done + + if [ "$needs_unsafe" = true ]; then + [ "$verbose" = true ] && echo "Checking current unsafe install setting..." + original_unsafe_setting=$("$ide_path/arduino-cli" config get library.enable_unsafe_install 2>/dev/null || echo "false") + if [ "$original_unsafe_setting" = "false" ]; then + [ "$verbose" = true ] && echo "Enabling unsafe installs for Git URLs..." + "$ide_path/arduino-cli" config set library.enable_unsafe_install true >/dev/null 2>&1 || \ + echo "WARNING: Failed to enable unsafe installs, Git URL installs may fail" >&2 + else + [ "$verbose" = true ] && echo "Unsafe installs already enabled" + fi + fi + + local rc=0 install_status=0 output="" + for lib in $libs; do + [ "$verbose" = true ] && echo "Processing library: $lib" + + if is_git_like_url "$lib"; then + [ "$verbose" = true ] && echo "Installing library from git URL: $lib" + if [ "$verbose" = true ]; then + "$ide_path/arduino-cli" lib install --git-url "$lib" + install_status=$? + else + output=$("$ide_path/arduino-cli" lib install --git-url "$lib" 2>&1) + install_status=$? + fi + else + [ "$verbose" = true ] && echo "Installing library by name: $lib" + if [ "$verbose" = true ]; then + "$ide_path/arduino-cli" lib install "$lib" + install_status=$? + else + output=$("$ide_path/arduino-cli" lib install "$lib" 2>&1) + install_status=$? + fi + fi + + # Treat "already installed"/"up to date" as success (idempotent) + if [ $install_status -ne 0 ] && echo "$output" | grep -qiE 'already installed|up to date'; then + install_status=0 + fi + + if [ "$verbose" != true ]; then + print_err_warnings "$install_status" "$output" + fi + + if [ $install_status -ne 0 ]; then + echo "ERROR: Failed to install library: $lib" >&2 + rc=$install_status + break + else + [ "$verbose" = true ] && echo "Successfully installed library: $lib" + fi + done + + if [ "$needs_unsafe" = true ] && [ "$original_unsafe_setting" = "false" ]; then + [ "$verbose" = true ] && echo "Restoring original unsafe install setting..." + "$ide_path/arduino-cli" config set library.enable_unsafe_install false >/dev/null 2>&1 || true + fi + + [ $rc -eq 0 ] && echo "Library installation completed" + return $rc +} + + USAGE=" USAGE: ${0} [command] [options] Available commands: @@ -587,6 +749,7 @@ Available commands: build: Build a sketch. chunk_build: Build a chunk of sketches. check_requirements: Check if target meets sketch requirements. + install_libs: Install libraries from ci.json file. " cmd=$1 @@ -606,6 +769,8 @@ case "$cmd" in ;; "check_requirements") check_requirements "$@" ;; + "install_libs") install_libs "$@" + ;; *) echo "ERROR: Unrecognized command" echo "$USAGE" diff --git a/.github/scripts/tests_run.sh b/.github/scripts/tests_run.sh index 1c4bee79742..c85db2e984a 100755 --- a/.github/scripts/tests_run.sh +++ b/.github/scripts/tests_run.sh @@ -115,14 +115,14 @@ function run_test { rm "$sketchdir"/diagram.json 2>/dev/null || true result=0 - printf "\033[95mpytest \"%s/test_%s.py\" --build-dir \"%s\" --junit-xml=\"%s\" -o junit_suite_name=%s_%s_%s_%s%s %s\033[0m\n" "$sketchdir" "$sketchname" "$build_dir" "$report_file" "$test_type" "$platform" "$target" "$sketchname" "$i" "${extra_args[*]@Q}" - bash -c "set +e; pytest \"$sketchdir/test_$sketchname.py\" --build-dir \"$build_dir\" --junit-xml=\"$report_file\" -o junit_suite_name=${test_type}_${platform}_${target}_${sketchname}${i} ${extra_args[*]@Q}; exit \$?" || result=$? + printf "\033[95mpytest -s \"%s/test_%s.py\" --build-dir \"%s\" --junit-xml=\"%s\" -o junit_suite_name=%s_%s_%s_%s%s %s\033[0m\n" "$sketchdir" "$sketchname" "$build_dir" "$report_file" "$test_type" "$platform" "$target" "$sketchname" "$i" "${extra_args[*]@Q}" + bash -c "set +e; pytest -s \"$sketchdir/test_$sketchname.py\" --build-dir \"$build_dir\" --junit-xml=\"$report_file\" -o junit_suite_name=${test_type}_${platform}_${target}_${sketchname}${i} ${extra_args[*]@Q}; exit \$?" || result=$? printf "\n" if [ $result -ne 0 ]; then result=0 printf "\033[95mRetrying test: %s -- Config: %s\033[0m\n" "$sketchname" "$i" - printf "\033[95mpytest \"%s/test_%s.py\" --build-dir \"%s\" --junit-xml=\"%s\" -o junit_suite_name=%s_%s_%s_%s%s %s\033[0m\n" "$sketchdir" "$sketchname" "$build_dir" "$report_file" "$test_type" "$platform" "$target" "$sketchname" "$i" "${extra_args[*]@Q}" - bash -c "set +e; pytest \"$sketchdir/test_$sketchname.py\" --build-dir \"$build_dir\" --junit-xml=\"$report_file\" -o junit_suite_name=${test_type}_${platform}_${target}_${sketchname}${i} ${extra_args[*]@Q}; exit \$?" || result=$? + printf "\033[95mpytest -s \"%s/test_%s.py\" --build-dir \"%s\" --junit-xml=\"%s\" -o junit_suite_name=%s_%s_%s_%s%s %s\033[0m\n" "$sketchdir" "$sketchname" "$build_dir" "$report_file" "$test_type" "$platform" "$target" "$sketchname" "$i" "${extra_args[*]@Q}" + bash -c "set +e; pytest -s \"$sketchdir/test_$sketchname.py\" --build-dir \"$build_dir\" --junit-xml=\"$report_file\" -o junit_suite_name=${test_type}_${platform}_${target}_${sketchname}${i} ${extra_args[*]@Q}; exit \$?" || result=$? printf "\n" if [ $result -ne 0 ]; then printf "\033[91mFailed test: %s -- Config: %s\033[0m\n\n" "$sketchname" "$i" diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c9800dfe2b..ca51f66721c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -373,7 +373,7 @@ if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_OpenThre endif() endif() -if(IDF_TARGET STREQUAL "esp32p4") +if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3" OR IDF_TARGET STREQUAL "esp32p4") list(APPEND requires esp_driver_touch_sens) endif() diff --git a/cores/esp32/esp32-hal-touch-ng.c b/cores/esp32/esp32-hal-touch-ng.c index 888a299ec0c..98f9052d18c 100644 --- a/cores/esp32/esp32-hal-touch-ng.c +++ b/cores/esp32/esp32-hal-touch-ng.c @@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. #include "soc/soc_caps.h" +#include "esp_idf_version.h" #if SOC_TOUCH_SENSOR_SUPPORTED -#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 for now +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3 -#include "driver/touch_sens.h" #include "esp32-hal-touch-ng.h" #include "esp32-hal-periman.h" @@ -37,11 +37,24 @@ typedef struct { static TouchInterruptHandle_t __touchInterruptHandlers[SOC_TOUCH_SENSOR_NUM] = { 0, }; - -static uint8_t _sample_num = 1; +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +static uint8_t _sample_num = 1; // only one sample configuration supported +static float _duration_ms = 5.0f; +static touch_volt_lim_l_t _volt_low = TOUCH_VOLT_LIM_L_0V5; +static touch_volt_lim_h_t _volt_high = TOUCH_VOLT_LIM_H_1V7; +static touch_intr_trig_mode_t _intr_trig_mode = TOUCH_INTR_TRIG_ON_BELOW_THRESH; +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 +static uint8_t _sample_num = 1; // only one sample configuration supported +static uint32_t _chg_times = 500; +static touch_volt_lim_l_t _volt_low = TOUCH_VOLT_LIM_L_0V5; +static touch_volt_lim_h_t _volt_high = TOUCH_VOLT_LIM_H_2V2; +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 +static uint8_t _sample_num = 1; // TODO: can be extended to multiple samples static uint32_t _div_num = 1; static uint8_t _coarse_freq_tune = 1; static uint8_t _fine_freq_tune = 1; +#endif + static uint8_t used_pads = 0; static uint32_t __touchSleepTime = 256; @@ -156,15 +169,28 @@ bool touchBenchmarkThreshold(uint8_t pad) { // Reconfigure passed pad with new threshold uint32_t benchmark[_sample_num] = {}; +#if SOC_TOUCH_SUPPORT_BENCHMARK // ESP32S2, ESP32S3,ESP32P4 if (touch_channel_read_data(touch_channel_handle[pad], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark) != ESP_OK) { log_e("Touch channel read data failed!"); return false; } +#else + if (touch_channel_read_data(touch_channel_handle[pad], TOUCH_CHAN_DATA_TYPE_SMOOTH, benchmark) != ESP_OK) { + log_e("Touch channel read data failed!"); + return false; + } +#endif + /* Calculate the proper active thresholds regarding the initial benchmark */ - touch_channel_config_t chan_cfg = {}; + touch_channel_config_t chan_cfg = TOUCH_CHANNEL_DEFAULT_CONFIG(); for (int i = 0; i < _sample_num; i++) { +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + chan_cfg.abs_active_thresh[i] = (uint32_t)(benchmark[i] * (1 - s_thresh2bm_ratio)); + log_v("Configured [CH %d] sample %d: benchmark = %" PRIu32 ", threshold = %" PRIu32 "\t", pad, i, benchmark[i], chan_cfg.abs_active_thresh[i]); +#else chan_cfg.active_thresh[i] = (uint32_t)(benchmark[i] * s_thresh2bm_ratio); log_v("Configured [CH %d] sample %d: benchmark = %" PRIu32 ", threshold = %" PRIu32 "\t", pad, i, benchmark[i], chan_cfg.active_thresh[i]); +#endif } /* Update the channel configuration */ if (touch_sensor_reconfig_channel(touch_channel_handle[pad], &chan_cfg) != ESP_OK) { @@ -178,17 +204,26 @@ static bool touchDetachBus(void *pin) { int8_t pad = digitalPinToTouchChannel((int)(pin - 1)); channels_initialized[pad] = false; //disable touch pad and delete the channel + if (!touchStop()) { + log_e("touchStop() failed!"); + return false; + } + if (!touchDisable()) { + log_e("touchDisable() failed!"); + return false; + } touch_sensor_del_channel(touch_channel_handle[pad]); used_pads--; if (used_pads == 0) { - touchStop(); - touchDisable(); if (touch_sensor_del_controller(touch_sensor_handle) != ESP_OK) //deinit touch module, as no pads are used { log_e("Touch module deinit failed!"); return false; } initialized = false; + } else { + touchEnable(); + touchStart(); } return true; } @@ -198,21 +233,40 @@ static void __touchInit() { return; } // Support only one sample configuration for now +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V1_DEFAULT_SAMPLE_CONFIG(_duration_ms, _volt_low, _volt_high); +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 + touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V2_DEFAULT_SAMPLE_CONFIG(_chg_times, _volt_low, _volt_high); +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG(_div_num, _coarse_freq_tune, _fine_freq_tune); +#endif touch_sensor_sample_config_t sample_cfg[_sample_num] = {}; sample_cfg[0] = single_sample_cfg; - /* Allocate new touch controller handle */ touch_sensor_config_t sens_cfg = { +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + .power_on_wait_us = __touchSleepTime, + .meas_interval_us = __touchMeasureTime, + .intr_trig_mode = _intr_trig_mode, + .intr_trig_group = TOUCH_INTR_TRIG_GROUP_BOTH, + .sample_cfg_num = _sample_num, + .sample_cfg = sample_cfg, +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 + .power_on_wait_us = __touchSleepTime, + .meas_interval_us = __touchMeasureTime, + .max_meas_time_us = 0, + .sample_cfg_num = _sample_num, + .sample_cfg = sample_cfg, +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 .power_on_wait_us = __touchSleepTime, .meas_interval_us = __touchMeasureTime, .max_meas_time_us = 0, .output_mode = TOUCH_PAD_OUT_AS_CLOCK, .sample_cfg_num = _sample_num, .sample_cfg = sample_cfg, +#endif }; - // touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(_sample_num, sample_cfg); if (touch_sensor_new_controller(&sens_cfg, &touch_sensor_handle) != ESP_OK) { goto err; } @@ -225,14 +279,10 @@ static void __touchInit() { } /* Register the touch sensor on_active and on_inactive callbacks */ - touch_event_callbacks_t callbacks = { - .on_active = __touchOnActiveISR, - .on_inactive = __touchOnInactiveISR, - .on_measure_done = NULL, - .on_scan_done = NULL, - .on_timeout = NULL, - .on_proximity_meas_done = NULL, - }; + touch_event_callbacks_t callbacks = {0}; + callbacks.on_active = __touchOnActiveISR; + callbacks.on_inactive = __touchOnInactiveISR; + if (touch_sensor_register_callbacks(touch_sensor_handle, &callbacks, NULL) != ESP_OK) { goto err; } @@ -253,9 +303,7 @@ static void __touchChannelInit(int pad) { // Initial setup with default Threshold __touchInterruptHandlers[pad].fn = NULL; - touch_channel_config_t chan_cfg = { - .active_thresh = {1000} // default threshold, will be updated after benchmark - }; + touch_channel_config_t chan_cfg = TOUCH_CHANNEL_DEFAULT_CONFIG(); if (!touchStop() || !touchDisable()) { log_e("Touch sensor stop and disable failed!"); @@ -323,8 +371,21 @@ static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Ar __touchInterruptHandlers[pad].arg = NULL; } else { // attach ISR User Call - __touchInit(); - __touchChannelInit(pad); + if (perimanGetPinBus(pin, ESP32_BUS_TYPE_TOUCH) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_TOUCH, touchDetachBus); + if (!perimanClearPinBus(pin)) { + log_e("Failed to clear pin bus"); + return; + } + __touchInit(); + __touchChannelInit(pad); + + if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_TOUCH, (void *)(pin + 1), -1, pad)) { + touchDetachBus((void *)(pin + 1)); + log_e("Failed to set bus to Peripheral manager"); + return; + } + } __touchInterruptHandlers[pad].fn = userFunc; __touchInterruptHandlers[pad].callWithArgs = callWithArgs; __touchInterruptHandlers[pad].arg = Args; @@ -338,7 +399,11 @@ static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Ar touch_channel_config_t chan_cfg = {}; for (int i = 0; i < _sample_num; i++) { +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + chan_cfg.abs_active_thresh[i] = threshold; +#else chan_cfg.active_thresh[i] = threshold; +#endif } if (touch_sensor_reconfig_channel(touch_channel_handle[pad], &chan_cfg) != ESP_OK) { @@ -375,7 +440,6 @@ bool touchInterruptGetLastStatus(uint8_t pin) { if (pad < 0) { return false; } - return __touchInterruptHandlers[pad].lastStatusIsPressed; } @@ -405,9 +469,13 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold) { touch_sleep_config_t deep_slp_cfg = { .slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP, +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + .deep_slp_sens_cfg = NULL, // Use the original touch sensor configuration +#else // SOC_TOUCH_SENSOR_VERSION 2 and 3// ESP32S2, ESP32S3, ESP32P4 .deep_slp_chan = touch_channel_handle[pad], .deep_slp_thresh = {threshold}, .deep_slp_sens_cfg = NULL, // Use the original touch sensor configuration +#endif }; // Register the deep sleep wake-up @@ -434,6 +502,29 @@ void touchSetTiming(float measure, uint32_t sleep) { __touchMeasureTime = measure; } +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +void touchSetConfig(float duration_ms, touch_volt_lim_l_t volt_low, touch_volt_lim_h_t volt_high) { + if (initialized) { + log_e("Touch sensor already initialized. Cannot set configuration."); + return; + } + _duration_ms = duration_ms; + _volt_low = volt_low; + _volt_high = volt_high; +} + +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 +void touchSetConfig(uint32_t chg_times, touch_volt_lim_l_t volt_low, touch_volt_lim_h_t volt_high) { + if (initialized) { + log_e("Touch sensor already initialized. Cannot set configuration."); + return; + } + _chg_times = chg_times; + _volt_low = volt_low; + _volt_high = volt_high; +} + +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 void touchSetConfig(uint32_t div_num, uint8_t coarse_freq_tune, uint8_t fine_freq_tune) { if (initialized) { log_e("Touch sensor already initialized. Cannot set configuration."); @@ -443,11 +534,22 @@ void touchSetConfig(uint32_t div_num, uint8_t coarse_freq_tune, uint8_t fine_fre _coarse_freq_tune = coarse_freq_tune; _fine_freq_tune = fine_freq_tune; } +#endif + +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +void touchInterruptSetThresholdDirection(bool mustbeLower) { + if (mustbeLower) { + _intr_trig_mode = TOUCH_INTR_TRIG_ON_BELOW_THRESH; + } else { + _intr_trig_mode = TOUCH_INTR_TRIG_ON_ABOVE_THRESH; + } +} +#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"))); -#endif /* SOC_TOUCH_SENSOR_VERSION == 3 */ +#endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-touch-ng.h b/cores/esp32/esp32-hal-touch-ng.h index 0d4eb79ac58..ebe49466bb9 100644 --- a/cores/esp32/esp32-hal-touch-ng.h +++ b/cores/esp32/esp32-hal-touch-ng.h @@ -21,14 +21,31 @@ #define MAIN_ESP32_HAL_TOUCH_NEW_H_ #include "soc/soc_caps.h" +#include "esp_idf_version.h" + #if SOC_TOUCH_SENSOR_SUPPORTED -#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3 #ifdef __cplusplus extern "C" { #endif #include "esp32-hal.h" +#include "driver/touch_sens.h" + +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#define TOUCH_CHANNEL_DEFAULT_CONFIG() \ + { \ + .abs_active_thresh = {1000}, .charge_speed = TOUCH_CHARGE_SPEED_7, .init_charge_volt = TOUCH_INIT_CHARGE_VOLT_DEFAULT, \ + .group = TOUCH_CHAN_TRIG_GROUP_BOTH, \ + } +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32-S2 & ESP32-S3 +#define TOUCH_CHANNEL_DEFAULT_CONFIG() \ + { .active_thresh = {2000}, .charge_speed = TOUCH_CHARGE_SPEED_7, .init_charge_volt = TOUCH_INIT_CHARGE_VOLT_DEFAULT, } +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32-P4 +#define TOUCH_CHANNEL_DEFAULT_CONFIG() \ + { .active_thresh = {1000}, } +#endif typedef uint32_t touch_value_t; @@ -40,11 +57,39 @@ typedef uint32_t touch_value_t; **/ void touchSetTiming(float measure, uint32_t sleep); +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +/* + * @param[in] duration_ms The measurement duration of the touch channel + * @param[in] volt_low The low voltage limit of the touch channel + * @param[in] volt_high The high voltage limit of the touch channel + */ +void touchSetConfig(float duration_ms, touch_volt_lim_l_t volt_low, touch_volt_lim_h_t volt_high); + +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 +/* + * @param[in] chg_times The charge times of the touch channel + * @param[in] volt_low The low voltage limit of the touch channel + * @param[in] volt_high The high voltage limit of the touch channel + */ +void touchSetConfig(uint32_t chg_times, touch_volt_lim_l_t volt_low, touch_volt_lim_h_t volt_high); + +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 /* * Tune the touch pad frequency. * Note: Must be called before setting up touch pads */ void touchSetConfig(uint32_t _div_num, uint8_t coarse_freq_tune, uint8_t fine_freq_tune); +#endif + +#if SOC_TOUCH_SENSOR_VERSION == 1 +/* + * 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. + * Note: Must be called before setting up touch pads + **/ +void touchInterruptSetThresholdDirection(bool mustbeLower); +#endif /* * Read touch pad value. @@ -86,6 +131,6 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold); } #endif -#endif /* SOC_TOUCH_SENSOR_VERSION == 3 */ +#endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ #endif /* MAIN_ESP32_HAL_TOUCH_H_ */ diff --git a/cores/esp32/esp32-hal-touch.c b/cores/esp32/esp32-hal-touch.c index 701bf6d16c9..10482234de0 100644 --- a/cores/esp32/esp32-hal-touch.c +++ b/cores/esp32/esp32-hal-touch.c @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. #include "soc/soc_caps.h" +#include "esp_idf_version.h" #if SOC_TOUCH_SENSOR_SUPPORTED -#if SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3 +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) && SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3 #include "driver/touch_sensor.h" #include "esp32-hal-touch.h" @@ -325,5 +326,5 @@ extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value extern void touchDetachInterrupt(uint8_t) __attribute__((weak, alias("__touchDettachInterrupt"))); extern void touchSetCycles(uint16_t, uint16_t) __attribute__((weak, alias("__touchSetCycles"))); -#endif /* SOC_TOUCH_SENSOR_VERSION <= 2 */ +#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) && SOC_TOUCH_SENSOR_VERSION <= 2 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-touch.h b/cores/esp32/esp32-hal-touch.h index 4b06c7db766..44c99dce206 100644 --- a/cores/esp32/esp32-hal-touch.h +++ b/cores/esp32/esp32-hal-touch.h @@ -21,8 +21,10 @@ #define MAIN_ESP32_HAL_TOUCH_H_ #include "soc/soc_caps.h" +#include "esp_idf_version.h" + #if SOC_TOUCH_SENSOR_SUPPORTED -#if SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32 ESP32S2 ESP32S3 +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) && SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3 #ifdef __cplusplus extern "C" { @@ -98,6 +100,6 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold); } #endif -#endif /* SOC_TOUCH_SENSOR_VERSION <= 2 */ +#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) && SOC_TOUCH_SENSOR_VERSION <= 2 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ #endif /* MAIN_ESP32_HAL_TOUCH_H_ */ diff --git a/docs/en/contributing.rst b/docs/en/contributing.rst index 7a7b99894eb..ae07bb57706 100644 --- a/docs/en/contributing.rst +++ b/docs/en/contributing.rst @@ -425,6 +425,10 @@ The ``ci.json`` file is used to specify how the test suite and sketches will han * ``fqbn``: A dictionary that specifies the FQBNs that will be used to compile the sketch. The key is the target name and the value is a list of FQBNs. The `default FQBNs `_ are used if this field is not specified. This overrides the default FQBNs and the ``fqbn_append`` field. +* ``libs``: A list of libraries that are required to run the test suite. The libraries will be installed automatically if they are not already present. + Libraries are installed using the ``arduino-cli lib install`` command, so you can specify libraries by name + version (e.g., ``AudioZero@1.0.0``) + or by URL (e.g., ``https://github.com/arduino-libraries/WiFi101.git``). + More information can be found in the `Arduino CLI documentation `_. The ``wifi`` test suite is a good example of how to use the ``ci.json`` file: diff --git a/idf_component.yml b/idf_component.yml index f9357a401f9..58377fab952 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -54,12 +54,12 @@ dependencies: espressif/esp_modem: version: "^1.1.0" espressif/esp-zboss-lib: - version: "==1.6.4" # compatible with esp-zigbee-lib 1.6.6 + version: "==1.6.4" # compatible with esp-zigbee-lib 1.6.7 require: public rules: - if: "target not in [esp32c2, esp32p4]" espressif/esp-zigbee-lib: - version: "==1.6.6" + version: "==1.6.7" require: public rules: - if: "target not in [esp32c2, esp32p4]" diff --git a/libraries/BLE/src/BLE2901.cpp b/libraries/BLE/src/BLE2901.cpp index 1fa4857ac33..3b5edb0b59f 100644 --- a/libraries/BLE/src/BLE2901.cpp +++ b/libraries/BLE/src/BLE2901.cpp @@ -47,7 +47,7 @@ BLE2901::BLE2901() : BLEDescriptor(BLEUUID((uint16_t)BLE2901_UUID)) {} /** * @brief Set the Characteristic User Description */ -void BLE2901::setDescription(String userDesc) { +void BLE2901::setDescription(const String &userDesc) { if (userDesc.length() > ESP_GATT_MAX_ATTR_LEN) { log_e("Size %d too large, must be no bigger than %d", userDesc.length(), ESP_GATT_MAX_ATTR_LEN); return; diff --git a/libraries/BLE/src/BLE2901.h b/libraries/BLE/src/BLE2901.h index 21e7cc9398c..87ce76090fe 100644 --- a/libraries/BLE/src/BLE2901.h +++ b/libraries/BLE/src/BLE2901.h @@ -40,7 +40,7 @@ class BLE2901 : public BLEDescriptor { ***************************************************************************/ BLE2901(); - void setDescription(String desc); + void setDescription(const String &desc); }; // BLE2901 #endif /* CONFIG_BLUEDROID_ENABLED || CONFIG_NIMBLE_ENABLED */ diff --git a/libraries/BLE/src/BLECharacteristic.cpp b/libraries/BLE/src/BLECharacteristic.cpp index 0234cd11cca..3d218e6bd13 100644 --- a/libraries/BLE/src/BLECharacteristic.cpp +++ b/libraries/BLE/src/BLECharacteristic.cpp @@ -346,7 +346,7 @@ void BLECharacteristic::setReadProperty(bool value) { * @param [in] data The data to set for the characteristic. * @param [in] length The length of the data in bytes. */ -void BLECharacteristic::setValue(uint8_t *data, size_t length) { +void BLECharacteristic::setValue(const uint8_t *data, size_t length) { // The call to BLEUtils::buildHexData() doesn't output anything if the log level is not // "VERBOSE". As it is quite CPU intensive, it is much better to not call it if not needed. #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE @@ -371,43 +371,28 @@ void BLECharacteristic::setValue(uint8_t *data, size_t length) { * @param [in] Set the value of the characteristic. * @return N/A. */ -void BLECharacteristic::setValue(String value) { - setValue((uint8_t *)(value.c_str()), value.length()); +void BLECharacteristic::setValue(const String &value) { + setValue(reinterpret_cast(value.c_str()), value.length()); } // setValue -void BLECharacteristic::setValue(uint16_t &data16) { - uint8_t temp[2]; - temp[0] = data16; - temp[1] = data16 >> 8; - setValue(temp, 2); +void BLECharacteristic::setValue(uint16_t data16) { + setValue(reinterpret_cast(&data16), sizeof(data16)); } // setValue -void BLECharacteristic::setValue(uint32_t &data32) { - uint8_t temp[4]; - temp[0] = data32; - temp[1] = data32 >> 8; - temp[2] = data32 >> 16; - temp[3] = data32 >> 24; - setValue(temp, 4); +void BLECharacteristic::setValue(uint32_t data32) { + setValue(reinterpret_cast(&data32), sizeof(data32)); } // setValue -void BLECharacteristic::setValue(int &data32) { - uint8_t temp[4]; - temp[0] = data32; - temp[1] = data32 >> 8; - temp[2] = data32 >> 16; - temp[3] = data32 >> 24; - setValue(temp, 4); +void BLECharacteristic::setValue(int data32) { + setValue(reinterpret_cast(&data32), sizeof(data32)); } // setValue -void BLECharacteristic::setValue(float &data32) { - float temp = data32; - setValue((uint8_t *)&temp, 4); +void BLECharacteristic::setValue(float data32) { + setValue(reinterpret_cast(&data32), sizeof(data32)); } // setValue -void BLECharacteristic::setValue(double &data64) { - double temp = data64; - setValue((uint8_t *)&temp, 8); +void BLECharacteristic::setValue(double data64) { + setValue(reinterpret_cast(&data64), sizeof(data64)); } // setValue /** diff --git a/libraries/BLE/src/BLECharacteristic.h b/libraries/BLE/src/BLECharacteristic.h index 27df5a30c3e..dc87177644f 100644 --- a/libraries/BLE/src/BLECharacteristic.h +++ b/libraries/BLE/src/BLECharacteristic.h @@ -184,13 +184,13 @@ class BLECharacteristic { void indicate(); void notify(bool is_notification = true); void setCallbacks(BLECharacteristicCallbacks *pCallbacks); - void setValue(uint8_t *data, size_t size); - void setValue(String value); - void setValue(uint16_t &data16); - void setValue(uint32_t &data32); - void setValue(int &data32); - void setValue(float &data32); - void setValue(double &data64); + void setValue(const uint8_t *data, size_t size); + void setValue(const String &value); + void setValue(uint16_t data16); + void setValue(uint32_t data32); + void setValue(int data32); + void setValue(float data32); + void setValue(double data64); String toString(); uint16_t getHandle(); void setAccessPermissions(uint8_t perm); diff --git a/libraries/BLE/src/BLEDescriptor.cpp b/libraries/BLE/src/BLEDescriptor.cpp index 51c77bb9b49..2452f3cd45b 100644 --- a/libraries/BLE/src/BLEDescriptor.cpp +++ b/libraries/BLE/src/BLEDescriptor.cpp @@ -181,7 +181,7 @@ void BLEDescriptor::setHandle(uint16_t handle) { * @param [in] data The data to set for the descriptor. * @param [in] length The length of the data in bytes. */ -void BLEDescriptor::setValue(uint8_t *data, size_t length) { +void BLEDescriptor::setValue(const uint8_t *data, size_t length) { if (length > m_value.attr_max_len) { log_e("Size %d too large, must be no bigger than %d", length, m_value.attr_max_len); return; @@ -203,8 +203,8 @@ void BLEDescriptor::setValue(uint8_t *data, size_t length) { * @brief Set the value of the descriptor. * @param [in] value The value of the descriptor in string form. */ -void BLEDescriptor::setValue(String value) { - setValue((uint8_t *)value.c_str(), value.length()); +void BLEDescriptor::setValue(const String &value) { + setValue(reinterpret_cast(value.c_str()), value.length()); } // setValue void BLEDescriptor::setAccessPermissions(uint8_t perm) { diff --git a/libraries/BLE/src/BLEDescriptor.h b/libraries/BLE/src/BLEDescriptor.h index d0d34b24388..83008743ae5 100644 --- a/libraries/BLE/src/BLEDescriptor.h +++ b/libraries/BLE/src/BLEDescriptor.h @@ -94,8 +94,8 @@ class BLEDescriptor { void setAccessPermissions(uint8_t perm); // Set the permissions of the descriptor. void setCallbacks(BLEDescriptorCallbacks *pCallbacks); // Set callbacks to be invoked for the descriptor. - void setValue(uint8_t *data, size_t size); // Set the value of the descriptor as a pointer to data. - void setValue(String value); // Set the value of the descriptor as a data buffer. + void setValue(const uint8_t *data, size_t size); // Set the value of the descriptor as a pointer to data. + void setValue(const String &value); // Set the value of the descriptor as a data buffer. String toString(); // Convert the descriptor to a string representation. diff --git a/libraries/BLE/src/BLEValue.cpp b/libraries/BLE/src/BLEValue.cpp index efc97697baa..6559766cfea 100644 --- a/libraries/BLE/src/BLEValue.cpp +++ b/libraries/BLE/src/BLEValue.cpp @@ -37,7 +37,7 @@ BLEValue::BLEValue() { * The accumulation is a growing set of data that is added to until a commit or cancel. * @param [in] part A message part being added. */ -void BLEValue::addPart(String part) { +void BLEValue::addPart(const String &part) { log_v(">> addPart: length=%d", part.length()); m_accumulation += part; } // addPart @@ -48,7 +48,7 @@ void BLEValue::addPart(String part) { * @param [in] pData A message part being added. * @param [in] length The number of bytes being added. */ -void BLEValue::addPart(uint8_t *pData, size_t length) { +void BLEValue::addPart(const uint8_t *pData, size_t length) { log_v(">> addPart: length=%d", length); m_accumulation += String((char *)pData, length); } // addPart @@ -121,7 +121,7 @@ void BLEValue::setReadOffset(uint16_t readOffset) { /** * @brief Set the current value. */ -void BLEValue::setValue(String value) { +void BLEValue::setValue(const String &value) { m_value = value; } // setValue @@ -130,7 +130,7 @@ void BLEValue::setValue(String value) { * @param [in] pData The data for the current value. * @param [in] The length of the new current value. */ -void BLEValue::setValue(uint8_t *pData, size_t length) { +void BLEValue::setValue(const uint8_t *pData, size_t length) { m_value = String((char *)pData, length); } // setValue diff --git a/libraries/BLE/src/BLEValue.h b/libraries/BLE/src/BLEValue.h index 56a7a5bc4ec..6a1b7cfd7e4 100644 --- a/libraries/BLE/src/BLEValue.h +++ b/libraries/BLE/src/BLEValue.h @@ -34,8 +34,8 @@ class BLEValue { ***************************************************************************/ BLEValue(); - void addPart(String part); - void addPart(uint8_t *pData, size_t length); + void addPart(const String &part); + void addPart(const uint8_t *pData, size_t length); void cancel(); void commit(); uint8_t *getData(); @@ -43,8 +43,8 @@ class BLEValue { uint16_t getReadOffset(); String getValue(); void setReadOffset(uint16_t readOffset); - void setValue(String value); - void setValue(uint8_t *pData, size_t length); + void setValue(const String &value); + void setValue(const uint8_t *pData, size_t length); private: /*************************************************************************** diff --git a/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino b/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino index 43f3bc36592..ac2b641be40 100644 --- a/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino +++ b/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino @@ -3,44 +3,53 @@ This is an example how to use Touch Intrrerupts The sketch will tell when it is touched and then released as like a push-button -This method based on touchInterruptSetThresholdDirection() is only available for ESP32 +This method based on touchInterruptGetLastStatus() */ #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); - } +int threshold = 0; // if 0 is used, benchmark value is used. Its by default 1,5% change, can be changed by touchSetDefaultThreshold(float percentage) +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("ESP32 Touch Interrupt Test"); - touchAttachInterrupt(T2, gotTouchEvent, threshold); - // Touch ISR will be activated when touchRead is lower than the Threshold - touchInterruptSetThresholdDirection(testingLower); + //Optional: Set the threshold to 5% of the benchmark value. Only effective if threshold = 0. + touchSetDefaultThreshold(5); + + //Set the touch pads + Serial.println("\n ESP32 Touch Interrupt Test\n"); + touchAttachInterrupt(T1, gotTouch1, threshold); + touchAttachInterrupt(T2, gotTouch2, threshold); } void loop() { - if (lastTouchActive != touchActive) { - lastTouchActive = touchActive; - if (touchActive) { - Serial.println(" ---- Touch was Pressed"); + if (touch1detected) { + touch1detected = false; + if (touchInterruptGetLastStatus(T1)) { + Serial.println(" --- T1 Touched"); } else { - Serial.println(" ---- Touch was Released"); + Serial.println(" --- T1 Released"); } } - Serial.printf("T2 pin2 = %d \n", touchRead(T2)); - delay(125); + if (touch2detected) { + touch2detected = false; + if (touchInterruptGetLastStatus(T2)) { + Serial.println(" --- T2 Touched"); + } else { + Serial.println(" --- T2 Released"); + } + } + + delay(80); } diff --git a/libraries/ESP32/examples/Touch/TouchButton/ci.json b/libraries/ESP32/examples/Touch/TouchButton/ci.json index cec76a84f9d..c0ecf9fc0a5 100644 --- a/libraries/ESP32/examples/Touch/TouchButton/ci.json +++ b/libraries/ESP32/examples/Touch/TouchButton/ci.json @@ -1,5 +1,5 @@ { "requires": [ - "CONFIG_SOC_TOUCH_VERSION_1=y" + "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" ] } diff --git a/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino b/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino deleted file mode 100644 index df9b3f41149..00000000000 --- a/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino +++ /dev/null @@ -1,51 +0,0 @@ -/* - -This is an example how to use Touch Intrrerupts -The sketch will tell when it is touched and then released 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() { - 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); -} diff --git a/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json b/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json deleted file mode 100644 index 2710fa7940e..00000000000 --- a/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "requires": [ - "CONFIG_SOC_TOUCH_VERSION_2=y" - ] -} diff --git a/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino b/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino index 3b4e5f0b9e9..130026d1ad7 100644 --- a/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino +++ b/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino @@ -3,11 +3,7 @@ This is an example how to use Touch Intrrerupts The bigger the threshold, the more sensible is the touch */ -#if CONFIG_IDF_TARGET_ESP32P4 -int threshold = 0; // when 0 is used, the benchmarked value will be used -#else -int threshold = 40; -#endif +int threshold = 0; // if 0 is used, benchmark value is used. Its by default 1,5% change, can be changed by touchSetDefaultThreshold(float percentage) bool touch1detected = false; bool touch2detected = false; @@ -23,6 +19,10 @@ void gotTouch2() { void setup() { Serial.begin(115200); delay(1000); // give me time to bring up serial monitor + + //Optional: Set the threshold to 5% of the benchmark value. Only effective if threshold = 0. + touchSetDefaultThreshold(5); + Serial.println("ESP32 Touch Interrupt Test"); touchAttachInterrupt(T2, gotTouch1, threshold); touchAttachInterrupt(T3, gotTouch2, threshold); diff --git a/libraries/ESP32/examples/Touch/TouchRead/TouchRead.ino b/libraries/ESP32/examples/Touch/TouchRead/TouchRead.ino index 8e93ba44691..ba221f3048f 100644 --- a/libraries/ESP32/examples/Touch/TouchRead/TouchRead.ino +++ b/libraries/ESP32/examples/Touch/TouchRead/TouchRead.ino @@ -1,5 +1,5 @@ // ESP32 Touch Test -// Just test touch pin - Touch0 is T0 which is on GPIO 4. +// Just test touch pin - Touch2 is T2 which is on GPIO 2. void setup() { Serial.begin(115200); @@ -8,6 +8,6 @@ void setup() { } void loop() { - Serial.println(touchRead(T1)); // get value using T0 + Serial.println(touchRead(T2)); // get value using T2 delay(1000); } diff --git a/libraries/HTTPClient/examples/CustomHeaders/CustomHeaders.ino b/libraries/HTTPClient/examples/CustomHeaders/CustomHeaders.ino new file mode 100644 index 00000000000..a73af191fcf --- /dev/null +++ b/libraries/HTTPClient/examples/CustomHeaders/CustomHeaders.ino @@ -0,0 +1,83 @@ +#include + +#include +#include + +// Enable or disable collecting all headers +#define COLLECT_ALL_HEADERS true + +void setup() { + + Serial.begin(115200); + + Serial.println(); + Serial.println(); + Serial.println(); + + for (uint8_t t = 4; t > 0; t--) { + Serial.printf("[SETUP] WAIT %d...\n", t); + Serial.flush(); + delay(1000); + } + + WiFi.begin("SSID", "PASSWORD"); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + Serial.println("Connected to WiFi: " + WiFi.SSID()); +} + +void loop() { + + HTTPClient http; + + Serial.print("[HTTP] Preparing HTTP request...\n"); + // This page will return the headers we want to test + some others + http.begin("https://httpbingo.org/response-headers?x-custom-header=value:42"); + +#if COLLECT_ALL_HEADERS + // Collect all headers + http.collectAllHeaders(); +#else + // Collect specific headers, only that one will be stored + const char *headerKeys[] = {"x-custom-header"}; + const size_t headerKeysCount = sizeof(headerKeys) / sizeof(headerKeys[0]); + http.collectHeaders(headerKeys, headerKeysCount); +#endif + + Serial.print("[HTTP] Sending HTTP GET request...\n"); + // start connection and send HTTP header + int httpCode = http.GET(); + + // httpCode will be negative on error + if (httpCode > 0) { + // HTTP header has been send and Server response header has been handled + Serial.printf("[HTTP] GET response code: %d\n", httpCode); + + Serial.println("[HTTP] Headers collected:"); + for (size_t i = 0; i < http.headers(); i++) { + Serial.printf("[HTTP] - '%s': '%s'\n", http.headerName(i).c_str(), http.header(i).c_str()); + } + + Serial.println("[HTTP] Has header 'x-custom-header'? " + String(http.hasHeader("x-custom-header")) + " (expected true)"); + Serial.printf("[HTTP] x-custom-header: '%s' (expected 'value:42')\n", http.header("x-custom-header").c_str()); + Serial.printf("[HTTP] non-existing-header: '%s' (expected empty string)\n", http.header("non-existing-header").c_str()); + +#if COLLECT_ALL_HEADERS + // Server response with multiple headers, one of them is 'server' + Serial.println("[HTTP] Has header 'server'? " + String(http.hasHeader("server")) + " (expected true)"); + Serial.printf("[HTTP] server: '%s'\n", http.header("server").c_str()); +#endif + + } else { + Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + + Serial.println("[HTTP] end connection\n\n"); + delay(5000); +} diff --git a/libraries/HTTPClient/examples/CustomHeaders/ci.json b/libraries/HTTPClient/examples/CustomHeaders/ci.json new file mode 100644 index 00000000000..618e46bd244 --- /dev/null +++ b/libraries/HTTPClient/examples/CustomHeaders/ci.json @@ -0,0 +1,6 @@ +{ + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] +} diff --git a/libraries/HTTPClient/src/HTTPClient.cpp b/libraries/HTTPClient/src/HTTPClient.cpp index 03d9a6204d5..8061042bd3f 100644 --- a/libraries/HTTPClient/src/HTTPClient.cpp +++ b/libraries/HTTPClient/src/HTTPClient.cpp @@ -90,9 +90,6 @@ HTTPClient::~HTTPClient() { if (_client) { _client->stop(); } - if (_currentHeaders) { - delete[] _currentHeaders; - } if (_tcpDeprecated) { _tcpDeprecated.reset(nullptr); } @@ -564,9 +561,12 @@ int HTTPClient::sendRequest(const char *type, uint8_t *payload, size_t size) { bool redirect = false; uint16_t redirectCount = 0; do { - // wipe out any existing headers from previous request - for (size_t i = 0; i < _headerKeysCount; i++) { - if (_currentHeaders[i].value.length() > 0) { + // wipe out any existing headers from previous request, but preserve the keys if collecting specific headers + if (_collectAllHeaders) { + _currentHeaders.clear(); + } else { + // Only clear values, keep the keys for specific header collection + for (size_t i = 0; i < _currentHeaders.size(); ++i) { _currentHeaders[i].value.clear(); } } @@ -1015,19 +1015,24 @@ void HTTPClient::addHeader(const String &name, const String &value, bool first, } } +void HTTPClient::collectAllHeaders(bool collectAll) { + _collectAllHeaders = collectAll; +} + void HTTPClient::collectHeaders(const char *headerKeys[], const size_t headerKeysCount) { - _headerKeysCount = headerKeysCount; - if (_currentHeaders) { - delete[] _currentHeaders; + if (_collectAllHeaders) { + log_w("collectHeaders is ignored when collectAllHeaders is set"); + return; } - _currentHeaders = new RequestArgument[_headerKeysCount]; - for (size_t i = 0; i < _headerKeysCount; i++) { + _currentHeaders.clear(); + _currentHeaders.resize(headerKeysCount); + for (size_t i = 0; i < headerKeysCount; i++) { _currentHeaders[i].key = headerKeys[i]; } } String HTTPClient::header(const char *name) { - for (size_t i = 0; i < _headerKeysCount; ++i) { + for (size_t i = 0; i < _currentHeaders.size(); ++i) { if (_currentHeaders[i].key.equalsIgnoreCase(name)) { return _currentHeaders[i].value; } @@ -1036,25 +1041,25 @@ String HTTPClient::header(const char *name) { } String HTTPClient::header(size_t i) { - if (i < _headerKeysCount) { + if (i < _currentHeaders.size()) { return _currentHeaders[i].value; } return String(); } String HTTPClient::headerName(size_t i) { - if (i < _headerKeysCount) { + if (i < _currentHeaders.size()) { return _currentHeaders[i].key; } return String(); } int HTTPClient::headers() { - return _headerKeysCount; + return _currentHeaders.size(); } bool HTTPClient::hasHeader(const char *name) { - for (size_t i = 0; i < _headerKeysCount; ++i) { + for (size_t i = 0; i < _currentHeaders.size(); ++i) { if ((_currentHeaders[i].key.equalsIgnoreCase(name)) && (_currentHeaders[i].value.length() > 0)) { return true; } @@ -1238,17 +1243,14 @@ int HTTPClient::handleHeaderResponse() { 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; // We found a match, stop looking + if (_collectAllHeaders && headerName.length() > 0) { + _currentHeaders.emplace_back(headerName, headerValue); + } else { + for (size_t i = 0; i < _currentHeaders.size(); ++i) { + if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) { + _currentHeaders[i].value = headerValue; + break; // We found a match, stop looking + } } } } diff --git a/libraries/HTTPClient/src/HTTPClient.h b/libraries/HTTPClient/src/HTTPClient.h index 80f6da28599..e07cd937d06 100644 --- a/libraries/HTTPClient/src/HTTPClient.h +++ b/libraries/HTTPClient/src/HTTPClient.h @@ -38,7 +38,7 @@ #include #endif // HTTPCLIENT_NOSECURE -/// Cookie jar support +/// Cookie jar and header support #include #define HTTPCLIENT_DEFAULT_TCP_TIMEOUT (5000) @@ -238,6 +238,7 @@ class HTTPClient { void addHeader(const String &name, const String &value, bool first = false, bool replace = true); /// Response handling + void collectAllHeaders(bool collectAll = true); void collectHeaders(const char *headerKeys[], const size_t headerKeysCount); String header(const char *name); // get request header value by name String header(size_t i); // get request header value by number @@ -294,6 +295,7 @@ class HTTPClient { uint16_t _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT; bool _useHTTP10 = false; bool _secure = false; + bool _collectAllHeaders = false; String _uri; String _protocol; @@ -304,8 +306,7 @@ class HTTPClient { String _acceptEncoding = "identity;q=1,chunked;q=0.1,*;q=0"; /// Response handling - RequestArgument *_currentHeaders = nullptr; - size_t _headerKeysCount = 0; + std::vector _currentHeaders; int _returnCode = 0; int _size = -1; diff --git a/tests/validation/touch/ci.json b/tests/validation/touch/ci.json index 855e9bd964d..3ccb5dfabe8 100644 --- a/tests/validation/touch/ci.json +++ b/tests/validation/touch/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "DebugLevel=verbose", "platforms": { "qemu": false, "wokwi": false diff --git a/tests/validation/touch/touch.ino b/tests/validation/touch/touch.ino index 97aac8a65e6..21ed6119c02 100644 --- a/tests/validation/touch/touch.ino +++ b/tests/validation/touch/touch.ino @@ -1,35 +1,30 @@ #include #include "soc/soc_caps.h" -#include "driver/touch_pad.h" - -#if SOC_TOUCH_SENSOR_VERSION == 3 #include "hal/touch_sensor_ll.h" -#endif #if CONFIG_IDF_TARGET_ESP32 -#define TEST_TOUCH_CHANNEL (9) +#define TEST_TOUCH_CHANNEL (7) static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { TOUCH_PAD_NUM0, //TOUCH_PAD_NUM1 is GPIO0, for download. - TOUCH_PAD_NUM2, TOUCH_PAD_NUM3, TOUCH_PAD_NUM4, TOUCH_PAD_NUM5, TOUCH_PAD_NUM6, TOUCH_PAD_NUM7, TOUCH_PAD_NUM8, TOUCH_PAD_NUM9 + TOUCH_PAD_NUM2, TOUCH_PAD_NUM3, TOUCH_PAD_NUM4, TOUCH_PAD_NUM5, TOUCH_PAD_NUM6, TOUCH_PAD_NUM7 /*,TOUCH_PAD_NUM8, TOUCH_PAD_NUM9*/ }; -uint8_t TOUCH_GPIOS[] = {4, 2, 15, 13, 12, 14, 27, 33, 32}; +uint8_t TOUCH_GPIOS[] = {4, /* 0,*/ 2, 15, 13, 12, 14, 27 /*, 33, 32*/}; #define NO_TOUCH_GPIO 25 #elif (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3) -#define TEST_TOUCH_CHANNEL (12) //14 +#define TEST_TOUCH_CHANNEL (8) //14 static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { - TOUCH_PAD_NUM1, TOUCH_PAD_NUM2, TOUCH_PAD_NUM3, TOUCH_PAD_NUM4, TOUCH_PAD_NUM5, TOUCH_PAD_NUM6, TOUCH_PAD_NUM7, - TOUCH_PAD_NUM8, TOUCH_PAD_NUM9, TOUCH_PAD_NUM10, TOUCH_PAD_NUM11, TOUCH_PAD_NUM12 - //TOUCH_PAD_NUM13, //Wrong reading - //TOUCH_PAD_NUM14 + TOUCH_PAD_NUM1, TOUCH_PAD_NUM2, TOUCH_PAD_NUM3, TOUCH_PAD_NUM4, TOUCH_PAD_NUM5, + TOUCH_PAD_NUM6, TOUCH_PAD_NUM7, TOUCH_PAD_NUM8 + /*TOUCH_PAD_NUM9, TOUCH_PAD_NUM10, TOUCH_PAD_NUM11, TOUCH_PAD_NUM12, TOUCH_PAD_NUM13, TOUCH_PAD_NUM14*/ }; -uint8_t TOUCH_GPIOS[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 /*,13,14*/}; +uint8_t TOUCH_GPIOS[] = {1, 2, 3, 4, 5, 6, 7, 8 /*, 9, 10, 11, 12, 13, 14*/}; #define NO_TOUCH_GPIO 17 @@ -47,21 +42,12 @@ uint8_t TOUCH_GPIOS[] = {2, 3, 4, 5, 6 /*, 7, 8, 9, 10, 11, 12 ,13, 14, 15*/}; #define NO_TOUCH_GPIO 17 #endif -#if CONFIG_IDF_TARGET_ESP32 -#define RELEASED_VALUE 75 //75+ read value to pass test -#define PRESSED_VALUE 20 //20- read value to pass test -#define INTERRUPT_THRESHOLD 40 -#elif CONFIG_IDF_TARGET_ESP32S2 -#define RELEASED_VALUE 10000 //10000- read value to pass test -#define PRESSED_VALUE 42000 //40000+ read value to pass test -#define INTERRUPT_THRESHOLD 30000 -#elif CONFIG_IDF_TARGET_ESP32S3 -#define RELEASED_VALUE 25000 //25000- read value to pass test -#define PRESSED_VALUE 90000 //90000+ read value to pass test -#define INTERRUPT_THRESHOLD 80000 -#elif CONFIG_IDF_TARGET_ESP32P4 -#define PRESSED_VALUE_DIFFERENCE 200 //200+ read value difference against the unpressed value -#define INTERRUPT_THRESHOLD 0 // Use benchmarked threshold +#define INTERRUPT_THRESHOLD 0 // Use benchmarked threshold + +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32P4 +#define PRESSED_VALUE_DIFFERENCE 200 //-200 for ESP32 and +200 for ESP32P4 read value difference against the unpressed value +#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32S2 +#define PRESSED_VALUE_DIFFERENCE 2000 //2000+ read value difference against the unpressed value #else #error Test not currently supported on this chip. Please adjust and try again! #endif @@ -82,7 +68,7 @@ void gotTouch2() { */ static void test_press_fake(touch_pad_t pad_num) { #if SOC_TOUCH_SENSOR_VERSION <= 2 - touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_1, TOUCH_PAD_TIE_OPT_DEFAULT); + touch_ll_set_charge_speed(pad_num, TOUCH_CHARGE_SPEED_4); #else touch_ll_set_internal_capacitor(0x7f); #endif @@ -93,7 +79,7 @@ static void test_press_fake(touch_pad_t pad_num) { */ static void test_release_fake(touch_pad_t pad_num) { #if SOC_TOUCH_SENSOR_VERSION <= 2 - touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT); + touch_ll_set_charge_speed(pad_num, TOUCH_CHARGE_SPEED_7); #else touch_ll_set_internal_capacitor(0); #endif @@ -113,31 +99,6 @@ void tearDown(void) { * Test Touch read on all available channels - compare values if reading is right */ void test_touch_read(void) { - -#if SOC_TOUCH_SENSOR_VERSION <= 2 - //TEST RELEASE STATE - for (int i = 0; i < sizeof(TOUCH_GPIOS); i++) { -#ifdef CONFIG_IDF_TARGET_ESP32 - TEST_ASSERT_GREATER_THAN(RELEASED_VALUE, touchRead(TOUCH_GPIOS[i])); -#else - TEST_ASSERT_LESS_THAN(RELEASED_VALUE, touchRead(TOUCH_GPIOS[i])); -#endif - } - - // TEST PRESS STATE - for (int j = 0; j < TEST_TOUCH_CHANNEL; j++) { - test_press_fake(touch_list[j]); - } - delay(100); - - for (int k = 0; k < sizeof(TOUCH_GPIOS); k++) { -#ifdef CONFIG_IDF_TARGET_ESP32 - TEST_ASSERT_LESS_THAN(PRESSED_VALUE, touchRead(TOUCH_GPIOS[k])); -#else - TEST_ASSERT_GREATER_THAN(PRESSED_VALUE, touchRead(TOUCH_GPIOS[k])); -#endif - } -#else //TOUCH V3 //TEST RELEASE STATE touch_value_t touch_unpressed[sizeof(TOUCH_GPIOS)]; for (int i = 0; i < sizeof(TOUCH_GPIOS); i++) { @@ -155,11 +116,18 @@ void test_touch_read(void) { touch_pressed[k] = touchRead(TOUCH_GPIOS[k]); } - // COMPARE PRESSED > UNPRESSED + // COMPARE PRESSED <-> UNPRESSED for (int l = 0; l < sizeof(TOUCH_GPIOS); l++) { - TEST_ASSERT_GREATER_THAN((touch_unpressed[l] + PRESSED_VALUE_DIFFERENCE), touch_pressed[l]); + //log_i("Touch %d: %d -> %d", TOUCH_GPIOS[l], touch_unpressed[l], touch_pressed[l]); + Serial.printf("Touch %d: %lu -> %lu\n", TOUCH_GPIOS[l], touch_unpressed[l], touch_pressed[l]); } + for (int l = 0; l < sizeof(TOUCH_GPIOS); l++) { +#if CONFIG_IDF_TARGET_ESP32 + TEST_ASSERT_LESS_THAN((touch_unpressed[l] - PRESSED_VALUE_DIFFERENCE), touch_pressed[l]); +#else + TEST_ASSERT_GREATER_THAN((touch_unpressed[l] + PRESSED_VALUE_DIFFERENCE), touch_pressed[l]); #endif + } } void test_touch_interrtupt(void) { @@ -170,7 +138,7 @@ void test_touch_interrtupt(void) { test_press_fake(touch_list[0]); test_press_fake(touch_list[1]); - delay(300); + delay(100); touchDetachInterrupt(TOUCH_GPIOS[0]); touchDetachInterrupt(TOUCH_GPIOS[1]); @@ -190,6 +158,10 @@ void setup() { ; } +#if SOC_TOUCH_SENSOR_VERSION == 3 + touch_ll_enable_internal_capacitor(true); +#endif + UNITY_BEGIN(); RUN_TEST(test_touch_read); RUN_TEST(test_touch_interrtupt);