From e1673e4c0ca89153e26d31cd783f0f8260c6d0fb Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 19 Aug 2024 14:50:26 +0300 Subject: [PATCH 001/409] fix(build): IDF release/v5.3 466a392a and initial changes --- .github/scripts/on-release.sh | 20 +- .github/workflows/push.yml | 43 +- .gitignore | 1 + CMakeLists.txt | 6 +- cores/esp32/Client.h | 2 + cores/esp32/HWCDC.cpp | 16 +- cores/esp32/HardwareSerial.cpp | 24 +- cores/esp32/HardwareSerial.h | 12 +- cores/esp32/esp32-hal-i2c-slave.c | 30 +- cores/esp32/esp32-hal-touch.c | 36 +- cores/esp32/esp32-hal-touch.h | 10 +- cores/esp32/esp32-hal-uart.c | 46 +- idf_component.yml | 2 +- .../SerialToSerialBT_Legacy.ino | 7 - .../SerialToSerialBT_SSP.ino | 5 - .../BluetoothSerial/src/BluetoothSerial.cpp | 15 - .../BluetoothSerial/src/BluetoothSerial.h | 5 - .../Serial_STD_Func_OnReceive.ino | 10 +- libraries/ESP_I2S/src/ESP_I2S.cpp | 2 +- libraries/ESP_I2S/src/ESP_I2S.h | 2 +- libraries/Ethernet/src/ETH.cpp | 5 + .../DiagnosticsSmokeTest.ino | 3 +- libraries/Network/src/NetworkClient.h | 2 - libraries/PPP/src/PPP.cpp | 2 +- package/package_esp32_index.template.json | 538 +++++++----------- platform.txt | 6 +- tests/validation/uart/uart.ino | 60 +- 27 files changed, 368 insertions(+), 542 deletions(-) diff --git a/.github/scripts/on-release.sh b/.github/scripts/on-release.sh index eb8f2be7b81..3c3cfc05895 100755 --- a/.github/scripts/on-release.sh +++ b/.github/scripts/on-release.sh @@ -219,12 +219,8 @@ find "$PKG_DIR" -name '*.git*' -type f -delete ## RVTC_NAME="riscv32-esp-elf-gcc" RVTC_NEW_NAME="esp-rv32" -X32TC_NAME="xtensa-esp32-elf-gcc" +X32TC_NAME="xtensa-esp-elf-gcc" X32TC_NEW_NAME="esp-x32" -XS2TC_NAME="xtensa-esp32s2-elf-gcc" -XS2TC_NEW_NAME="esp-xs2" -XS3TC_NAME="xtensa-esp32s3-elf-gcc" -XS3TC_NEW_NAME="esp-xs3" # Replace tools locations in platform.txt echo "Generating platform.txt..." @@ -233,9 +229,7 @@ sed "s/version=.*/version=$RELEASE_TAG/g" | \ sed 's/tools\.esp32-arduino-libs\.path\.windows=.*//g' | \ sed 's/{runtime\.platform\.path}.tools.esp32-arduino-libs/\{runtime.tools.esp32-arduino-libs.path\}/g' | \ sed 's/{runtime\.platform\.path}.tools.xtensa-esp-elf-gdb/\{runtime.tools.xtensa-esp-elf-gdb.path\}/g' | \ -sed "s/{runtime\.platform\.path}.tools.xtensa-esp32-elf/\\{runtime.tools.$X32TC_NEW_NAME.path\\}/g" | \ -sed "s/{runtime\.platform\.path}.tools.xtensa-esp32s2-elf/\\{runtime.tools.$XS2TC_NEW_NAME.path\\}/g" | \ -sed "s/{runtime\.platform\.path}.tools.xtensa-esp32s3-elf/\\{runtime.tools.$XS3TC_NEW_NAME.path\\}/g" | \ +sed "s/{runtime\.platform\.path}.tools.xtensa-esp-elf/\\{runtime.tools.$X32TC_NEW_NAME.path\\}/g" | \ sed 's/{runtime\.platform\.path}.tools.riscv32-esp-elf-gdb/\{runtime.tools.riscv32-esp-elf-gdb.path\}/g' | \ sed "s/{runtime\.platform\.path}.tools.riscv32-esp-elf/\\{runtime.tools.$RVTC_NEW_NAME.path\\}/g" | \ sed 's/{runtime\.platform\.path}.tools.esptool/\{runtime.tools.esptool_py.path\}/g' | \ @@ -355,15 +349,7 @@ rvtc_jq_arg="\ (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$X32TC_NAME\")).version = \"$RVTC_VERSION\" |\ (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$X32TC_NAME\")).name = \"$X32TC_NEW_NAME\" |\ (.packages[0].tools[] | select(.name==\"$X32TC_NAME\")).version = \"$RVTC_VERSION\" |\ - (.packages[0].tools[] | select(.name==\"$X32TC_NAME\")).name = \"$X32TC_NEW_NAME\" |\ - (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$XS2TC_NAME\")).version = \"$RVTC_VERSION\" |\ - (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$XS2TC_NAME\")).name = \"$XS2TC_NEW_NAME\" |\ - (.packages[0].tools[] | select(.name==\"$XS2TC_NAME\")).version = \"$RVTC_VERSION\" |\ - (.packages[0].tools[] | select(.name==\"$XS2TC_NAME\")).name = \"$XS2TC_NEW_NAME\" |\ - (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$XS3TC_NAME\")).version = \"$RVTC_VERSION\" |\ - (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$XS3TC_NAME\")).name = \"$XS3TC_NEW_NAME\" |\ - (.packages[0].tools[] | select(.name==\"$XS3TC_NAME\")).version = \"$RVTC_VERSION\" |\ - (.packages[0].tools[] | select(.name==\"$XS3TC_NAME\")).name = \"$XS3TC_NEW_NAME\"" + (.packages[0].tools[] | select(.name==\"$X32TC_NAME\")).name = \"$X32TC_NEW_NAME\"" cat "$PACKAGE_JSON_TEMPLATE" | jq "$rvtc_jq_arg" > "$OUTPUT_DIR/package-$LIBS_PROJ_NAME-rvfix.json" PACKAGE_JSON_TEMPLATE="$OUTPUT_DIR/package-$LIBS_PROJ_NAME-rvfix.json" diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 2f14a6fb62f..251d787dfd9 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -194,28 +194,29 @@ jobs: - name: Build Sketches run: bash ./.github/scripts/on-push.sh - # PlatformIO on Windows, Ubuntu and Mac - build-platformio: - name: PlatformIO on ${{ matrix.os }} - needs: gen-chunks - if: | - needs.gen-chunks.outputs.build_all == 'true' || - needs.gen-chunks.outputs.build_static_sketches == 'true' || - needs.gen-chunks.outputs.build_platformio == 'true' - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] + # # PlatformIO on Windows, Ubuntu and Mac + # build-platformio: + # name: PlatformIO on ${{ matrix.os }} + # needs: gen-chunks + # if: | + # needs.gen-chunks.outputs.build_all == 'true' || + # needs.gen-chunks.outputs.build_static_sketches == 'true' || + # needs.gen-chunks.outputs.build_platformio == 'true' + # runs-on: ${{ matrix.os }} + # strategy: + # fail-fast: false + # matrix: + # os: [ubuntu-latest, windows-latest, macOS-latest] - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: Build Sketches - run: bash ./.github/scripts/on-push.sh 1 1 #equal and non-zero to trigger PIO + # steps: + # - uses: actions/checkout@v4 + # - uses: actions/setup-python@v5 + # with: + # python-version: '3.x' + # - name: Build Sketches + # run: bash ./.github/scripts/on-push.sh 1 1 #equal and non-zero to trigger PIO + # ESP-IDF component build build-esp-idf-component: name: Build with ESP-IDF ${{ matrix.idf_ver }} for ${{ matrix.idf_target }} needs: gen-chunks @@ -231,7 +232,7 @@ jobs: # See https://hub.docker.com/r/espressif/idf/tags and # https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-docker-image.html # for details. - idf_ver: ["release-v5.1"] + idf_ver: ["release-v5.3"] idf_target: ["esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2"] container: espressif/idf:${{ matrix.idf_ver }} steps: diff --git a/.gitignore b/.gitignore index 1519de52764..d254d439834 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ tools/esp32-arduino-libs +tools/xtensa-esp-elf tools/xtensa-esp32-elf tools/xtensa-esp32s2-elf tools/xtensa-esp32s3-elf diff --git a/CMakeLists.txt b/CMakeLists.txt index a11d4809049..252059a8907 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ # export ARDUINO_SKIP_IDF_VERSION_CHECK=1 # idf.py build -set(min_supported_idf_version "5.1.0") -set(max_supported_idf_version "5.1.99") +set(min_supported_idf_version "5.3.0") +set(max_supported_idf_version "5.3.99") set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}.${IDF_VERSION_PATCH}") if ("${idf_version}" AND NOT "$ENV{ARDUINO_SKIP_IDF_VERSION_CHECK}") @@ -293,7 +293,7 @@ endforeach() set(includedirs variants/${CONFIG_ARDUINO_VARIANT}/ cores/esp32/ ${ARDUINO_LIBRARIES_INCLUDEDIRS}) set(srcs ${CORE_SRCS} ${ARDUINO_LIBRARIES_SRCS}) set(priv_includes cores/esp32/libb64) -set(requires spi_flash esp_partition mbedtls wpa_supplicant esp_adc esp_eth http_parser espressif__network_provisioning) +set(requires spi_flash esp_partition mbedtls wpa_supplicant esp_adc esp_eth http_parser esp_ringbuf esp_driver_gptimer esp_driver_usb_serial_jtag driver espressif__network_provisioning) set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support bt esp_hid usb esp_psram ${ARDUINO_LIBRARIES_REQUIRES}) if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_OpenThread) diff --git a/cores/esp32/Client.h b/cores/esp32/Client.h index ab013612401..4ea10d070fb 100644 --- a/cores/esp32/Client.h +++ b/cores/esp32/Client.h @@ -26,7 +26,9 @@ class Client : public Stream { public: virtual int connect(IPAddress ip, uint16_t port) = 0; + virtual int connect(IPAddress ip, uint16_t port, int32_t timeout) = 0; virtual int connect(const char *host, uint16_t port) = 0; + virtual int connect(const char *host, uint16_t port, int32_t timeout) = 0; virtual size_t write(uint8_t) = 0; virtual size_t write(const uint8_t *buf, size_t size) = 0; virtual int available() = 0; diff --git a/cores/esp32/HWCDC.cpp b/cores/esp32/HWCDC.cpp index b0f653e889e..59709fd4f86 100644 --- a/cores/esp32/HWCDC.cpp +++ b/cores/esp32/HWCDC.cpp @@ -286,14 +286,14 @@ bool HWCDC::deinit(void *busptr) { running = true; // Setting USB D+ D- pins bool retCode = true; - retCode &= perimanClearPinBus(USB_DM_GPIO_NUM); - retCode &= perimanClearPinBus(USB_DP_GPIO_NUM); + retCode &= perimanClearPinBus(USB_INT_PHY0_DM_GPIO_NUM); + retCode &= perimanClearPinBus(USB_INT_PHY0_DP_GPIO_NUM); if (retCode) { // Force the host to re-enumerate (BUS_RESET) - pinMode(USB_DM_GPIO_NUM, OUTPUT_OPEN_DRAIN); - pinMode(USB_DP_GPIO_NUM, OUTPUT_OPEN_DRAIN); - digitalWrite(USB_DM_GPIO_NUM, LOW); - digitalWrite(USB_DP_GPIO_NUM, LOW); + pinMode(USB_INT_PHY0_DM_GPIO_NUM, OUTPUT_OPEN_DRAIN); + pinMode(USB_INT_PHY0_DP_GPIO_NUM, OUTPUT_OPEN_DRAIN); + digitalWrite(USB_INT_PHY0_DM_GPIO_NUM, LOW); + digitalWrite(USB_INT_PHY0_DP_GPIO_NUM, LOW); } // release the flag running = false; @@ -323,11 +323,11 @@ void HWCDC::begin(unsigned long baud) { // delay(10); // USB Host has to enumerate it again // Peripheral Manager setting for USB D+ D- pins - uint8_t pin = USB_DM_GPIO_NUM; + uint8_t pin = USB_INT_PHY0_DM_GPIO_NUM; if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_USB_DM, (void *)this, -1, -1)) { goto err; } - pin = USB_DP_GPIO_NUM; + pin = USB_INT_PHY0_DP_GPIO_NUM; if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_USB_DP, (void *)this, -1, -1)) { goto err; } diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index 1f064faada6..c1cf8200a32 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -26,23 +26,23 @@ void serialEvent(void) __attribute__((weak)); void serialEvent(void) {} -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 void serialEvent1(void) __attribute__((weak)); void serialEvent1(void) {} -#endif /* SOC_UART_NUM > 1 */ +#endif /* SOC_UART_HP_NUM > 1 */ -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 void serialEvent2(void) __attribute__((weak)); void serialEvent2(void) {} -#endif /* SOC_UART_NUM > 2 */ +#endif /* SOC_UART_HP_NUM > 2 */ #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) // There is always Seria0 for UART0 HardwareSerial Serial0(0); -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 HardwareSerial Serial1(1); #endif -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 HardwareSerial Serial2(2); #endif @@ -72,12 +72,12 @@ void serialEventRun(void) { if (Serial0.available()) { serialEvent(); } -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 if (Serial1.available()) { serialEvent1(); } #endif -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 if (Serial2.available()) { serialEvent2(); } @@ -279,8 +279,8 @@ void HardwareSerial::_uartEventTask(void *args) { } void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms, uint8_t rxfifo_full_thrhd) { - if (_uart_nr >= SOC_UART_NUM) { - log_e("Serial number is invalid, please use a number from 0 to %u", SOC_UART_NUM - 1); + if (_uart_nr >= SOC_UART_HP_NUM) { + log_e("Serial number is invalid, please use a number from 0 to %u", SOC_UART_HP_NUM - 1); return; } @@ -305,7 +305,7 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in txPin = _txPin < 0 ? (int8_t)SOC_TX0 : _txPin; } break; -#if SOC_UART_NUM > 1 // may save some flash bytes... +#if SOC_UART_HP_NUM > 1 // may save some flash bytes... case UART_NUM_1: if (rxPin < 0 && txPin < 0) { // do not change RX1/TX1 if it has already been set before @@ -314,7 +314,7 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in } break; #endif -#if SOC_UART_NUM > 2 // may save some flash bytes... +#if SOC_UART_HP_NUM > 2 // may save some flash bytes... case UART_NUM_2: if (rxPin < 0 && txPin < 0) { // do not change RX2/TX2 if it has already been set before diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index 3fd5e7dc99b..2d280b053de 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -146,7 +146,7 @@ typedef enum { // Default pins for UART1 are arbitrary, and defined here for convenience. -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 #ifndef RX1 #if CONFIG_IDF_TARGET_ESP32 #define RX1 (gpio_num_t)26 @@ -182,11 +182,11 @@ typedef enum { #define TX1 (gpio_num_t)1 #endif #endif -#endif /* SOC_UART_NUM > 1 */ +#endif /* SOC_UART_HP_NUM > 1 */ // Default pins for UART2 are arbitrary, and defined here for convenience. -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 #ifndef RX2 #if CONFIG_IDF_TARGET_ESP32 #define RX2 (gpio_num_t)4 @@ -202,7 +202,7 @@ typedef enum { #define TX2 (gpio_num_t)20 #endif #endif -#endif /* SOC_UART_NUM > 2 */ +#endif /* SOC_UART_HP_NUM > 2 */ typedef std::function OnReceiveCb; typedef std::function OnReceiveErrorCb; @@ -357,10 +357,10 @@ extern void serialEventRun(void) __attribute__((weak)); #endif // ARDUINO_USB_CDC_ON_BOOT // There is always Seria0 for UART0 extern HardwareSerial Serial0; -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 extern HardwareSerial Serial1; #endif -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 extern HardwareSerial Serial2; #endif #endif //!defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) diff --git a/cores/esp32/esp32-hal-i2c-slave.c b/cores/esp32/esp32-hal-i2c-slave.c index edae1e57c92..5504fd62adf 100644 --- a/cores/esp32/esp32-hal-i2c-slave.c +++ b/cores/esp32/esp32-hal-i2c-slave.c @@ -49,7 +49,7 @@ #define I2C_SLAVE_USE_RX_QUEUE 0 // 1: Queue, 0: RingBuffer -#if SOC_I2C_NUM > 1 +#if SOC_HP_I2C_NUM > 1 #define I2C_SCL_IDX(p) ((p == 0) ? I2CEXT0_SCL_OUT_IDX : ((p == 1) ? I2CEXT1_SCL_OUT_IDX : 0)) #define I2C_SDA_IDX(p) ((p == 0) ? I2CEXT0_SDA_OUT_IDX : ((p == 1) ? I2CEXT1_SDA_OUT_IDX : 0)) #else @@ -99,14 +99,14 @@ typedef union { uint32_t val; } i2c_slave_queue_event_t; -static i2c_slave_struct_t _i2c_bus_array[SOC_I2C_NUM] = { +static i2c_slave_struct_t _i2c_bus_array[SOC_HP_I2C_NUM] = { {&I2C0, 0, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 #if !CONFIG_DISABLE_HAL_LOCKS , NULL #endif }, -#if SOC_I2C_NUM > 1 +#if SOC_HP_I2C_NUM > 1 {&I2C1, 1, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 #if !CONFIG_DISABLE_HAL_LOCKS , @@ -210,7 +210,7 @@ static bool i2cSlaveDetachBus(void *bus_i2c_num); //===================================================================================================================== esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_callback, i2c_slave_receive_cb_t receive_callback, void *arg) { - if (num >= SOC_I2C_NUM) { + if (num >= SOC_HP_I2C_NUM) { log_e("Invalid port num: %u", num); return ESP_ERR_INVALID_ARG; } @@ -224,7 +224,7 @@ esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_ca } esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency, size_t rx_len, size_t tx_len) { - if (num >= SOC_I2C_NUM) { + if (num >= SOC_HP_I2C_NUM) { log_e("Invalid port num: %u", num); return ESP_ERR_INVALID_ARG; } @@ -309,14 +309,14 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t if (i2c->num == 0) { periph_ll_enable_clk_clear_rst(PERIPH_I2C0_MODULE); -#if SOC_I2C_NUM > 1 +#if SOC_HP_I2C_NUM > 1 } else { periph_ll_enable_clk_clear_rst(PERIPH_I2C1_MODULE); #endif } i2c_ll_slave_init(i2c->dev); - i2c_ll_set_fifo_mode(i2c->dev, true); + i2c_ll_slave_set_fifo_mode(i2c->dev, true); i2c_ll_set_slave_addr(i2c->dev, slaveID, false); i2c_ll_set_tout(i2c->dev, I2C_LL_MAX_TIMEOUT); i2c_slave_set_frequency(i2c, frequency); @@ -337,13 +337,13 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK); i2c_ll_clear_intr_mask(i2c->dev, I2C_LL_INTR_MASK); - i2c_ll_set_fifo_mode(i2c->dev, true); + i2c_ll_slave_set_fifo_mode(i2c->dev, true); if (!i2c->intr_handle) { uint32_t flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED; if (i2c->num == 0) { ret = esp_intr_alloc(ETS_I2C_EXT0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); -#if SOC_I2C_NUM > 1 +#if SOC_HP_I2C_NUM > 1 } else { ret = esp_intr_alloc(ETS_I2C_EXT1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); #endif @@ -375,7 +375,7 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t } esp_err_t i2cSlaveDeinit(uint8_t num) { - if (num >= SOC_I2C_NUM) { + if (num >= SOC_HP_I2C_NUM) { log_e("Invalid port num: %u", num); return ESP_ERR_INVALID_ARG; } @@ -398,7 +398,7 @@ esp_err_t i2cSlaveDeinit(uint8_t num) { } size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms) { - if (num >= SOC_I2C_NUM) { + if (num >= SOC_HP_I2C_NUM) { log_e("Invalid port num: %u", num); return 0; } @@ -515,16 +515,16 @@ static bool i2c_slave_set_frequency(i2c_slave_struct_t *i2c, uint32_t clk_speed) i2c_hal_clk_config_t clk_cal; #if SOC_I2C_SUPPORT_APB - i2c_ll_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal); + i2c_ll_master_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal); i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_APB); /*!< I2C source clock from APB, 80M*/ #elif SOC_I2C_SUPPORT_XTAL - i2c_ll_cal_bus_clk(XTAL_CLK_FREQ, clk_speed, &clk_cal); + i2c_ll_master_cal_bus_clk(XTAL_CLK_FREQ, clk_speed, &clk_cal); i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_XTAL); /*!< I2C source clock from XTAL, 40M */ #endif i2c_ll_set_txfifo_empty_thr(i2c->dev, a); i2c_ll_set_rxfifo_full_thr(i2c->dev, SOC_I2C_FIFO_LEN - a); - i2c_ll_set_bus_timing(i2c->dev, &clk_cal); - i2c_ll_set_filter(i2c->dev, 3); + i2c_ll_master_set_bus_timing(i2c->dev, &clk_cal); + i2c_ll_master_set_filter(i2c->dev, 3); return true; } diff --git a/cores/esp32/esp32-hal-touch.c b/cores/esp32/esp32-hal-touch.c index d32b34d0173..764b7dbb73f 100644 --- a/cores/esp32/esp32-hal-touch.c +++ b/cores/esp32/esp32-hal-touch.c @@ -22,10 +22,10 @@ Internal Private Touch Data Structure and Functions */ -#if SOC_TOUCH_VERSION_1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 static uint16_t __touchSleepCycles = 0x1000; static uint16_t __touchMeasureCycles = 0x1000; -#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 static uint16_t __touchSleepCycles = TOUCH_PAD_SLEEP_CYCLE_DEFAULT; static uint16_t __touchMeasureCycles = TOUCH_PAD_MEASURE_CYCLE_DEFAULT; #endif @@ -37,7 +37,7 @@ typedef struct { voidFuncPtr fn; bool callWithArgs; void *arg; -#if SOC_TOUCH_VERSION_2 // Only for ESP32S2 and ESP32S3 +#if SOC_TOUCH_SENSOR_VERSION == 2 // Only for ESP32S2 and ESP32S3 bool lastStatusIsPressed; #endif } TouchInterruptHandle_t; @@ -51,7 +51,7 @@ static bool initialized = false; static bool channels_initialized[SOC_TOUCH_SENSOR_NUM] = {false}; static void ARDUINO_ISR_ATTR __touchISR(void *arg) { -#if SOC_TOUCH_VERSION_1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 uint32_t pad_intr = touch_pad_get_status(); //clear interrupt touch_pad_clear_status(); @@ -68,7 +68,7 @@ static void ARDUINO_ISR_ATTR __touchISR(void *arg) { } } } -#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 +#elif SOC_TOUCH_SENSOR_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) { @@ -93,9 +93,9 @@ static void ARDUINO_ISR_ATTR __touchISR(void *arg) { static void __touchSetCycles(uint16_t measure, uint16_t sleep) { __touchSleepCycles = sleep; __touchMeasureCycles = measure; -#if SOC_TOUCH_VERSION_1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 touch_pad_set_measurement_clock_cycles(measure); -#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 touch_pad_set_charge_discharge_times(measure); #endif touch_pad_set_measurement_interval(sleep); @@ -123,7 +123,7 @@ static void __touchInit() { esp_err_t err = ESP_OK; -#if SOC_TOUCH_VERSION_1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 err = touch_pad_init(); if (err != ESP_OK) { goto err; @@ -143,8 +143,8 @@ static void __touchInit() { if (err != ESP_OK) { goto err; } - touch_pad_intr_enable(); // returns ESP_OK -#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 + touch_pad_intr_enable(); // returns ESP_OK +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 err = touch_pad_init(); if (err != ESP_OK) { goto err; @@ -179,11 +179,11 @@ static void __touchChannelInit(int pad) { return; } -#if SOC_TOUCH_VERSION_1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 // Initial no Threshold and setup __touchInterruptHandlers[pad].fn = NULL; - touch_pad_config(pad, SOC_TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK -#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 + touch_pad_config(pad, TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 // Initial no Threshold and setup __touchInterruptHandlers[pad].fn = NULL; touch_pad_config(pad); // returns ESP_OK @@ -238,7 +238,7 @@ static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Ar if (userFunc == NULL) { // detach ISR User Call __touchInterruptHandlers[pad].fn = NULL; - threshold = SOC_TOUCH_PAD_THRESHOLD_MAX; // deactivate the ISR with SOC_TOUCH_PAD_THRESHOLD_MAX + threshold = TOUCH_PAD_THRESHOLD_MAX; // deactivate the ISR with SOC_TOUCH_PAD_THRESHOLD_MAX } else { // attach ISR User Call __touchInit(); @@ -270,7 +270,7 @@ static void __touchDettachInterrupt(uint8_t pin) { External Public Touch API Functions */ -#if SOC_TOUCH_VERSION_1 // Only for ESP32 SoC +#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC void touchInterruptSetThresholdDirection(bool mustbeLower) { if (mustbeLower) { touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW); @@ -278,7 +278,7 @@ void touchInterruptSetThresholdDirection(bool mustbeLower) { touch_pad_set_trigger_mode(TOUCH_TRIGGER_ABOVE); } } -#elif SOC_TOUCH_VERSION_2 // Only for ESP32S2 and ESP32S3 +#elif SOC_TOUCH_SENSOR_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); @@ -307,10 +307,10 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold) { return; } } -#if SOC_TOUCH_VERSION_1 // Only for ESP32 SoC +#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC touch_pad_set_thresh(pad, threshold); -#elif SOC_TOUCH_VERSION_2 +#elif SOC_TOUCH_SENSOR_VERSION == 2 touch_pad_sleep_channel_enable(pad, true); touch_pad_sleep_set_threshold(pad, threshold); diff --git a/cores/esp32/esp32-hal-touch.h b/cores/esp32/esp32-hal-touch.h index db33ce3bc6a..115d6cdc9cf 100644 --- a/cores/esp32/esp32-hal-touch.h +++ b/cores/esp32/esp32-hal-touch.h @@ -29,13 +29,13 @@ extern "C" { #include "esp32-hal.h" -#if !defined(SOC_TOUCH_VERSION_1) && !defined(SOC_TOUCH_VERSION_2) +#if !SOC_TOUCH_SENSOR_SUPPORTED #error Touch IDF driver Not supported! #endif -#if SOC_TOUCH_VERSION_1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 typedef uint16_t touch_value_t; -#elif SOC_TOUCH_VERSION_2 // ESP32S2 ESP32S3 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2 ESP32S3 typedef uint32_t touch_value_t; #endif @@ -71,7 +71,7 @@ void touchDetachInterrupt(uint8_t pin); * Default if Lower. **/ -#if SOC_TOUCH_VERSION_1 // Only for ESP32 SoC +#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC void touchInterruptSetThresholdDirection(bool mustbeLower); #endif @@ -83,7 +83,7 @@ void touchInterruptSetThresholdDirection(bool mustbeLower); * as soon as the touchpad is touched and/or released **/ -#if SOC_TOUCH_VERSION_2 // Only for ESP32S2 and ESP32S3 +#if SOC_TOUCH_SENSOR_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 diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index 7608502d0f8..e4432f5110f 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -61,10 +61,10 @@ struct uart_struct_t { static uart_t _uart_bus_array[] = { {0, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 {1, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, #endif -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 {2, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, #endif }; @@ -81,10 +81,10 @@ static uart_t _uart_bus_array[] = { static uart_t _uart_bus_array[] = { {NULL, 0, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 {NULL, 1, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, #endif -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 {NULL, 2, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, #endif }; @@ -94,8 +94,8 @@ static uart_t _uart_bus_array[] = { // Negative Pin Number will keep it unmodified, thus this function can detach individual pins // This function will also unset the pins in the Peripheral Manager and set the pin to -1 after detaching static bool _uartDetachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) { - if (uart_num >= SOC_UART_NUM) { - log_e("Serial number is invalid, please use number from 0 to %u", SOC_UART_NUM - 1); + if (uart_num >= SOC_UART_HP_NUM) { + log_e("Serial number is invalid, please use number from 0 to %u", SOC_UART_HP_NUM - 1); return false; } // get UART information @@ -181,8 +181,8 @@ static bool _uartDetachBus_RTS(void *busptr) { // Attach function for UART // connects the IO Pad, set Paripheral Manager and internal UART structure data static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) { - if (uart_num >= SOC_UART_NUM) { - log_e("Serial number is invalid, please use number from 0 to %u", SOC_UART_NUM - 1); + if (uart_num >= SOC_UART_HP_NUM) { + log_e("Serial number is invalid, please use number from 0 to %u", SOC_UART_HP_NUM - 1); return false; } // get UART information @@ -308,8 +308,8 @@ bool uartIsDriverInstalled(uart_t *uart) { // Negative Pin Number will keep it unmodified, thus this function can set individual pins // When pins are changed, it will detach the previous one bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) { - if (uart_num >= SOC_UART_NUM) { - log_e("Serial number is invalid, please use number from 0 to %u", SOC_UART_NUM - 1); + if (uart_num >= SOC_UART_HP_NUM) { + log_e("Serial number is invalid, please use number from 0 to %u", SOC_UART_HP_NUM - 1); return false; } // get UART information @@ -378,7 +378,7 @@ bool _testUartBegin( uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint32_t rx_buffer_size, uint32_t tx_buffer_size, bool inverted, uint8_t rxfifo_full_thrhd ) { - if (uart_nr >= SOC_UART_NUM) { + if (uart_nr >= SOC_UART_HP_NUM) { return false; // no new driver has to be installed } uart_t *uart = &_uart_bus_array[uart_nr]; @@ -400,8 +400,8 @@ uart_t *uartBegin( uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint32_t rx_buffer_size, uint32_t tx_buffer_size, bool inverted, uint8_t rxfifo_full_thrhd ) { - if (uart_nr >= SOC_UART_NUM) { - log_e("UART number is invalid, please use number from 0 to %u", SOC_UART_NUM - 1); + if (uart_nr >= SOC_UART_HP_NUM) { + log_e("UART number is invalid, please use number from 0 to %u", SOC_UART_HP_NUM - 1); return NULL; // no new driver was installed } uart_t *uart = &_uart_bus_array[uart_nr]; @@ -604,8 +604,8 @@ bool uartSetRxFIFOFull(uart_t *uart, uint8_t numBytesFIFOFull) { } void uartEnd(uint8_t uart_num) { - if (uart_num >= SOC_UART_NUM) { - log_e("Serial number is invalid, please use number from 0 to %u", SOC_UART_NUM - 1); + if (uart_num >= SOC_UART_HP_NUM) { + log_e("Serial number is invalid, please use number from 0 to %u", SOC_UART_HP_NUM - 1); return; } // get UART information @@ -819,14 +819,14 @@ static void ARDUINO_ISR_ATTR uart0_write_char(char c) { uart_ll_write_txfifo(&UART0, (const uint8_t *)&c, 1); } -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 static void ARDUINO_ISR_ATTR uart1_write_char(char c) { while (uart_ll_get_txfifo_len(&UART1) == 0); uart_ll_write_txfifo(&UART1, (const uint8_t *)&c, 1); } #endif -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 static void ARDUINO_ISR_ATTR uart2_write_char(char c) { while (uart_ll_get_txfifo_len(&UART2) == 0); uart_ll_write_txfifo(&UART2, (const uint8_t *)&c, 1); @@ -836,10 +836,10 @@ static void ARDUINO_ISR_ATTR uart2_write_char(char c) { void uart_install_putc() { switch (s_uart_debug_nr) { case 0: ets_install_putc1((void (*)(char)) & uart0_write_char); break; -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 case 1: ets_install_putc1((void (*)(char)) & uart1_write_char); break; #endif -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 case 2: ets_install_putc1((void (*)(char)) & uart2_write_char); break; #endif default: ets_install_putc1(NULL); break; @@ -850,7 +850,7 @@ void uart_install_putc() { // Routines that take care of UART mode in the HardwareSerial Class code // used to set UART_MODE_RS485_HALF_DUPLEX auto RTS for TXD for ESP32 chips bool uartSetMode(uart_t *uart, uart_mode_t mode) { - if (uart == NULL || uart->num >= SOC_UART_NUM) { + if (uart == NULL || uart->num >= SOC_UART_HP_NUM) { return false; } @@ -861,7 +861,7 @@ bool uartSetMode(uart_t *uart, uart_mode_t mode) { } void uartSetDebug(uart_t *uart) { - if (uart == NULL || uart->num >= SOC_UART_NUM) { + if (uart == NULL || uart->num >= SOC_UART_HP_NUM) { s_uart_debug_nr = -1; } else { s_uart_debug_nr = uart->num; @@ -1103,7 +1103,7 @@ unsigned long uartDetectBaudrate(uart_t *uart) { */ // gets the right TX or RX SIGNAL, based on the UART number from gpio_sig_map.h -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 #define UART_TX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0TXD_OUT_IDX : (uartNumber == UART_NUM_1 ? U1TXD_OUT_IDX : U2TXD_OUT_IDX)) #define UART_RX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0RXD_IN_IDX : (uartNumber == UART_NUM_1 ? U1RXD_IN_IDX : U2RXD_IN_IDX)) #else @@ -1115,7 +1115,7 @@ unsigned long uartDetectBaudrate(uart_t *uart) { This creates a loop that lets us receive anything we send on the UART without external wires. */ void uart_internal_loopback(uint8_t uartNum, int8_t rxPin) { - if (uartNum > SOC_UART_NUM - 1 || !GPIO_IS_VALID_GPIO(rxPin)) { + if (uartNum > SOC_UART_HP_NUM - 1 || !GPIO_IS_VALID_GPIO(rxPin)) { return; } esp_rom_gpio_connect_out_signal(rxPin, UART_TX_SIGNAL(uartNum), false, false); diff --git a/idf_component.yml b/idf_component.yml index 2f74301ea10..e6831d71b44 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -42,7 +42,7 @@ files: - "platform.txt" - "programmers.txt" dependencies: - idf: ">=5.1,<5.2" + idf: ">=5.3,<5.4" # mdns 1.2.1 is necessary to build H2 with no WiFi espressif/mdns: version: "^1.2.3" diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/SerialToSerialBT_Legacy.ino b/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/SerialToSerialBT_Legacy.ino index 343bd79c79b..d184a4ea769 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/SerialToSerialBT_Legacy.ino +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/SerialToSerialBT_Legacy.ino @@ -17,12 +17,6 @@ #error Serial Port Profile for Bluetooth is not available or not enabled. It is only available for the ESP32 chip. #endif -// Check Simple Secure Pairing -#if defined(CONFIG_BT_SSP_ENABLED) -#warning Legacy Pairing is disabled (CONFIG_BT_SSP_ENABLED is enabled. Disable it in menuconfig). -void setup() {} -void loop() {} -#else const char *deviceName = "ESP32_Legacy_example"; BluetoothSerial SerialBT; @@ -62,4 +56,3 @@ void loop() { delay(1); // Feed the watchdog } } -#endif diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/SerialToSerialBT_SSP.ino b/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/SerialToSerialBT_SSP.ino index eb0c05e0038..e5d05eed14e 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/SerialToSerialBT_SSP.ino +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/SerialToSerialBT_SSP.ino @@ -22,11 +22,6 @@ #error Serial Port Profile for Bluetooth is not available or not enabled. It is only available for the ESP32 chip. #endif -// Check Simple Secure Pairing -#if !defined(CONFIG_BT_SSP_ENABLED) -#error Simple Secure Pairing for Bluetooth is not available or not enabled. -#endif - const char *deviceName = "ESP32_SSP_example"; // The following lines defines the method of pairing diff --git a/libraries/BluetoothSerial/src/BluetoothSerial.cpp b/libraries/BluetoothSerial/src/BluetoothSerial.cpp index bcb94db910f..12c09d68305 100644 --- a/libraries/BluetoothSerial/src/BluetoothSerial.cpp +++ b/libraries/BluetoothSerial/src/BluetoothSerial.cpp @@ -71,11 +71,9 @@ static esp_bd_addr_t _peer_bd_addr; static char _remote_name[ESP_BT_GAP_MAX_BDNAME_LEN + 1]; static bool _isRemoteAddressSet; static bool _isMaster; -#ifdef CONFIG_BT_SSP_ENABLED static bool _enableSSP; static bool _IO_CAP_INPUT; static bool _IO_CAP_OUTPUT; -#endif esp_bt_pin_code_t _pin_code = {0}; uint8_t _pin_code_len = 0; // Number of valid Bytes in the esp_bt_pin_code_t array static esp_spp_sec_t _sec_mask; @@ -538,7 +536,6 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa esp_bt_gap_pin_reply(param->pin_req.bda, true, _pin_code_len, _pin_code); } break; -#ifdef CONFIG_BT_SSP_ENABLED case ESP_BT_GAP_CFM_REQ_EVT: // Enum 6 - Security Simple Pairing User Confirmation request. log_i("ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val); if (confirm_request_callback) { @@ -549,13 +546,10 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, false); } break; -#endif case ESP_BT_GAP_KEY_NOTIF_EVT: // Enum 7 - Security Simple Pairing Passkey Notification log_i("ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey); break; - -#ifdef CONFIG_BT_SSP_ENABLED case ESP_BT_GAP_KEY_REQ_EVT: // Enum 8 - Security Simple Pairing Passkey request log_i("ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!"); if (key_request_callback) { @@ -566,7 +560,6 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, false); } break; -#endif case ESP_BT_GAP_READ_RSSI_DELTA_EVT: // Enum 9 - Read rssi event log_i("ESP_BT_GAP_READ_RSSI_DELTA_EVT Read rssi event"); @@ -707,7 +700,6 @@ static bool _init_bt(const char *deviceName, bt_mode mode) { log_i("device name set"); esp_bt_dev_set_device_name(deviceName); -#ifdef CONFIG_BT_SSP_ENABLED if (_enableSSP) { log_i("Simple Secure Pairing"); esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; @@ -723,7 +715,6 @@ static bool _init_bt(const char *deviceName, bt_mode mode) { } esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t)); } -#endif // the default BTA_DM_COD_LOUDSPEAKER does not work with the macOS BT stack esp_bt_cod_t cod; @@ -894,7 +885,6 @@ void BluetoothSerial::memrelease() { esp_bt_mem_release(ESP_BT_MODE_BTDM); } -#ifdef CONFIG_BT_SSP_ENABLED void BluetoothSerial::onConfirmRequest(ConfirmRequestCb cb) { confirm_request_callback = cb; } @@ -906,7 +896,6 @@ void BluetoothSerial::onKeyRequest(KeyRequestCb cb) { void BluetoothSerial::respondPasskey(uint32_t passkey) { esp_bt_gap_ssp_passkey_reply(current_bd_addr, true, passkey); } -#endif void BluetoothSerial::onAuthComplete(AuthCompleteCb cb) { auth_complete_callback = cb; @@ -921,7 +910,6 @@ esp_err_t BluetoothSerial::register_callback(esp_spp_cb_t callback) { return ESP_OK; } -#ifdef CONFIG_BT_SSP_ENABLED // Enable Simple Secure Pairing (using generated PIN) // This must be called before calling begin, otherwise has no effect! void BluetoothSerial::enableSSP() { @@ -957,8 +945,6 @@ void BluetoothSerial::disableSSP() { _enableSSP = false; } -#else - bool BluetoothSerial::setPin(const char *pin, uint8_t pin_code_len) { if (pin_code_len == 0 || pin_code_len > 16) { log_e("PIN code must be 1-16 Bytes long! Called with length %d", pin_code_len); @@ -968,7 +954,6 @@ bool BluetoothSerial::setPin(const char *pin, uint8_t pin_code_len) { memcpy(_pin_code, pin, pin_code_len); return (esp_bt_gap_set_pin(ESP_BT_PIN_TYPE_FIXED, _pin_code_len, _pin_code) == ESP_OK); } -#endif bool BluetoothSerial::connect(String remoteName) { bool retval = false; diff --git a/libraries/BluetoothSerial/src/BluetoothSerial.h b/libraries/BluetoothSerial/src/BluetoothSerial.h index 6b7ba419e00..d59fbf1f714 100644 --- a/libraries/BluetoothSerial/src/BluetoothSerial.h +++ b/libraries/BluetoothSerial/src/BluetoothSerial.h @@ -56,21 +56,16 @@ class BluetoothSerial : public Stream { void onData(BluetoothSerialDataCb cb); esp_err_t register_callback(esp_spp_cb_t callback); -#ifdef CONFIG_BT_SSP_ENABLED void onConfirmRequest(ConfirmRequestCb cb); void onKeyRequest(KeyRequestCb cb); void respondPasskey(uint32_t passkey); -#endif void onAuthComplete(AuthCompleteCb cb); void confirmReply(boolean confirm); -#ifdef CONFIG_BT_SSP_ENABLED void enableSSP(); void enableSSP(bool inputCapability, bool outputCapability); void disableSSP(); -#else bool setPin(const char *pin, uint8_t pin_code_len); -#endif bool connect(String remoteName); bool connect( uint8_t remoteAddress[], int channel = 0, esp_spp_sec_t sec_mask = (ESP_SPP_SEC_ENCRYPT | ESP_SPP_SEC_AUTHENTICATE), diff --git a/libraries/ESP32/examples/Serial/Serial_STD_Func_OnReceive/Serial_STD_Func_OnReceive.ino b/libraries/ESP32/examples/Serial/Serial_STD_Func_OnReceive/Serial_STD_Func_OnReceive.ino index eff21a1939e..3c5ff0ba6fc 100644 --- a/libraries/ESP32/examples/Serial/Serial_STD_Func_OnReceive/Serial_STD_Func_OnReceive.ino +++ b/libraries/ESP32/examples/Serial/Serial_STD_Func_OnReceive/Serial_STD_Func_OnReceive.ino @@ -11,7 +11,7 @@ */ // soc/soc_caps.h has information about each SoC target -// in this example, we use SOC_UART_NUM that goes from 1 to 3, +// in this example, we use SOC_UART_HP_NUM that goes from 1 to 3, // depending on the number of available UARTs in the ESP32xx // This makes the code transparent to what SoC is used. #include "soc/soc_caps.h" @@ -24,9 +24,9 @@ #define TXPIN 5 // GPIO 5 => TX for Serial1 or Serial2 // declare testingSerial (as reference) related to TEST_UART number defined above (only for Serial1 and Serial2) -#if SOC_UART_NUM > 1 && TEST_UART == 1 +#if SOC_UART_HP_NUM > 1 && TEST_UART == 1 HardwareSerial &testingSerial = Serial1; -#elif SOC_UART_NUM > 2 && TEST_UART == 2 +#elif SOC_UART_HP_NUM > 2 && TEST_UART == 2 HardwareSerial &testingSerial = Serial2; #endif @@ -36,11 +36,11 @@ void processOnReceiving(HardwareSerial &mySerial) { int8_t uart_num = -1; if (&mySerial == &Serial0) { uart_num = 0; -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 } else if (&mySerial == &Serial1) { uart_num = 1; #endif -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 } else if (&mySerial == &Serial2) { uart_num = 2; #endif diff --git a/libraries/ESP_I2S/src/ESP_I2S.cpp b/libraries/ESP_I2S/src/ESP_I2S.cpp index 84050dfa6f8..50f76b41a3f 100644 --- a/libraries/ESP_I2S/src/ESP_I2S.cpp +++ b/libraries/ESP_I2S/src/ESP_I2S.cpp @@ -819,7 +819,7 @@ size_t I2SClass::readBytes(char *buffer, size_t size) { return total_size; } -size_t I2SClass::write(uint8_t *buffer, size_t size) { +size_t I2SClass::write(const uint8_t *buffer, size_t size) { size_t written = 0; size_t bytes_sent = 0; last_error = ESP_FAIL; diff --git a/libraries/ESP_I2S/src/ESP_I2S.h b/libraries/ESP_I2S/src/ESP_I2S.h index c83e3815ddb..60ccf0d4265 100644 --- a/libraries/ESP_I2S/src/ESP_I2S.h +++ b/libraries/ESP_I2S/src/ESP_I2S.h @@ -62,7 +62,7 @@ class I2SClass : public Stream { bool end(); size_t readBytes(char *buffer, size_t size); - size_t write(uint8_t *buffer, size_t size); + size_t write(const uint8_t *buffer, size_t size); i2s_chan_handle_t txChan(); uint32_t txSampleRate(); diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 4d215d80034..48e8460fe2d 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -170,6 +170,11 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i Network.begin(); _ethernets[_eth_index] = this; +#if CONFIG_IDF_TARGET_ESP32 +#undef DEFAULT_RMII_CLK_GPIO +#define DEFAULT_RMII_CLK_GPIO (emac_rmii_clock_gpio_t)(CONFIG_ETH_RMII_CLK_IN_GPIO) +#endif + eth_esp32_emac_config_t mac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); mac_config.clock_config.rmii.clock_mode = (clock_mode) ? EMAC_CLK_OUT : EMAC_CLK_EXT_IN; mac_config.clock_config.rmii.clock_gpio = (1 == clock_mode) ? EMAC_APPL_CLK_OUT_GPIO diff --git a/libraries/Insights/examples/DiagnosticsSmokeTest/DiagnosticsSmokeTest.ino b/libraries/Insights/examples/DiagnosticsSmokeTest/DiagnosticsSmokeTest.ino index 2178c9bcd17..485da5b0bc2 100644 --- a/libraries/Insights/examples/DiagnosticsSmokeTest/DiagnosticsSmokeTest.ino +++ b/libraries/Insights/examples/DiagnosticsSmokeTest/DiagnosticsSmokeTest.ino @@ -36,7 +36,8 @@ static void smoke_test() { Insights.event(TAG, "[count][%d]", count); } else { log_e("[count][%d] [crash_count][%" PRIu32 "] [excvaddr][0x0f] Crashing...", count, s_reset_count); - *(int *)0x0F = 0x10; + //ToDo: find better way to crash + //*(int *)0x0F = 0x10; } } diff --git a/libraries/Network/src/NetworkClient.h b/libraries/Network/src/NetworkClient.h index 572292a7a99..7f37e0ff6e1 100644 --- a/libraries/Network/src/NetworkClient.h +++ b/libraries/Network/src/NetworkClient.h @@ -28,8 +28,6 @@ class NetworkClientRxBuffer; class ESPLwIPClient : public Client { public: - virtual int connect(IPAddress ip, uint16_t port, int32_t timeout) = 0; - virtual int connect(const char *host, uint16_t port, int32_t timeout) = 0; virtual void setConnectionTimeout(uint32_t milliseconds) = 0; }; diff --git a/libraries/PPP/src/PPP.cpp b/libraries/PPP/src/PPP.cpp index 8c25fe6aad5..bef283671da 100644 --- a/libraries/PPP/src/PPP.cpp +++ b/libraries/PPP/src/PPP.cpp @@ -279,7 +279,7 @@ bool PPPClass::begin(ppp_modem_model_t model, uint8_t uart_num, int baud_rate) { dte_config.uart_config.flow_control = _flow_ctrl; dte_config.uart_config.rx_buffer_size = _rx_buffer_size; dte_config.uart_config.tx_buffer_size = _tx_buffer_size; - dte_config.uart_config.port_num = _uart_num; + dte_config.uart_config.port_num = (uart_port_t)_uart_num; dte_config.uart_config.baud_rate = baud_rate; /* Configure the DCE */ diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 9f612b34646..8c585fa86ed 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -42,42 +42,32 @@ { "packager": "esp32", "name": "esp32-arduino-libs", - "version": "idf-release_v5.1-c608177cf9" + "version": "idf-release_v5.3-466a392a" }, { "packager": "esp32", - "name": "xtensa-esp32-elf-gcc", - "version": "esp-12.2.0_20230208" - }, - { - "packager": "esp32", - "name": "xtensa-esp32s2-elf-gcc", - "version": "esp-12.2.0_20230208" - }, - { - "packager": "esp32", - "name": "xtensa-esp32s3-elf-gcc", - "version": "esp-12.2.0_20230208" + "name": "xtensa-esp-elf-gcc", + "version": "esp-13.2.0_20240530" }, { "packager": "esp32", "name": "xtensa-esp-elf-gdb", - "version": "12.1_20231023" + "version": "14.2_20240403" }, { "packager": "esp32", "name": "riscv32-esp-elf-gcc", - "version": "esp-12.2.0_20230208" + "version": "esp-13.2.0_20240530" }, { "packager": "esp32", "name": "riscv32-esp-elf-gdb", - "version": "12.1_20231023" + "version": "14.2_20240403" }, { "packager": "esp32", "name": "openocd-esp32", - "version": "v0.12.0-esp32-20240726" + "version": "v0.12.0-esp32-20240318" }, { "packager": "esp32", @@ -105,490 +95,366 @@ "tools": [ { "name": "esp32-arduino-libs", - "version": "idf-release_v5.1-c608177cf9", + "version": "idf-release_v5.3-466a392a", "systems": [ { "host": "i686-mingw32", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/7b015a59844d511b72663a266e5793fb98eecaa1", - "archiveFileName": "esp32-arduino-libs-7b015a59844d511b72663a266e5793fb98eecaa1.zip", - "checksum": "SHA-256:392c411dc6b8253a3d067fda6c41a3f67ade2f99259a1a707630568e8f80f055", - "size": "310235817" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", + "size": "318864212" }, { "host": "x86_64-mingw32", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/7b015a59844d511b72663a266e5793fb98eecaa1", - "archiveFileName": "esp32-arduino-libs-7b015a59844d511b72663a266e5793fb98eecaa1.zip", - "checksum": "SHA-256:392c411dc6b8253a3d067fda6c41a3f67ade2f99259a1a707630568e8f80f055", - "size": "310235817" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", + "size": "318864212" }, { "host": "arm64-apple-darwin", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/7b015a59844d511b72663a266e5793fb98eecaa1", - "archiveFileName": "esp32-arduino-libs-7b015a59844d511b72663a266e5793fb98eecaa1.zip", - "checksum": "SHA-256:392c411dc6b8253a3d067fda6c41a3f67ade2f99259a1a707630568e8f80f055", - "size": "310235817" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", + "size": "318864212" }, { "host": "x86_64-apple-darwin", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/7b015a59844d511b72663a266e5793fb98eecaa1", - "archiveFileName": "esp32-arduino-libs-7b015a59844d511b72663a266e5793fb98eecaa1.zip", - "checksum": "SHA-256:392c411dc6b8253a3d067fda6c41a3f67ade2f99259a1a707630568e8f80f055", - "size": "310235817" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", + "size": "318864212" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/7b015a59844d511b72663a266e5793fb98eecaa1", - "archiveFileName": "esp32-arduino-libs-7b015a59844d511b72663a266e5793fb98eecaa1.zip", - "checksum": "SHA-256:392c411dc6b8253a3d067fda6c41a3f67ade2f99259a1a707630568e8f80f055", - "size": "310235817" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", + "size": "318864212" }, { "host": "i686-pc-linux-gnu", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/7b015a59844d511b72663a266e5793fb98eecaa1", - "archiveFileName": "esp32-arduino-libs-7b015a59844d511b72663a266e5793fb98eecaa1.zip", - "checksum": "SHA-256:392c411dc6b8253a3d067fda6c41a3f67ade2f99259a1a707630568e8f80f055", - "size": "310235817" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/7b015a59844d511b72663a266e5793fb98eecaa1", - "archiveFileName": "esp32-arduino-libs-7b015a59844d511b72663a266e5793fb98eecaa1.zip", - "checksum": "SHA-256:392c411dc6b8253a3d067fda6c41a3f67ade2f99259a1a707630568e8f80f055", - "size": "310235817" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/7b015a59844d511b72663a266e5793fb98eecaa1", - "archiveFileName": "esp32-arduino-libs-7b015a59844d511b72663a266e5793fb98eecaa1.zip", - "checksum": "SHA-256:392c411dc6b8253a3d067fda6c41a3f67ade2f99259a1a707630568e8f80f055", - "size": "310235817" - } - ] - }, - { - "name": "xtensa-esp32-elf-gcc", - "version": "esp-12.2.0_20230208", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:e8d35938385447cf9c34735fee2a3b2b61cca6be07db77a45856a1c2a347e423", - "size": "111766903" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:569988acfc2673369f222037c64bac96990cee08cebeebc4f8860e0d984f8bd9", - "size": "106473247" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:6a844f16021e936cc9b87b203978356f57ab2144554f6f2a0f73ffa3d3d316c5", - "size": "105576049" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "checksum": "SHA-256:743d6f03a89329bb09f9550d27fcab677f5cf06b4720793bbcef7883a932681d", - "size": "114870843" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "checksum": "SHA-256:4d32d764e984f3a570aacfb2f4957619540fb4629534d969b2e83997901334c3", - "size": "119424029" - }, - { - "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "checksum": "SHA-256:dc8fa7f4933bf5cb08e83bacce6160cc9dfe93d7aad1e8f92599bb81ff5b2e28", - "size": "106136827" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "checksum": "SHA-256:62bb6428d107ed3f44c212c77ecf24804b74c97327b0f0ad2029c656c6dbd6ee", - "size": "130847086" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:8febfe4a6476efc69012390106c8c660a14418f025137b0513670c72124339cf", - "size": "134985117" - } - ] - }, - { - "name": "xtensa-esp32s2-elf-gcc", - "version": "esp-12.2.0_20230208", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:2ff838520a5003d2768b275f5bb5ead69dd2388c3b7cd9043cb59891ba43147f", - "size": "112199211" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", + "size": "318864212" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:6d79d5b14fc7129a9b8208d54e19b05dedb565f50f7a96264c9df84b06ad3be0", - "size": "106953064" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", + "size": "318864212" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:e5bd03b6ad19179b015a93ada9992adc3610036ebf6aeb0835a09c9aadb50a14", - "size": "106026829" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "checksum": "SHA-256:fb45943557b2d201bbb1bdc7514a1872f9bb96c2dfb48b95abdba281cc792f75", - "size": "115288662" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "checksum": "SHA-256:e965236cb80e45282d16f40184af183e013b63b177bd1884736c463eac636564", - "size": "119711811" - }, - { - "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "checksum": "SHA-256:78a55eec18650b21378d97494989ffe208748e0f49bb2b2d6756b264e1863919", - "size": "106540817" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "checksum": "SHA-256:1e6dac5162ab75f94b88c47ebeabb6600c652fb4f615ed07c1724d037c02fd19", - "size": "131273859" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:8a785cc4e0838cebe404f82c0ead7a0f9ac5fabc660a742e33a41ddac6326cc1", - "size": "135373049" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", + "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", + "size": "318864212" } ] }, { - "name": "xtensa-esp32s3-elf-gcc", - "version": "esp-12.2.0_20230208", + "name": "xtensa-esp-elf-gcc", + "version": "esp-13.2.0_20240530", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:61495ffe575e00c6998ae7274ff917658c04bded62ece0937c7042d6dcbf46de", - "size": "111971129" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/xtensa-esp-elf-13.2.0_20240530-x86_64-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-13.2.0_20240530-x86_64-linux-gnu.tar.gz", + "checksum": "SHA-256:bce77e8480701d5a90545369d1b5848f6048eb39c0022d2446d1e33a8e127490", + "size": "208911713" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:9008d395be46fcfe68c7de6edc850fc1595f28323a28e7922e5c085bd310cb90", - "size": "106616800" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/xtensa-esp-elf-13.2.0_20240530-aarch64-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-13.2.0_20240530-aarch64-linux-gnu.tar.gz", + "checksum": "SHA-256:7c9e3c1adc733d042ed87b92daa1d6396e1b441c1755f1fa14cb88855719ba88", + "size": "202519931" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:568857bdac7dea389dffc7fbc6871b4af299150a8ecf1bf965f224d2a1655edb", - "size": "105700326" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/xtensa-esp-elf-13.2.0_20240530-arm-linux-gnueabi.tar.gz", + "archiveFileName": "xtensa-esp-elf-13.2.0_20240530-arm-linux-gnueabi.tar.gz", + "checksum": "SHA-256:d6955e8ea6af91574bf9213b92f32ca09eb8640103446b7fa19a63cfeeec5421", + "size": "202206516" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "checksum": "SHA-256:d122738bcc6c2f52d05fa89b2fb1afe6a7894cda8a07a1879aca867a31507ed0", - "size": "115098400" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/xtensa-esp-elf-13.2.0_20240530-i586-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-13.2.0_20240530-i586-linux-gnu.tar.gz", + "checksum": "SHA-256:3666ee74ecb693ee6488f11469802630a7b0d32608184045a4f35cb413f59e3d", + "size": "213304863" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "checksum": "SHA-256:7defcddb98788b0991416ad2e0cb6a3b248b8030f22d5d76b8832117cc1494ca", - "size": "119883189" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/xtensa-esp-elf-13.2.0_20240530-x86_64-apple-darwin.tar.gz", + "archiveFileName": "xtensa-esp-elf-13.2.0_20240530-x86_64-apple-darwin.tar.gz", + "checksum": "SHA-256:948cf57b6eecc898b5f70e06ad08ba88c08b627be570ec631dfcd72f6295194a", + "size": "221357024" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "checksum": "SHA-256:b59e076f8e4b9ca99535d449f9fc4cbb443188051dce4ad934e38f16b095f8d9", - "size": "106464677" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/xtensa-esp-elf-13.2.0_20240530-aarch64-apple-darwin.tar.gz", + "archiveFileName": "xtensa-esp-elf-13.2.0_20240530-aarch64-apple-darwin.tar.gz", + "checksum": "SHA-256:6f03fdf0cc14a7f3900ee59977f62e8626d8b7c208506e52f1fd883ac223427a", + "size": "199689745" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "checksum": "SHA-256:3ddf51774817e815e5d41c312a90c1159226978fb45fd0d4f7085c567f8b73ab", - "size": "131134034" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/xtensa-esp-elf-13.2.0_20240530-i686-w64-mingw32_hotfix.zip", + "archiveFileName": "xtensa-esp-elf-13.2.0_20240530-i686-w64-mingw32_hotfix.zip", + "checksum": "SHA-256:d6b227c50e3c8e21d62502b3140e5ab74a4cb502c2b4169c36238b9858a8fb88", + "size": "266042967" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:1d15ca65e3508388a86d8bed3048c46d07538f5bc88d3e4296f9c03152087cd1", - "size": "135381926" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/xtensa-esp-elf-13.2.0_20240530-x86_64-w64-mingw32_hotfix.zip", + "archiveFileName": "xtensa-esp-elf-13.2.0_20240530-x86_64-w64-mingw32_hotfix.zip", + "checksum": "SHA-256:155ee97b531236e6a7c763395c68ca793e55e74d2cb4d38a23057a153e01e7d0", + "size": "269831985" } ] }, { "name": "xtensa-esp-elf-gdb", - "version": "12.1_20231023", + "version": "14.2_20240403", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-x86_64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:d0743ec43cd92c35452a9097f7863281de4e72f04120d63cfbcf9d591a373529", - "size": "36942094" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-x86_64-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-x86_64-linux-gnu.tar.gz", + "checksum": "SHA-256:9d68472d4cba5cf8c2b79d94f86f92c828e76a632bd1e6be5e7706e5b304d36e", + "size": "31010320" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-aarch64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:bc1fac0366c6a08e26c45896ca21c8c90efc2cdd431b8ba084e8772e15502d0e", - "size": "37134601" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-aarch64-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-aarch64-linux-gnu.tar.gz", + "checksum": "SHA-256:bdabc3217994815fc311c4e16e588b78f6596b5ad4ffa46c80b40e982cfb1e66", + "size": "30954580" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-arm-linux-gnueabi.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:25efc51d52b71f097ccec763c5c885c8f5026b432fec4b5badd6a5f36fe34d04", - "size": "34579556" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-arm-linux-gnueabi.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-arm-linux-gnueabi.tar.gz", + "checksum": "SHA-256:d54b8d703ba897b28c627da3d27106a3906dd01ba298778a67064710bc33c76d", + "size": "28697281" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-i586-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-i586-linux-gnu.tar.gz", - "checksum": "SHA-256:e0af0b3b4a6b29a843cd5f47e331a966d9258f7d825b4656c6251490f71b05b2", - "size": "35676578" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-i586-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-i586-linux-gnu.tar.gz", + "checksum": "SHA-256:64d3bc992ed8fdec383d49e8b803ac494605a38117c8293db8da055037de96b0", + "size": "29890994" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-x86_64-apple-darwin14.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-x86_64-apple-darwin14.tar.gz", - "checksum": "SHA-256:bd146fd99a52b2d71c7ce0f62b9e18f3423d6cae7b2b2c954046b0dd7a23142f", - "size": "52863941" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-x86_64-apple-darwin14.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-x86_64-apple-darwin14.tar.gz", + "checksum": "SHA-256:023e74b3fda793da4bc0509b02de776ee0dad6efaaac17bef5916fb7dc9c26b9", + "size": "44446611" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-aarch64-apple-darwin21.1.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-aarch64-apple-darwin21.1.tar.gz", - "checksum": "SHA-256:5edc76565bf9d2fadf24e443ddf3df7567354f336a65d4af5b2ee805cdfcec24", - "size": "33504923" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-aarch64-apple-darwin21.1.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-aarch64-apple-darwin21.1.tar.gz", + "checksum": "SHA-256:ea757c6bf8c25238f6d2fdcc6bbab25a1b00608a0f9e19b7ddd2f37ddbdc3fb1", + "size": "37021423" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-i686-w64-mingw32.zip", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-i686-w64-mingw32.zip", - "checksum": "SHA-256:ea4f3ee6b95ad1ad2e07108a21a50037a3e64a420cdeb34b2ba95d612faed898", - "size": "31068749" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-i686-w64-mingw32.zip", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-i686-w64-mingw32.zip", + "checksum": "SHA-256:322e8d9b700dc32d8158e3dc55fb85ec55de48d0bb7789375ee39a28d5d655e2", + "size": "26302466" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-x86_64-w64-mingw32.zip", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:13bb97f39173948d1cfb6e651d9b335ea9d52f1fdd0dda1eda3a2d23d8c63644", - "size": "33514906" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-x86_64-w64-mingw32.zip", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-x86_64-w64-mingw32.zip", + "checksum": "SHA-256:a27a2fe20f192f8e0a51b8936428b4e1cf8935cfe008ee445cc49f6fc7f6db2e", + "size": "28366035" } ] }, { "name": "riscv32-esp-elf-gcc", - "version": "esp-12.2.0_20230208", + "version": "esp-13.2.0_20240530", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:1eb0d65990547ee9706b90406600cbc3638814d5feb7c1f7b44bb5416478a5bd", - "size": "257615266" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/riscv32-esp-elf-13.2.0_20240530-x86_64-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-13.2.0_20240530-x86_64-linux-gnu.tar.gz", + "checksum": "SHA-256:e7fbfffbb19dcd3764a9848a141bf44e19ad0b48e0bd1515912345c26fe52fba", + "size": "294346758" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:921fcdc170c7fe5d6a0a30470ed1875c8926d910c19739fc950c8d1836e4c1c5", - "size": "253094184" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/riscv32-esp-elf-13.2.0_20240530-aarch64-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-13.2.0_20240530-aarch64-linux-gnu.tar.gz", + "checksum": "SHA-256:a178a895b807ed2e87d5d62153c36a6aae048581f527c0eb152f0a02b8de9571", + "size": "288374597" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:f66e06312b58251c2121c1b1df1102565708573b86b2a9fe0c03ea1b0e9a7511", - "size": "252558021" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/riscv32-esp-elf-13.2.0_20240530-arm-linux-gnueabi.tar.gz", + "archiveFileName": "riscv32-esp-elf-13.2.0_20240530-arm-linux-gnueabi.tar.gz", + "checksum": "SHA-256:4a2f176d0f5bc8a70645975e2a08ea94145fb69b7225c5cdcbd6024a4836aaf5", + "size": "287737495" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "checksum": "SHA-256:8abcac0331ef8973d1c705e77523364ebec7e98b37640d4a1d036912f3cbe946", - "size": "261248375" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/riscv32-esp-elf-13.2.0_20240530-i586-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-13.2.0_20240530-i586-linux-gnu.tar.gz", + "checksum": "SHA-256:7a6f02f1b2effafb18600bbf602818f6923fd320f000fb8659f34acbfda8812f", + "size": "299138540" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "checksum": "SHA-256:76a334bc75a4e3891c222c84d7968817f2d0699d2976fc2a1658e56395283bec", - "size": "268987133" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/riscv32-esp-elf-13.2.0_20240530-x86_64-apple-darwin.tar.gz", + "archiveFileName": "riscv32-esp-elf-13.2.0_20240530-x86_64-apple-darwin.tar.gz", + "checksum": "SHA-256:a193b4f025d0d836b0a9d9cbe760af1c53e53af66fc332fe98952bc4c456dd9a", + "size": "305025700" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "checksum": "SHA-256:f30571945b257a10a26901bba3c5892e07c192aacf9ed6e8fcd11ca36ed827d2", - "size": "252159713" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/riscv32-esp-elf-13.2.0_20240530-aarch64-apple-darwin.tar.gz", + "archiveFileName": "riscv32-esp-elf-13.2.0_20240530-aarch64-apple-darwin.tar.gz", + "checksum": "SHA-256:7082dd2e2123dea5609a24092d19ac6612ae7e219df1d298de6b2f64cb4af0df", + "size": "285458443" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "checksum": "SHA-256:a5dfbb6dbf6fc6c6ea9beb2723af059ba3c5b2c86c2f0dc3b21afdc7bb229bf5", - "size": "324863847" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/riscv32-esp-elf-13.2.0_20240530-i686-w64-mingw32.zip", + "archiveFileName": "riscv32-esp-elf-13.2.0_20240530-i686-w64-mingw32.zip", + "checksum": "SHA-256:590bfb10576702639825581cc00c445da6e577012840a787137417e80d15f46d", + "size": "366573064" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:9deae9e0013b2f7bbf017f9c8135755bfa89522f337c7dca35872bf12ec08176", - "size": "328092732" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-13.2.0_20240530/riscv32-esp-elf-13.2.0_20240530-x86_64-w64-mingw32.zip", + "archiveFileName": "riscv32-esp-elf-13.2.0_20240530-x86_64-w64-mingw32.zip", + "checksum": "SHA-256:413eb9f6adf8fdaf25544d014c850fc09eb38bb93a2fc5ebd107ab1b0de1bb3a", + "size": "369820297" } ] }, { "name": "riscv32-esp-elf-gdb", - "version": "12.1_20231023", + "version": "14.2_20240403", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-x86_64-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:2c78b806be176b1e449e07ff83429d38dfc39a13f89a127ac1ffa6c1230537a0", - "size": "36630145" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-x86_64-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-x86_64-linux-gnu.tar.gz", + "checksum": "SHA-256:ce004bc0bbd71b246800d2d13b239218b272a38bd528e316f21f1af2db8a4b13", + "size": "30707431" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-aarch64-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:33f80117c8777aaff9179e27953e41764c5c46b3c576dc96a37ecc7a368807ec", - "size": "36980143" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-aarch64-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-aarch64-linux-gnu.tar.gz", + "checksum": "SHA-256:ba10f2866c61410b88c65957274280b1a62e3bed05131654ed9b6758efe18e55", + "size": "30824065" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-arm-linux-gnueabi.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:292e6ec0a9381c1480bbadf5caae25e86428b68fb5d030c9be7deda5e7f070e0", - "size": "34950318" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-arm-linux-gnueabi.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-arm-linux-gnueabi.tar.gz", + "checksum": "SHA-256:88539db5d987f28827efac7e26080a2803b9b539342ccd2963ccfdd56d7f08f7", + "size": "29000575" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-i586-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-i586-linux-gnu.tar.gz", - "checksum": "SHA-256:68a25fbcfc6371ec4dbe503ec92211977eb2006f0c29e67dbce6b93c70c6b7ec", - "size": "35801607" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-i586-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-i586-linux-gnu.tar.gz", + "checksum": "SHA-256:0e628ee37438ab6ba05eb889a76d09e50cb98e0020a16b8e2b935c5cf19b4ed2", + "size": "29947521" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-x86_64-apple-darwin14.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-x86_64-apple-darwin14.tar.gz", - "checksum": "SHA-256:322c722e6c12225ed8cd97f95a0375105756dc5113d369958ce0858ad1a90257", - "size": "52618688" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-x86_64-apple-darwin14.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-x86_64-apple-darwin14.tar.gz", + "checksum": "SHA-256:8f6bda832d70dad5860a639d55aba4237bd10cbac9f4822db1eece97357b34a9", + "size": "44196117" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-aarch64-apple-darwin21.1.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-aarch64-apple-darwin21.1.tar.gz", - "checksum": "SHA-256:c2224b3a8d02451c530cf004c29653292d963a1b4021b4b472b862b6dbe97e0b", - "size": "33149392" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-aarch64-apple-darwin21.1.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-aarch64-apple-darwin21.1.tar.gz", + "checksum": "SHA-256:d88b6116e86456c8480ce9bc95aed375a35c0d091f1da0a53b86be0e6ef3d320", + "size": "36794404" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-i686-w64-mingw32.zip", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-i686-w64-mingw32.zip", - "checksum": "SHA-256:4b42149a99dd87ee7e6dde25c99bad966c7f964253fa8f771593d7cef69f5602", - "size": "31635103" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-i686-w64-mingw32.zip", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-i686-w64-mingw32.zip", + "checksum": "SHA-256:d6e7ce05805b0d8d4dd138ad239b98a1adf8da98941867d60760eb1ae5361730", + "size": "26486295" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-x86_64-w64-mingw32.zip", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:728231546ad5006d34463f972658b2a89e52f660a42abab08a29bedd4a8046ad", - "size": "33400816" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-x86_64-w64-mingw32.zip", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-x86_64-w64-mingw32.zip", + "checksum": "SHA-256:5c9f211dc46daf6b96fad09d709284a0f0186fef8947d9f6edd6bca5b5ad4317", + "size": "27942579" } ] }, { "name": "openocd-esp32", - "version": "v0.12.0-esp32-20240726", + "version": "v0.12.0-esp32-20240318", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240726/openocd-esp32-linux-amd64-0.12.0-esp32-20240726.tar.gz", - "archiveFileName": "openocd-esp32-linux-amd64-0.12.0-esp32-20240726.tar.gz", - "checksum": "SHA-256:31fabbda5f39262ea4ed8cbba8adedc1d39838f01043cfab95435743c126ac56", - "size": "2368175" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-linux-amd64-0.12.0-esp32-20240318.tar.gz", + "archiveFileName": "openocd-esp32-linux-amd64-0.12.0-esp32-20240318.tar.gz", + "checksum": "SHA-256:cf26c5cef4f6b04aa23cd2778675604e5a74a4ce4d8d17b854d05fbcb782d52c", + "size": "2252682" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240726/openocd-esp32-linux-arm64-0.12.0-esp32-20240726.tar.gz", - "archiveFileName": "openocd-esp32-linux-arm64-0.12.0-esp32-20240726.tar.gz", - "checksum": "SHA-256:05589effadc93440ecca4a8ecc64e78dc94185a4ab72bc54634751dd7b6060d0", - "size": "2239793" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-linux-arm64-0.12.0-esp32-20240318.tar.gz", + "archiveFileName": "openocd-esp32-linux-arm64-0.12.0-esp32-20240318.tar.gz", + "checksum": "SHA-256:9b97a37aa2cab94424a778c25c0b4aa0f90d6ef9cda764a1d9289d061305f4b7", + "size": "2132904" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240726/openocd-esp32-linux-armel-0.12.0-esp32-20240726.tar.gz", - "archiveFileName": "openocd-esp32-linux-armel-0.12.0-esp32-20240726.tar.gz", - "checksum": "SHA-256:25d241fd7467cc5aa8ec3256f2efca27d86bde7cf5577c32f742ad1cc598ad7d", - "size": "2388355" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-linux-armel-0.12.0-esp32-20240318.tar.gz", + "archiveFileName": "openocd-esp32-linux-armel-0.12.0-esp32-20240318.tar.gz", + "checksum": "SHA-256:b7e82776ec374983807d3389df09c632ad9bc8341f2075690b6b500319dfeaf4", + "size": "2271761" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240726/openocd-esp32-macos-0.12.0-esp32-20240726.tar.gz", - "archiveFileName": "openocd-esp32-macos-0.12.0-esp32-20240726.tar.gz", - "checksum": "SHA-256:c3fb8209dd046f83e9fe98b054649020991aea0ac95cf175a41967d446330148", - "size": "2478569" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-macos-0.12.0-esp32-20240318.tar.gz", + "archiveFileName": "openocd-esp32-macos-0.12.0-esp32-20240318.tar.gz", + "checksum": "SHA-256:b16c3082c94df1079367c44d99f7a8605534cd48aabc18898e46e94a2c8c57e7", + "size": "2365588" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240726/openocd-esp32-macos-arm64-0.12.0-esp32-20240726.tar.gz", - "archiveFileName": "openocd-esp32-macos-arm64-0.12.0-esp32-20240726.tar.gz", - "checksum": "SHA-256:45b317f233ae7bf3059a93db925d8794affd393b170ef496da08fa3f2b360ac7", - "size": "2522358" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-macos-arm64-0.12.0-esp32-20240318.tar.gz", + "archiveFileName": "openocd-esp32-macos-arm64-0.12.0-esp32-20240318.tar.gz", + "checksum": "SHA-256:534ec925ae6e35e869e4e4e6e4d2c4a1eb081f97ebcc2dd5efdc52d12f4c2f86", + "size": "2406377" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240726/openocd-esp32-win32-0.12.0-esp32-20240726.zip", - "archiveFileName": "openocd-esp32-win32-0.12.0-esp32-20240726.zip", - "checksum": "SHA-256:9735c9ada83bab1ff2b306f06b96421572fa12d01a751e09e10f243222fd95c4", - "size": "2907592" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-win32-0.12.0-esp32-20240318.zip", + "archiveFileName": "openocd-esp32-win32-0.12.0-esp32-20240318.zip", + "checksum": "SHA-256:d379329eba052435173ab0d69c9b15bc164a6ce489e2a67cd11169d2dabff633", + "size": "2783915" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240726/openocd-esp32-win64-0.12.0-esp32-20240726.zip", - "archiveFileName": "openocd-esp32-win64-0.12.0-esp32-20240726.zip", - "checksum": "SHA-256:139d5ae128ea12023793e8bccdde7dd14383ad38c265cf66c9c6cc7c804e1333", - "size": "2907591" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-win32-0.12.0-esp32-20240318.zip", + "archiveFileName": "openocd-esp32-win32-0.12.0-esp32-20240318.zip", + "checksum": "SHA-256:d379329eba052435173ab0d69c9b15bc164a6ce489e2a67cd11169d2dabff633", + "size": "2783915" } ] }, diff --git a/platform.txt b/platform.txt index f3eb69f0862..57609e5dda3 100644 --- a/platform.txt +++ b/platform.txt @@ -3,9 +3,7 @@ version=3.0.4 tools.esp32-arduino-libs.path={runtime.platform.path}/tools/esp32-arduino-libs tools.esp32-arduino-libs.path.windows={runtime.platform.path}\tools\esp32-arduino-libs -tools.xtensa-esp32-elf-gcc.path={runtime.platform.path}/tools/xtensa-esp32-elf -tools.xtensa-esp32s2-elf-gcc.path={runtime.platform.path}/tools/xtensa-esp32s2-elf -tools.xtensa-esp32s3-elf-gcc.path={runtime.platform.path}/tools/xtensa-esp32s3-elf +tools.xtensa-esp-elf-gcc.path={runtime.platform.path}/tools/xtensa-esp-elf tools.xtensa-esp-elf-gdb.path={runtime.platform.path}/tools/xtensa-esp-elf-gdb tools.riscv32-esp-elf-gcc.path={runtime.platform.path}/tools/riscv32-esp-elf tools.riscv32-esp-elf-gdb.path={runtime.platform.path}/tools/riscv32-esp-elf-gdb @@ -27,7 +25,7 @@ tools.gen_esp32part.cmd.windows="{runtime.platform.path}\tools\gen_esp32part.exe tools.gen_insights_pkg.cmd=python3 "{runtime.platform.path}"/tools/gen_insights_package.py tools.gen_insights_pkg.cmd.windows="{runtime.platform.path}\tools\gen_insights_package.exe" -compiler.path={tools.{build.tarch}-{build.target}-elf-gcc.path}/bin/ +compiler.path={tools.{build.tarch}-esp-elf-gcc.path}/bin/ compiler.prefix={build.tarch}-{build.target}-elf- compiler.sdk.path={tools.esp32-arduino-libs.path}/{build.mcu} diff --git a/tests/validation/uart/uart.ino b/tests/validation/uart/uart.ino index 527d28241d9..a68ef879659 100644 --- a/tests/validation/uart/uart.ino +++ b/tests/validation/uart/uart.ino @@ -46,7 +46,7 @@ * */ -#if SOC_UART_NUM == 2 +#if SOC_UART_HP_NUM == 2 // Used for the pin swap test #define NEW_RX1 9 #define NEW_TX1 10 @@ -64,14 +64,14 @@ extern int8_t uart_get_TxPin(uint8_t uart_num); // This function starts all the available test UARTs void start_serial(unsigned long baudrate = 115200) { -#if SOC_UART_NUM >= 2 +#if SOC_UART_HP_NUM >= 2 Serial1.begin(baudrate); while (!Serial1) { delay(10); } #endif -#if SOC_UART_NUM >= 3 +#if SOC_UART_HP_NUM >= 3 Serial2.begin(baudrate); while (!Serial2) { delay(10); @@ -81,11 +81,11 @@ void start_serial(unsigned long baudrate = 115200) { // This function stops all the available test UARTs void stop_serial(bool hard_stop = false) { -#if SOC_UART_NUM >= 2 +#if SOC_UART_HP_NUM >= 2 Serial1.end(/*hard_stop*/); #endif -#if SOC_UART_NUM >= 3 +#if SOC_UART_HP_NUM >= 3 Serial2.end(/*hard_stop*/); #endif } @@ -93,14 +93,14 @@ void stop_serial(bool hard_stop = false) { // This function transmits a message and checks if it was received correctly void transmit_and_check_msg(const String msg_append, bool perform_assert = true) { delay(100); // Wait for some settings changes to take effect -#if SOC_UART_NUM == 2 +#if SOC_UART_HP_NUM == 2 Serial1.print("Hello from Serial1 (UART1) >>> via loopback >>> Serial1 (UART1) " + msg_append); Serial1.flush(); delay(100); if (perform_assert) { TEST_ASSERT_EQUAL_STRING(("Hello from Serial1 (UART1) >>> via loopback >>> Serial1 (UART1) " + msg_append).c_str(), recv_msg.c_str()); } -#elif SOC_UART_NUM == 3 +#elif SOC_UART_HP_NUM == 3 Serial1.print("Hello from Serial1 (UART1) >>> to >>> Serial2 (UART2) " + msg_append); Serial1.flush(); delay(100); @@ -126,9 +126,9 @@ void transmit_and_check_msg(const String msg_append, bool perform_assert = true) void task_delayed_msg(void *pvParameters) { HardwareSerial *selected_serial; -#if SOC_UART_NUM == 2 +#if SOC_UART_HP_NUM == 2 selected_serial = &Serial; -#elif SOC_UART_NUM == 3 +#elif SOC_UART_HP_NUM == 3 selected_serial = &Serial1; #endif @@ -143,14 +143,14 @@ void task_delayed_msg(void *pvParameters) { // This function is automatically called by unity before each test is run void setUp(void) { start_serial(115200); -#if SOC_UART_NUM == 2 +#if SOC_UART_HP_NUM == 2 log_d("Setup internal loop-back from and back to Serial1 (UART1) TX >> Serial1 (UART1) RX"); Serial1.onReceive([]() { onReceive_cb(Serial1); }); uart_internal_loopback(1, RX1); -#elif SOC_UART_NUM == 3 +#elif SOC_UART_HP_NUM == 3 log_d("Setup internal loop-back between Serial1 (UART1) <<--->> Serial2 (UART2)"); Serial1.onReceive([]() { @@ -180,11 +180,11 @@ void onReceive_cb(HardwareSerial &selected_serial) { if (&selected_serial == &Serial) { uart_num = 0; -#if SOC_UART_NUM >= 2 +#if SOC_UART_HP_NUM >= 2 } else if (&selected_serial == &Serial1) { uart_num = 1; #endif -#if SOC_UART_NUM >= 3 +#if SOC_UART_HP_NUM >= 3 } else if (&selected_serial == &Serial2) { uart_num = 2; #endif @@ -225,7 +225,7 @@ void change_baudrate_test(void) { Serial1.updateBaudRate(9600); TEST_ASSERT_UINT_WITHIN(192, 9600, Serial1.baudRate()); -#if SOC_UART_NUM == 3 +#if SOC_UART_HP_NUM == 3 Serial2.updateBaudRate(9600); TEST_ASSERT_UINT_WITHIN(192, 9600, Serial2.baudRate()); #endif @@ -239,7 +239,7 @@ void change_baudrate_test(void) { //Baudrate error should be within 2% of the target baudrate TEST_ASSERT_UINT_WITHIN(2304, 115200, Serial1.baudRate()); -#if SOC_UART_NUM == 3 +#if SOC_UART_HP_NUM == 3 TEST_ASSERT_UINT_WITHIN(2304, 115200, Serial2.baudRate()); #endif @@ -419,20 +419,20 @@ void change_pins_test(void) { log_d("Disabling UART loopback"); -#if SOC_UART_NUM == 2 +#if SOC_UART_HP_NUM == 2 esp_rom_gpio_connect_out_signal(SOC_RX0, SIG_GPIO_OUT_IDX, false, false); -#elif SOC_UART_NUM == 3 +#elif SOC_UART_HP_NUM == 3 esp_rom_gpio_connect_out_signal(RX1, SIG_GPIO_OUT_IDX, false, false); esp_rom_gpio_connect_out_signal(RX2, SIG_GPIO_OUT_IDX, false, false); #endif log_d("Swapping UART pins"); -#if SOC_UART_NUM == 2 +#if SOC_UART_HP_NUM == 2 Serial1.setPins(NEW_RX1, NEW_TX1); TEST_ASSERT_EQUAL(NEW_RX1, uart_get_RxPin(1)); TEST_ASSERT_EQUAL(NEW_TX1, uart_get_TxPin(1)); -#elif SOC_UART_NUM == 3 +#elif SOC_UART_HP_NUM == 3 Serial1.setPins(RX2, TX2); Serial2.setPins(RX1, TX1); TEST_ASSERT_EQUAL(RX2, uart_get_RxPin(1)); @@ -445,9 +445,9 @@ void change_pins_test(void) { log_d("Re-enabling UART loopback"); -#if SOC_UART_NUM == 2 +#if SOC_UART_HP_NUM == 2 uart_internal_loopback(1, NEW_RX1); -#elif SOC_UART_NUM == 3 +#elif SOC_UART_HP_NUM == 3 uart_internal_loopback(1, RX1); uart_internal_loopback(2, RX2); #endif @@ -467,10 +467,10 @@ void auto_baudrate_test(void) { log_d("Stopping test serial. Using Serial2 for ESP32 and Serial1 for ESP32-S2."); -#if SOC_UART_NUM == 2 +#if SOC_UART_HP_NUM == 2 selected_serial = &Serial1; uart_internal_loopback(0, RX1); -#elif SOC_UART_NUM == 3 +#elif SOC_UART_HP_NUM == 3 selected_serial = &Serial2; #endif @@ -485,7 +485,7 @@ void auto_baudrate_test(void) { selected_serial->begin(0); baudrate = selected_serial->baudRate(); -#if SOC_UART_NUM == 2 +#if SOC_UART_HP_NUM == 2 Serial.end(); Serial.begin(115200); #endif @@ -504,7 +504,7 @@ void periman_test(void) { Wire.begin(RX1, TX1); -#if SOC_UART_NUM == 3 +#if SOC_UART_HP_NUM == 3 Wire1.begin(RX2, TX2); #endif @@ -518,11 +518,11 @@ void periman_test(void) { Serial1.setPins(RX1, TX1); -#if SOC_UART_NUM == 3 +#if SOC_UART_HP_NUM == 3 Serial2.setPins(RX2, TX2); uart_internal_loopback(1, RX2); uart_internal_loopback(2, RX1); -#elif SOC_UART_NUM == 2 +#elif SOC_UART_HP_NUM == 2 uart_internal_loopback(1, RX1); #endif @@ -565,19 +565,19 @@ void setup() { while (!Serial) { delay(10); } - log_d("SOC_UART_NUM = %d", SOC_UART_NUM); + log_d("SOC_UART_HP_NUM = %d", SOC_UART_HP_NUM); // Begin needs to be called before setting up the loopback because it creates the serial object start_serial(115200); -#if SOC_UART_NUM == 2 +#if SOC_UART_HP_NUM == 2 log_d("Setup internal loop-back from and back to Serial1 (UART1) TX >> Serial1 (UART1) RX"); Serial1.onReceive([]() { onReceive_cb(Serial1); }); uart_internal_loopback(1, RX1); -#elif SOC_UART_NUM == 3 +#elif SOC_UART_HP_NUM == 3 log_d("Setup internal loop-back between Serial1 (UART1) <<--->> Serial2 (UART2)"); Serial1.onReceive([]() { From f77ce040db4504c91f918874bab5af52dfdb58a6 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 20 Aug 2024 00:51:23 +0300 Subject: [PATCH 002/409] fix(build): Fix many warnings --- cores/esp32/esp32-hal-cpu.c | 8 ++-- cores/esp32/esp32-hal-misc.c | 10 ++--- .../BluetoothSerial/src/BluetoothSerial.cpp | 2 +- libraries/ESP_I2S/src/ESP_I2S.cpp | 2 +- libraries/Ethernet/src/ETH.cpp | 4 +- libraries/SD_MMC/src/SD_MMC.cpp | 3 +- libraries/WiFi/src/WiFiGeneric.cpp | 43 ++++++++++--------- 7 files changed, 37 insertions(+), 35 deletions(-) diff --git a/cores/esp32/esp32-hal-cpu.c b/cores/esp32/esp32-hal-cpu.c index 7027c7cad9d..2420dfbeeb0 100644 --- a/cores/esp32/esp32-hal-cpu.c +++ b/cores/esp32/esp32-hal-cpu.c @@ -21,7 +21,7 @@ #include "soc/rtc.h" #if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #endif #include "soc/efuse_reg.h" #include "esp32-hal.h" @@ -30,13 +30,13 @@ #include "esp_system.h" #ifdef ESP_IDF_VERSION_MAJOR // IDF 4+ #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 -#include "freertos/xtensa_timer.h" +#include "xtensa_timer.h" #include "esp32/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32S2 -#include "freertos/xtensa_timer.h" +#include "xtensa_timer.h" #include "esp32s2/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32S3 -#include "freertos/xtensa_timer.h" +#include "xtensa_timer.h" #include "esp32s3/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32C2 #include "esp32c2/rom/rtc.h" diff --git a/cores/esp32/esp32-hal-misc.c b/cores/esp32/esp32-hal-misc.c index 82363b97bd0..7dfca6134b2 100644 --- a/cores/esp32/esp32-hal-misc.c +++ b/cores/esp32/esp32-hal-misc.c @@ -31,7 +31,7 @@ #include "soc/rtc.h" #if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #endif #include "esp_task_wdt.h" #include "esp32-hal.h" @@ -147,14 +147,14 @@ void feedLoopWDT() { #endif void enableCore0WDT() { - TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0); + TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCore(0); if (idle_0 == NULL || esp_task_wdt_add(idle_0) != ESP_OK) { log_e("Failed to add Core 0 IDLE task to WDT"); } } void disableCore0WDT() { - TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0); + TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCore(0); if (idle_0 == NULL || esp_task_wdt_delete(idle_0) != ESP_OK) { log_e("Failed to remove Core 0 IDLE task from WDT"); } @@ -162,14 +162,14 @@ void disableCore0WDT() { #ifndef CONFIG_FREERTOS_UNICORE void enableCore1WDT() { - TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1); + TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCore(1); if (idle_1 == NULL || esp_task_wdt_add(idle_1) != ESP_OK) { log_e("Failed to add Core 1 IDLE task to WDT"); } } void disableCore1WDT() { - TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1); + TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCore(1); if (idle_1 == NULL || esp_task_wdt_delete(idle_1) != ESP_OK) { log_e("Failed to remove Core 1 IDLE task from WDT"); } diff --git a/libraries/BluetoothSerial/src/BluetoothSerial.cpp b/libraries/BluetoothSerial/src/BluetoothSerial.cpp index 12c09d68305..3d00504c1b1 100644 --- a/libraries/BluetoothSerial/src/BluetoothSerial.cpp +++ b/libraries/BluetoothSerial/src/BluetoothSerial.cpp @@ -698,7 +698,7 @@ static bool _init_bt(const char *deviceName, bt_mode mode) { } log_i("device name set"); - esp_bt_dev_set_device_name(deviceName); + esp_bt_gap_set_device_name(deviceName); if (_enableSSP) { log_i("Simple Secure Pairing"); diff --git a/libraries/ESP_I2S/src/ESP_I2S.cpp b/libraries/ESP_I2S/src/ESP_I2S.cpp index 50f76b41a3f..8b136ba5c47 100644 --- a/libraries/ESP_I2S/src/ESP_I2S.cpp +++ b/libraries/ESP_I2S/src/ESP_I2S.cpp @@ -12,7 +12,7 @@ #define I2S_READ_CHUNK_SIZE 1920 #define I2S_DEFAULT_CFG() \ - { .id = I2S_NUM_AUTO, .role = I2S_ROLE_MASTER, .dma_desc_num = 6, .dma_frame_num = 240, .auto_clear = true, } + { .id = I2S_NUM_AUTO, .role = I2S_ROLE_MASTER, .dma_desc_num = 6, .dma_frame_num = 240, .auto_clear = true, .auto_clear_before_cb = false, .intr_priority = 0 } #define I2S_STD_CHAN_CFG(_sample_rate, _data_bit_width, _slot_mode) \ { \ diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 48e8460fe2d..bc5a94484da 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -181,8 +181,8 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i : (2 == clock_mode) ? EMAC_CLK_OUT_GPIO : (3 == clock_mode) ? EMAC_CLK_OUT_180_GPIO : EMAC_CLK_IN_GPIO; - mac_config.smi_mdc_gpio_num = digitalPinToGPIONumber(mdc); - mac_config.smi_mdio_gpio_num = digitalPinToGPIONumber(mdio); + mac_config.smi_gpio.mdc_num = digitalPinToGPIONumber(mdc); + mac_config.smi_gpio.mdio_num = digitalPinToGPIONumber(mdio); _pin_mcd = digitalPinToGPIONumber(mdc); _pin_mdio = digitalPinToGPIONumber(mdio); diff --git a/libraries/SD_MMC/src/SD_MMC.cpp b/libraries/SD_MMC/src/SD_MMC.cpp index 13e5fcf27fc..024f8b4e3d7 100644 --- a/libraries/SD_MMC/src/SD_MMC.cpp +++ b/libraries/SD_MMC/src/SD_MMC.cpp @@ -175,7 +175,8 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_ _mode1bit = mode1bit; esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = format_if_mount_failed, .max_files = maxOpenFiles, .allocation_unit_size = 0, .disk_status_check_enable = false + .format_if_mount_failed = format_if_mount_failed, .max_files = maxOpenFiles, .allocation_unit_size = 0, .disk_status_check_enable = false, + .use_one_fat = false }; esp_err_t ret = esp_vfs_fat_sdmmc_mount(mountpoint, &host, &slot_config, &mount_config, &_card); diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index 6ddf384d009..ccc9518132b 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -39,6 +39,7 @@ extern "C" { #include #include #include +#include #include "lwip/ip_addr.h" #include "lwip/opt.h" #include "lwip/err.h" @@ -693,9 +694,9 @@ bool WiFiGenericClass::initiateFTM(uint8_t frm_count, uint16_t burst_period, uin */ 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; + esp_phy_ant_gpio_config_t wifi_ant_io; - if (ESP_OK != esp_wifi_get_ant_gpio(&wifi_ant_io)) { + if (ESP_OK != esp_phy_get_ant_gpio(&wifi_ant_io)) { log_e("Failed to get antenna configuration"); return false; } @@ -705,56 +706,56 @@ bool WiFiGenericClass::setDualAntennaConfig(uint8_t gpio_ant1, uint8_t gpio_ant2 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)) { + if (ESP_OK != esp_phy_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, - .rx_ant_default = WIFI_ANT_MAX, // Ignored in AUTO mode - .tx_ant_mode = WIFI_ANT_MODE_AUTO, + esp_phy_ant_config_t ant_config = { + .rx_ant_mode = ESP_PHY_ANT_MODE_AUTO, + .rx_ant_default = ESP_PHY_ANT_MAX, // Ignored in AUTO mode + .tx_ant_mode = ESP_PHY_ANT_MODE_AUTO, .enabled_ant0 = 1, .enabled_ant1 = 2, }; 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_ANT0: ant_config.rx_ant_mode = ESP_PHY_ANT_MODE_ANT0; break; + case WIFI_RX_ANT1: ant_config.rx_ant_mode = ESP_PHY_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; + ant_config.rx_ant_default = ESP_PHY_ANT_ANT0; + ant_config.rx_ant_mode = ESP_PHY_ANT_MODE_AUTO; // Force TX for AUTO if RX is AUTO - ant_config.tx_ant_mode = WIFI_ANT_MODE_AUTO; + ant_config.tx_ant_mode = ESP_PHY_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; + ant_config.rx_ant_mode = ESP_PHY_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_ANT0: ant_config.tx_ant_mode = ESP_PHY_ANT_MODE_ANT0; break; + case WIFI_TX_ANT1: ant_config.tx_ant_mode = ESP_PHY_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; + ant_config.rx_ant_default = ESP_PHY_ANT_ANT0; + ant_config.tx_ant_mode = ESP_PHY_ANT_MODE_AUTO; // Force RX for AUTO if RX is AUTO - ant_config.rx_ant_mode = WIFI_ANT_MODE_AUTO; + ant_config.rx_ant_mode = ESP_PHY_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; + ant_config.rx_ant_default = ESP_PHY_ANT_ANT0; + ant_config.tx_ant_mode = ESP_PHY_ANT_MODE_AUTO; break; } set_ant: - if (ESP_OK != esp_wifi_set_ant(&ant_config)) { + if (ESP_OK != esp_phy_set_ant(&ant_config)) { log_e("Failed to set antenna configuration"); return false; } From 54f1c22672950c5b64af475b5ac4bc1ec9b5ad73 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 20 Aug 2024 01:16:59 +0300 Subject: [PATCH 003/409] fix(build): Fix warning in FFat --- libraries/FFat/src/FFat.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/FFat/src/FFat.cpp b/libraries/FFat/src/FFat.cpp index 1227e172602..41d941b4726 100644 --- a/libraries/FFat/src/FFat.cpp +++ b/libraries/FFat/src/FFat.cpp @@ -46,7 +46,8 @@ bool F_Fat::begin(bool formatOnFail, const char *basePath, uint8_t maxOpenFiles, } esp_vfs_fat_mount_config_t conf = { - .format_if_mount_failed = formatOnFail, .max_files = maxOpenFiles, .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, .disk_status_check_enable = false + .format_if_mount_failed = formatOnFail, .max_files = maxOpenFiles, .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, .disk_status_check_enable = false, + .use_one_fat = false }; esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(basePath, partitionLabel, &conf, &_wl_handle); if (err) { @@ -98,7 +99,8 @@ bool F_Fat::format(bool full_wipe, char *partitionLabel) { } // Now do a mount with format_if_fail (which it will) esp_vfs_fat_mount_config_t conf = { - .format_if_mount_failed = true, .max_files = 1, .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, .disk_status_check_enable = false + .format_if_mount_failed = true, .max_files = 1, .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, .disk_status_check_enable = false, + .use_one_fat = false }; result = esp_vfs_fat_spiflash_mount_rw_wl("/format_ffat", partitionLabel, &conf, &temp_handle); esp_vfs_fat_spiflash_unmount_rw_wl("/format_ffat", temp_handle); From c7e01e72a197f8a4982fb0a06838a51d6f72acb0 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 20 Aug 2024 13:02:29 +0300 Subject: [PATCH 004/409] add(build): Add initial ESP32-P4 skeleton Required to start compilation. Board is currently hidden and many options are removed --- boards.txt | 84 +++++++++++++++++++++++++++++++++ idf_component.yml | 1 + variants/esp32p4/pins_arduino.h | 30 ++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 variants/esp32p4/pins_arduino.h diff --git a/boards.txt b/boards.txt index 7ea34347dfe..8b3d48df2fb 100644 --- a/boards.txt +++ b/boards.txt @@ -162,6 +162,90 @@ esp32c2.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +esp32p4.name=ESP32P4 Dev Module +esp32p4.hide=true + +esp32p4.bootloader.tool=esptool_py +esp32p4.bootloader.tool.default=esptool_py + +esp32p4.upload.tool=esptool_py +esp32p4.upload.tool.default=esptool_py +esp32p4.upload.tool.network=esp_ota + +esp32p4.upload.maximum_size=1310720 +esp32p4.upload.maximum_data_size=327680 +esp32p4.upload.flags= +esp32p4.upload.extra_flags= +esp32p4.upload.use_1200bps_touch=false +esp32p4.upload.wait_for_upload_port=false + +esp32p4.serial.disableDTR=false +esp32p4.serial.disableRTS=false + +esp32p4.build.tarch=riscv32 +esp32p4.build.target=esp +esp32p4.build.mcu=esp32p4 +esp32p4.build.core=esp32 +esp32p4.build.variant=esp32p4 +esp32p4.build.board=ESP32P4_DEV +esp32p4.build.bootloader_addr=0x0 + +esp32p4.build.cdc_on_boot=0 +esp32p4.build.f_cpu=400000000L +esp32p4.build.flash_size=4MB +esp32p4.build.flash_freq=80m +esp32p4.build.img_freq=80m +esp32p4.build.flash_mode=qio +esp32p4.build.boot=qio +esp32p4.build.partitions=default +esp32p4.build.defines= + +## IDE 2.0 Seems to not update the value +esp32p4.menu.JTAGAdapter.default=Disabled +esp32p4.menu.JTAGAdapter.default.build.copy_jtag_files=0 + +esp32p4.menu.CDCOnBoot.default=Disabled +esp32p4.menu.CDCOnBoot.default.build.cdc_on_boot=0 +esp32p4.menu.CDCOnBoot.cdc=Enabled +esp32p4.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +esp32p4.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +esp32p4.menu.PartitionScheme.default.build.partitions=default +esp32p4.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +esp32p4.menu.PartitionScheme.no_fs.build.partitions=no_fs +esp32p4.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +esp32p4.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +esp32p4.menu.PartitionScheme.huge_app.build.partitions=huge_app +esp32p4.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +esp32p4.menu.PartitionScheme.custom=Custom +esp32p4.menu.PartitionScheme.custom.build.partitions= +esp32p4.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +esp32p4.menu.UploadSpeed.921600=921600 +esp32p4.menu.UploadSpeed.921600.upload.speed=921600 +esp32p4.menu.UploadSpeed.115200=115200 +esp32p4.menu.UploadSpeed.115200.upload.speed=115200 + +esp32p4.menu.DebugLevel.none=None +esp32p4.menu.DebugLevel.none.build.code_debug=0 +esp32p4.menu.DebugLevel.error=Error +esp32p4.menu.DebugLevel.error.build.code_debug=1 +esp32p4.menu.DebugLevel.warn=Warn +esp32p4.menu.DebugLevel.warn.build.code_debug=2 +esp32p4.menu.DebugLevel.info=Info +esp32p4.menu.DebugLevel.info.build.code_debug=3 +esp32p4.menu.DebugLevel.debug=Debug +esp32p4.menu.DebugLevel.debug.build.code_debug=4 +esp32p4.menu.DebugLevel.verbose=Verbose +esp32p4.menu.DebugLevel.verbose.build.code_debug=5 + +esp32p4.menu.EraseFlash.none=Disabled +esp32p4.menu.EraseFlash.none.upload.erase_cmd= +esp32p4.menu.EraseFlash.all=Enabled +esp32p4.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + esp32h2.name=ESP32H2 Dev Module esp32h2.bootloader.tool=esptool_py diff --git a/idf_component.yml b/idf_component.yml index e6831d71b44..55f35376b1b 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -9,6 +9,7 @@ targets: - esp32c3 - esp32c6 - esp32h2 + - esp32p4 tags: - arduino files: diff --git a/variants/esp32p4/pins_arduino.h b/variants/esp32p4/pins_arduino.h new file mode 100644 index 00000000000..87d0548cf3c --- /dev/null +++ b/variants/esp32p4/pins_arduino.h @@ -0,0 +1,30 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define PIN_NEOPIXEL 44 +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() +#define RGB_BUILTIN LED_BUILTIN +#define RGB_BRIGHTNESS 64 + +// BOOT_MODE 35 +// BOOT_MODE2 36 pullup + +static const uint8_t TX = 37; +static const uint8_t RX = 38; + +static const uint8_t SDA = 7; +static const uint8_t SCL = 8; + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 12; +static const uint8_t SCK = 13; + +#endif /* Pins_Arduino_h */ From 4c4906f4703821d100bf353ec425057c7569f78b Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Wed, 28 Aug 2024 04:50:49 -0300 Subject: [PATCH 005/409] fix(uart): sleep retention (#10248) * fix(uart): sleep retention sets new flag from IDF 5.3 that causes error with Serial.begin(115200). * fix(typo): typo and commentaries * feat(uart): adds memset to make structure empty * fix(uart): missing parentesis - typo * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- cores/esp32/esp32-hal-uart.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index e4432f5110f..c2065e806c4 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -497,6 +497,8 @@ uart_t *uartBegin( log_v("UART%d not installed. Starting installation", uart_nr); } uart_config_t uart_config; + memset(&uart_config, 0, sizeof(uart_config_t)); + uart_config.flags.backup_before_sleep = false; // new flag from IDF v5.3 uart_config.data_bits = (config & 0xc) >> 2; uart_config.parity = (config & 0x3); uart_config.stop_bits = (config & 0x30) >> 4; From 0b842442c96e963c2f35b8b65e8879b7af16d1e3 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 28 Aug 2024 16:11:35 +0300 Subject: [PATCH 006/409] Update core version to 3.1.0 --- cores/esp32/esp_arduino_version.h | 4 ++-- libraries/ArduinoOTA/library.properties | 2 +- libraries/AsyncUDP/library.properties | 2 +- libraries/BLE/library.properties | 2 +- libraries/BluetoothSerial/library.properties | 2 +- libraries/DNSServer/library.properties | 2 +- libraries/EEPROM/library.properties | 2 +- libraries/ESP32/library.properties | 2 +- libraries/ESP_I2S/library.properties | 2 +- libraries/ESP_NOW/library.properties | 2 +- libraries/ESP_SR/library.properties | 2 +- libraries/ESPmDNS/library.properties | 2 +- libraries/Ethernet/library.properties | 2 +- libraries/FFat/library.properties | 2 +- libraries/FS/library.properties | 2 +- libraries/HTTPClient/library.properties | 2 +- libraries/HTTPUpdate/library.properties | 2 +- libraries/HTTPUpdateServer/library.properties | 2 +- libraries/Insights/library.properties | 2 +- libraries/LittleFS/library.properties | 2 +- libraries/NetBIOS/library.properties | 2 +- libraries/Network/library.properties | 2 +- libraries/NetworkClientSecure/library.properties | 2 +- libraries/OpenThread/library.properties | 2 +- libraries/PPP/library.properties | 2 +- libraries/Preferences/library.properties | 2 +- libraries/RainMaker/library.properties | 2 +- libraries/SD/library.properties | 2 +- libraries/SD_MMC/library.properties | 2 +- libraries/SPI/library.properties | 2 +- libraries/SPIFFS/library.properties | 2 +- libraries/SimpleBLE/library.properties | 2 +- libraries/TFLiteMicro/library.properties | 2 +- libraries/Ticker/library.properties | 2 +- libraries/USB/library.properties | 2 +- libraries/Update/library.properties | 2 +- libraries/WebServer/library.properties | 2 +- libraries/WiFi/library.properties | 2 +- libraries/WiFiProv/library.properties | 2 +- libraries/Wire/library.properties | 2 +- package.json | 2 +- platform.txt | 2 +- 42 files changed, 43 insertions(+), 43 deletions(-) diff --git a/cores/esp32/esp_arduino_version.h b/cores/esp32/esp_arduino_version.h index adc8415dbd9..c2921b95fb8 100644 --- a/cores/esp32/esp_arduino_version.h +++ b/cores/esp32/esp_arduino_version.h @@ -21,9 +21,9 @@ extern "C" { /** Major version number (X.x.x) */ #define ESP_ARDUINO_VERSION_MAJOR 3 /** Minor version number (x.X.x) */ -#define ESP_ARDUINO_VERSION_MINOR 0 +#define ESP_ARDUINO_VERSION_MINOR 1 /** Patch version number (x.x.X) */ -#define ESP_ARDUINO_VERSION_PATCH 4 +#define ESP_ARDUINO_VERSION_PATCH 0 /** * Macro to convert ARDUINO version number into an integer diff --git a/libraries/ArduinoOTA/library.properties b/libraries/ArduinoOTA/library.properties index a8336230f79..54ad6eafb21 100644 --- a/libraries/ArduinoOTA/library.properties +++ b/libraries/ArduinoOTA/library.properties @@ -1,5 +1,5 @@ name=ArduinoOTA -version=3.0.4 +version=3.1.0 author=Ivan Grokhotkov and Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables Over The Air upgrades, via wifi and espota.py UDP request/TCP download. diff --git a/libraries/AsyncUDP/library.properties b/libraries/AsyncUDP/library.properties index 92332f78599..24457a39b90 100644 --- a/libraries/AsyncUDP/library.properties +++ b/libraries/AsyncUDP/library.properties @@ -1,5 +1,5 @@ name=ESP32 Async UDP -version=3.0.4 +version=3.1.0 author=Me-No-Dev maintainer=Me-No-Dev sentence=Async UDP Library for ESP32 diff --git a/libraries/BLE/library.properties b/libraries/BLE/library.properties index 82395a1f6d5..32ad36b5f44 100644 --- a/libraries/BLE/library.properties +++ b/libraries/BLE/library.properties @@ -1,5 +1,5 @@ name=BLE -version=3.0.4 +version=3.1.0 author=Neil Kolban maintainer=Dariusz Krempa sentence=BLE functions for ESP32 diff --git a/libraries/BluetoothSerial/library.properties b/libraries/BluetoothSerial/library.properties index a91e8455e05..6db3a01bb19 100644 --- a/libraries/BluetoothSerial/library.properties +++ b/libraries/BluetoothSerial/library.properties @@ -1,5 +1,5 @@ name=BluetoothSerial -version=3.0.4 +version=3.1.0 author=Evandro Copercini maintainer=Evandro Copercini sentence=Simple UART to Classical Bluetooth bridge for ESP32 diff --git a/libraries/DNSServer/library.properties b/libraries/DNSServer/library.properties index bb4ed950fad..077d9237f21 100644 --- a/libraries/DNSServer/library.properties +++ b/libraries/DNSServer/library.properties @@ -1,5 +1,5 @@ name=DNSServer -version=3.0.4 +version=3.1.0 author=Kristijan Novoselić maintainer=Kristijan Novoselić, sentence=A simple DNS server for ESP32. diff --git a/libraries/EEPROM/library.properties b/libraries/EEPROM/library.properties index 6297bedcb22..bf75d618898 100644 --- a/libraries/EEPROM/library.properties +++ b/libraries/EEPROM/library.properties @@ -1,5 +1,5 @@ name=EEPROM -version=3.0.4 +version=3.1.0 author=Ivan Grokhotkov maintainer=Paolo Becchi sentence=Enables reading and writing data a sequential, addressable FLASH storage diff --git a/libraries/ESP32/library.properties b/libraries/ESP32/library.properties index c0897f23eee..1bb1ed21750 100644 --- a/libraries/ESP32/library.properties +++ b/libraries/ESP32/library.properties @@ -1,5 +1,5 @@ name=ESP32 -version=3.0.4 +version=3.1.0 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 sketches examples diff --git a/libraries/ESP_I2S/library.properties b/libraries/ESP_I2S/library.properties index ad0e4fbdc59..807f7daeb9d 100644 --- a/libraries/ESP_I2S/library.properties +++ b/libraries/ESP_I2S/library.properties @@ -1,5 +1,5 @@ name=ESP_I2S -version=3.0.4 +version=3.1.0 author=me-no-dev maintainer=me-no-dev sentence=Library for ESP I2S communication diff --git a/libraries/ESP_NOW/library.properties b/libraries/ESP_NOW/library.properties index 1d1dc8926a1..42876f47f95 100644 --- a/libraries/ESP_NOW/library.properties +++ b/libraries/ESP_NOW/library.properties @@ -1,5 +1,5 @@ name=ESP_NOW -version=3.0.4 +version=3.1.0 author=me-no-dev maintainer=P-R-O-C-H-Y sentence=Library for ESP_NOW diff --git a/libraries/ESP_SR/library.properties b/libraries/ESP_SR/library.properties index bf3ab3a14ba..a81cff2fe9d 100644 --- a/libraries/ESP_SR/library.properties +++ b/libraries/ESP_SR/library.properties @@ -1,5 +1,5 @@ name=ESP_SR -version=3.0.4 +version=3.1.0 author=me-no-dev maintainer=me-no-dev sentence=Library for ESP Sound Recognition diff --git a/libraries/ESPmDNS/library.properties b/libraries/ESPmDNS/library.properties index 64ff66c3a1e..4f65114fd0b 100644 --- a/libraries/ESPmDNS/library.properties +++ b/libraries/ESPmDNS/library.properties @@ -1,5 +1,5 @@ name=ESPmDNS -version=3.0.4 +version=3.1.0 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 mDNS Library diff --git a/libraries/Ethernet/library.properties b/libraries/Ethernet/library.properties index 1fc7df2192d..70aa24ec4aa 100644 --- a/libraries/Ethernet/library.properties +++ b/libraries/Ethernet/library.properties @@ -1,5 +1,5 @@ name=Ethernet -version=3.0.4 +version=3.1.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables network connection (local and Internet) using the ESP32 Ethernet. diff --git a/libraries/FFat/library.properties b/libraries/FFat/library.properties index 87dda7b1299..dae11e43aaf 100644 --- a/libraries/FFat/library.properties +++ b/libraries/FFat/library.properties @@ -1,5 +1,5 @@ name=FFat -version=3.0.4 +version=3.1.0 author=Hristo Gochkov, Ivan Grokhtkov, Larry Bernstone maintainer=Hristo Gochkov sentence=ESP32 FAT on Flash File System diff --git a/libraries/FS/library.properties b/libraries/FS/library.properties index 676faf43e99..009383ab0c8 100644 --- a/libraries/FS/library.properties +++ b/libraries/FS/library.properties @@ -1,5 +1,5 @@ name=FS -version=3.0.4 +version=3.1.0 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 File System diff --git a/libraries/HTTPClient/library.properties b/libraries/HTTPClient/library.properties index 40da6a0cde9..203b8929d30 100644 --- a/libraries/HTTPClient/library.properties +++ b/libraries/HTTPClient/library.properties @@ -1,5 +1,5 @@ name=HTTPClient -version=3.0.4 +version=3.1.0 author=Markus Sattler maintainer=Markus Sattler sentence=HTTP Client for ESP32 diff --git a/libraries/HTTPUpdate/library.properties b/libraries/HTTPUpdate/library.properties index ab7e9b6f872..ac903dd71cf 100644 --- a/libraries/HTTPUpdate/library.properties +++ b/libraries/HTTPUpdate/library.properties @@ -1,5 +1,5 @@ name=HTTPUpdate -version=3.0.4 +version=3.1.0 author=Markus Sattler maintainer=Markus Sattler sentence=Http Update for ESP32 diff --git a/libraries/HTTPUpdateServer/library.properties b/libraries/HTTPUpdateServer/library.properties index 249eb5ea173..b26bd2cad7b 100644 --- a/libraries/HTTPUpdateServer/library.properties +++ b/libraries/HTTPUpdateServer/library.properties @@ -1,5 +1,5 @@ name=HTTPUpdateServer -version=3.0.4 +version=3.1.0 author=Hristo Kapanakov maintainer= sentence=Simple HTTP Update server based on the WebServer diff --git a/libraries/Insights/library.properties b/libraries/Insights/library.properties index cabf05f2806..af213a1e70d 100644 --- a/libraries/Insights/library.properties +++ b/libraries/Insights/library.properties @@ -1,5 +1,5 @@ name=ESP Insights -version=3.0.4 +version=3.1.0 author=Sanket Wadekar maintainer=Sanket Wadekar sentence=ESP Insights diff --git a/libraries/LittleFS/library.properties b/libraries/LittleFS/library.properties index f443b70bc2f..86c4c43eeca 100644 --- a/libraries/LittleFS/library.properties +++ b/libraries/LittleFS/library.properties @@ -1,5 +1,5 @@ name=LittleFS -version=3.0.4 +version=3.1.0 author= maintainer= sentence=LittleFS for esp32 diff --git a/libraries/NetBIOS/library.properties b/libraries/NetBIOS/library.properties index fdf9b63a0d2..42555781f75 100644 --- a/libraries/NetBIOS/library.properties +++ b/libraries/NetBIOS/library.properties @@ -1,5 +1,5 @@ name=NetBIOS -version=3.0.4 +version=3.1.0 author=Pablo@xpablo.cz maintainer=Hristo Gochkov sentence=Enables NBNS (NetBIOS) name resolution. diff --git a/libraries/Network/library.properties b/libraries/Network/library.properties index 49aadb7b874..8a1567e68a9 100644 --- a/libraries/Network/library.properties +++ b/libraries/Network/library.properties @@ -1,5 +1,5 @@ name=Networking -version=3.0.4 +version=3.1.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=General network management library. diff --git a/libraries/NetworkClientSecure/library.properties b/libraries/NetworkClientSecure/library.properties index 2a0ca88ffbe..d810e852524 100644 --- a/libraries/NetworkClientSecure/library.properties +++ b/libraries/NetworkClientSecure/library.properties @@ -1,5 +1,5 @@ name=NetworkClientSecure -version=3.0.4 +version=3.1.0 author=Evandro Luis Copercini maintainer=Github Community sentence=Enables secure network connection (local and Internet) using the ESP32 built-in WiFi. diff --git a/libraries/OpenThread/library.properties b/libraries/OpenThread/library.properties index 6a16dabddd0..19d37749a92 100644 --- a/libraries/OpenThread/library.properties +++ b/libraries/OpenThread/library.properties @@ -1,5 +1,5 @@ name=OpenThread -version=3.0.4 +version=3.1.0 author=Rodrigo Garcia | GitHub @SuGlider maintainer=Rodrigo Garcia sentence=Library for OpenThread Network on ESP32. diff --git a/libraries/PPP/library.properties b/libraries/PPP/library.properties index 0403b576df2..e2b290cc893 100644 --- a/libraries/PPP/library.properties +++ b/libraries/PPP/library.properties @@ -1,5 +1,5 @@ name=PPP -version=3.0.4 +version=3.1.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables network connection using GSM Modem. diff --git a/libraries/Preferences/library.properties b/libraries/Preferences/library.properties index 8437425c04d..90cd20d75c3 100644 --- a/libraries/Preferences/library.properties +++ b/libraries/Preferences/library.properties @@ -1,5 +1,5 @@ name=Preferences -version=3.0.4 +version=3.1.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Provides friendly access to ESP32's Non-Volatile Storage diff --git a/libraries/RainMaker/library.properties b/libraries/RainMaker/library.properties index e6bdd2f4579..0c3e6e26697 100644 --- a/libraries/RainMaker/library.properties +++ b/libraries/RainMaker/library.properties @@ -1,5 +1,5 @@ name=ESP RainMaker -version=3.0.4 +version=3.1.0 author=Sweety Mhaiske maintainer=Hristo Gochkov sentence=ESP RainMaker Support diff --git a/libraries/SD/library.properties b/libraries/SD/library.properties index 98d93943a7f..3fd1a3f8a3e 100644 --- a/libraries/SD/library.properties +++ b/libraries/SD/library.properties @@ -1,5 +1,5 @@ name=SD -version=3.0.4 +version=3.1.0 author=Arduino, SparkFun maintainer=Arduino sentence=Enables reading and writing on SD cards. For all Arduino boards. diff --git a/libraries/SD_MMC/library.properties b/libraries/SD_MMC/library.properties index 242fc62ecac..94586e8e1ec 100644 --- a/libraries/SD_MMC/library.properties +++ b/libraries/SD_MMC/library.properties @@ -1,5 +1,5 @@ name=SD_MMC -version=3.0.4 +version=3.1.0 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 SDMMC File System diff --git a/libraries/SPI/library.properties b/libraries/SPI/library.properties index 804f86e93c2..a7a7204db62 100644 --- a/libraries/SPI/library.properties +++ b/libraries/SPI/library.properties @@ -1,5 +1,5 @@ name=SPI -version=3.0.4 +version=3.1.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables the communication with devices that use the Serial Peripheral Interface (SPI) Bus. For all Arduino boards, BUT Arduino DUE. diff --git a/libraries/SPIFFS/library.properties b/libraries/SPIFFS/library.properties index 9aaf1d9c575..132ff5fb7f1 100644 --- a/libraries/SPIFFS/library.properties +++ b/libraries/SPIFFS/library.properties @@ -1,5 +1,5 @@ name=SPIFFS -version=3.0.4 +version=3.1.0 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 SPIFFS File System diff --git a/libraries/SimpleBLE/library.properties b/libraries/SimpleBLE/library.properties index c49cd51b389..ae28a21c0df 100644 --- a/libraries/SimpleBLE/library.properties +++ b/libraries/SimpleBLE/library.properties @@ -1,5 +1,5 @@ name=SimpleBLE -version=3.0.4 +version=3.1.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Provides really simple BLE advertizer with just on and off diff --git a/libraries/TFLiteMicro/library.properties b/libraries/TFLiteMicro/library.properties index 1a966476619..cde7d21bec1 100644 --- a/libraries/TFLiteMicro/library.properties +++ b/libraries/TFLiteMicro/library.properties @@ -1,5 +1,5 @@ name=TFLite Micro -version=3.0.4 +version=3.1.0 author=Sanket Wadekar maintainer=Sanket Wadekar sentence=TensorFlow Lite for Microcontrollers diff --git a/libraries/Ticker/library.properties b/libraries/Ticker/library.properties index 297e3221b1d..d6e9829c6ef 100644 --- a/libraries/Ticker/library.properties +++ b/libraries/Ticker/library.properties @@ -1,5 +1,5 @@ name=Ticker -version=3.0.4 +version=3.1.0 author=Bert Melis maintainer=Hristo Gochkov sentence=Allows to call functions with a given interval. diff --git a/libraries/USB/library.properties b/libraries/USB/library.properties index 209fca7ebc3..752acf3a803 100644 --- a/libraries/USB/library.properties +++ b/libraries/USB/library.properties @@ -1,5 +1,5 @@ name=USB -version=3.0.4 +version=3.1.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=ESP32S2 USB Library diff --git a/libraries/Update/library.properties b/libraries/Update/library.properties index b70add08cad..9d480986b1e 100644 --- a/libraries/Update/library.properties +++ b/libraries/Update/library.properties @@ -1,5 +1,5 @@ name=Update -version=3.0.4 +version=3.1.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=ESP32 Sketch Update Library diff --git a/libraries/WebServer/library.properties b/libraries/WebServer/library.properties index 10dc2ff1a4f..89e35e4713d 100644 --- a/libraries/WebServer/library.properties +++ b/libraries/WebServer/library.properties @@ -1,5 +1,5 @@ name=WebServer -version=3.0.4 +version=3.1.0 author=Ivan Grokhotkov maintainer=Ivan Grokhtkov sentence=Simple web server library diff --git a/libraries/WiFi/library.properties b/libraries/WiFi/library.properties index 5acbee86744..925616ea561 100644 --- a/libraries/WiFi/library.properties +++ b/libraries/WiFi/library.properties @@ -1,5 +1,5 @@ name=WiFi -version=3.0.4 +version=3.1.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables network connection (local and Internet) using the ESP32 built-in WiFi. diff --git a/libraries/WiFiProv/library.properties b/libraries/WiFiProv/library.properties index 886697c9af9..20e27fc5097 100644 --- a/libraries/WiFiProv/library.properties +++ b/libraries/WiFiProv/library.properties @@ -1,5 +1,5 @@ name=WiFiProv -version=3.0.4 +version=3.1.0 author=Switi Mhaiske maintainer=Hristo Gochkov sentence=Enables provisioning. diff --git a/libraries/Wire/library.properties b/libraries/Wire/library.properties index 0c7fa749a7b..a2d79eee81b 100644 --- a/libraries/Wire/library.properties +++ b/libraries/Wire/library.properties @@ -1,5 +1,5 @@ name=Wire -version=3.0.4 +version=3.1.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. For esp8266 boards. diff --git a/package.json b/package.json index 487bcc77a2c..2e53f41d4c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "framework-arduinoespressif32", - "version": "3.0.4", + "version": "3.1.0", "description": "Arduino Wiring-based Framework for the Espressif ESP32, ESP32-S and ESP32-C series of SoCs", "keywords": [ "framework", diff --git a/platform.txt b/platform.txt index e7b8391b9dc..ebc8d23a5c7 100644 --- a/platform.txt +++ b/platform.txt @@ -1,5 +1,5 @@ name=ESP32 Arduino -version=3.0.4 +version=3.1.0 tools.esp32-arduino-libs.path={runtime.platform.path}/tools/esp32-arduino-libs tools.esp32-arduino-libs.path.windows={runtime.platform.path}\tools\esp32-arduino-libs From 57518b821c338382945bc014c8ddfcb93741acf2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 14:11:51 +0000 Subject: [PATCH 007/409] ci(pre-commit): Apply automatic fixes --- libraries/ESP_I2S/src/ESP_I2S.cpp | 7 +++++-- libraries/FFat/src/FFat.cpp | 8 +++++--- libraries/SD_MMC/src/SD_MMC.cpp | 5 ++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/libraries/ESP_I2S/src/ESP_I2S.cpp b/libraries/ESP_I2S/src/ESP_I2S.cpp index 8b136ba5c47..395c7b587ed 100644 --- a/libraries/ESP_I2S/src/ESP_I2S.cpp +++ b/libraries/ESP_I2S/src/ESP_I2S.cpp @@ -11,8 +11,11 @@ #define I2S_READ_CHUNK_SIZE 1920 -#define I2S_DEFAULT_CFG() \ - { .id = I2S_NUM_AUTO, .role = I2S_ROLE_MASTER, .dma_desc_num = 6, .dma_frame_num = 240, .auto_clear = true, .auto_clear_before_cb = false, .intr_priority = 0 } +#define I2S_DEFAULT_CFG() \ + { \ + .id = I2S_NUM_AUTO, .role = I2S_ROLE_MASTER, .dma_desc_num = 6, .dma_frame_num = 240, .auto_clear = true, .auto_clear_before_cb = false, \ + .intr_priority = 0 \ + } #define I2S_STD_CHAN_CFG(_sample_rate, _data_bit_width, _slot_mode) \ { \ diff --git a/libraries/FFat/src/FFat.cpp b/libraries/FFat/src/FFat.cpp index 41d941b4726..003339152fe 100644 --- a/libraries/FFat/src/FFat.cpp +++ b/libraries/FFat/src/FFat.cpp @@ -46,7 +46,10 @@ bool F_Fat::begin(bool formatOnFail, const char *basePath, uint8_t maxOpenFiles, } esp_vfs_fat_mount_config_t conf = { - .format_if_mount_failed = formatOnFail, .max_files = maxOpenFiles, .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, .disk_status_check_enable = false, + .format_if_mount_failed = formatOnFail, + .max_files = maxOpenFiles, + .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, + .disk_status_check_enable = false, .use_one_fat = false }; esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(basePath, partitionLabel, &conf, &_wl_handle); @@ -99,8 +102,7 @@ bool F_Fat::format(bool full_wipe, char *partitionLabel) { } // Now do a mount with format_if_fail (which it will) esp_vfs_fat_mount_config_t conf = { - .format_if_mount_failed = true, .max_files = 1, .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, .disk_status_check_enable = false, - .use_one_fat = false + .format_if_mount_failed = true, .max_files = 1, .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, .disk_status_check_enable = false, .use_one_fat = false }; result = esp_vfs_fat_spiflash_mount_rw_wl("/format_ffat", partitionLabel, &conf, &temp_handle); esp_vfs_fat_spiflash_unmount_rw_wl("/format_ffat", temp_handle); diff --git a/libraries/SD_MMC/src/SD_MMC.cpp b/libraries/SD_MMC/src/SD_MMC.cpp index 024f8b4e3d7..6bbcf44d010 100644 --- a/libraries/SD_MMC/src/SD_MMC.cpp +++ b/libraries/SD_MMC/src/SD_MMC.cpp @@ -175,7 +175,10 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_ _mode1bit = mode1bit; esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = format_if_mount_failed, .max_files = maxOpenFiles, .allocation_unit_size = 0, .disk_status_check_enable = false, + .format_if_mount_failed = format_if_mount_failed, + .max_files = maxOpenFiles, + .allocation_unit_size = 0, + .disk_status_check_enable = false, .use_one_fat = false }; From 564612dacc7310a10b9778c5389c15b0db4192eb Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Wed, 28 Aug 2024 22:45:33 +0300 Subject: [PATCH 008/409] IDF release/v5.3 0bbd7281 (#10258) --- package/package_esp32_index.template.json | 68 +++++++++++------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 8c585fa86ed..d14b71a7491 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -42,7 +42,7 @@ { "packager": "esp32", "name": "esp32-arduino-libs", - "version": "idf-release_v5.3-466a392a" + "version": "idf-release_v5.3-0bbd7281" }, { "packager": "esp32", @@ -95,63 +95,63 @@ "tools": [ { "name": "esp32-arduino-libs", - "version": "idf-release_v5.3-466a392a", + "version": "idf-release_v5.3-0bbd7281", "systems": [ { "host": "i686-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", - "size": "318864212" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", + "size": "319140606" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", - "size": "318864212" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", + "size": "319140606" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", - "size": "318864212" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", + "size": "319140606" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", - "size": "318864212" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", + "size": "319140606" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", - "size": "318864212" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", + "size": "319140606" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", - "size": "318864212" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", + "size": "319140606" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", - "size": "318864212" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", + "size": "319140606" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-466a392a.zip", - "checksum": "SHA-256:8c2d36bd4be5b6a9446efd3c2b2f93f544f4b2a22dab23c4991aec5711c72884", - "size": "318864212" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", + "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", + "size": "319140606" } ] }, From 67682088cabc60f2b4f6d459d5635245c9ff9ca6 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Wed, 18 Sep 2024 15:56:37 +0300 Subject: [PATCH 009/409] IDF release/v5.3 (#10272) * IDF release/v5.3 2c46030b * IDF release/v5.3 cc3203dc * IDF release/v5.3 4d0db704 --- package/package_esp32_index.template.json | 128 +++++++++++----------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index d14b71a7491..701e77b3b21 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -42,7 +42,7 @@ { "packager": "esp32", "name": "esp32-arduino-libs", - "version": "idf-release_v5.3-0bbd7281" + "version": "idf-release_v5.3-4d0db704" }, { "packager": "esp32", @@ -67,7 +67,7 @@ { "packager": "esp32", "name": "openocd-esp32", - "version": "v0.12.0-esp32-20240318" + "version": "v0.12.0-esp32-20240821" }, { "packager": "esp32", @@ -95,63 +95,63 @@ "tools": [ { "name": "esp32-arduino-libs", - "version": "idf-release_v5.3-0bbd7281", + "version": "idf-release_v5.3-4d0db704", "systems": [ { "host": "i686-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", - "size": "319140606" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", + "size": "320072134" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", - "size": "319140606" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", + "size": "320072134" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", - "size": "319140606" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", + "size": "320072134" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", - "size": "319140606" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", + "size": "320072134" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", - "size": "319140606" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", + "size": "320072134" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", - "size": "319140606" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", + "size": "320072134" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", - "size": "319140606" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", + "size": "320072134" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-0bbd7281.zip", - "checksum": "SHA-256:e436e8ba703cf78ec81d80e956d2ae4a5e754f280950520ad7c425bb56738a80", - "size": "319140606" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", + "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", + "size": "320072134" } ] }, @@ -405,56 +405,56 @@ }, { "name": "openocd-esp32", - "version": "v0.12.0-esp32-20240318", + "version": "v0.12.0-esp32-20240821", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-linux-amd64-0.12.0-esp32-20240318.tar.gz", - "archiveFileName": "openocd-esp32-linux-amd64-0.12.0-esp32-20240318.tar.gz", - "checksum": "SHA-256:cf26c5cef4f6b04aa23cd2778675604e5a74a4ce4d8d17b854d05fbcb782d52c", - "size": "2252682" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-linux-amd64-0.12.0-esp32-20240821.tar.gz", + "archiveFileName": "openocd-esp32-linux-amd64-0.12.0-esp32-20240821.tar.gz", + "checksum": "SHA-256:f8c68541fa38307bc0c0763b7e1e3fe4e943d5d45da07d817a73b492e103b652", + "size": "2373094" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-linux-arm64-0.12.0-esp32-20240318.tar.gz", - "archiveFileName": "openocd-esp32-linux-arm64-0.12.0-esp32-20240318.tar.gz", - "checksum": "SHA-256:9b97a37aa2cab94424a778c25c0b4aa0f90d6ef9cda764a1d9289d061305f4b7", - "size": "2132904" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-linux-arm64-0.12.0-esp32-20240821.tar.gz", + "archiveFileName": "openocd-esp32-linux-arm64-0.12.0-esp32-20240821.tar.gz", + "checksum": "SHA-256:4d6e263d84e447354dc685848557d6c284dda7fe007ee451f729a7edfa7baad7", + "size": "2251272" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-linux-armel-0.12.0-esp32-20240318.tar.gz", - "archiveFileName": "openocd-esp32-linux-armel-0.12.0-esp32-20240318.tar.gz", - "checksum": "SHA-256:b7e82776ec374983807d3389df09c632ad9bc8341f2075690b6b500319dfeaf4", - "size": "2271761" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-linux-armel-0.12.0-esp32-20240821.tar.gz", + "archiveFileName": "openocd-esp32-linux-armel-0.12.0-esp32-20240821.tar.gz", + "checksum": "SHA-256:9d45679f2c4cf450d5e2350047cf57bb76dde2487d30cebce0a72c9173b5c45b", + "size": "2390074" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-macos-0.12.0-esp32-20240318.tar.gz", - "archiveFileName": "openocd-esp32-macos-0.12.0-esp32-20240318.tar.gz", - "checksum": "SHA-256:b16c3082c94df1079367c44d99f7a8605534cd48aabc18898e46e94a2c8c57e7", - "size": "2365588" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-macos-0.12.0-esp32-20240821.tar.gz", + "archiveFileName": "openocd-esp32-macos-0.12.0-esp32-20240821.tar.gz", + "checksum": "SHA-256:565c8fabc5f19a6e7a0864a294d74b307eec30b9291d16d3fc90e273f0330cb4", + "size": "2485320" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-macos-arm64-0.12.0-esp32-20240318.tar.gz", - "archiveFileName": "openocd-esp32-macos-arm64-0.12.0-esp32-20240318.tar.gz", - "checksum": "SHA-256:534ec925ae6e35e869e4e4e6e4d2c4a1eb081f97ebcc2dd5efdc52d12f4c2f86", - "size": "2406377" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-macos-arm64-0.12.0-esp32-20240821.tar.gz", + "archiveFileName": "openocd-esp32-macos-arm64-0.12.0-esp32-20240821.tar.gz", + "checksum": "SHA-256:68c5c7cf3d15b9810939a5edabc6ff2c9f4fc32262de91fc292a180bc5cc0637", + "size": "2530336" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-win32-0.12.0-esp32-20240318.zip", - "archiveFileName": "openocd-esp32-win32-0.12.0-esp32-20240318.zip", - "checksum": "SHA-256:d379329eba052435173ab0d69c9b15bc164a6ce489e2a67cd11169d2dabff633", - "size": "2783915" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-win32-0.12.0-esp32-20240821.zip", + "archiveFileName": "openocd-esp32-win32-0.12.0-esp32-20240821.zip", + "checksum": "SHA-256:463fc2903ddaf03f86ff50836c5c63cc696550b0446140159eddfd2e85570c5d", + "size": "2916409" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-win32-0.12.0-esp32-20240318.zip", - "archiveFileName": "openocd-esp32-win32-0.12.0-esp32-20240318.zip", - "checksum": "SHA-256:d379329eba052435173ab0d69c9b15bc164a6ce489e2a67cd11169d2dabff633", - "size": "2783915" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-win64-0.12.0-esp32-20240821.zip", + "archiveFileName": "openocd-esp32-win64-0.12.0-esp32-20240821.zip", + "checksum": "SHA-256:550f57369f1f1f6cc600b5dffa3378fd6164d8ea8db7c567cf41091771f090cb", + "size": "2916408" } ] }, From a4c33e3897facd6e6f85547c746d33e9019bb0b2 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:18:28 -0300 Subject: [PATCH 010/409] feat(esp32p4): Add initial ESP32-P4 support (#10358) * feat(esp32p4): Initial changes required for ESP32-P4 * esp32-p4: Initial changes to build with Arduino Signed-off-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> * fix(esp32p4): Fix lib builder errors * change(esp32p4): Unhide board * ci(esp32p4): Add ESP32-P4 to workflow * change(esptool): Update esptool to 4.8.0 * fix(build): Fix redefinition errors * fix(build): Remove old commands * change(esptool): Remove unsupported 32-bit tools * fix(get.py): Force exe generation * Revert "fix(get.py): Force exe generation" This reverts commit 979b16b3b19d02917ddccf0139c6913cca618714. * fix(get.py): Fix system check * change(tools): Push generated binaries to PR * ci(esp32p4): Add missing ESP32-P4 entries * fix(esp32p4): Add chip info * fix(esp32p4): Fix build commands * docs(esp32p4): Add missing references to P4 * fix(esp32p4): Fix clock sources definitions * fix(esp32p4): Set CPU frequency to 360 MHz so it is stable in all chips * refactor(esp32p4): Change preprocessor conditionals for maintainability Co-authored-by: me-no-dev * fix(esp32p4): Add missing menu options * fix(esp32p4): Mark as not in development json in readme * fix(esp32p4): Add P4 to ci.json files * ci(pre-commit): Apply automatic fixes * fix(get.py): Remove unused include * ci(pre-commit): Apply automatic fixes * change(tools): Push generated binaries to PR * ci(pre-commit): Apply automatic fixes * fix(ci.json): Fix formatting --------- Signed-off-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Co-authored-by: Jason2866 <24528715+Jason2866@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: me-no-dev Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .github/scripts/on-push.sh | 1 + .github/scripts/sketch_utils.sh | 4 + .github/workflows/lib.yml | 3 + .github/workflows/push.yml | 2 +- .github/workflows/tests.yml | 4 +- .github/workflows/tests_wokwi.yml | 2 +- README.md | 1 + boards.txt | 91 +- cores/esp32/Esp.cpp | 6 + cores/esp32/HardwareSerial.h | 12 + cores/esp32/chip-debug-report.cpp | 6 + cores/esp32/esp32-hal-adc.c | 10 +- cores/esp32/esp32-hal-cpu.c | 33 +- cores/esp32/esp32-hal-i2c-slave.c | 802 +++++++++--------- cores/esp32/esp32-hal-i2c.c | 17 +- cores/esp32/esp32-hal-ledc.c | 5 + cores/esp32/esp32-hal-matrix.c | 2 + cores/esp32/esp32-hal-misc.c | 4 +- cores/esp32/esp32-hal-psram.c | 2 + cores/esp32/esp32-hal-spi.c | 252 +++--- cores/esp32/esp32-hal-spi.h | 8 +- cores/esp32/esp32-hal-touch.c | 21 +- cores/esp32/esp32-hal-touch.h | 2 + cores/esp32/esp32-hal-uart.c | 20 +- docs/en/lib_builder.rst | 1 + idf_component.yml | 1 + .../ArduinoOTA/examples/BasicOTA/ci.json | 3 +- .../AsyncUDP/examples/AsyncUDPClient/ci.json | 3 +- .../examples/AsyncUDPMulticastServer/ci.json | 3 +- .../AsyncUDP/examples/AsyncUDPServer/ci.json | 3 +- .../BLE/examples/BLE5_extended_scan/ci.json | 1 + .../examples/BLE5_multi_advertising/ci.json | 2 +- .../BLE5_periodic_advertising/ci.json | 6 +- .../BLE/examples/BLE5_periodic_sync/ci.json | 4 + libraries/BLE/examples/Beacon_Scanner/ci.json | 4 + libraries/BLE/examples/Client/ci.json | 2 + .../BLE/examples/EddystoneTLM_Beacon/ci.json | 1 + .../BLE/examples/EddystoneURL_Beacon/ci.json | 1 + libraries/BLE/examples/Notify/ci.json | 2 + libraries/BLE/examples/Scan/ci.json | 1 + libraries/BLE/examples/Server/ci.json | 7 +- .../BLE/examples/Server_multiconnect/ci.json | 5 + libraries/BLE/examples/UART/ci.json | 4 + libraries/BLE/examples/Write/ci.json | 2 + libraries/BLE/examples/iBeacon/ci.json | 2 + .../examples/DiscoverConnect/ci.json | 1 + .../examples/GetLocalMAC/ci.json | 1 + .../examples/SerialToSerialBT/ci.json | 1 + .../examples/SerialToSerialBTM/ci.json | 1 + .../examples/SerialToSerialBT_Legacy/ci.json | 1 + .../examples/SerialToSerialBT_SSP/ci.json | 1 + .../bt_classic_device_discovery/ci.json | 1 + .../examples/bt_remove_paired_devices/ci.json | 1 + .../DNSServer/examples/CaptivePortal/ci.json | 3 +- .../examples/Camera/CameraWebServer/ci.json | 3 +- .../examples/DeepSleep/ExternalWakeUp/ci.json | 3 +- .../DeepSleep/SmoothBlink_ULP_Code/ci.json | 1 + .../examples/RMT/RMTLoopback/RMTLoopback.ino | 2 +- .../ResetReason/ResetReason/ResetReason.ino | 2 + .../ESP32/examples/Time/SimpleTime/ci.json | 3 +- .../examples/Zigbee/Zigbee_Light_Bulb/ci.json | 1 + .../Zigbee/Zigbee_Light_Switch/ci.json | 1 + .../Zigbee/Zigbee_Temperature_Sensor/ci.json | 1 + .../examples/Zigbee/Zigbee_Thermostat/ci.json | 1 + .../examples/ESP_NOW_Broadcast_Master/ci.json | 3 +- .../examples/ESP_NOW_Broadcast_Slave/ci.json | 3 +- .../ESP_NOW/examples/ESP_NOW_Network/ci.json | 3 +- .../ESP_NOW/examples/ESP_NOW_Serial/ci.json | 3 +- libraries/ESP_SR/examples/Basic/ci.json | 1 + .../ESPmDNS/examples/mDNS-SD_Extended/ci.json | 3 +- .../ESPmDNS/examples/mDNS_Web_Server/ci.json | 3 +- .../Ethernet/examples/ETH_WIFI_BRIDGE/ci.json | 3 +- libraries/Ethernet/src/ETH.cpp | 6 +- libraries/FFat/examples/FFat_time/ci.json | 3 +- .../HTTPClient/examples/Authorization/ci.json | 3 +- .../examples/BasicHttpClient/ci.json | 3 +- .../examples/BasicHttpsClient/ci.json | 3 +- .../examples/HTTPClientEnterprise/ci.json | 3 +- .../examples/ReuseConnection/ci.json | 3 +- .../examples/StreamHttpClient/ci.json | 3 +- .../HTTPUpdate/examples/httpUpdate/ci.json | 3 +- .../examples/httpUpdateSPIFFS/ci.json | 3 +- .../examples/httpUpdateSecure/ci.json | 3 +- .../examples/WebUpdater/ci.json | 3 +- .../examples/DiagnosticsSmokeTest/ci.json | 3 +- .../examples/MinimalDiagnostics/ci.json | 3 +- .../LittleFS/examples/LITTLEFS_time/ci.json | 3 +- libraries/NetBIOS/examples/ESP_NBNST/ci.json | 3 +- .../examples/WiFiClientInsecure/ci.json | 3 +- .../examples/WiFiClientPSK/ci.json | 3 +- .../examples/WiFiClientSecure/ci.json | 3 +- .../WiFiClientSecureEnterprise/ci.json | 3 +- .../WiFiClientSecureProtocolUpgrade/ci.json | 3 +- .../WiFiClientShowPeerCredentials/ci.json | 3 +- .../WiFiClientTrustOnFirstUse/ci.json | 3 +- .../examples/COAP/coap_lamp/ci.json | 1 + .../examples/COAP/coap_switch/ci.json | 7 +- .../OpenThread/examples/SimpleCLI/ci.json | 8 +- .../OpenThread/examples/SimpleNode/ci.json | 6 +- .../ExtendedRouterNode/ci.json | 8 +- .../SimpleThreadNetwork/LeaderNode/ci.json | 1 + .../SimpleThreadNetwork/RouterNode/ci.json | 1 + .../OpenThread/examples/ThreadScan/ci.json | 1 + .../OpenThread/examples/onReceive/ci.json | 1 + .../PPP/examples/PPP_WIFI_BRIDGE/ci.json | 3 +- libraries/PPP/src/PPP.cpp | 6 +- .../RainMaker/examples/RMakerCustom/ci.json | 3 +- .../examples/RMakerCustomAirCooler/ci.json | 3 +- .../examples/RMakerSonoffDualR3/ci.json | 3 +- .../RainMaker/examples/RMakerSwitch/ci.json | 3 +- libraries/SD/examples/SD_time/ci.json | 3 +- libraries/SD_MMC/examples/SD2USBMSC/ci.json | 1 + libraries/SD_MMC/examples/SDMMC_Test/ci.json | 1 + libraries/SD_MMC/examples/SDMMC_time/ci.json | 1 + libraries/SD_MMC/src/SD_MMC.cpp | 14 +- libraries/SPI/src/SPI.cpp | 2 +- libraries/SPIFFS/examples/SPIFFS_time/ci.json | 3 +- .../examples/SimpleBleDevice/ci.json | 1 + .../Update/examples/AWS_S3_OTA_Update/ci.json | 3 +- .../Update/examples/HTTPS_OTA_Update/ci.json | 3 +- .../HTTP_Client_AES_OTA_Update/ci.json | 3 +- .../HTTP_Server_AES_OTA_Update/ci.json | 3 +- .../Update/examples/OTAWebUpdater/ci.json | 3 +- .../examples/AdvancedWebServer/ci.json | 3 +- .../WebServer/examples/FSBrowser/ci.json | 3 +- libraries/WebServer/examples/Filters/ci.json | 3 +- .../WebServer/examples/HelloServer/ci.json | 3 +- .../examples/HttpAdvancedAuth/ci.json | 3 +- .../examples/HttpAuthCallback/ci.json | 3 +- .../examples/HttpAuthCallbackInline/ci.json | 3 +- .../WebServer/examples/HttpBasicAuth/ci.json | 3 +- .../examples/HttpBasicAuthSHA1/ci.json | 3 +- .../HttpBasicAuthSHA1orBearerToken/ci.json | 3 +- .../examples/MultiHomedServers/ci.json | 3 +- .../WebServer/examples/PathArgServer/ci.json | 3 +- .../WebServer/examples/SDWebServer/ci.json | 3 +- .../examples/SimpleAuthentification/ci.json | 3 +- .../WebServer/examples/UploadHugeFile/ci.json | 3 +- .../WebServer/examples/WebServer/ci.json | 3 +- .../WebServer/examples/WebUpdate/ci.json | 3 +- .../WiFi/examples/FTM/FTM_Initiator/ci.json | 3 +- .../WiFi/examples/FTM/FTM_Responder/ci.json | 3 +- .../WiFi/examples/SimpleWiFiServer/ci.json | 3 +- libraries/WiFi/examples/WPS/ci.json | 3 +- .../WiFi/examples/WiFiAccessPoint/ci.json | 3 +- .../WiFi/examples/WiFiBlueToothSwitch/ci.json | 1 + libraries/WiFi/examples/WiFiClient/ci.json | 3 +- .../WiFi/examples/WiFiClientBasic/ci.json | 3 +- .../WiFi/examples/WiFiClientConnect/ci.json | 3 +- .../examples/WiFiClientEnterprise/ci.json | 3 +- .../WiFi/examples/WiFiClientEvents/ci.json | 3 +- .../WiFi/examples/WiFiClientStaticIP/ci.json | 3 +- libraries/WiFi/examples/WiFiExtender/ci.json | 3 +- libraries/WiFi/examples/WiFiIPv6/ci.json | 3 +- libraries/WiFi/examples/WiFiMulti/ci.json | 3 +- .../WiFi/examples/WiFiMultiAdvanced/ci.json | 3 +- libraries/WiFi/examples/WiFiScan/ci.json | 3 +- libraries/WiFi/examples/WiFiScanAsync/ci.json | 3 +- .../WiFi/examples/WiFiScanDualAntenna/ci.json | 3 +- libraries/WiFi/examples/WiFiScanTime/ci.json | 3 +- .../WiFi/examples/WiFiSmartConfig/ci.json | 3 +- .../WiFi/examples/WiFiTelnetToSerial/ci.json | 3 +- libraries/WiFi/examples/WiFiUDPClient/ci.json | 3 +- libraries/WiFiProv/examples/WiFiProv/ci.json | 3 +- package/package_esp32_index.template.json | 56 +- platform.txt | 11 +- tools/get.exe | Bin 6930008 -> 6943192 bytes tools/get.py | 8 + tools/platformio-build.py | 2 +- 169 files changed, 1079 insertions(+), 706 deletions(-) diff --git a/.github/scripts/on-push.sh b/.github/scripts/on-push.sh index 08ff505f1c0..73d9eeee398 100755 --- a/.github/scripts/on-push.sh +++ b/.github/scripts/on-push.sh @@ -91,6 +91,7 @@ if [ "$BUILD_PIO" -eq 0 ]; then fi #build sketches for different targets + build "esp32p4" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32" build "esp32s3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32" build "esp32s2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32" build "esp32c3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32" diff --git a/.github/scripts/sketch_utils.sh b/.github/scripts/sketch_utils.sh index 813f61210cd..5af47dcb138 100755 --- a/.github/scripts/sketch_utils.sh +++ b/.github/scripts/sketch_utils.sh @@ -89,6 +89,7 @@ function build_sketch(){ # build_sketch [ex esp32c3_opts="PartitionScheme=huge_app,FlashMode=dio" esp32c6_opts="PartitionScheme=huge_app,FlashMode=dio" esp32h2_opts="PartitionScheme=huge_app,FlashMode=dio" + esp32p4_opts="PartitionScheme=huge_app,FlashMode=dio" # Select the common part of the FQBN based on the target. The rest will be # appended depending on the passed options. @@ -112,6 +113,9 @@ function build_sketch(){ # build_sketch [ex "esp32h2") fqbn="espressif:esp32:esp32h2:${options:-$esp32h2_opts}" ;; + "esp32p4") + fqbn="espressif:esp32:esp32p4:${options:-$esp32p4_opts}" + ;; esac # Make it look like a JSON array. diff --git a/.github/workflows/lib.yml b/.github/workflows/lib.yml index 894df61f4fd..7a7b863095d 100644 --- a/.github/workflows/lib.yml +++ b/.github/workflows/lib.yml @@ -42,6 +42,7 @@ jobs: - esp32s3 - esp32c6 - esp32h2 + - esp32p4 include: - target: esp32 @@ -56,6 +57,8 @@ jobs: fqbn: espressif:esp32:esp32c6 - target: esp32h2 fqbn: espressif:esp32:esp32h2 + - target: esp32p4 + fqbn: espressif:esp32:esp32p4 steps: diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index d5c12c6d3e9..8d25b1a234d 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -233,7 +233,7 @@ jobs: # https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-docker-image.html # for details. idf_ver: ["release-v5.3"] - idf_target: ["esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2"] + idf_target: ["esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"] container: espressif/idf:${{ matrix.idf_ver }} steps: - name: Check out arduino-esp32 as a component diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 26de19d8f10..1ae748923b5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -88,7 +88,7 @@ jobs: strategy: matrix: type: ${{ fromJson(needs.gen-matrix.outputs.build-types) }} - chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'] + chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32p4'] with: type: ${{ matrix.type }} chip: ${{ matrix.chip }} @@ -105,7 +105,7 @@ jobs: fail-fast: false matrix: type: ${{ fromJson(needs.gen-matrix.outputs.hw-types) }} - chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'] + chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32p4'] with: type: ${{ matrix.type }} chip: ${{ matrix.chip }} diff --git a/.github/workflows/tests_wokwi.yml b/.github/workflows/tests_wokwi.yml index f016cad25e0..14f85ee606e 100644 --- a/.github/workflows/tests_wokwi.yml +++ b/.github/workflows/tests_wokwi.yml @@ -165,7 +165,7 @@ jobs: fail-fast: false matrix: type: ['validation'] - chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'] + chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32p4'] steps: - name: Report pending uses: actions/github-script@v7 diff --git a/README.md b/README.md index ee1880b8d05..d3dca34aafe 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ Here are the ESP32 series supported by the Arduino-ESP32 project: | ESP32-S3 | Yes | Yes | [ESP32-S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) | | ESP32-C6 | Yes | Yes | [ESP32-C6](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) | | ESP32-H2 | Yes | Yes | [ESP32-H2](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) | +| ESP32-P4 | No | No | [ESP32-P4](https://www.espressif.com/sites/default/files/documentation/esp32-p4_datasheet_en.pdf) | > [!NOTE] > ESP32-C2 is also supported by Arduino-ESP32 but requires rebuilding the static libraries. This is not trivial and requires a good understanding of the ESP-IDF diff --git a/boards.txt b/boards.txt index ad47e0df455..f95cf4c21d3 100644 --- a/boards.txt +++ b/boards.txt @@ -163,7 +163,6 @@ esp32c2.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## esp32p4.name=ESP32P4 Dev Module -esp32p4.hide=true esp32p4.bootloader.tool=esptool_py esp32p4.bootloader.tool.default=esptool_py @@ -188,10 +187,10 @@ esp32p4.build.mcu=esp32p4 esp32p4.build.core=esp32 esp32p4.build.variant=esp32p4 esp32p4.build.board=ESP32P4_DEV -esp32p4.build.bootloader_addr=0x0 +esp32p4.build.bootloader_addr=0x2000 esp32p4.build.cdc_on_boot=0 -esp32p4.build.f_cpu=400000000L +esp32p4.build.f_cpu=360000000L esp32p4.build.flash_size=4MB esp32p4.build.flash_freq=80m esp32p4.build.img_freq=80m @@ -203,6 +202,25 @@ esp32p4.build.defines= ## IDE 2.0 Seems to not update the value esp32p4.menu.JTAGAdapter.default=Disabled esp32p4.menu.JTAGAdapter.default.build.copy_jtag_files=0 +esp32p4.menu.JTAGAdapter.builtin=Integrated USB JTAG +esp32p4.menu.JTAGAdapter.builtin.build.openocdscript=esp32p4-builtin.cfg +esp32p4.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +esp32p4.menu.JTAGAdapter.external=FTDI Adapter +esp32p4.menu.JTAGAdapter.external.build.openocdscript=esp32p4-ftdi.cfg +esp32p4.menu.JTAGAdapter.external.build.copy_jtag_files=1 +esp32p4.menu.JTAGAdapter.bridge=ESP USB Bridge +esp32p4.menu.JTAGAdapter.bridge.build.openocdscript=esp32p4-bridge.cfg +esp32p4.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +esp32p4.menu.CDCOnBoot.default=Disabled +esp32p4.menu.CDCOnBoot.default.build.cdc_on_boot=0 +esp32p4.menu.CDCOnBoot.cdc=Enabled +esp32p4.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +esp32p4.menu.PSRAM.disabled=Disabled +esp32p4.menu.PSRAM.disabled.build.defines= +esp32p4.menu.PSRAM.enabled=Enabled +esp32p4.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM esp32p4.menu.CDCOnBoot.default=Disabled esp32p4.menu.CDCOnBoot.default.build.cdc_on_boot=0 @@ -211,20 +229,87 @@ esp32p4.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 esp32p4.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) esp32p4.menu.PartitionScheme.default.build.partitions=default +esp32p4.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +esp32p4.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +esp32p4.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +esp32p4.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +esp32p4.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +esp32p4.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +esp32p4.menu.PartitionScheme.minimal.build.partitions=minimal esp32p4.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) esp32p4.menu.PartitionScheme.no_fs.build.partitions=no_fs esp32p4.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +esp32p4.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +esp32p4.menu.PartitionScheme.no_ota.build.partitions=no_ota +esp32p4.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +esp32p4.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +esp32p4.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +esp32p4.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +esp32p4.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +esp32p4.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +esp32p4.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +esp32p4.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +esp32p4.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +esp32p4.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 esp32p4.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) esp32p4.menu.PartitionScheme.huge_app.build.partitions=huge_app esp32p4.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +esp32p4.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +esp32p4.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +esp32p4.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +esp32p4.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +esp32p4.menu.PartitionScheme.fatflash.build.partitions=ffat +esp32p4.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +esp32p4.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +esp32p4.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +esp32p4.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 esp32p4.menu.PartitionScheme.custom=Custom esp32p4.menu.PartitionScheme.custom.build.partitions= esp32p4.menu.PartitionScheme.custom.upload.maximum_size=16777216 +## From https://docs.espressif.com/projects/esp-idf/en/latest/esp32p4/api-reference/kconfig.html#config-esp-default-cpu-freq-mhz +esp32p4.menu.CPUFreq.360=360MHz +esp32p4.menu.CPUFreq.360.build.f_cpu=360000000L +esp32p4.menu.CPUFreq.40=40MHz +esp32p4.menu.CPUFreq.40.build.f_cpu=40000000L + +esp32p4.menu.FlashMode.qio=QIO +esp32p4.menu.FlashMode.qio.build.flash_mode=dio +esp32p4.menu.FlashMode.qio.build.boot=qio +esp32p4.menu.FlashMode.dio=DIO +esp32p4.menu.FlashMode.dio.build.flash_mode=dio +esp32p4.menu.FlashMode.dio.build.boot=dio + +esp32p4.menu.FlashFreq.80=80MHz +esp32p4.menu.FlashFreq.80.build.flash_freq=80m +esp32p4.menu.FlashFreq.40=40MHz +esp32p4.menu.FlashFreq.40.build.flash_freq=40m + +esp32p4.menu.FlashSize.4M=4MB (32Mb) +esp32p4.menu.FlashSize.4M.build.flash_size=4MB +esp32p4.menu.FlashSize.8M=8MB (64Mb) +esp32p4.menu.FlashSize.8M.build.flash_size=8MB +esp32p4.menu.FlashSize.8M.build.partitions=default_8MB +esp32p4.menu.FlashSize.2M=2MB (16Mb) +esp32p4.menu.FlashSize.2M.build.flash_size=2MB +esp32p4.menu.FlashSize.2M.build.partitions=minimal +esp32p4.menu.FlashSize.16M=16MB (128Mb) +esp32p4.menu.FlashSize.16M.build.flash_size=16MB + esp32p4.menu.UploadSpeed.921600=921600 esp32p4.menu.UploadSpeed.921600.upload.speed=921600 esp32p4.menu.UploadSpeed.115200=115200 esp32p4.menu.UploadSpeed.115200.upload.speed=115200 +esp32p4.menu.UploadSpeed.256000.windows=256000 +esp32p4.menu.UploadSpeed.256000.upload.speed=256000 +esp32p4.menu.UploadSpeed.230400.windows.upload.speed=256000 +esp32p4.menu.UploadSpeed.230400=230400 +esp32p4.menu.UploadSpeed.230400.upload.speed=230400 +esp32p4.menu.UploadSpeed.460800.linux=460800 +esp32p4.menu.UploadSpeed.460800.macosx=460800 +esp32p4.menu.UploadSpeed.460800.upload.speed=460800 +esp32p4.menu.UploadSpeed.512000.windows=512000 +esp32p4.menu.UploadSpeed.512000.upload.speed=512000 esp32p4.menu.DebugLevel.none=None esp32p4.menu.DebugLevel.none.build.code_debug=0 diff --git a/cores/esp32/Esp.cpp b/cores/esp32/Esp.cpp index 483e888f64f..6a6ed11e463 100644 --- a/cores/esp32/Esp.cpp +++ b/cores/esp32/Esp.cpp @@ -60,6 +60,9 @@ extern "C" { #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/spi_flash.h" #define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32h2 is located at 0x0000 +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/spi_flash.h" +#define ESP_FLASH_IMAGE_BASE 0x2000 // Esp32p4 is located at 0x2000 #else #error Target CONFIG_IDF_TARGET is not supported #endif @@ -335,6 +338,8 @@ uint32_t EspClass::getFlashChipSpeed(void) { return magicFlashChipSpeed(fhdr.spi_speed); } +// FIXME for P4 +#if !defined(CONFIG_IDF_TARGET_ESP32P4) FlashMode_t EspClass::getFlashChipMode(void) { #if CONFIG_IDF_TARGET_ESP32S2 uint32_t spi_ctrl = REG_READ(PERIPHS_SPI_FLASH_CTRL); @@ -361,6 +366,7 @@ FlashMode_t EspClass::getFlashChipMode(void) { } return (FM_DOUT); } +#endif // if !defined(CONFIG_IDF_TARGET_ESP32P4) uint32_t EspClass::magicFlashChipSize(uint8_t byte) { /* diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index 23a8823dff7..fc5dd92440d 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -125,6 +125,8 @@ typedef enum { #define SOC_RX0 (gpio_num_t)17 #elif CONFIG_IDF_TARGET_ESP32H2 #define SOC_RX0 (gpio_num_t)23 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define SOC_RX0 (gpio_num_t)38 #endif #endif @@ -141,6 +143,8 @@ typedef enum { #define SOC_TX0 (gpio_num_t)16 #elif CONFIG_IDF_TARGET_ESP32H2 #define SOC_TX0 (gpio_num_t)24 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define SOC_TX0 (gpio_num_t)37 #endif #endif @@ -162,6 +166,8 @@ typedef enum { #define RX1 (gpio_num_t)4 #elif CONFIG_IDF_TARGET_ESP32H2 #define RX1 (gpio_num_t)0 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define RX1 (gpio_num_t)11 #endif #endif @@ -180,6 +186,8 @@ typedef enum { #define TX1 (gpio_num_t)5 #elif CONFIG_IDF_TARGET_ESP32H2 #define TX1 (gpio_num_t)1 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define TX1 (gpio_num_t)10 #endif #endif #endif /* SOC_UART_HP_NUM > 1 */ @@ -192,6 +200,8 @@ typedef enum { #define RX2 (gpio_num_t)4 #elif CONFIG_IDF_TARGET_ESP32S3 #define RX2 (gpio_num_t)19 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define RX2 (gpio_num_t)15 #endif #endif @@ -200,6 +210,8 @@ typedef enum { #define TX2 (gpio_num_t)25 #elif CONFIG_IDF_TARGET_ESP32S3 #define TX2 (gpio_num_t)20 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define TX2 (gpio_num_t)14 #endif #endif #endif /* SOC_UART_HP_NUM > 2 */ diff --git a/cores/esp32/chip-debug-report.cpp b/cores/esp32/chip-debug-report.cpp index 239ae3e97c9..daafef3cab9 100644 --- a/cores/esp32/chip-debug-report.cpp +++ b/cores/esp32/chip-debug-report.cpp @@ -64,6 +64,9 @@ static void printPkgVersion(void) { #elif CONFIG_IDF_TARGET_ESP32H2 uint32_t pkg_ver = REG_GET_FIELD(EFUSE_RD_MAC_SYS_4_REG, EFUSE_PKG_VERSION); chip_report_printf("%lu", pkg_ver); +#elif CONFIG_IDF_TARGET_ESP32P4 + uint32_t pkg_ver = REG_GET_FIELD(EFUSE_RD_MAC_SYS_2_REG, EFUSE_PKG_VERSION); + chip_report_printf("%lu", pkg_ver); #else chip_report_printf("Unknown"); #endif @@ -84,6 +87,7 @@ static void printChipInfo(void) { case CHIP_ESP32C3: chip_report_printf("ESP32-C3\n"); break; case CHIP_ESP32C6: chip_report_printf("ESP32-C6\n"); break; case CHIP_ESP32H2: chip_report_printf("ESP32-H2\n"); break; + case CHIP_ESP32P4: chip_report_printf("ESP32-P4\n"); break; default: chip_report_printf("Unknown %d\n", info.model); break; } printPkgVersion(); @@ -105,6 +109,8 @@ static void printChipInfo(void) { static void printFlashInfo(void) { #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 #define ESP_FLASH_IMAGE_BASE 0x1000 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define ESP_FLASH_IMAGE_BASE 0x2000 #else #define ESP_FLASH_IMAGE_BASE 0x0000 #endif diff --git a/cores/esp32/esp32-hal-adc.c b/cores/esp32/esp32-hal-adc.c index ee9cd02a623..c7cc1f5d556 100644 --- a/cores/esp32/esp32-hal-adc.c +++ b/cores/esp32/esp32-hal-adc.c @@ -75,7 +75,7 @@ static bool adcDetachBus(void *pin) { if (err != ESP_OK) { return false; } -#elif !defined(CONFIG_IDF_TARGET_ESP32H2) +#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle); if (err != ESP_OK) { return false; @@ -127,7 +127,7 @@ esp_err_t __analogChannelConfig(adc_bitwidth_t width, adc_attenuation_t atten, i log_e("adc_cali_create_scheme_curve_fitting failed with error: %d", err); return err; } -#elif !defined(CONFIG_IDF_TARGET_ESP32H2) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED +#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED log_d("Deleting ADC_UNIT_%d line cali handle", adc_unit); err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle); if (err != ESP_OK) { @@ -310,7 +310,7 @@ uint32_t __analogReadMilliVolts(uint8_t pin) { .bitwidth = __analogWidth, }; err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_handle[adc_unit].adc_cali_handle); -#elif !defined(CONFIG_IDF_TARGET_ESP32H2) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED +#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED adc_cali_line_fitting_config_t cali_config = { .unit_id = adc_unit, .bitwidth = __analogWidth, @@ -379,7 +379,7 @@ static bool adcContinuousDetachBus(void *adc_unit_number) { if (err != ESP_OK) { return false; } -#elif !defined(CONFIG_IDF_TARGET_ESP32H2) +#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle); if (err != ESP_OK) { return false; @@ -552,7 +552,7 @@ bool analogContinuous(const uint8_t pins[], size_t pins_count, uint32_t conversi .bitwidth = __adcContinuousWidth, }; err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_handle[adc_unit].adc_cali_handle); -#elif !defined(CONFIG_IDF_TARGET_ESP32H2) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED +#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED adc_cali_line_fitting_config_t cali_config = { .unit_id = adc_unit, .bitwidth = __adcContinuousWidth, diff --git a/cores/esp32/esp32-hal-cpu.c b/cores/esp32/esp32-hal-cpu.c index 2420dfbeeb0..f0a30b50afc 100644 --- a/cores/esp32/esp32-hal-cpu.c +++ b/cores/esp32/esp32-hal-cpu.c @@ -19,7 +19,7 @@ #include "esp_attr.h" #include "esp_log.h" #include "soc/rtc.h" -#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) +#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4) #include "soc/rtc_cntl_reg.h" #include "soc/syscon_reg.h" #endif @@ -46,6 +46,8 @@ #include "esp32c6/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/rtc.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif @@ -161,13 +163,13 @@ bool removeApbChangeCallback(void *arg, apb_change_cb_t cb) { } static uint32_t calculateApb(rtc_cpu_freq_config_t *conf) { -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 - return APB_CLK_FREQ; -#else +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 if (conf->freq_mhz >= 80) { return 80 * MHZ; } return (conf->source_freq_mhz * MHZ) / conf->div; +#else + return APB_CLK_FREQ; #endif } @@ -177,7 +179,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { rtc_cpu_freq_config_t conf, cconf; uint32_t capb, apb; //Get XTAL Frequency and calculate min CPU MHz -#ifndef CONFIG_IDF_TARGET_ESP32H2 +#if (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) rtc_xtal_freq_t xtal = rtc_clk_xtal_freq_get(); #endif #if CONFIG_IDF_TARGET_ESP32 @@ -193,7 +195,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { } } #endif -#ifndef CONFIG_IDF_TARGET_ESP32H2 +#if (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) if (cpu_freq_mhz > xtal && cpu_freq_mhz != 240 && cpu_freq_mhz != 160 && cpu_freq_mhz != 120 && cpu_freq_mhz != 80) { if (xtal >= RTC_XTAL_FREQ_40M) { log_e("Bad frequency: %u MHz! Options are: 240, 160, 120, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal / 2, xtal / 4); @@ -235,7 +237,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { } //Make the frequency change rtc_clk_cpu_freq_set_config_fast(&conf); -#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) +#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) if (capb != apb) { //Update REF_TICK (uncomment if REF_TICK is different than 1MHz) //if(conf.freq_mhz < 80){ @@ -248,11 +250,8 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { } #endif //Update FreeRTOS Tick Divisor -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 -#elif CONFIG_IDF_TARGET_ESP32S3 - -#else +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 uint32_t fcpu = (conf.freq_mhz >= 80) ? (conf.freq_mhz * MHZ) : (apb); _xt_tick_divisor = fcpu / XT_TICK_PER_SEC; #endif @@ -263,13 +262,19 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { #ifdef SOC_CLK_APLL_SUPPORTED log_d( "%s: %u / %u = %u Mhz, APB: %u Hz", - (conf.source == RTC_CPU_FREQ_SRC_PLL) ? "PLL" - : ((conf.source == RTC_CPU_FREQ_SRC_APLL) ? "APLL" : ((conf.source == RTC_CPU_FREQ_SRC_XTAL) ? "XTAL" : "8M")), + (conf.source == SOC_CPU_CLK_SRC_PLL) ? "PLL" + : ((conf.source == SOC_CPU_CLK_SRC_APLL) ? "APLL" + : ((conf.source == SOC_CPU_CLK_SRC_XTAL) ? "XTAL" +#ifdef CONFIG_IDF_TARGET_ESP32P4 + : "17.5M"), +#else + : "8M")), +#endif conf.source_freq_mhz, conf.div, conf.freq_mhz, apb ); #else log_d( - "%s: %u / %u = %u Mhz, APB: %u Hz", (conf.source == RTC_CPU_FREQ_SRC_PLL) ? "PLL" : ((conf.source == RTC_CPU_FREQ_SRC_XTAL) ? "XTAL" : "17.5M"), + "%s: %u / %u = %u Mhz, APB: %u Hz", (conf.source == SOC_CPU_CLK_SRC_PLL) ? "PLL" : ((conf.source == SOC_CPU_CLK_SRC_XTAL) ? "XTAL" : "17.5M"), conf.source_freq_mhz, conf.div, conf.freq_mhz, apb ); #endif diff --git a/cores/esp32/esp32-hal-i2c-slave.c b/cores/esp32/esp32-hal-i2c-slave.c index 5504fd62adf..14da815455b 100644 --- a/cores/esp32/esp32-hal-i2c-slave.c +++ b/cores/esp32/esp32-hal-i2c-slave.c @@ -41,14 +41,32 @@ #include "esp_intr_alloc.h" #include "soc/i2c_reg.h" #include "soc/i2c_struct.h" +#include "soc/periph_defs.h" #include "hal/i2c_ll.h" #include "hal/clk_gate_ll.h" #include "esp32-hal-log.h" #include "esp32-hal-i2c-slave.h" #include "esp32-hal-periman.h" +#include "esp_private/periph_ctrl.h" + +#if SOC_PERIPH_CLK_CTRL_SHARED +#define I2C_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define I2C_CLOCK_SRC_ATOMIC() +#endif + +#if !SOC_RCC_IS_INDEPENDENT +#define I2C_RCC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define I2C_RCC_ATOMIC() +#endif #define I2C_SLAVE_USE_RX_QUEUE 0 // 1: Queue, 0: RingBuffer +#ifdef CONFIG_IDF_TARGET_ESP32P4 +#define I2C_SCL_IDX(p) ((p == 0) ? I2C0_SCL_PAD_OUT_IDX : ((p == 1) ? I2C1_SCL_PAD_OUT_IDX : 0)) +#define I2C_SDA_IDX(p) ((p == 0) ? I2C0_SDA_PAD_OUT_IDX : ((p == 1) ? I2C1_SDA_PAD_OUT_IDX : 0)) +#else #if SOC_HP_I2C_NUM > 1 #define I2C_SCL_IDX(p) ((p == 0) ? I2CEXT0_SCL_OUT_IDX : ((p == 1) ? I2CEXT1_SCL_OUT_IDX : 0)) #define I2C_SDA_IDX(p) ((p == 0) ? I2CEXT0_SDA_OUT_IDX : ((p == 1) ? I2CEXT1_SDA_OUT_IDX : 0)) @@ -56,6 +74,7 @@ #define I2C_SCL_IDX(p) I2CEXT0_SCL_OUT_IDX #define I2C_SDA_IDX(p) I2CEXT0_SDA_OUT_IDX #endif +#endif // ifdef CONFIG_IDF_TARGET_ESP32P4 #if CONFIG_IDF_TARGET_ESP32 #define I2C_TXFIFO_WM_INT_ENA I2C_TXFIFO_EMPTY_INT_ENA @@ -173,19 +192,19 @@ static inline void i2c_ll_stretch_clr(i2c_dev_t *hw) { } static inline bool i2c_ll_slave_addressed(i2c_dev_t *hw) { -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 - return hw->sr.slave_addressed; -#else +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 return hw->status_reg.slave_addressed; +#else + return hw->sr.slave_addressed; #endif } static inline bool i2c_ll_slave_rw(i2c_dev_t *hw) //not exposed by hal_ll { -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 - return hw->sr.slave_rw; -#else +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 return hw->status_reg.slave_rw; +#else + return hw->sr.slave_rw; #endif } @@ -306,7 +325,7 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency = 100000L; } frequency = (frequency * 5) / 4; - +#if !defined(CONFIG_IDF_TARGET_ESP32P4) if (i2c->num == 0) { periph_ll_enable_clk_clear_rst(PERIPH_I2C0_MODULE); #if SOC_HP_I2C_NUM > 1 @@ -314,6 +333,7 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t periph_ll_enable_clk_clear_rst(PERIPH_I2C1_MODULE); #endif } +#endif // !defined(CONFIG_IDF_TARGET_ESP32P4) i2c_ll_slave_init(i2c->dev); i2c_ll_slave_set_fifo_mode(i2c->dev, true); @@ -341,145 +361,155 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t if (!i2c->intr_handle) { uint32_t flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED; +#if !defined(CONFIG_IDF_TARGET_ESP32P4) if (i2c->num == 0) { ret = esp_intr_alloc(ETS_I2C_EXT0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); #if SOC_HP_I2C_NUM > 1 } else { ret = esp_intr_alloc(ETS_I2C_EXT1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); #endif - } +#endif // !defined(CONFIG_IDF_TARGET_ESP32P4) +#ifdef CONFIG_IDF_TARGET_ESP32P4 + if (i2c->num == 0) { + ret = esp_intr_alloc(ETS_I2C0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); +#if SOC_I2C_NUM > 1 + } else { + ret = esp_intr_alloc(ETS_I2C1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); +#endif +#endif // #ifdef CONFIG_IDF_TARGET_ESP32P4 + } - if (ret != ESP_OK) { - log_e("install interrupt handler Failed=%d", ret); - goto fail; + if (ret != ESP_OK) { + log_e("install interrupt handler Failed=%d", ret); + goto fail; + } } - } - i2c_ll_txfifo_rst(i2c->dev); - i2c_ll_rxfifo_rst(i2c->dev); - i2c_ll_slave_enable_rx_it(i2c->dev); - i2c_ll_set_stretch(i2c->dev, 0x3FF); - i2c_ll_update(i2c->dev); - if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_SLAVE_SDA, (void *)(i2c->num + 1), i2c->num, -1) - || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_SLAVE_SCL, (void *)(i2c->num + 1), i2c->num, -1)) { - i2cSlaveDetachBus((void *)(i2c->num + 1)); - ret = ESP_FAIL; - } - I2C_SLAVE_MUTEX_UNLOCK(); - return ret; + i2c_ll_txfifo_rst(i2c->dev); + i2c_ll_rxfifo_rst(i2c->dev); + i2c_ll_slave_enable_rx_it(i2c->dev); + i2c_ll_set_stretch(i2c->dev, 0x3FF); + i2c_ll_update(i2c->dev); + if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_SLAVE_SDA, (void *)(i2c->num + 1), i2c->num, -1) + || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_SLAVE_SCL, (void *)(i2c->num + 1), i2c->num, -1)) { + i2cSlaveDetachBus((void *)(i2c->num + 1)); + ret = ESP_FAIL; + } + I2C_SLAVE_MUTEX_UNLOCK(); + return ret; fail: - i2c_slave_free_resources(i2c); - I2C_SLAVE_MUTEX_UNLOCK(); - return ret; -} - -esp_err_t i2cSlaveDeinit(uint8_t num) { - if (num >= SOC_HP_I2C_NUM) { - log_e("Invalid port num: %u", num); - return ESP_ERR_INVALID_ARG; + i2c_slave_free_resources(i2c); + I2C_SLAVE_MUTEX_UNLOCK(); + return ret; } - i2c_slave_struct_t *i2c = &_i2c_bus_array[num]; + esp_err_t i2cSlaveDeinit(uint8_t num) { + if (num >= SOC_HP_I2C_NUM) { + log_e("Invalid port num: %u", num); + return ESP_ERR_INVALID_ARG; + } + + i2c_slave_struct_t *i2c = &_i2c_bus_array[num]; #if !CONFIG_DISABLE_HAL_LOCKS - if (!i2c->lock) { - log_e("Lock is not initialized! Did you call i2c_slave_init()?"); - return ESP_ERR_NO_MEM; - } + if (!i2c->lock) { + log_e("Lock is not initialized! Did you call i2c_slave_init()?"); + return ESP_ERR_NO_MEM; + } #endif - I2C_SLAVE_MUTEX_LOCK(); - int scl = i2c->scl; - int sda = i2c->sda; - i2c_slave_free_resources(i2c); - perimanClearPinBus(scl); - perimanClearPinBus(sda); - I2C_SLAVE_MUTEX_UNLOCK(); - return ESP_OK; -} - -size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms) { - if (num >= SOC_HP_I2C_NUM) { - log_e("Invalid port num: %u", num); - return 0; - } - uint32_t to_queue = 0, to_fifo = 0; - i2c_slave_struct_t *i2c = &_i2c_bus_array[num]; + I2C_SLAVE_MUTEX_LOCK(); + int scl = i2c->scl; + int sda = i2c->sda; + i2c_slave_free_resources(i2c); + perimanClearPinBus(scl); + perimanClearPinBus(sda); + I2C_SLAVE_MUTEX_UNLOCK(); + return ESP_OK; + } + + size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms) { + if (num >= SOC_HP_I2C_NUM) { + log_e("Invalid port num: %u", num); + return 0; + } + uint32_t to_queue = 0, to_fifo = 0; + i2c_slave_struct_t *i2c = &_i2c_bus_array[num]; #if !CONFIG_DISABLE_HAL_LOCKS - if (!i2c->lock) { - log_e("Lock is not initialized! Did you call i2c_slave_init()?"); - return ESP_ERR_NO_MEM; - } + if (!i2c->lock) { + log_e("Lock is not initialized! Did you call i2c_slave_init()?"); + return ESP_ERR_NO_MEM; + } #endif - if (!i2c->tx_queue) { - return 0; - } - I2C_SLAVE_MUTEX_LOCK(); + if (!i2c->tx_queue) { + return 0; + } + I2C_SLAVE_MUTEX_LOCK(); #if CONFIG_IDF_TARGET_ESP32 - i2c_ll_slave_disable_tx_it(i2c->dev); - uint32_t txfifo_len = 0; - i2c_ll_get_txfifo_len(i2c->dev, &txfifo_len); - if (txfifo_len < SOC_I2C_FIFO_LEN) { - i2c_ll_txfifo_rst(i2c->dev); - } + i2c_ll_slave_disable_tx_it(i2c->dev); + uint32_t txfifo_len = 0; + i2c_ll_get_txfifo_len(i2c->dev, &txfifo_len); + if (txfifo_len < SOC_I2C_FIFO_LEN) { + i2c_ll_txfifo_rst(i2c->dev); + } #endif - i2c_ll_get_txfifo_len(i2c->dev, &to_fifo); - if (to_fifo) { - if (len < to_fifo) { - to_fifo = len; - } - i2c_ll_write_txfifo(i2c->dev, (uint8_t *)buf, to_fifo); - buf += to_fifo; - len -= to_fifo; - //reset tx_queue - xQueueReset(i2c->tx_queue); - //write the rest of the bytes to the queue - if (len) { - to_queue = uxQueueSpacesAvailable(i2c->tx_queue); - if (len < to_queue) { - to_queue = len; + i2c_ll_get_txfifo_len(i2c->dev, &to_fifo); + if (to_fifo) { + if (len < to_fifo) { + to_fifo = len; } - for (size_t i = 0; i < to_queue; i++) { - if (xQueueSend(i2c->tx_queue, &buf[i], timeout_ms / portTICK_PERIOD_MS) != pdTRUE) { - xQueueReset(i2c->tx_queue); - to_queue = 0; - break; + i2c_ll_write_txfifo(i2c->dev, (uint8_t *)buf, to_fifo); + buf += to_fifo; + len -= to_fifo; + //reset tx_queue + xQueueReset(i2c->tx_queue); + //write the rest of the bytes to the queue + if (len) { + to_queue = uxQueueSpacesAvailable(i2c->tx_queue); + if (len < to_queue) { + to_queue = len; + } + for (size_t i = 0; i < to_queue; i++) { + if (xQueueSend(i2c->tx_queue, &buf[i], timeout_ms / portTICK_PERIOD_MS) != pdTRUE) { + xQueueReset(i2c->tx_queue); + to_queue = 0; + break; + } + } + //no need to enable TX_EMPTY if tx_queue is empty + if (to_queue) { + i2c_ll_slave_enable_tx_it(i2c->dev); } - } - //no need to enable TX_EMPTY if tx_queue is empty - if (to_queue) { - i2c_ll_slave_enable_tx_it(i2c->dev); } } + I2C_SLAVE_MUTEX_UNLOCK(); + return to_queue + to_fifo; } - I2C_SLAVE_MUTEX_UNLOCK(); - return to_queue + to_fifo; -} -//===================================================================================================================== -//-------------------------------------- Private Functions ------------------------------------------------------------ -//===================================================================================================================== + //===================================================================================================================== + //-------------------------------------- Private Functions ------------------------------------------------------------ + //===================================================================================================================== -static void i2c_slave_free_resources(i2c_slave_struct_t *i2c) { - i2c_slave_detach_gpio(i2c); - i2c_ll_set_slave_addr(i2c->dev, 0, false); - i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK); - i2c_ll_clear_intr_mask(i2c->dev, I2C_LL_INTR_MASK); + static void i2c_slave_free_resources(i2c_slave_struct_t * i2c) { + i2c_slave_detach_gpio(i2c); + i2c_ll_set_slave_addr(i2c->dev, 0, false); + i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK); + i2c_ll_clear_intr_mask(i2c->dev, I2C_LL_INTR_MASK); - if (i2c->intr_handle) { - esp_intr_free(i2c->intr_handle); - i2c->intr_handle = NULL; - } + if (i2c->intr_handle) { + esp_intr_free(i2c->intr_handle); + i2c->intr_handle = NULL; + } - if (i2c->task_handle) { - vTaskDelete(i2c->task_handle); - i2c->task_handle = NULL; - } + if (i2c->task_handle) { + vTaskDelete(i2c->task_handle); + i2c->task_handle = NULL; + } #if I2C_SLAVE_USE_RX_QUEUE - if (i2c->rx_queue) { - vQueueDelete(i2c->rx_queue); - i2c->rx_queue = NULL; - } + if (i2c->rx_queue) { + vQueueDelete(i2c->rx_queue); + i2c->rx_queue = NULL; + } #else if (i2c->rx_ring_buf) { vRingbufferDelete(i2c->rx_ring_buf); @@ -487,198 +517,202 @@ static void i2c_slave_free_resources(i2c_slave_struct_t *i2c) { } #endif - if (i2c->tx_queue) { - vQueueDelete(i2c->tx_queue); - i2c->tx_queue = NULL; - } - - if (i2c->event_queue) { - vQueueDelete(i2c->event_queue); - i2c->event_queue = NULL; - } + if (i2c->tx_queue) { + vQueueDelete(i2c->tx_queue); + i2c->tx_queue = NULL; + } - i2c->rx_data_count = 0; -} + if (i2c->event_queue) { + vQueueDelete(i2c->event_queue); + i2c->event_queue = NULL; + } -static bool i2c_slave_set_frequency(i2c_slave_struct_t *i2c, uint32_t clk_speed) { - if (i2c == NULL) { - log_e("no control buffer"); - return false; - } - if (clk_speed > 1100000UL) { - clk_speed = 1100000UL; + i2c->rx_data_count = 0; } - // Adjust Fifo thresholds based on frequency - uint32_t a = (clk_speed / 50000L) + 2; - log_d("Fifo thresholds: rx_fifo_full = %d, tx_fifo_empty = %d", SOC_I2C_FIFO_LEN - a, a); + static bool i2c_slave_set_frequency(i2c_slave_struct_t * i2c, uint32_t clk_speed) { + if (i2c == NULL) { + log_e("no control buffer"); + return false; + } + if (clk_speed > 1100000UL) { + clk_speed = 1100000UL; + } + + // Adjust Fifo thresholds based on frequency + uint32_t a = (clk_speed / 50000L) + 2; + log_d("Fifo thresholds: rx_fifo_full = %d, tx_fifo_empty = %d", SOC_I2C_FIFO_LEN - a, a); - i2c_hal_clk_config_t clk_cal; + i2c_hal_clk_config_t clk_cal; #if SOC_I2C_SUPPORT_APB - i2c_ll_master_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal); - i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_APB); /*!< I2C source clock from APB, 80M*/ + i2c_ll_master_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal); + I2C_CLOCK_SRC_ATOMIC() { + i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_APB); /*!< I2C source clock from APB, 80M*/ + } #elif SOC_I2C_SUPPORT_XTAL i2c_ll_master_cal_bus_clk(XTAL_CLK_FREQ, clk_speed, &clk_cal); - i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_XTAL); /*!< I2C source clock from XTAL, 40M */ + I2C_CLOCK_SRC_ATOMIC() { + i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_XTAL); /*!< I2C source clock from XTAL, 40M */ + } #endif - i2c_ll_set_txfifo_empty_thr(i2c->dev, a); - i2c_ll_set_rxfifo_full_thr(i2c->dev, SOC_I2C_FIFO_LEN - a); - i2c_ll_master_set_bus_timing(i2c->dev, &clk_cal); - i2c_ll_master_set_filter(i2c->dev, 3); - return true; -} + i2c_ll_set_txfifo_empty_thr(i2c->dev, a); + i2c_ll_set_rxfifo_full_thr(i2c->dev, SOC_I2C_FIFO_LEN - a); + i2c_ll_master_set_bus_timing(i2c->dev, &clk_cal); + i2c_ll_master_set_filter(i2c->dev, 3); + return true; + } -static void i2c_slave_delay_us(uint64_t us) { - uint64_t m = esp_timer_get_time(); - if (us) { - uint64_t e = (m + us); - if (m > e) { //overflow - while ((uint64_t)esp_timer_get_time() > e); + static void i2c_slave_delay_us(uint64_t us) { + uint64_t m = esp_timer_get_time(); + if (us) { + uint64_t e = (m + us); + if (m > e) { //overflow + while ((uint64_t)esp_timer_get_time() > e); + } + while ((uint64_t)esp_timer_get_time() < e); } - while ((uint64_t)esp_timer_get_time() < e); } -} -static void i2c_slave_gpio_mode(int8_t pin, gpio_mode_t mode) { - gpio_config_t conf = { - .pin_bit_mask = 1LL << pin, .mode = mode, .pull_up_en = GPIO_PULLUP_ENABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, .intr_type = GPIO_INTR_DISABLE - }; - gpio_config(&conf); -} + static void i2c_slave_gpio_mode(int8_t pin, gpio_mode_t mode) { + gpio_config_t conf = { + .pin_bit_mask = 1LL << pin, .mode = mode, .pull_up_en = GPIO_PULLUP_ENABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, .intr_type = GPIO_INTR_DISABLE + }; + gpio_config(&conf); + } -static bool i2c_slave_check_line_state(int8_t sda, int8_t scl) { - if (sda < 0 || scl < 0) { - return false; //return false since there is nothing to do - } - // if the bus is not 'clear' try the cycling SCL until SDA goes High or 9 cycles - gpio_set_level(sda, 1); - gpio_set_level(scl, 1); - i2c_slave_gpio_mode(sda, GPIO_MODE_INPUT | GPIO_MODE_DEF_OD); - i2c_slave_gpio_mode(scl, GPIO_MODE_INPUT | GPIO_MODE_DEF_OD); - gpio_set_level(scl, 1); - - if (!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state - log_w("invalid state sda(%d)=%d, scl(%d)=%d", sda, gpio_get_level(sda), scl, gpio_get_level(scl)); - for (uint8_t a = 0; a < 9; a++) { - i2c_slave_delay_us(5); - if (gpio_get_level(sda) && gpio_get_level(scl)) { // bus recovered - log_w("Recovered after %d Cycles", a); - gpio_set_level(sda, 0); // start + static bool i2c_slave_check_line_state(int8_t sda, int8_t scl) { + if (sda < 0 || scl < 0) { + return false; //return false since there is nothing to do + } + // if the bus is not 'clear' try the cycling SCL until SDA goes High or 9 cycles + gpio_set_level(sda, 1); + gpio_set_level(scl, 1); + i2c_slave_gpio_mode(sda, GPIO_MODE_INPUT | GPIO_MODE_DEF_OD); + i2c_slave_gpio_mode(scl, GPIO_MODE_INPUT | GPIO_MODE_DEF_OD); + gpio_set_level(scl, 1); + + if (!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state + log_w("invalid state sda(%d)=%d, scl(%d)=%d", sda, gpio_get_level(sda), scl, gpio_get_level(scl)); + for (uint8_t a = 0; a < 9; a++) { i2c_slave_delay_us(5); - for (uint8_t a = 0; a < 9; a++) { - gpio_set_level(scl, 1); + if (gpio_get_level(sda) && gpio_get_level(scl)) { // bus recovered + log_w("Recovered after %d Cycles", a); + gpio_set_level(sda, 0); // start i2c_slave_delay_us(5); - gpio_set_level(scl, 0); + for (uint8_t a = 0; a < 9; a++) { + gpio_set_level(scl, 1); + i2c_slave_delay_us(5); + gpio_set_level(scl, 0); + i2c_slave_delay_us(5); + } + gpio_set_level(scl, 1); i2c_slave_delay_us(5); + gpio_set_level(sda, 1); // stop + break; } - gpio_set_level(scl, 1); + gpio_set_level(scl, 0); i2c_slave_delay_us(5); - gpio_set_level(sda, 1); // stop - break; + gpio_set_level(scl, 1); } - gpio_set_level(scl, 0); - i2c_slave_delay_us(5); - gpio_set_level(scl, 1); } - } - - if (!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state - log_e("Bus Invalid State, Can't init sda=%d, scl=%d", gpio_get_level(sda), gpio_get_level(scl)); - return false; // bus is busy - } - return true; -} -static bool i2c_slave_attach_gpio(i2c_slave_struct_t *i2c, int8_t sda, int8_t scl) { - if (i2c == NULL) { - log_e("no control block"); - return false; + if (!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state + log_e("Bus Invalid State, Can't init sda=%d, scl=%d", gpio_get_level(sda), gpio_get_level(scl)); + return false; // bus is busy + } + return true; } - if ((sda < 0) || (scl < 0)) { - log_e("bad pins sda=%d, scl=%d", sda, scl); - return false; - } + static bool i2c_slave_attach_gpio(i2c_slave_struct_t * i2c, int8_t sda, int8_t scl) { + if (i2c == NULL) { + log_e("no control block"); + return false; + } - i2c->scl = scl; - gpio_set_level(scl, 1); - i2c_slave_gpio_mode(scl, GPIO_MODE_INPUT_OUTPUT_OD); - gpio_matrix_out(scl, I2C_SCL_IDX(i2c->num), false, false); - gpio_matrix_in(scl, I2C_SCL_IDX(i2c->num), false); + if ((sda < 0) || (scl < 0)) { + log_e("bad pins sda=%d, scl=%d", sda, scl); + return false; + } - i2c->sda = sda; - gpio_set_level(sda, 1); - i2c_slave_gpio_mode(sda, GPIO_MODE_INPUT_OUTPUT_OD); - gpio_matrix_out(sda, I2C_SDA_IDX(i2c->num), false, false); - gpio_matrix_in(sda, I2C_SDA_IDX(i2c->num), false); + i2c->scl = scl; + gpio_set_level(scl, 1); + i2c_slave_gpio_mode(scl, GPIO_MODE_INPUT_OUTPUT_OD); + gpio_matrix_out(scl, I2C_SCL_IDX(i2c->num), false, false); + gpio_matrix_in(scl, I2C_SCL_IDX(i2c->num), false); - return true; -} + i2c->sda = sda; + gpio_set_level(sda, 1); + i2c_slave_gpio_mode(sda, GPIO_MODE_INPUT_OUTPUT_OD); + gpio_matrix_out(sda, I2C_SDA_IDX(i2c->num), false, false); + gpio_matrix_in(sda, I2C_SDA_IDX(i2c->num), false); -static bool i2c_slave_detach_gpio(i2c_slave_struct_t *i2c) { - if (i2c == NULL) { - log_e("no control Block"); - return false; - } - if (i2c->scl >= 0) { - gpio_matrix_out(i2c->scl, 0x100, false, false); - gpio_matrix_in(0x30, I2C_SCL_IDX(i2c->num), false); - i2c_slave_gpio_mode(i2c->scl, GPIO_MODE_INPUT); - i2c->scl = -1; // un attached - } - if (i2c->sda >= 0) { - gpio_matrix_out(i2c->sda, 0x100, false, false); - gpio_matrix_in(0x30, I2C_SDA_IDX(i2c->num), false); - i2c_slave_gpio_mode(i2c->sda, GPIO_MODE_INPUT); - i2c->sda = -1; // un attached + return true; } - return true; -} -static bool i2c_slave_send_event(i2c_slave_struct_t *i2c, i2c_slave_queue_event_t *event) { - bool pxHigherPriorityTaskWoken = false; - if (i2c->event_queue) { - if (xQueueSendFromISR(i2c->event_queue, event, (BaseType_t *const)&pxHigherPriorityTaskWoken) != pdTRUE) { - //log_e("event_queue_full"); + static bool i2c_slave_detach_gpio(i2c_slave_struct_t * i2c) { + if (i2c == NULL) { + log_e("no control Block"); + return false; + } + if (i2c->scl >= 0) { + gpio_matrix_out(i2c->scl, 0x100, false, false); + gpio_matrix_in(0x30, I2C_SCL_IDX(i2c->num), false); + i2c_slave_gpio_mode(i2c->scl, GPIO_MODE_INPUT); + i2c->scl = -1; // un attached } + if (i2c->sda >= 0) { + gpio_matrix_out(i2c->sda, 0x100, false, false); + gpio_matrix_in(0x30, I2C_SDA_IDX(i2c->num), false); + i2c_slave_gpio_mode(i2c->sda, GPIO_MODE_INPUT); + i2c->sda = -1; // un attached + } + return true; } - return pxHigherPriorityTaskWoken; -} -static bool i2c_slave_handle_tx_fifo_empty(i2c_slave_struct_t *i2c) { - bool pxHigherPriorityTaskWoken = false; - uint32_t d = 0, moveCnt = 0; - i2c_ll_get_txfifo_len(i2c->dev, &moveCnt); - while (moveCnt > 0) { // read tx queue until Fifo is full or queue is empty - if (xQueueReceiveFromISR(i2c->tx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) == pdTRUE) { - i2c_ll_write_txfifo(i2c->dev, (uint8_t *)&d, 1); - moveCnt--; - } else { - i2c_ll_slave_disable_tx_it(i2c->dev); - break; + static bool i2c_slave_send_event(i2c_slave_struct_t * i2c, i2c_slave_queue_event_t * event) { + bool pxHigherPriorityTaskWoken = false; + if (i2c->event_queue) { + if (xQueueSendFromISR(i2c->event_queue, event, (BaseType_t *const)&pxHigherPriorityTaskWoken) != pdTRUE) { + //log_e("event_queue_full"); + } + } + return pxHigherPriorityTaskWoken; + } + + static bool i2c_slave_handle_tx_fifo_empty(i2c_slave_struct_t * i2c) { + bool pxHigherPriorityTaskWoken = false; + uint32_t d = 0, moveCnt = 0; + i2c_ll_get_txfifo_len(i2c->dev, &moveCnt); + while (moveCnt > 0) { // read tx queue until Fifo is full or queue is empty + if (xQueueReceiveFromISR(i2c->tx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) == pdTRUE) { + i2c_ll_write_txfifo(i2c->dev, (uint8_t *)&d, 1); + moveCnt--; + } else { + i2c_ll_slave_disable_tx_it(i2c->dev); + break; + } } + return pxHigherPriorityTaskWoken; } - return pxHigherPriorityTaskWoken; -} -static bool i2c_slave_handle_rx_fifo_full(i2c_slave_struct_t *i2c, uint32_t len) { + static bool i2c_slave_handle_rx_fifo_full(i2c_slave_struct_t * i2c, uint32_t len) { #if I2C_SLAVE_USE_RX_QUEUE - uint32_t d = 0; + uint32_t d = 0; #else uint8_t data[SOC_I2C_FIFO_LEN]; #endif - bool pxHigherPriorityTaskWoken = false; + bool pxHigherPriorityTaskWoken = false; #if I2C_SLAVE_USE_RX_QUEUE - while (len > 0) { - i2c_ll_read_rxfifo(i2c->dev, (uint8_t *)&d, 1); - if (xQueueSendFromISR(i2c->rx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) != pdTRUE) { - log_e("rx_queue_full"); - } else { - i2c->rx_data_count++; - } - if (--len == 0) { - len = i2c_ll_get_rxfifo_cnt(i2c->dev); - } + while (len > 0) { + i2c_ll_read_rxfifo(i2c->dev, (uint8_t *)&d, 1); + if (xQueueSendFromISR(i2c->rx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) != pdTRUE) { + log_e("rx_queue_full"); + } else { + i2c->rx_data_count++; + } + if (--len == 0) { + len = i2c_ll_get_rxfifo_cnt(i2c->dev); + } #else if (len) { i2c_ll_read_rxfifo(i2c->dev, data, len); @@ -688,109 +722,109 @@ static bool i2c_slave_handle_rx_fifo_full(i2c_slave_struct_t *i2c, uint32_t len) i2c->rx_data_count += len; } #endif + } + return pxHigherPriorityTaskWoken; } - return pxHigherPriorityTaskWoken; -} - -static void i2c_slave_isr_handler(void *arg) { - bool pxHigherPriorityTaskWoken = false; - i2c_slave_struct_t *i2c = (i2c_slave_struct_t *)arg; // recover data - uint32_t activeInt = 0; - i2c_ll_get_intr_mask(i2c->dev, &activeInt); - i2c_ll_clear_intr_mask(i2c->dev, activeInt); - uint32_t rx_fifo_len = 0; - i2c_ll_get_rxfifo_cnt(i2c->dev, &rx_fifo_len); - bool slave_rw = i2c_ll_slave_rw(i2c->dev); + static void i2c_slave_isr_handler(void *arg) { + bool pxHigherPriorityTaskWoken = false; + i2c_slave_struct_t *i2c = (i2c_slave_struct_t *)arg; // recover data - if (activeInt & I2C_RXFIFO_WM_INT_ENA) { // RX FiFo Full - pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len); - i2c_ll_slave_enable_rx_it(i2c->dev); //is this necessary? - } + uint32_t activeInt = 0; + i2c_ll_get_intr_mask(i2c->dev, &activeInt); + i2c_ll_clear_intr_mask(i2c->dev, activeInt); + uint32_t rx_fifo_len = 0; + i2c_ll_get_rxfifo_cnt(i2c->dev, &rx_fifo_len); + bool slave_rw = i2c_ll_slave_rw(i2c->dev); - if (activeInt & I2C_TRANS_COMPLETE_INT_ENA) { // STOP - if (rx_fifo_len) { //READ RX FIFO + if (activeInt & I2C_RXFIFO_WM_INT_ENA) { // RX FiFo Full pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len); + i2c_ll_slave_enable_rx_it(i2c->dev); //is this necessary? } - if (i2c->rx_data_count) { //WRITE or RepeatedStart - //SEND RX Event - i2c_slave_queue_event_t event; - event.event = I2C_SLAVE_EVT_RX; - event.stop = !slave_rw; - event.param = i2c->rx_data_count; - pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event); - //Zero RX count - i2c->rx_data_count = 0; - } - if (slave_rw) { // READ -#if CONFIG_IDF_TARGET_ESP32 - if (i2c->dev->status_reg.scl_main_state_last == 6) { - //SEND TX Event + + if (activeInt & I2C_TRANS_COMPLETE_INT_ENA) { // STOP + if (rx_fifo_len) { //READ RX FIFO + pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len); + } + if (i2c->rx_data_count) { //WRITE or RepeatedStart + //SEND RX Event i2c_slave_queue_event_t event; - event.event = I2C_SLAVE_EVT_TX; + event.event = I2C_SLAVE_EVT_RX; + event.stop = !slave_rw; + event.param = i2c->rx_data_count; pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event); + //Zero RX count + i2c->rx_data_count = 0; } + if (slave_rw) { // READ +#if CONFIG_IDF_TARGET_ESP32 + if (i2c->dev->status_reg.scl_main_state_last == 6) { + //SEND TX Event + i2c_slave_queue_event_t event; + event.event = I2C_SLAVE_EVT_TX; + pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event); + } #else //reset TX data i2c_ll_txfifo_rst(i2c->dev); uint8_t d; while (xQueueReceiveFromISR(i2c->tx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) == pdTRUE); //flush partial write #endif + } } - } #ifndef CONFIG_IDF_TARGET_ESP32 - if (activeInt & I2C_SLAVE_STRETCH_INT_ENA) { // STRETCH - i2c_stretch_cause_t cause = i2c_ll_stretch_cause(i2c->dev); - if (cause == I2C_STRETCH_CAUSE_MASTER_READ) { - //on C3 RX data disappears with repeated start, so we need to get it here - if (rx_fifo_len) { + if (activeInt & I2C_SLAVE_STRETCH_INT_ENA) { // STRETCH + i2c_stretch_cause_t cause = i2c_ll_stretch_cause(i2c->dev); + if (cause == I2C_STRETCH_CAUSE_MASTER_READ) { + //on C3 RX data disappears with repeated start, so we need to get it here + if (rx_fifo_len) { + pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len); + } + //SEND TX Event + i2c_slave_queue_event_t event; + event.event = I2C_SLAVE_EVT_TX; + pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event); + //will clear after execution + } else if (cause == I2C_STRETCH_CAUSE_TX_FIFO_EMPTY) { + pxHigherPriorityTaskWoken |= i2c_slave_handle_tx_fifo_empty(i2c); + i2c_ll_stretch_clr(i2c->dev); + } else if (cause == I2C_STRETCH_CAUSE_RX_FIFO_FULL) { pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len); + i2c_ll_stretch_clr(i2c->dev); } - //SEND TX Event - i2c_slave_queue_event_t event; - event.event = I2C_SLAVE_EVT_TX; - pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event); - //will clear after execution - } else if (cause == I2C_STRETCH_CAUSE_TX_FIFO_EMPTY) { - pxHigherPriorityTaskWoken |= i2c_slave_handle_tx_fifo_empty(i2c); - i2c_ll_stretch_clr(i2c->dev); - } else if (cause == I2C_STRETCH_CAUSE_RX_FIFO_FULL) { - pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len); - i2c_ll_stretch_clr(i2c->dev); } - } #endif - if (activeInt & I2C_TXFIFO_WM_INT_ENA) { // TX FiFo Empty - pxHigherPriorityTaskWoken |= i2c_slave_handle_tx_fifo_empty(i2c); - } + if (activeInt & I2C_TXFIFO_WM_INT_ENA) { // TX FiFo Empty + pxHigherPriorityTaskWoken |= i2c_slave_handle_tx_fifo_empty(i2c); + } - if (pxHigherPriorityTaskWoken) { - portYIELD_FROM_ISR(); + if (pxHigherPriorityTaskWoken) { + portYIELD_FROM_ISR(); + } } -} -static size_t i2c_slave_read_rx(i2c_slave_struct_t *i2c, uint8_t *data, size_t len) { - if (!len) { - return 0; - } -#if I2C_SLAVE_USE_RX_QUEUE - uint8_t d = 0; - BaseType_t res = pdTRUE; - for (size_t i = 0; i < len; i++) { - if (data) { - res = xQueueReceive(i2c->rx_queue, &data[i], 0); - } else { - res = xQueueReceive(i2c->rx_queue, &d, 0); + static size_t i2c_slave_read_rx(i2c_slave_struct_t * i2c, uint8_t * data, size_t len) { + if (!len) { + return 0; } - if (res != pdTRUE) { - log_e("Read Queue(%u) Failed", i); - len = i; - break; +#if I2C_SLAVE_USE_RX_QUEUE + uint8_t d = 0; + BaseType_t res = pdTRUE; + for (size_t i = 0; i < len; i++) { + if (data) { + res = xQueueReceive(i2c->rx_queue, &data[i], 0); + } else { + res = xQueueReceive(i2c->rx_queue, &d, 0); + } + if (res != pdTRUE) { + log_e("Read Queue(%u) Failed", i); + len = i; + break; + } } - } - return (data) ? len : 0; + return (data) ? len : 0; #else size_t dlen = 0, to_read = len, so_far = 0, available = 0; uint8_t *rx_data = NULL; @@ -817,55 +851,55 @@ static size_t i2c_slave_read_rx(i2c_slave_struct_t *i2c, uint8_t *data, size_t l } return (data) ? so_far : 0; #endif -} - -static void i2c_slave_task(void *pv_args) { - i2c_slave_struct_t *i2c = (i2c_slave_struct_t *)pv_args; - i2c_slave_queue_event_t event; - size_t len = 0; - bool stop = false; - uint8_t *data = NULL; - for (;;) { - if (xQueueReceive(i2c->event_queue, &event, portMAX_DELAY) == pdTRUE) { - // Write - if (event.event == I2C_SLAVE_EVT_RX) { - len = event.param; - stop = event.stop; - data = (len > 0) ? (uint8_t *)malloc(len) : NULL; - - if (len && data == NULL) { - log_e("Malloc (%u) Failed", len); - } - len = i2c_slave_read_rx(i2c, data, len); - if (i2c->receive_callback) { - i2c->receive_callback(i2c->num, data, len, stop, i2c->arg); - } - free(data); + } - // Read - } else if (event.event == I2C_SLAVE_EVT_TX) { - if (i2c->request_callback) { - i2c->request_callback(i2c->num, i2c->arg); + static void i2c_slave_task(void *pv_args) { + i2c_slave_struct_t *i2c = (i2c_slave_struct_t *)pv_args; + i2c_slave_queue_event_t event; + size_t len = 0; + bool stop = false; + uint8_t *data = NULL; + for (;;) { + if (xQueueReceive(i2c->event_queue, &event, portMAX_DELAY) == pdTRUE) { + // Write + if (event.event == I2C_SLAVE_EVT_RX) { + len = event.param; + stop = event.stop; + data = (len > 0) ? (uint8_t *)malloc(len) : NULL; + + if (len && data == NULL) { + log_e("Malloc (%u) Failed", len); + } + len = i2c_slave_read_rx(i2c, data, len); + if (i2c->receive_callback) { + i2c->receive_callback(i2c->num, data, len, stop, i2c->arg); + } + free(data); + + // Read + } else if (event.event == I2C_SLAVE_EVT_TX) { + if (i2c->request_callback) { + i2c->request_callback(i2c->num, i2c->arg); + } + i2c_ll_stretch_clr(i2c->dev); } - i2c_ll_stretch_clr(i2c->dev); } } + vTaskDelete(NULL); } - vTaskDelete(NULL); -} -static bool i2cSlaveDetachBus(void *bus_i2c_num) { - uint8_t num = (int)bus_i2c_num - 1; - i2c_slave_struct_t *i2c = &_i2c_bus_array[num]; - if (i2c->scl == -1 && i2c->sda == -1) { + static bool i2cSlaveDetachBus(void *bus_i2c_num) { + uint8_t num = (int)bus_i2c_num - 1; + i2c_slave_struct_t *i2c = &_i2c_bus_array[num]; + if (i2c->scl == -1 && i2c->sda == -1) { + return true; + } + esp_err_t err = i2cSlaveDeinit(num); + if (err != ESP_OK) { + log_e("i2cSlaveDeinit failed with error: %d", err); + return false; + } return true; } - esp_err_t err = i2cSlaveDeinit(num); - if (err != ESP_OK) { - log_e("i2cSlaveDeinit failed with error: %d", err); - return false; - } - return true; -} #endif /* SOC_I2C_SUPPORT_SLAVE */ diff --git a/cores/esp32/esp32-hal-i2c.c b/cores/esp32/esp32-hal-i2c.c index 419ce66bb9b..359b2161201 100644 --- a/cores/esp32/esp32-hal-i2c.c +++ b/cores/esp32/esp32-hal-i2c.c @@ -29,6 +29,19 @@ #include "hal/i2c_ll.h" #include "driver/i2c.h" #include "esp32-hal-periman.h" +#include "esp_private/periph_ctrl.h" + +#if SOC_PERIPH_CLK_CTRL_SHARED +#define I2C_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define I2C_CLOCK_SRC_ATOMIC() +#endif + +#if !SOC_RCC_IS_INDEPENDENT +#define I2C_RCC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define I2C_RCC_ATOMIC() +#endif #if SOC_I2C_SUPPORT_APB || SOC_I2C_SUPPORT_XTAL #include "esp_private/esp_clk.h" @@ -388,7 +401,9 @@ esp_err_t i2cSetClock(uint8_t i2c_num, uint32_t frequency) { periph_rtc_dig_clk8m_enable(); } #endif - i2c_hal_set_bus_timing(&(hal), frequency, i2c_clk_alloc[src_clk].clk, i2c_clk_alloc[src_clk].clk_freq); + I2C_CLOCK_SRC_ATOMIC() { + i2c_hal_set_bus_timing(&(hal), frequency, i2c_clk_alloc[src_clk].clk, i2c_clk_alloc[src_clk].clk_freq); + } bus[i2c_num].frequency = frequency; //Clock Stretching Timeout: 20b:esp32, 5b:esp32-c3, 24b:esp32-s2 i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT); diff --git a/cores/esp32/esp32-hal-ledc.c b/cores/esp32/esp32-hal-ledc.c index 7d748f98a56..0a3ec5a60c7 100644 --- a/cores/esp32/esp32-hal-ledc.c +++ b/cores/esp32/esp32-hal-ledc.c @@ -323,11 +323,16 @@ bool ledcOutputInvert(uint8_t pin, bool out_invert) { ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC); if (bus != NULL) { gpio_set_level(pin, out_invert); + +#ifdef CONFIG_IDF_TARGET_ESP32P4 + esp_rom_gpio_connect_out_signal(pin, LEDC_LS_SIG_OUT_PAD_OUT0_IDX + ((bus->channel) % 8), out_invert, 0); +#else #ifdef SOC_LEDC_SUPPORT_HS_MODE esp_rom_gpio_connect_out_signal(pin, ((bus->channel / 8 == 0) ? LEDC_HS_SIG_OUT0_IDX : LEDC_LS_SIG_OUT0_IDX) + ((bus->channel) % 8), out_invert, 0); #else esp_rom_gpio_connect_out_signal(pin, LEDC_LS_SIG_OUT0_IDX + ((bus->channel) % 8), out_invert, 0); #endif +#endif // ifdef CONFIG_IDF_TARGET_ESP32P4 return true; } return false; diff --git a/cores/esp32/esp32-hal-matrix.c b/cores/esp32/esp32-hal-matrix.c index fba044d0c85..7cddb4e04db 100644 --- a/cores/esp32/esp32-hal-matrix.c +++ b/cores/esp32/esp32-hal-matrix.c @@ -32,6 +32,8 @@ #include "esp32c6/rom/gpio.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/gpio.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/gpio.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif diff --git a/cores/esp32/esp32-hal-misc.c b/cores/esp32/esp32-hal-misc.c index 7dfca6134b2..ab46eba3d09 100644 --- a/cores/esp32/esp32-hal-misc.c +++ b/cores/esp32/esp32-hal-misc.c @@ -29,7 +29,7 @@ #endif //CONFIG_BT_ENABLED #include #include "soc/rtc.h" -#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) +#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4) #include "soc/rtc_cntl_reg.h" #include "soc/syscon_reg.h" #endif @@ -53,6 +53,8 @@ #include "esp32c6/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/rtc.h" #else #error Target CONFIG_IDF_TARGET is not supported diff --git a/cores/esp32/esp32-hal-psram.c b/cores/esp32/esp32-hal-psram.c index 5a741908f07..f28095a6fd8 100644 --- a/cores/esp32/esp32-hal-psram.c +++ b/cores/esp32/esp32-hal-psram.c @@ -27,6 +27,8 @@ #include "esp32s2/rom/cache.h" #elif CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/rom/cache.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/cache.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif diff --git a/cores/esp32/esp32-hal-spi.c b/cores/esp32/esp32-hal-spi.c index 857c3d4bb2e..8c8ce0b7705 100644 --- a/cores/esp32/esp32-hal-spi.c +++ b/cores/esp32/esp32-hal-spi.c @@ -22,11 +22,13 @@ #include "esp_attr.h" #include "soc/spi_reg.h" #include "soc/spi_struct.h" +#include "soc/periph_defs.h" #include "soc/io_mux_reg.h" #include "soc/gpio_sig_map.h" #include "soc/rtc.h" #include "hal/clk_gate_ll.h" #include "esp32-hal-periman.h" +#include "esp_private/periph_ctrl.h" #include "esp_system.h" #include "esp_intr_alloc.h" @@ -55,6 +57,9 @@ #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/ets_sys.h" #include "esp32h2/rom/gpio.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/ets_sys.h" +#include "esp32p4/rom/gpio.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif @@ -96,6 +101,24 @@ struct spi_struct_t { #define SPI_FSPI_SS_IDX(n) ((n == 0) ? FSPICS0_OUT_IDX : ((n == 1) ? FSPICS1_OUT_IDX : 0)) #define SPI_SS_IDX(p, n) ((p == 0) ? SPI_FSPI_SS_IDX(n) : ((p == 1) ? SPI_HSPI_SS_IDX(n) : 0)) +#elif CONFIG_IDF_TARGET_ESP32P4 +// ESP32P4 +#define SPI_COUNT (2) // SPI2 and SPI3. SPI0 and SPI1 are reserved for flash and PSRAM + +#define SPI_CLK_IDX(p) ((p == 0) ? SPI2_CK_PAD_OUT_IDX : ((p == 1) ? SPI3_CK_PAD_OUT_IDX : 0)) +#define SPI_MISO_IDX(p) ((p == 0) ? SPI2_Q_PAD_OUT_IDX : ((p == 1) ? SPI3_QO_PAD_OUT_IDX : 0)) +#define SPI_MOSI_IDX(p) ((p == 0) ? SPI2_D_PAD_IN_IDX : ((p == 1) ? SPI3_D_PAD_IN_IDX : 0)) + +#define SPI_HSPI_SS_IDX(n) ((n == 0) ? SPI3_CS_PAD_OUT_IDX : ((n == 1) ? SPI3_CS1_PAD_OUT_IDX : ((n == 2) ? SPI3_CS2_PAD_OUT_IDX : 0))) + +#define SPI_FSPI_SS_IDX(n) \ + ((n == 0) ? SPI2_CS_PAD_OUT_IDX \ + : ((n == 1) ? SPI2_CS1_PAD_OUT_IDX \ + : ((n == 2) ? SPI2_CS2_PAD_OUT_IDX \ + : ((n == 3) ? SPI2_CS3_PAD_OUT_IDX : ((n == 4) ? SPI2_CS4_PAD_OUT_IDX : ((n == 5) ? SPI2_CS5_PAD_OUT_IDX : 0)))))) + +#define SPI_SS_IDX(p, n) ((p == 0) ? SPI_FSPI_SS_IDX(n) : ((p == 1) ? SPI_HSPI_SS_IDX(n) : 0)) + #elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 // ESP32C3 #define SPI_COUNT (1) @@ -125,13 +148,12 @@ struct spi_struct_t { #if CONFIG_DISABLE_HAL_LOCKS #define SPI_MUTEX_LOCK() #define SPI_MUTEX_UNLOCK() - -static spi_t _spi_bus_array[] = { ++ static spi_t _spi_bus_array[] = { #if CONFIG_IDF_TARGET_ESP32S2 {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 0, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 1, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 2, -1, -1, -1, -1} -#elif CONFIG_IDF_TARGET_ESP32S3 +#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 1, -1, -1, -1, -1} #elif CONFIG_IDF_TARGET_ESP32C2 {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1} @@ -157,7 +179,7 @@ static spi_t _spi_bus_array[] = { {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 0, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 1, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 2, -1, -1, -1, -1} -#elif CONFIG_IDF_TARGET_ESP32S3 +#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 1, -1, -1, -1, -1} #elif CONFIG_IDF_TARGET_ESP32C2 {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1} @@ -369,11 +391,10 @@ void spiEnableSSPins(spi_t *spi, uint8_t ss_mask) { return; } SPI_MUTEX_LOCK(); -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.val &= ~(ss_mask & SPI_SS_MASK_ALL); -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.val &= ~(ss_mask & SPI_SS_MASK_ALL); +#else + spi->dev->misc.val &= ~(ss_mask & SPI_SS_MASK_ALL); #endif SPI_MUTEX_UNLOCK(); } @@ -383,11 +404,10 @@ void spiDisableSSPins(spi_t *spi, uint8_t ss_mask) { return; } SPI_MUTEX_LOCK(); -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.val |= (ss_mask & SPI_SS_MASK_ALL); -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.val |= (ss_mask & SPI_SS_MASK_ALL); +#else + spi->dev->misc.val |= (ss_mask & SPI_SS_MASK_ALL); #endif SPI_MUTEX_UNLOCK(); } @@ -417,11 +437,10 @@ void spiSSSet(spi_t *spi) { return; } SPI_MUTEX_LOCK(); -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.cs_keep_active = 1; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.cs_keep_active = 1; +#else + spi->dev->misc.cs_keep_active = 1; #endif SPI_MUTEX_UNLOCK(); } @@ -431,11 +450,10 @@ void spiSSClear(spi_t *spi) { return; } SPI_MUTEX_LOCK(); -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.cs_keep_active = 0; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.cs_keep_active = 0; +#else + spi->dev->misc.cs_keep_active = 0; #endif SPI_MUTEX_UNLOCK(); } @@ -460,11 +478,10 @@ uint8_t spiGetDataMode(spi_t *spi) { if (!spi) { return 0; } -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - bool idleEdge = spi->dev->misc.ck_idle_edge; -#else +#if CONFIG_IDF_TARGET_ESP32 bool idleEdge = spi->dev->pin.ck_idle_edge; +#else + bool idleEdge = spi->dev->misc.ck_idle_edge; #endif bool outEdge = spi->dev->user.ck_out_edge; if (idleEdge) { @@ -486,39 +503,35 @@ void spiSetDataMode(spi_t *spi, uint8_t dataMode) { SPI_MUTEX_LOCK(); switch (dataMode) { case SPI_MODE1: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 0; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 0; +#else + spi->dev->misc.ck_idle_edge = 0; #endif spi->dev->user.ck_out_edge = 1; break; case SPI_MODE2: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 1; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 1; +#else + spi->dev->misc.ck_idle_edge = 1; #endif spi->dev->user.ck_out_edge = 1; break; case SPI_MODE3: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 1; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 1; +#else + spi->dev->misc.ck_idle_edge = 1; #endif spi->dev->user.ck_out_edge = 0; break; case SPI_MODE0: default: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 0; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 0; +#else + spi->dev->misc.ck_idle_edge = 0; #endif spi->dev->user.ck_out_edge = 0; break; @@ -564,11 +577,10 @@ static void spiInitBus(spi_t *spi) { spi->dev->slave.trans_done = 0; #endif spi->dev->slave.val = 0; -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.val = 0; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.val = 0; +#else + spi->dev->misc.val = 0; #endif spi->dev->user.val = 0; spi->dev->user1.val = 0; @@ -648,18 +660,18 @@ spi_t *spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST); } -#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#elif defined(__PERIPH_CTRL_ALLOW_LEGACY_API) periph_ll_reset(PERIPH_SPI2_MODULE); periph_ll_enable_clk_clear_rst(PERIPH_SPI2_MODULE); #endif SPI_MUTEX_LOCK(); spiInitBus(spi); -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->clk_gate.clk_en = 1; spi->dev->clk_gate.mst_clk_sel = 1; spi->dev->clk_gate.mst_clk_active = 1; -#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 +#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) spi->dev->dma_conf.tx_seg_trans_clr_en = 1; spi->dev->dma_conf.rx_seg_trans_clr_en = 1; spi->dev->dma_conf.dma_seg_trans_en = 0; @@ -670,7 +682,7 @@ spi_t *spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t spi->dev->user.doutdin = 1; int i; for (i = 0; i < 16; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = 0x00000000; #else spi->dev->data_buf[i] = 0x00000000; @@ -697,7 +709,7 @@ void spiWaitReady(spi_t *spi) { #if CONFIG_IDF_TARGET_ESP32S2 #define usr_mosi_dbitlen usr_mosi_bit_len #define usr_miso_dbitlen usr_miso_bit_len -#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#elif !defined(CONFIG_IDF_TARGET_ESP32) #define usr_mosi_dbitlen ms_data_bitlen #define usr_miso_dbitlen ms_data_bitlen #define mosi_dlen ms_dlen @@ -718,13 +730,13 @@ void spiWrite(spi_t *spi, const uint32_t *data, uint8_t len) { spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif for (i = 0; i < len; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = data[i]; #else spi->dev->data_buf[i] = data[i]; #endif } -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -745,20 +757,20 @@ void spiTransfer(spi_t *spi, uint32_t *data, uint8_t len) { spi->dev->mosi_dlen.usr_mosi_dbitlen = (len * 32) - 1; spi->dev->miso_dlen.usr_miso_dbitlen = (len * 32) - 1; for (i = 0; i < len; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = data[i]; #else spi->dev->data_buf[i] = data[i]; #endif } -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); for (i = 0; i < len; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data[i] = spi->dev->data_buf[i].val; #else data[i] = spi->dev->data_buf[i]; @@ -776,13 +788,13 @@ void spiWriteByte(spi_t *spi, uint8_t data) { #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -798,18 +810,18 @@ uint8_t spiTransferByte(spi_t *spi, uint8_t data) { SPI_MUTEX_LOCK(); spi->dev->mosi_dlen.usr_mosi_dbitlen = 7; spi->dev->miso_dlen.usr_miso_dbitlen = 7; -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val & 0xFF; #else data = spi->dev->data_buf[0] & 0xFF; @@ -839,12 +851,12 @@ void spiWriteWord(spi_t *spi, uint16_t data) { #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -863,18 +875,18 @@ uint16_t spiTransferWord(spi_t *spi, uint16_t data) { SPI_MUTEX_LOCK(); spi->dev->mosi_dlen.usr_mosi_dbitlen = 15; spi->dev->miso_dlen.usr_miso_dbitlen = 15; -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val; #else data = spi->dev->data_buf[0]; @@ -898,12 +910,12 @@ void spiWriteLong(spi_t *spi, uint32_t data) { #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -922,18 +934,18 @@ uint32_t spiTransferLong(spi_t *spi, uint32_t data) { SPI_MUTEX_LOCK(); spi->dev->mosi_dlen.usr_mosi_dbitlen = 31; spi->dev->miso_dlen.usr_miso_dbitlen = 31; -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val; #else data = spi->dev->data_buf[0]; @@ -972,14 +984,14 @@ static void __spiTransferBytes(spi_t *spi, const uint8_t *data, uint8_t *out, ui spi->dev->miso_dlen.usr_miso_dbitlen = ((bytes * 8) - 1); for (i = 0; i < words; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = wordsBuf[i]; //copy buffer to spi fifo #else spi->dev->data_buf[i] = wordsBuf[i]; //copy buffer to spi fifo #endif } -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -989,7 +1001,7 @@ static void __spiTransferBytes(spi_t *spi, const uint8_t *data, uint8_t *out, ui if (out) { for (i = 0; i < words; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 wordsBuf[i] = spi->dev->data_buf[i].val; //copy spi fifo to buffer #else wordsBuf[i] = spi->dev->data_buf[i]; //copy spi fifo to buffer @@ -1061,39 +1073,35 @@ void spiTransaction(spi_t *spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bit spi->dev->clock.val = clockDiv; switch (dataMode) { case SPI_MODE1: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 0; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 0; +#else + spi->dev->misc.ck_idle_edge = 0; #endif spi->dev->user.ck_out_edge = 1; break; case SPI_MODE2: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 1; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 1; +#else + spi->dev->misc.ck_idle_edge = 1; #endif spi->dev->user.ck_out_edge = 1; break; case SPI_MODE3: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 1; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 1; +#else + spi->dev->misc.ck_idle_edge = 1; #endif spi->dev->user.ck_out_edge = 0; break; case SPI_MODE0: default: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 0; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 0; +#else + spi->dev->misc.ck_idle_edge = 0; #endif spi->dev->user.ck_out_edge = 0; break; @@ -1105,7 +1113,7 @@ void spiTransaction(spi_t *spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bit spi->dev->ctrl.wr_bit_order = 1; spi->dev->ctrl.rd_bit_order = 1; } -#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) // Sync new config with hardware, fixes https://github.com/espressif/arduino-esp32/issues/9221 spi->dev->cmd.update = 1; while (spi->dev->cmd.update); @@ -1134,12 +1142,12 @@ void ARDUINO_ISR_ATTR spiWriteByteNL(spi_t *spi, uint8_t data) { #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -1153,18 +1161,18 @@ uint8_t spiTransferByteNL(spi_t *spi, uint8_t data) { } spi->dev->mosi_dlen.usr_mosi_dbitlen = 7; spi->dev->miso_dlen.usr_miso_dbitlen = 7; -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val & 0xFF; #else data = spi->dev->data_buf[0] & 0xFF; @@ -1183,12 +1191,12 @@ void ARDUINO_ISR_ATTR spiWriteShortNL(spi_t *spi, uint16_t data) { #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -1205,18 +1213,18 @@ uint16_t spiTransferShortNL(spi_t *spi, uint16_t data) { } spi->dev->mosi_dlen.usr_mosi_dbitlen = 15; spi->dev->miso_dlen.usr_miso_dbitlen = 15; -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val & 0xFFFF; #else data = spi->dev->data_buf[0] & 0xFFFF; @@ -1238,12 +1246,12 @@ void ARDUINO_ISR_ATTR spiWriteLongNL(spi_t *spi, uint32_t data) { #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -1260,18 +1268,18 @@ uint32_t spiTransferLongNL(spi_t *spi, uint32_t data) { } spi->dev->mosi_dlen.usr_mosi_dbitlen = 31; spi->dev->miso_dlen.usr_miso_dbitlen = 31; -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val; #else data = spi->dev->data_buf[0]; @@ -1302,13 +1310,13 @@ void spiWriteNL(spi_t *spi, const void *data_in, uint32_t len) { spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif for (size_t i = 0; i < c_longs; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = data[i]; #else spi->dev->data_buf[i] = data[i]; #endif } -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -1341,7 +1349,7 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint spi->dev->miso_dlen.usr_miso_dbitlen = (c_len * 8) - 1; if (data) { for (size_t i = 0; i < c_longs; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = data[i]; #else spi->dev->data_buf[i] = data[i]; @@ -1349,14 +1357,14 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint } } else { for (size_t i = 0; i < c_longs; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = 0xFFFFFFFF; #else spi->dev->data_buf[i] = 0xFFFFFFFF; #endif } } -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -1365,13 +1373,13 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint if (result) { if (c_len & 3) { for (size_t i = 0; i < (c_longs - 1); i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 result[i] = spi->dev->data_buf[i].val; #else result[i] = spi->dev->data_buf[i]; #endif } -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 uint32_t last_data = spi->dev->data_buf[c_longs - 1].val; #else uint32_t last_data = spi->dev->data_buf[c_longs - 1]; @@ -1383,7 +1391,7 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint } } else { for (size_t i = 0; i < c_longs; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 result[i] = spi->dev->data_buf[i].val; #else result[i] = spi->dev->data_buf[i]; @@ -1425,18 +1433,18 @@ void spiTransferBitsNL(spi_t *spi, uint32_t data, uint32_t *out, uint8_t bits) { spi->dev->mosi_dlen.usr_mosi_dbitlen = (bits - 1); spi->dev->miso_dlen.usr_miso_dbitlen = (bits - 1); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val; #else data = spi->dev->data_buf[0]; @@ -1477,34 +1485,34 @@ void ARDUINO_ISR_ATTR spiWritePixelsNL(spi_t *spi, const void *data_in, uint32_t if (msb) { if (l_bytes && i == (c_longs - 1)) { if (l_bytes == 2) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 MSB_16_SET(spi->dev->data_buf[i].val, data[i]); #else MSB_16_SET(spi->dev->data_buf[i], data[i]); #endif } else { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = data[i] & 0xFF; #else spi->dev->data_buf[i] = data[i] & 0xFF; #endif } } else { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 MSB_PIX_SET(spi->dev->data_buf[i].val, data[i]); #else MSB_PIX_SET(spi->dev->data_buf[i], data[i]); #endif } } else { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = data[i]; #else spi->dev->data_buf[i] = data[i]; #endif } } -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -1528,7 +1536,7 @@ typedef union { uint32_t clkcnt_l : 6; /*it must be equal to spi_clkcnt_N.*/ uint32_t clkcnt_h : 6; /*it must be floor((spi_clkcnt_N+1)/2-1).*/ uint32_t clkcnt_n : 6; /*it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_N+1)*/ -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) uint32_t clkdiv_pre : 4; /*it is pre-divider of spi_clk.*/ uint32_t reserved : 9; /*reserved*/ #else @@ -1573,7 +1581,7 @@ uint32_t spiFrequencyToClockDiv(uint32_t freq) { while (calPreVari++ <= 1) { calPre = (((apb_freq / (reg.clkcnt_n + 1)) / freq) - 1) + calPreVari; -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) if (calPre > 0xF) { reg.clkdiv_pre = 0xF; #else diff --git a/cores/esp32/esp32-hal-spi.h b/cores/esp32/esp32-hal-spi.h index a238cada87d..b77abff7854 100644 --- a/cores/esp32/esp32-hal-spi.h +++ b/cores/esp32/esp32-hal-spi.h @@ -28,10 +28,7 @@ extern "C" { #define SPI_HAS_TRANSACTION -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32S3 -#define FSPI 0 -#define HSPI 1 -#elif CONFIG_IDF_TARGET_ESP32S2 +#ifdef CONFIG_IDF_TARGET_ESP32S2 #define FSPI 1 //SPI 1 bus. ESP32S2: for external memory only (can use the same data lines but different SS) #define HSPI 2 //SPI 2 bus. ESP32S2: external memory or device - it can be matrixed to any pins #define SPI2 2 // Another name for ESP32S2 SPI 2 @@ -40,6 +37,9 @@ extern "C" { #define FSPI 1 //SPI 1 bus attached to the flash (can use the same data lines but different SS) #define HSPI 2 //SPI 2 bus normally mapped to pins 12 - 15, but can be matrixed to any pins #define VSPI 3 //SPI 3 bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins +#else +#define FSPI 0 +#define HSPI 1 #endif // This defines are not representing the real Divider of the ESP32 diff --git a/cores/esp32/esp32-hal-touch.c b/cores/esp32/esp32-hal-touch.c index 764b7dbb73f..4c0ed92656c 100644 --- a/cores/esp32/esp32-hal-touch.c +++ b/cores/esp32/esp32-hal-touch.c @@ -14,6 +14,10 @@ #include "soc/soc_caps.h" #if SOC_TOUCH_SENSOR_SUPPORTED +#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 +// ToDo: Implement touch sensor for ESP32P4 +#warning "Touch sensor not implemented for ESP32P4 yet" +#else #include "driver/touch_sensor.h" #include "esp32-hal-touch.h" #include "esp32-hal-periman.h" @@ -22,7 +26,7 @@ Internal Private Touch Data Structure and Functions */ -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 static uint16_t __touchSleepCycles = 0x1000; static uint16_t __touchMeasureCycles = 0x1000; #elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 @@ -51,7 +55,7 @@ static bool initialized = false; static bool channels_initialized[SOC_TOUCH_SENSOR_NUM] = {false}; static void ARDUINO_ISR_ATTR __touchISR(void *arg) { -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 uint32_t pad_intr = touch_pad_get_status(); //clear interrupt touch_pad_clear_status(); @@ -93,7 +97,7 @@ static void ARDUINO_ISR_ATTR __touchISR(void *arg) { static void __touchSetCycles(uint16_t measure, uint16_t sleep) { __touchSleepCycles = sleep; __touchMeasureCycles = measure; -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 touch_pad_set_measurement_clock_cycles(measure); #elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 touch_pad_set_charge_discharge_times(measure); @@ -123,7 +127,7 @@ static void __touchInit() { esp_err_t err = ESP_OK; -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 err = touch_pad_init(); if (err != ESP_OK) { goto err; @@ -143,7 +147,7 @@ static void __touchInit() { if (err != ESP_OK) { goto err; } - touch_pad_intr_enable(); // returns ESP_OK + touch_pad_intr_enable(); // returns ESP_OK #elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 err = touch_pad_init(); if (err != ESP_OK) { @@ -179,11 +183,11 @@ static void __touchChannelInit(int pad) { return; } -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 // Initial no Threshold and setup __touchInterruptHandlers[pad].fn = NULL; touch_pad_config(pad, TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK -#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 // Initial no Threshold and setup __touchInterruptHandlers[pad].fn = NULL; touch_pad_config(pad); // returns ESP_OK @@ -270,7 +274,7 @@ static void __touchDettachInterrupt(uint8_t pin) { External Public Touch API Functions */ -#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC +#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC void touchInterruptSetThresholdDirection(bool mustbeLower) { if (mustbeLower) { touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW); @@ -324,4 +328,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 == 3 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-touch.h b/cores/esp32/esp32-hal-touch.h index 115d6cdc9cf..cc140d81bb0 100644 --- a/cores/esp32/esp32-hal-touch.h +++ b/cores/esp32/esp32-hal-touch.h @@ -37,6 +37,8 @@ extern "C" { typedef uint16_t touch_value_t; #elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2 ESP32S3 typedef uint32_t touch_value_t; +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 +typedef uint32_t touch_value_t; #endif /* diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index 2af23e075cc..82c9d8808d0 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -625,7 +625,7 @@ void uartSetRxInvert(uart_t *uart, bool invert) { if (uart == NULL) { return; } -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 // POTENTIAL ISSUE :: original code only set/reset rxd_inv bit // IDF or LL set/reset the whole inv_mask! // if (invert) @@ -898,7 +898,7 @@ int log_printfv(const char *format, va_list arg) { #endif */ #if (ARDUINO_USB_CDC_ON_BOOT == 1 && ARDUINO_USB_MODE == 0) || CONFIG_IDF_TARGET_ESP32C3 \ - || ((CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C6) && ARDUINO_USB_CDC_ON_BOOT == 1) + || ((CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32P4) && ARDUINO_USB_CDC_ON_BOOT == 1) vsnprintf(temp, len + 1, format, arg); ets_printf("%s", temp); #else @@ -1105,6 +1105,20 @@ unsigned long uartDetectBaudrate(uart_t *uart) { */ // gets the right TX or RX SIGNAL, based on the UART number from gpio_sig_map.h +#ifdef CONFIG_IDF_TARGET_ESP32P4 +#define UART_TX_SIGNAL(uartNumber) \ + (uartNumber == UART_NUM_0 \ + ? UART0_TXD_PAD_OUT_IDX \ + : (uartNumber == UART_NUM_1 \ + ? UART1_TXD_PAD_OUT_IDX \ + : (uartNumber == UART_NUM_2 ? UART2_TXD_PAD_OUT_IDX : (uartNumber == UART_NUM_3 ? UART3_TXD_PAD_OUT_IDX : UART4_TXD_PAD_OUT_IDX)))) +#define UART_RX_SIGNAL(uartNumber) \ + (uartNumber == UART_NUM_0 \ + ? UART0_RXD_PAD_IN_IDX \ + : (uartNumber == UART_NUM_1 \ + ? UART1_RXD_PAD_IN_IDX \ + : (uartNumber == UART_NUM_2 ? UART2_RXD_PAD_IN_IDX : (uartNumber == UART_NUM_3 ? UART3_RXD_PAD_IN_IDX : UART4_RXD_PAD_IN_IDX)))) +#else #if SOC_UART_HP_NUM > 2 #define UART_TX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0TXD_OUT_IDX : (uartNumber == UART_NUM_1 ? U1TXD_OUT_IDX : U2TXD_OUT_IDX)) #define UART_RX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0RXD_IN_IDX : (uartNumber == UART_NUM_1 ? U1RXD_IN_IDX : U2RXD_IN_IDX)) @@ -1112,6 +1126,8 @@ unsigned long uartDetectBaudrate(uart_t *uart) { #define UART_TX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0TXD_OUT_IDX : U1TXD_OUT_IDX) #define UART_RX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0RXD_IN_IDX : U1RXD_IN_IDX) #endif +#endif // ifdef CONFIG_IDF_TARGET_ESP32P4 + /* This function internally binds defined UARTs TX signal with defined RX pin of any UART (same or different). This creates a loop that lets us receive anything we send on the UART without external wires. diff --git a/docs/en/lib_builder.rst b/docs/en/lib_builder.rst index 3d28761ab2d..fc488566878 100644 --- a/docs/en/lib_builder.rst +++ b/docs/en/lib_builder.rst @@ -157,6 +157,7 @@ This build command will build for the ESP32-S3 target. You can specify other tar * esp32c3 * esp32c6 * esp32h2 +* esp32p4 Set Build Type ^^^^^^^^^^^^^^ diff --git a/idf_component.yml b/idf_component.yml index 4b3e582d256..3b83650bf5b 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -21,6 +21,7 @@ files: - "variants/esp32c3/**/*" - "variants/esp32c6/**/*" - "variants/esp32h2/**/*" + - "variants/esp32p4/**/*" exclude: - "docs/" - "docs/**/*" diff --git a/libraries/ArduinoOTA/examples/BasicOTA/ci.json b/libraries/ArduinoOTA/examples/BasicOTA/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/ArduinoOTA/examples/BasicOTA/ci.json +++ b/libraries/ArduinoOTA/examples/BasicOTA/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/AsyncUDP/examples/AsyncUDPClient/ci.json b/libraries/AsyncUDP/examples/AsyncUDPClient/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/AsyncUDP/examples/AsyncUDPClient/ci.json +++ b/libraries/AsyncUDP/examples/AsyncUDPClient/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/AsyncUDP/examples/AsyncUDPMulticastServer/ci.json b/libraries/AsyncUDP/examples/AsyncUDPMulticastServer/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/AsyncUDP/examples/AsyncUDPMulticastServer/ci.json +++ b/libraries/AsyncUDP/examples/AsyncUDPMulticastServer/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/AsyncUDP/examples/AsyncUDPServer/ci.json b/libraries/AsyncUDP/examples/AsyncUDPServer/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/AsyncUDP/examples/AsyncUDPServer/ci.json +++ b/libraries/AsyncUDP/examples/AsyncUDPServer/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/BLE/examples/BLE5_extended_scan/ci.json b/libraries/BLE/examples/BLE5_extended_scan/ci.json index edef5051e09..e97e4cf7fea 100644 --- a/libraries/BLE/examples/BLE5_extended_scan/ci.json +++ b/libraries/BLE/examples/BLE5_extended_scan/ci.json @@ -1,6 +1,7 @@ { "targets": { "esp32": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BLE/examples/BLE5_multi_advertising/ci.json b/libraries/BLE/examples/BLE5_multi_advertising/ci.json index edef5051e09..fc9f75986fe 100644 --- a/libraries/BLE/examples/BLE5_multi_advertising/ci.json +++ b/libraries/BLE/examples/BLE5_multi_advertising/ci.json @@ -1,6 +1,6 @@ { "targets": { - "esp32": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BLE/examples/BLE5_periodic_advertising/ci.json b/libraries/BLE/examples/BLE5_periodic_advertising/ci.json index edef5051e09..a034e239a3f 100644 --- a/libraries/BLE/examples/BLE5_periodic_advertising/ci.json +++ b/libraries/BLE/examples/BLE5_periodic_advertising/ci.json @@ -1,6 +1,10 @@ { "targets": { "esp32": false, - "esp32s2": false + "esp32c2": false, + "esp32c3": false, + "esp32p4": false, + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/BLE/examples/BLE5_periodic_sync/ci.json b/libraries/BLE/examples/BLE5_periodic_sync/ci.json index edef5051e09..715becda6cb 100644 --- a/libraries/BLE/examples/BLE5_periodic_sync/ci.json +++ b/libraries/BLE/examples/BLE5_periodic_sync/ci.json @@ -1,6 +1,10 @@ { "targets": { "esp32": false, + "esp32c3": false, + "esp32c6": false, + "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BLE/examples/Beacon_Scanner/ci.json b/libraries/BLE/examples/Beacon_Scanner/ci.json index 1443137ab0d..ee810400be6 100644 --- a/libraries/BLE/examples/Beacon_Scanner/ci.json +++ b/libraries/BLE/examples/Beacon_Scanner/ci.json @@ -1,5 +1,9 @@ { "targets": { + "esp32c3": false, + "esp32c6": false, + "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BLE/examples/Client/ci.json b/libraries/BLE/examples/Client/ci.json index 1443137ab0d..eb6596c4a37 100644 --- a/libraries/BLE/examples/Client/ci.json +++ b/libraries/BLE/examples/Client/ci.json @@ -1,5 +1,7 @@ { "targets": { + "esp32c3": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BLE/examples/EddystoneTLM_Beacon/ci.json b/libraries/BLE/examples/EddystoneTLM_Beacon/ci.json index 521ae8f5ff1..156dda6560c 100644 --- a/libraries/BLE/examples/EddystoneTLM_Beacon/ci.json +++ b/libraries/BLE/examples/EddystoneTLM_Beacon/ci.json @@ -1,6 +1,7 @@ { "targets": { "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BLE/examples/EddystoneURL_Beacon/ci.json b/libraries/BLE/examples/EddystoneURL_Beacon/ci.json index 521ae8f5ff1..156dda6560c 100644 --- a/libraries/BLE/examples/EddystoneURL_Beacon/ci.json +++ b/libraries/BLE/examples/EddystoneURL_Beacon/ci.json @@ -1,6 +1,7 @@ { "targets": { "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BLE/examples/Notify/ci.json b/libraries/BLE/examples/Notify/ci.json index 1443137ab0d..156dda6560c 100644 --- a/libraries/BLE/examples/Notify/ci.json +++ b/libraries/BLE/examples/Notify/ci.json @@ -1,5 +1,7 @@ { "targets": { + "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BLE/examples/Scan/ci.json b/libraries/BLE/examples/Scan/ci.json index 1443137ab0d..fc9f75986fe 100644 --- a/libraries/BLE/examples/Scan/ci.json +++ b/libraries/BLE/examples/Scan/ci.json @@ -1,5 +1,6 @@ { "targets": { + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BLE/examples/Server/ci.json b/libraries/BLE/examples/Server/ci.json index 1443137ab0d..a034e239a3f 100644 --- a/libraries/BLE/examples/Server/ci.json +++ b/libraries/BLE/examples/Server/ci.json @@ -1,5 +1,10 @@ { "targets": { - "esp32s2": false + "esp32": false, + "esp32c2": false, + "esp32c3": false, + "esp32p4": false, + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/BLE/examples/Server_multiconnect/ci.json b/libraries/BLE/examples/Server_multiconnect/ci.json index 1443137ab0d..715becda6cb 100644 --- a/libraries/BLE/examples/Server_multiconnect/ci.json +++ b/libraries/BLE/examples/Server_multiconnect/ci.json @@ -1,5 +1,10 @@ { "targets": { + "esp32": false, + "esp32c3": false, + "esp32c6": false, + "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BLE/examples/UART/ci.json b/libraries/BLE/examples/UART/ci.json index 1443137ab0d..ee810400be6 100644 --- a/libraries/BLE/examples/UART/ci.json +++ b/libraries/BLE/examples/UART/ci.json @@ -1,5 +1,9 @@ { "targets": { + "esp32c3": false, + "esp32c6": false, + "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BLE/examples/Write/ci.json b/libraries/BLE/examples/Write/ci.json index 1443137ab0d..eb6596c4a37 100644 --- a/libraries/BLE/examples/Write/ci.json +++ b/libraries/BLE/examples/Write/ci.json @@ -1,5 +1,7 @@ { "targets": { + "esp32c3": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BLE/examples/iBeacon/ci.json b/libraries/BLE/examples/iBeacon/ci.json index 1443137ab0d..156dda6560c 100644 --- a/libraries/BLE/examples/iBeacon/ci.json +++ b/libraries/BLE/examples/iBeacon/ci.json @@ -1,5 +1,7 @@ { "targets": { + "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/BluetoothSerial/examples/DiscoverConnect/ci.json b/libraries/BluetoothSerial/examples/DiscoverConnect/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/BluetoothSerial/examples/DiscoverConnect/ci.json +++ b/libraries/BluetoothSerial/examples/DiscoverConnect/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/BluetoothSerial/examples/GetLocalMAC/ci.json b/libraries/BluetoothSerial/examples/GetLocalMAC/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/BluetoothSerial/examples/GetLocalMAC/ci.json +++ b/libraries/BluetoothSerial/examples/GetLocalMAC/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json b/libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json b/libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json +++ b/libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json b/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json b/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/BluetoothSerial/examples/bt_classic_device_discovery/ci.json b/libraries/BluetoothSerial/examples/bt_classic_device_discovery/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/BluetoothSerial/examples/bt_classic_device_discovery/ci.json +++ b/libraries/BluetoothSerial/examples/bt_classic_device_discovery/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/BluetoothSerial/examples/bt_remove_paired_devices/ci.json b/libraries/BluetoothSerial/examples/bt_remove_paired_devices/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/BluetoothSerial/examples/bt_remove_paired_devices/ci.json +++ b/libraries/BluetoothSerial/examples/bt_remove_paired_devices/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/DNSServer/examples/CaptivePortal/ci.json b/libraries/DNSServer/examples/CaptivePortal/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/DNSServer/examples/CaptivePortal/ci.json +++ b/libraries/DNSServer/examples/CaptivePortal/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESP32/examples/Camera/CameraWebServer/ci.json b/libraries/ESP32/examples/Camera/CameraWebServer/ci.json index 25c42144223..cd679adefad 100644 --- a/libraries/ESP32/examples/Camera/CameraWebServer/ci.json +++ b/libraries/ESP32/examples/Camera/CameraWebServer/ci.json @@ -2,6 +2,7 @@ "targets": { "esp32c3": false, "esp32c6": false, - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ci.json b/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ci.json index 25c42144223..cd679adefad 100644 --- a/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ci.json +++ b/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ci.json @@ -2,6 +2,7 @@ "targets": { "esp32c3": false, "esp32c6": false, - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESP32/examples/DeepSleep/SmoothBlink_ULP_Code/ci.json b/libraries/ESP32/examples/DeepSleep/SmoothBlink_ULP_Code/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/ESP32/examples/DeepSleep/SmoothBlink_ULP_Code/ci.json +++ b/libraries/ESP32/examples/DeepSleep/SmoothBlink_ULP_Code/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopback.ino b/libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopback.ino index eada1c7ea6b..17e7af290bf 100644 --- a/libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopback.ino +++ b/libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopback.ino @@ -21,7 +21,7 @@ * */ -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 // ESP32 C3 has only 2 channels for RX and 2 for TX, thus MAX RMT_MEM is 128 #define RMT_TX_PIN 4 #define RMT_RX_PIN 5 diff --git a/libraries/ESP32/examples/ResetReason/ResetReason/ResetReason.ino b/libraries/ESP32/examples/ResetReason/ResetReason/ResetReason.ino index 3c9dbb9b12f..0104c6422f2 100644 --- a/libraries/ESP32/examples/ResetReason/ResetReason/ResetReason.ino +++ b/libraries/ESP32/examples/ResetReason/ResetReason/ResetReason.ino @@ -26,6 +26,8 @@ #include "esp32c6/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/rtc.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif diff --git a/libraries/ESP32/examples/Time/SimpleTime/ci.json b/libraries/ESP32/examples/Time/SimpleTime/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/ESP32/examples/Time/SimpleTime/ci.json +++ b/libraries/ESP32/examples/Time/SimpleTime/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/ci.json b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/ci.json index 7cfaa76784d..7b73237d754 100644 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/ci.json +++ b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/ci.json @@ -4,6 +4,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/ci.json b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/ci.json index 7cfaa76784d..7b73237d754 100644 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/ci.json +++ b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/ci.json @@ -4,6 +4,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/ci.json b/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/ci.json index 7cfaa76784d..7b73237d754 100644 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/ci.json +++ b/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/ci.json @@ -4,6 +4,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/ci.json b/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/ci.json index 7cfaa76784d..7b73237d754 100644 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/ci.json +++ b/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/ci.json @@ -4,6 +4,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ci.json b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ci.json +++ b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ci.json b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ci.json +++ b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Network/ci.json b/libraries/ESP_NOW/examples/ESP_NOW_Network/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Network/ci.json +++ b/libraries/ESP_NOW/examples/ESP_NOW_Network/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Serial/ci.json b/libraries/ESP_NOW/examples/ESP_NOW_Serial/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Serial/ci.json +++ b/libraries/ESP_NOW/examples/ESP_NOW_Serial/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESP_SR/examples/Basic/ci.json b/libraries/ESP_SR/examples/Basic/ci.json index dca52699ab3..98703e79183 100644 --- a/libraries/ESP_SR/examples/Basic/ci.json +++ b/libraries/ESP_SR/examples/Basic/ci.json @@ -9,6 +9,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/ESPmDNS/examples/mDNS-SD_Extended/ci.json b/libraries/ESPmDNS/examples/mDNS-SD_Extended/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/ESPmDNS/examples/mDNS-SD_Extended/ci.json +++ b/libraries/ESPmDNS/examples/mDNS-SD_Extended/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESPmDNS/examples/mDNS_Web_Server/ci.json b/libraries/ESPmDNS/examples/mDNS_Web_Server/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/ESPmDNS/examples/mDNS_Web_Server/ci.json +++ b/libraries/ESPmDNS/examples/mDNS_Web_Server/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/Ethernet/examples/ETH_WIFI_BRIDGE/ci.json b/libraries/Ethernet/examples/ETH_WIFI_BRIDGE/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/Ethernet/examples/ETH_WIFI_BRIDGE/ci.json +++ b/libraries/Ethernet/examples/ETH_WIFI_BRIDGE/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index bc5a94484da..13f9c11f7fe 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -30,7 +30,9 @@ #include "driver/gpio.h" #include "driver/spi_master.h" #if CONFIG_ETH_USE_ESP32_EMAC +#if defined __has_include && __has_include("soc/emac_ext_struct.h") #include "soc/emac_ext_struct.h" +#endif /* __has_include("soc/emac_ext_struct.h" */ #include "soc/rtc.h" #endif /* CONFIG_ETH_USE_ESP32_EMAC */ #include "esp32-hal-periman.h" @@ -146,7 +148,7 @@ void ETHClass::setTaskStackSize(size_t size) { _task_stack_size = size; } -#if CONFIG_ETH_USE_ESP32_EMAC +#if (CONFIG_ETH_USE_ESP32_EMAC && !defined(CONFIG_IDF_TARGET_ESP32P4)) bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, int power, eth_clock_mode_t clock_mode) { esp_err_t ret = ESP_OK; if (_eth_index > 2) { @@ -898,7 +900,7 @@ void ETHClass::end(void) { #if ETH_SPI_SUPPORTS_CUSTOM _spi = NULL; #endif -#if CONFIG_ETH_USE_ESP32_EMAC +#if (CONFIG_ETH_USE_ESP32_EMAC && !defined(CONFIG_IDF_TARGET_ESP32P4)) perimanSetBusDeinit(ESP32_BUS_TYPE_ETHERNET_RMII, empty_ethDetachBus); perimanSetBusDeinit(ESP32_BUS_TYPE_ETHERNET_CLK, empty_ethDetachBus); perimanSetBusDeinit(ESP32_BUS_TYPE_ETHERNET_MCD, empty_ethDetachBus); diff --git a/libraries/FFat/examples/FFat_time/ci.json b/libraries/FFat/examples/FFat_time/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/FFat/examples/FFat_time/ci.json +++ b/libraries/FFat/examples/FFat_time/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/HTTPClient/examples/Authorization/ci.json b/libraries/HTTPClient/examples/Authorization/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/HTTPClient/examples/Authorization/ci.json +++ b/libraries/HTTPClient/examples/Authorization/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/HTTPClient/examples/BasicHttpClient/ci.json b/libraries/HTTPClient/examples/BasicHttpClient/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/HTTPClient/examples/BasicHttpClient/ci.json +++ b/libraries/HTTPClient/examples/BasicHttpClient/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/HTTPClient/examples/BasicHttpsClient/ci.json b/libraries/HTTPClient/examples/BasicHttpsClient/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/HTTPClient/examples/BasicHttpsClient/ci.json +++ b/libraries/HTTPClient/examples/BasicHttpsClient/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json b/libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json +++ b/libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/HTTPClient/examples/ReuseConnection/ci.json b/libraries/HTTPClient/examples/ReuseConnection/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/HTTPClient/examples/ReuseConnection/ci.json +++ b/libraries/HTTPClient/examples/ReuseConnection/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/HTTPClient/examples/StreamHttpClient/ci.json b/libraries/HTTPClient/examples/StreamHttpClient/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/HTTPClient/examples/StreamHttpClient/ci.json +++ b/libraries/HTTPClient/examples/StreamHttpClient/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/HTTPUpdate/examples/httpUpdate/ci.json b/libraries/HTTPUpdate/examples/httpUpdate/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/HTTPUpdate/examples/httpUpdate/ci.json +++ b/libraries/HTTPUpdate/examples/httpUpdate/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/HTTPUpdate/examples/httpUpdateSPIFFS/ci.json b/libraries/HTTPUpdate/examples/httpUpdateSPIFFS/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/HTTPUpdate/examples/httpUpdateSPIFFS/ci.json +++ b/libraries/HTTPUpdate/examples/httpUpdateSPIFFS/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json b/libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json +++ b/libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/HTTPUpdateServer/examples/WebUpdater/ci.json b/libraries/HTTPUpdateServer/examples/WebUpdater/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/HTTPUpdateServer/examples/WebUpdater/ci.json +++ b/libraries/HTTPUpdateServer/examples/WebUpdater/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/Insights/examples/DiagnosticsSmokeTest/ci.json b/libraries/Insights/examples/DiagnosticsSmokeTest/ci.json index 90f5ecfe4d2..0d8130e329a 100644 --- a/libraries/Insights/examples/DiagnosticsSmokeTest/ci.json +++ b/libraries/Insights/examples/DiagnosticsSmokeTest/ci.json @@ -1,6 +1,7 @@ { "targets": { "esp32c6": false, - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/Insights/examples/MinimalDiagnostics/ci.json b/libraries/Insights/examples/MinimalDiagnostics/ci.json index 90f5ecfe4d2..0d8130e329a 100644 --- a/libraries/Insights/examples/MinimalDiagnostics/ci.json +++ b/libraries/Insights/examples/MinimalDiagnostics/ci.json @@ -1,6 +1,7 @@ { "targets": { "esp32c6": false, - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/LittleFS/examples/LITTLEFS_time/ci.json b/libraries/LittleFS/examples/LITTLEFS_time/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/LittleFS/examples/LITTLEFS_time/ci.json +++ b/libraries/LittleFS/examples/LITTLEFS_time/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/NetBIOS/examples/ESP_NBNST/ci.json b/libraries/NetBIOS/examples/ESP_NBNST/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/NetBIOS/examples/ESP_NBNST/ci.json +++ b/libraries/NetBIOS/examples/ESP_NBNST/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientInsecure/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientInsecure/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientInsecure/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientInsecure/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientPSK/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientPSK/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientPSK/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientPSK/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientSecureProtocolUpgrade/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientSecureProtocolUpgrade/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientSecureProtocolUpgrade/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientSecureProtocolUpgrade/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientShowPeerCredentials/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientShowPeerCredentials/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientShowPeerCredentials/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientShowPeerCredentials/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientTrustOnFirstUse/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientTrustOnFirstUse/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientTrustOnFirstUse/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientTrustOnFirstUse/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/ci.json b/libraries/OpenThread/examples/COAP/coap_lamp/ci.json index c60d9179992..a034e239a3f 100644 --- a/libraries/OpenThread/examples/COAP/coap_lamp/ci.json +++ b/libraries/OpenThread/examples/COAP/coap_lamp/ci.json @@ -3,6 +3,7 @@ "esp32": false, "esp32c2": false, "esp32c3": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/OpenThread/examples/COAP/coap_switch/ci.json b/libraries/OpenThread/examples/COAP/coap_switch/ci.json index c60d9179992..715becda6cb 100644 --- a/libraries/OpenThread/examples/COAP/coap_switch/ci.json +++ b/libraries/OpenThread/examples/COAP/coap_switch/ci.json @@ -1,9 +1,10 @@ { "targets": { "esp32": false, - "esp32c2": false, "esp32c3": false, - "esp32s2": false, - "esp32s3": false + "esp32c6": false, + "esp32h2": false, + "esp32p4": false, + "esp32s2": false } } diff --git a/libraries/OpenThread/examples/SimpleCLI/ci.json b/libraries/OpenThread/examples/SimpleCLI/ci.json index c60d9179992..ee810400be6 100644 --- a/libraries/OpenThread/examples/SimpleCLI/ci.json +++ b/libraries/OpenThread/examples/SimpleCLI/ci.json @@ -1,9 +1,9 @@ { "targets": { - "esp32": false, - "esp32c2": false, "esp32c3": false, - "esp32s2": false, - "esp32s3": false + "esp32c6": false, + "esp32h2": false, + "esp32p4": false, + "esp32s2": false } } diff --git a/libraries/OpenThread/examples/SimpleNode/ci.json b/libraries/OpenThread/examples/SimpleNode/ci.json index c60d9179992..eb6596c4a37 100644 --- a/libraries/OpenThread/examples/SimpleNode/ci.json +++ b/libraries/OpenThread/examples/SimpleNode/ci.json @@ -1,9 +1,7 @@ { "targets": { - "esp32": false, - "esp32c2": false, "esp32c3": false, - "esp32s2": false, - "esp32s3": false + "esp32p4": false, + "esp32s2": false } } diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json index c60d9179992..156dda6560c 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json @@ -1,9 +1,7 @@ { "targets": { - "esp32": false, - "esp32c2": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false + "esp32h2": false, + "esp32p4": false, + "esp32s2": false } } diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json index c60d9179992..a034e239a3f 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json @@ -3,6 +3,7 @@ "esp32": false, "esp32c2": false, "esp32c3": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json index c60d9179992..a034e239a3f 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json @@ -3,6 +3,7 @@ "esp32": false, "esp32c2": false, "esp32c3": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/OpenThread/examples/ThreadScan/ci.json b/libraries/OpenThread/examples/ThreadScan/ci.json index c60d9179992..a034e239a3f 100644 --- a/libraries/OpenThread/examples/ThreadScan/ci.json +++ b/libraries/OpenThread/examples/ThreadScan/ci.json @@ -3,6 +3,7 @@ "esp32": false, "esp32c2": false, "esp32c3": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/OpenThread/examples/onReceive/ci.json b/libraries/OpenThread/examples/onReceive/ci.json index c60d9179992..a034e239a3f 100644 --- a/libraries/OpenThread/examples/onReceive/ci.json +++ b/libraries/OpenThread/examples/onReceive/ci.json @@ -3,6 +3,7 @@ "esp32": false, "esp32c2": false, "esp32c3": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/PPP/examples/PPP_WIFI_BRIDGE/ci.json b/libraries/PPP/examples/PPP_WIFI_BRIDGE/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/PPP/examples/PPP_WIFI_BRIDGE/ci.json +++ b/libraries/PPP/examples/PPP_WIFI_BRIDGE/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/PPP/src/PPP.cpp b/libraries/PPP/src/PPP.cpp index 28d6ddd8396..e77a78b77b7 100644 --- a/libraries/PPP/src/PPP.cpp +++ b/libraries/PPP/src/PPP.cpp @@ -7,6 +7,7 @@ #include #include "driver/uart.h" #include "hal/uart_ll.h" +#include "esp_private/uart_share_hw_ctrl.h" #define PPP_CMD_MODE_CHECK(x) \ if (_dce == NULL) { \ @@ -653,7 +654,10 @@ bool PPPClass::setBaudrate(int baudrate) { log_e("uart_get_sclk_freq failed with %d %s", err, esp_err_to_name(err)); return false; } - uart_ll_set_baudrate(UART_LL_GET_HW(_uart_num), (uint32_t)baudrate, sclk_freq); + + HP_UART_SRC_CLK_ATOMIC() { + uart_ll_set_baudrate(UART_LL_GET_HW(_uart_num), (uint32_t)baudrate, sclk_freq); + } return true; } diff --git a/libraries/RainMaker/examples/RMakerCustom/ci.json b/libraries/RainMaker/examples/RMakerCustom/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/RainMaker/examples/RMakerCustom/ci.json +++ b/libraries/RainMaker/examples/RMakerCustom/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/RainMaker/examples/RMakerCustomAirCooler/ci.json b/libraries/RainMaker/examples/RMakerCustomAirCooler/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/RainMaker/examples/RMakerCustomAirCooler/ci.json +++ b/libraries/RainMaker/examples/RMakerCustomAirCooler/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/RainMaker/examples/RMakerSonoffDualR3/ci.json b/libraries/RainMaker/examples/RMakerSonoffDualR3/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/RainMaker/examples/RMakerSonoffDualR3/ci.json +++ b/libraries/RainMaker/examples/RMakerSonoffDualR3/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/RainMaker/examples/RMakerSwitch/ci.json b/libraries/RainMaker/examples/RMakerSwitch/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/RainMaker/examples/RMakerSwitch/ci.json +++ b/libraries/RainMaker/examples/RMakerSwitch/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/SD/examples/SD_time/ci.json b/libraries/SD/examples/SD_time/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/SD/examples/SD_time/ci.json +++ b/libraries/SD/examples/SD_time/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/SD_MMC/examples/SD2USBMSC/ci.json b/libraries/SD_MMC/examples/SD2USBMSC/ci.json index 97ae5ee5616..715becda6cb 100644 --- a/libraries/SD_MMC/examples/SD2USBMSC/ci.json +++ b/libraries/SD_MMC/examples/SD2USBMSC/ci.json @@ -4,6 +4,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/SD_MMC/examples/SDMMC_Test/ci.json b/libraries/SD_MMC/examples/SDMMC_Test/ci.json index 35b6e255471..ee810400be6 100644 --- a/libraries/SD_MMC/examples/SDMMC_Test/ci.json +++ b/libraries/SD_MMC/examples/SDMMC_Test/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/SD_MMC/examples/SDMMC_time/ci.json b/libraries/SD_MMC/examples/SDMMC_time/ci.json index 35b6e255471..ee810400be6 100644 --- a/libraries/SD_MMC/examples/SDMMC_time/ci.json +++ b/libraries/SD_MMC/examples/SDMMC_time/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/SD_MMC/src/SD_MMC.cpp b/libraries/SD_MMC/src/SD_MMC.cpp index 6bbcf44d010..80cb150baa2 100644 --- a/libraries/SD_MMC/src/SD_MMC.cpp +++ b/libraries/SD_MMC/src/SD_MMC.cpp @@ -35,6 +35,7 @@ using namespace fs; SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) { +#if !defined(CONFIG_IDF_TARGET_ESP32P4) #if defined(SOC_SDMMC_USE_GPIO_MATRIX) && defined(BOARD_HAS_SDMMC) _pin_clk = SDMMC_CLK; _pin_cmd = SDMMC_CMD; @@ -44,8 +45,9 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) { _pin_d2 = SDMMC_D2; _pin_d3 = SDMMC_D3; #endif // BOARD_HAS_1BIT_SDMMC +#endif // !defined(CONFIG_IDF_TARGET_ESP32P4) -#elif SOC_SDMMC_USE_IOMUX +#elif SOC_SDMMC_USE_IOMUX && defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32) _pin_clk = SDMMC_SLOT1_IOMUX_PIN_NUM_CLK; _pin_cmd = SDMMC_SLOT1_IOMUX_PIN_NUM_CMD; _pin_d0 = SDMMC_SLOT1_IOMUX_PIN_NUM_D0; @@ -54,6 +56,16 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) { _pin_d2 = SDMMC_SLOT1_IOMUX_PIN_NUM_D2; _pin_d3 = SDMMC_SLOT1_IOMUX_PIN_NUM_D3; #endif // BOARD_HAS_1BIT_SDMMC + +#elif SOC_SDMMC_USE_IOMUX && defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32P4) + _pin_clk = SDMMC_SLOT0_IOMUX_PIN_NUM_CLK; + _pin_cmd = SDMMC_SLOT0_IOMUX_PIN_NUM_CMD; + _pin_d0 = SDMMC_SLOT0_IOMUX_PIN_NUM_D0; +#ifndef BOARD_HAS_1BIT_SDMMC + _pin_d1 = SDMMC_SLOT0_IOMUX_PIN_NUM_D1; + _pin_d2 = SDMMC_SLOT0_IOMUX_PIN_NUM_D2; + _pin_d3 = SDMMC_SLOT0_IOMUX_PIN_NUM_D3; +#endif // BOARD_HAS_1BIT_SDMMC #endif } diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 93c686a0d13..35e52f43e4d 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -83,7 +83,7 @@ void SPIClass::begin(int8_t sck, int8_t miso, int8_t mosi, int8_t ss) { _miso = (_spi_num == FSPI) ? MISO : -1; _mosi = (_spi_num == FSPI) ? MOSI : -1; _ss = (_spi_num == FSPI) ? SS : -1; -#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 _sck = SCK; _miso = MISO; _mosi = MOSI; diff --git a/libraries/SPIFFS/examples/SPIFFS_time/ci.json b/libraries/SPIFFS/examples/SPIFFS_time/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/SPIFFS/examples/SPIFFS_time/ci.json +++ b/libraries/SPIFFS/examples/SPIFFS_time/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/SimpleBLE/examples/SimpleBleDevice/ci.json b/libraries/SimpleBLE/examples/SimpleBleDevice/ci.json index a571a89a877..eb6596c4a37 100644 --- a/libraries/SimpleBLE/examples/SimpleBleDevice/ci.json +++ b/libraries/SimpleBLE/examples/SimpleBleDevice/ci.json @@ -1,6 +1,7 @@ { "targets": { "esp32c3": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/Update/examples/AWS_S3_OTA_Update/ci.json b/libraries/Update/examples/AWS_S3_OTA_Update/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/Update/examples/AWS_S3_OTA_Update/ci.json +++ b/libraries/Update/examples/AWS_S3_OTA_Update/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/Update/examples/HTTPS_OTA_Update/ci.json b/libraries/Update/examples/HTTPS_OTA_Update/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/Update/examples/HTTPS_OTA_Update/ci.json +++ b/libraries/Update/examples/HTTPS_OTA_Update/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/Update/examples/HTTP_Client_AES_OTA_Update/ci.json b/libraries/Update/examples/HTTP_Client_AES_OTA_Update/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/Update/examples/HTTP_Client_AES_OTA_Update/ci.json +++ b/libraries/Update/examples/HTTP_Client_AES_OTA_Update/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/Update/examples/HTTP_Server_AES_OTA_Update/ci.json b/libraries/Update/examples/HTTP_Server_AES_OTA_Update/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/Update/examples/HTTP_Server_AES_OTA_Update/ci.json +++ b/libraries/Update/examples/HTTP_Server_AES_OTA_Update/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/Update/examples/OTAWebUpdater/ci.json b/libraries/Update/examples/OTAWebUpdater/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/Update/examples/OTAWebUpdater/ci.json +++ b/libraries/Update/examples/OTAWebUpdater/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/AdvancedWebServer/ci.json b/libraries/WebServer/examples/AdvancedWebServer/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/AdvancedWebServer/ci.json +++ b/libraries/WebServer/examples/AdvancedWebServer/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/FSBrowser/ci.json b/libraries/WebServer/examples/FSBrowser/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/FSBrowser/ci.json +++ b/libraries/WebServer/examples/FSBrowser/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/Filters/ci.json b/libraries/WebServer/examples/Filters/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/Filters/ci.json +++ b/libraries/WebServer/examples/Filters/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/HelloServer/ci.json b/libraries/WebServer/examples/HelloServer/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/HelloServer/ci.json +++ b/libraries/WebServer/examples/HelloServer/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/HttpAdvancedAuth/ci.json b/libraries/WebServer/examples/HttpAdvancedAuth/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/HttpAdvancedAuth/ci.json +++ b/libraries/WebServer/examples/HttpAdvancedAuth/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/HttpAuthCallback/ci.json b/libraries/WebServer/examples/HttpAuthCallback/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/HttpAuthCallback/ci.json +++ b/libraries/WebServer/examples/HttpAuthCallback/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/HttpAuthCallbackInline/ci.json b/libraries/WebServer/examples/HttpAuthCallbackInline/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/HttpAuthCallbackInline/ci.json +++ b/libraries/WebServer/examples/HttpAuthCallbackInline/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/HttpBasicAuth/ci.json b/libraries/WebServer/examples/HttpBasicAuth/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/HttpBasicAuth/ci.json +++ b/libraries/WebServer/examples/HttpBasicAuth/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/HttpBasicAuthSHA1/ci.json b/libraries/WebServer/examples/HttpBasicAuthSHA1/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/HttpBasicAuthSHA1/ci.json +++ b/libraries/WebServer/examples/HttpBasicAuthSHA1/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/HttpBasicAuthSHA1orBearerToken/ci.json b/libraries/WebServer/examples/HttpBasicAuthSHA1orBearerToken/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/HttpBasicAuthSHA1orBearerToken/ci.json +++ b/libraries/WebServer/examples/HttpBasicAuthSHA1orBearerToken/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/MultiHomedServers/ci.json b/libraries/WebServer/examples/MultiHomedServers/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/MultiHomedServers/ci.json +++ b/libraries/WebServer/examples/MultiHomedServers/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/PathArgServer/ci.json b/libraries/WebServer/examples/PathArgServer/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/PathArgServer/ci.json +++ b/libraries/WebServer/examples/PathArgServer/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/SDWebServer/ci.json b/libraries/WebServer/examples/SDWebServer/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/SDWebServer/ci.json +++ b/libraries/WebServer/examples/SDWebServer/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/SimpleAuthentification/ci.json b/libraries/WebServer/examples/SimpleAuthentification/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/SimpleAuthentification/ci.json +++ b/libraries/WebServer/examples/SimpleAuthentification/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/UploadHugeFile/ci.json b/libraries/WebServer/examples/UploadHugeFile/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/UploadHugeFile/ci.json +++ b/libraries/WebServer/examples/UploadHugeFile/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/WebServer/ci.json b/libraries/WebServer/examples/WebServer/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/WebServer/ci.json +++ b/libraries/WebServer/examples/WebServer/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WebServer/examples/WebUpdate/ci.json b/libraries/WebServer/examples/WebUpdate/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WebServer/examples/WebUpdate/ci.json +++ b/libraries/WebServer/examples/WebUpdate/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/FTM/FTM_Initiator/ci.json b/libraries/WiFi/examples/FTM/FTM_Initiator/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/FTM/FTM_Initiator/ci.json +++ b/libraries/WiFi/examples/FTM/FTM_Initiator/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/FTM/FTM_Responder/ci.json b/libraries/WiFi/examples/FTM/FTM_Responder/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/FTM/FTM_Responder/ci.json +++ b/libraries/WiFi/examples/FTM/FTM_Responder/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/SimpleWiFiServer/ci.json b/libraries/WiFi/examples/SimpleWiFiServer/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/SimpleWiFiServer/ci.json +++ b/libraries/WiFi/examples/SimpleWiFiServer/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WPS/ci.json b/libraries/WiFi/examples/WPS/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WPS/ci.json +++ b/libraries/WiFi/examples/WPS/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiAccessPoint/ci.json b/libraries/WiFi/examples/WiFiAccessPoint/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiAccessPoint/ci.json +++ b/libraries/WiFi/examples/WiFiAccessPoint/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiBlueToothSwitch/ci.json b/libraries/WiFi/examples/WiFiBlueToothSwitch/ci.json index 521ae8f5ff1..156dda6560c 100644 --- a/libraries/WiFi/examples/WiFiBlueToothSwitch/ci.json +++ b/libraries/WiFi/examples/WiFiBlueToothSwitch/ci.json @@ -1,6 +1,7 @@ { "targets": { "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/WiFi/examples/WiFiClient/ci.json b/libraries/WiFi/examples/WiFiClient/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiClient/ci.json +++ b/libraries/WiFi/examples/WiFiClient/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiClientBasic/ci.json b/libraries/WiFi/examples/WiFiClientBasic/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiClientBasic/ci.json +++ b/libraries/WiFi/examples/WiFiClientBasic/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiClientConnect/ci.json b/libraries/WiFi/examples/WiFiClientConnect/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiClientConnect/ci.json +++ b/libraries/WiFi/examples/WiFiClientConnect/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiClientEnterprise/ci.json b/libraries/WiFi/examples/WiFiClientEnterprise/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiClientEnterprise/ci.json +++ b/libraries/WiFi/examples/WiFiClientEnterprise/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiClientEvents/ci.json b/libraries/WiFi/examples/WiFiClientEvents/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiClientEvents/ci.json +++ b/libraries/WiFi/examples/WiFiClientEvents/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiClientStaticIP/ci.json b/libraries/WiFi/examples/WiFiClientStaticIP/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiClientStaticIP/ci.json +++ b/libraries/WiFi/examples/WiFiClientStaticIP/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiExtender/ci.json b/libraries/WiFi/examples/WiFiExtender/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiExtender/ci.json +++ b/libraries/WiFi/examples/WiFiExtender/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiIPv6/ci.json b/libraries/WiFi/examples/WiFiIPv6/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiIPv6/ci.json +++ b/libraries/WiFi/examples/WiFiIPv6/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiMulti/ci.json b/libraries/WiFi/examples/WiFiMulti/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiMulti/ci.json +++ b/libraries/WiFi/examples/WiFiMulti/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiMultiAdvanced/ci.json b/libraries/WiFi/examples/WiFiMultiAdvanced/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiMultiAdvanced/ci.json +++ b/libraries/WiFi/examples/WiFiMultiAdvanced/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiScan/ci.json b/libraries/WiFi/examples/WiFiScan/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiScan/ci.json +++ b/libraries/WiFi/examples/WiFiScan/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiScanAsync/ci.json b/libraries/WiFi/examples/WiFiScanAsync/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiScanAsync/ci.json +++ b/libraries/WiFi/examples/WiFiScanAsync/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiScanDualAntenna/ci.json b/libraries/WiFi/examples/WiFiScanDualAntenna/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiScanDualAntenna/ci.json +++ b/libraries/WiFi/examples/WiFiScanDualAntenna/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiScanTime/ci.json b/libraries/WiFi/examples/WiFiScanTime/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiScanTime/ci.json +++ b/libraries/WiFi/examples/WiFiScanTime/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiSmartConfig/ci.json b/libraries/WiFi/examples/WiFiSmartConfig/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiSmartConfig/ci.json +++ b/libraries/WiFi/examples/WiFiSmartConfig/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiTelnetToSerial/ci.json b/libraries/WiFi/examples/WiFiTelnetToSerial/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiTelnetToSerial/ci.json +++ b/libraries/WiFi/examples/WiFiTelnetToSerial/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFi/examples/WiFiUDPClient/ci.json b/libraries/WiFi/examples/WiFiUDPClient/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFi/examples/WiFiUDPClient/ci.json +++ b/libraries/WiFi/examples/WiFiUDPClient/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/WiFiProv/examples/WiFiProv/ci.json b/libraries/WiFiProv/examples/WiFiProv/ci.json index d8b3664bc65..ed63a39b4c0 100644 --- a/libraries/WiFiProv/examples/WiFiProv/ci.json +++ b/libraries/WiFiProv/examples/WiFiProv/ci.json @@ -1,5 +1,6 @@ { "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 701e77b3b21..21b3635bfcc 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -460,56 +460,42 @@ }, { "name": "esptool_py", - "version": "4.6", + "version": "4.8.0", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-src.tar.gz", - "archiveFileName": "esptool-v4.6-src.tar.gz", - "checksum": "SHA-256:22f9bad0cd1cea14e554ac1f4a6d8f67415ff7029a66ce9130756276e7264e5a", - "size": "99141" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-src.tar.gz", - "archiveFileName": "esptool-v4.6-src.tar.gz", - "checksum": "SHA-256:22f9bad0cd1cea14e554ac1f4a6d8f67415ff7029a66ce9130756276e7264e5a", - "size": "99141" + "url": "https://github.com/espressif/esptool/releases/download/v4.8.0/esptool-v4.8.0-linux-amd64.zip", + "archiveFileName": "esptool-v4.8.0-linux-amd64.zip", + "checksum": "SHA-256:e637adc204b74b980013e89dafce6e056401ec26c94e205b0158075a836c56c6", + "size": "64617780" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-src.tar.gz", - "archiveFileName": "esptool-v4.6-src.tar.gz", - "checksum": "SHA-256:22f9bad0cd1cea14e554ac1f4a6d8f67415ff7029a66ce9130756276e7264e5a", - "size": "99141" + "url": "https://github.com/espressif/esptool/releases/download/v4.8.0/esptool-v4.8.0-linux-arm64.zip", + "archiveFileName": "esptool-v4.8.0-linux-arm64.zip", + "checksum": "SHA-256:c3a7749bed8d1929b0ad35743cc5557d60ecb81a10ffac28cb55ed1545e0223a", + "size": "54432155" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-src.tar.gz", - "archiveFileName": "esptool-v4.6-src.tar.gz", - "checksum": "SHA-256:22f9bad0cd1cea14e554ac1f4a6d8f67415ff7029a66ce9130756276e7264e5a", - "size": "99141" + "url": "https://github.com/espressif/esptool/releases/download/v4.8.0/esptool-v4.8.0-linux-arm32.zip", + "archiveFileName": "esptool-v4.8.0-linux-arm32.zip", + "checksum": "SHA-256:b781a86b53a17d24e02996c0a7958f9b76f6873fc1cc07c64ab6326e19395570", + "size": "45858426" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-macos.tar.gz", - "archiveFileName": "esptool-v4.6-macos.tar.gz", - "checksum": "SHA-256:885ec69fcffdcb9e7c6eacd2589f13a45ce6bcb6742bea368ec3a73bcca6dd59", - "size": "5851297" + "url": "https://github.com/espressif/esptool/releases/download/v4.8.0/esptool-v4.8.0-macos.zip", + "archiveFileName": "esptool-v4.8.0-macos.zip", + "checksum": "SHA-256:73bba755d2da15ef18b8b8d8fe37c459d296648efb02d5449a3fc0035930306a", + "size": "29821710" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-win64.zip", - "archiveFileName": "esptool-v4.6-win64.zip", - "checksum": "SHA-256:c7c68cd1aa520cbfce488ff6a77818ece272272eb012831b9d9ab1280a7c393f", - "size": "6638480" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-win64.zip", - "archiveFileName": "esptool-v4.6-win64.zip", - "checksum": "SHA-256:c7c68cd1aa520cbfce488ff6a77818ece272272eb012831b9d9ab1280a7c393f", - "size": "6638480" + "url": "https://github.com/espressif/esptool/releases/download/v4.8.0/esptool-v4.8.0-win64.zip", + "archiveFileName": "esptool-v4.8.0-win64.zip", + "checksum": "SHA-256:5575beabfe8c1c1ea7c1a0f1bd42ee97ac3f4c4dae5fc74cda58be0e23016da3", + "size": "33608471" } ] }, diff --git a/platform.txt b/platform.txt index ebc8d23a5c7..b9c31d4337f 100644 --- a/platform.txt +++ b/platform.txt @@ -10,7 +10,7 @@ tools.riscv32-esp-elf-gdb.path={runtime.platform.path}/tools/riscv32-esp-elf-gdb tools.esptool_py.path={runtime.platform.path}/tools/esptool tools.esptool_py.cmd=esptool -tools.esptool_py.cmd.linux=esptool.py +tools.esptool_py.cmd.linux=esptool tools.esptool_py.cmd.windows=esptool.exe tools.esptool_py.network_cmd=python3 "{runtime.platform.path}/tools/espota.py" -r @@ -84,6 +84,7 @@ build.extra_flags.esp32c2=-DARDUINO_USB_CDC_ON_BOOT=0 build.extra_flags.esp32c3=-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} build.extra_flags.esp32c6=-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} build.extra_flags.esp32h2=-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} +build.extra_flags.esp32p4=-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} # This can be overriden in boards.txt build.zigbee_mode= @@ -101,7 +102,7 @@ build.code_debug=0 build.defines= build.loop_core= build.event_core= -build.extra_flags=-DARDUINO_HOST_OS="{runtime.os}" -DARDUINO_FQBN="{build.fqbn}" -DESP32 -DCORE_DEBUG_LEVEL={build.code_debug} {build.loop_core} {build.event_core} {build.defines} {build.extra_flags.{build.mcu}} {build.zigbee_mode} +build.extra_flags=-DARDUINO_HOST_OS="{runtime.os}" -DARDUINO_FQBN="{build.fqbn}" -DESP32=ESP32 -DCORE_DEBUG_LEVEL={build.code_debug} {build.loop_core} {build.event_core} {build.defines} {build.extra_flags.{build.mcu}} {build.zigbee_mode} build.extra_libs= build.memory_type={build.boot}_qspi @@ -121,7 +122,6 @@ recipe.hooks.prebuild.3.pattern.windows=cmd /c if not exist "{build.path}\partit # Check if custom bootloader exist: source > variant > build.boot recipe.hooks.prebuild.4.pattern_args=--chip {build.mcu} elf2image --flash_mode {build.flash_mode} --flash_freq {build.img_freq} --flash_size {build.flash_size} -o recipe.hooks.prebuild.4.pattern=/usr/bin/env bash -c "[ -f "{build.source.path}"/bootloader.bin ] && cp -f "{build.source.path}"/bootloader.bin "{build.path}"/{build.project_name}.bootloader.bin || ( [ -f "{build.variant.path}"/{build.custom_bootloader}.bin ] && cp "{build.variant.path}"/{build.custom_bootloader}.bin "{build.path}"/{build.project_name}.bootloader.bin || "{tools.esptool_py.path}"/{tools.esptool_py.cmd} {recipe.hooks.prebuild.4.pattern_args} "{build.path}"/{build.project_name}.bootloader.bin "{compiler.sdk.path}"/bin/bootloader_{build.boot}_{build.boot_freq}.elf )" -recipe.hooks.prebuild.4.pattern.linux=/usr/bin/env bash -c "[ -f "{build.source.path}"/bootloader.bin ] && cp -f "{build.source.path}"/bootloader.bin "{build.path}"/{build.project_name}.bootloader.bin || ( [ -f "{build.variant.path}"/{build.custom_bootloader}.bin ] && cp "{build.variant.path}"/{build.custom_bootloader}.bin "{build.path}"/{build.project_name}.bootloader.bin || python3 "{tools.esptool_py.path}"/{tools.esptool_py.cmd} {recipe.hooks.prebuild.4.pattern_args} "{build.path}"/{build.project_name}.bootloader.bin "{compiler.sdk.path}"/bin/bootloader_{build.boot}_{build.boot_freq}.elf )" recipe.hooks.prebuild.4.pattern.windows=cmd /c IF EXIST "{build.source.path}\bootloader.bin" ( COPY /y "{build.source.path}\bootloader.bin" "{build.path}\{build.project_name}.bootloader.bin" ) ELSE ( IF EXIST "{build.variant.path}\{build.custom_bootloader}.bin" ( COPY "{build.variant.path}\{build.custom_bootloader}.bin" "{build.path}\{build.project_name}.bootloader.bin" ) ELSE ( "{tools.esptool_py.path}\{tools.esptool_py.cmd}" {recipe.hooks.prebuild.4.pattern_args} "{build.path}\{build.project_name}.bootloader.bin" "{compiler.sdk.path}\bin\bootloader_{build.boot}_{build.boot_freq}.elf" ) ) # Check if custom build options exist in the sketch folder @@ -162,7 +162,6 @@ recipe.objcopy.partitions.bin.pattern={tools.gen_esp32part.cmd} -q "{build.path} ## Create bin recipe.objcopy.bin.pattern_args=--chip {build.mcu} elf2image --flash_mode "{build.flash_mode}" --flash_freq "{build.img_freq}" --flash_size "{build.flash_size}" --elf-sha256-offset 0xb0 -o "{build.path}/{build.project_name}.bin" "{build.path}/{build.project_name}.elf" recipe.objcopy.bin.pattern="{tools.esptool_py.path}/{tools.esptool_py.cmd}" {recipe.objcopy.bin.pattern_args} -recipe.objcopy.bin.pattern.linux=python3 "{tools.esptool_py.path}/{tools.esptool_py.cmd}" {recipe.objcopy.bin.pattern_args} ## Create Insights Firmware Package recipe.hooks.objcopy.postobjcopy.1.pattern_args={build.path} {build.project_name} "{build.source.path}" @@ -176,7 +175,6 @@ recipe.hooks.objcopy.postobjcopy.2.pattern.windows=cmd /c if exist "{build.path} # Create merged binary recipe.hooks.objcopy.postobjcopy.3.pattern_args=--chip {build.mcu} merge_bin -o "{build.path}/{build.project_name}.merged.bin" --fill-flash-size {build.flash_size} --flash_mode keep --flash_freq keep --flash_size keep {build.bootloader_addr} "{build.path}/{build.project_name}.bootloader.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin" 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0x10000 "{build.path}/{build.project_name}.bin" recipe.hooks.objcopy.postobjcopy.3.pattern="{tools.esptool_py.path}/{tools.esptool_py.cmd}" {recipe.hooks.objcopy.postobjcopy.3.pattern_args} -recipe.hooks.objcopy.postobjcopy.3.pattern.linux=python3 "{tools.esptool_py.path}/{tools.esptool_py.cmd}" {recipe.hooks.objcopy.postobjcopy.3.pattern_args} ## Save bin recipe.output.tmp_file={build.project_name}.bin @@ -286,7 +284,6 @@ tools.esptool_py.upload.params.verbose= tools.esptool_py.upload.params.quiet= tools.esptool_py.upload.pattern_args=--chip {build.mcu} --port "{serial.port}" --baud {upload.speed} {upload.flags} --before default_reset --after hard_reset write_flash {upload.erase_cmd} -z --flash_mode keep --flash_freq keep --flash_size keep {build.bootloader_addr} "{build.path}/{build.project_name}.bootloader.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin" 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0x10000 "{build.path}/{build.project_name}.bin" {upload.extra_flags} tools.esptool_py.upload.pattern="{path}/{cmd}" {upload.pattern_args} -tools.esptool_py.upload.pattern.linux=python3 "{path}/{cmd}" {upload.pattern_args} ## Program Application ## ------------------- @@ -294,7 +291,6 @@ tools.esptool_py.program.params.verbose= tools.esptool_py.program.params.quiet= tools.esptool_py.program.pattern_args=--chip {build.mcu} --port "{serial.port}" --baud {upload.speed} {upload.flags} --before default_reset --after hard_reset write_flash -z --flash_mode keep --flash_freq keep --flash_size keep 0x10000 "{build.path}/{build.project_name}.bin" tools.esptool_py.program.pattern="{path}/{cmd}" {program.pattern_args} -tools.esptool_py.program.pattern.linux=python3 "{path}/{cmd}" {program.pattern_args} ## Erase Chip (before burning the bootloader) ## ------------------------------------------ @@ -303,7 +299,6 @@ tools.esptool_py.erase.params.verbose= tools.esptool_py.erase.params.quiet= tools.esptool_py.erase.pattern_args=--chip {build.mcu} --port "{serial.port}" --baud {upload.speed} {upload.flags} --before default_reset --after hard_reset erase_flash tools.esptool_py.erase.pattern="{path}/{cmd}" {erase.pattern_args} -tools.esptool_py.erase.pattern.linux=python3 "{path}/{cmd}" {erase.pattern_args} ## Burn Bootloader ## --------------- diff --git a/tools/get.exe b/tools/get.exe index 161cb193cae89e3dbc84006a7c7332e2683eb329..2082c7a4b68b6438c4f43a736a9d1b6aedda614f 100644 GIT binary patch delta 152918 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
0B%e@fJaaId;=?OP_rRCmU`>SnfAUEcPoi=C;m z-m7k3dsWT$soUP(2b8Fq?NgV^e>F|_ zG$~OP+@o&KdsM^rtWk245;XvORL%CN%l95tvps64_S~pMHD!;Q?0eJ@?@{Yv&mF3n zs$X7JUGSoEN&DB|!rH>Rm31@gde&yvZLIgPKE(P6>*K7eSvRuY#`*y36RdZ$UctJO zbpz{ztm|0sVBN&}B&(W;FL3c&f4MqaZ)d%im9yh(`TlJU{LJ04m5bSW4=Yz=D;Kx* zW>#(v?@;@WWvusexm^C%<*awHUc=hR>D2Vysn*^uwT5;or?pe9 zlbveX?^Kg=ms(1@_&fFMkezCQ>{7om*`-$0F11*9Dj%^^{r+U9n&`XKf0Ey+7Tr#@ zBzCIRwo@(LooadRQqyUd>i(U|=k8Mb)Ba}em1dqq&D>kfJm}5bTg^PVnt9Zkx3KbP zHb2bDldbttR_@(qo~+G0ip@OQ%{-}^uVj6Um1jls^{iL3-pHz&@tRs>g3@*`nLiu^M#iZ2ULQfEp< zo$i-`@<@pOK+8;>tJldtWsGz}mevFEjAV3tree~|0>N;^6`{X{PpMd92>LyLN}ikl zP=0=GQ1{5c_DU-W1eX{t`4>d9JbqbZI{o1z{aZ2pA$?xdK>gC%fBvw^Or94A(jQT! z7y3m2*~w2U)juUTQ_Ja}7bq%emL3dwg7?@o&6%9fZK*JV>W{ICJYjc4B}}RC1{Tww zh$T}%uMMuFPttNDUR9toH7^*@!!pk~9{R(Y)PhhrK;H(}%iqDuKZ^+7D@&TENA+5_ z*=bg}`fpbY3o6Whe?>VZv*+i`E;#z1luEXYHpR zT^}|=X4k4J-S6i= zEh?yL`wx5zOY#fVf0Ju=mH*&TQd*T$RG3qNPDl=6Mi|0OUg)7eVKePs`5z*OjIf!! zSodP41b0);iC)7We3c6N8<{N3=-^B;xnyRMnM3AnJN+{a8T!Y+IP*u!C3S``AR=Dl zbXpK!4d_b$e|^*-TW4E0TR(e3LV}Hden?13uqE4)zaE}}cL|;C$+p!0{QM99Nyj+< zFZpTE8nms0F4r#CO6|6v`T3$pj|6DKKkUiJy!+PPndW+WLXW>E{MaM4hrNfb2j)DH zZp(npkWWKw6rTb5@Xv6>_o3C15SLqPLfTRJf0xjyf5ZFK41Cq2<5$+tHwm57e=6Rl zevRwuas+w1WE z_OmuY{I}QPU;Vi^VZp!f)qmwo|9AXZo#6T}YyW?~`p;MY`Rf1ISBDY?{ae@Xf9F?+ z69)cE66Mgn;pm^nA#{&8_UFX^1GI9thzwb)7k_mU+p!hL_9jl&@rITto3TteqU<>A z2E>SWB#kwE=*}>SvZJDn+y}PJVq2g^KZ30c^hYR)EzlM%x=6PDXo~_xfdUH@m=^u% zN7wz?qDFTEZr15JXND9d(kT{2NX(r(_uRSnydQV|UD@-?!1XFz4;)odgd&)ul*2nK zGk?1CGKV{N)S6b-7{XL1R@2Km^))A6OOzATk2%R&s+^*}?hMt^<#cVhJY36^Gqru? zeYI>kTiajWPw==iQhTiY81xe&>5SGMFF#%zE05L2%j30)@#!L5kc+e!zN>Ar@)JFfLj=i)eU~sLSvr3_)dx8uo+QZAeGo%@i6GDPL5_+q z6XbXw60?27=Vv}{DrvQ3dOcHdm@4e^5 z8G<|~O4b?c`A9}*KUBpzasFao5z!A`mS7GIxxC|@503*Y++Z4>37I~QWBI=KILCnCcE8;4Q zyhJ01X`~=tgOQiTHH+Q(s+e6;0rEVo$;9;!HBl6Eu& zvLzLEyzya5ye{Tp{w2Xm%86U|(f*3tEEs<&)T`2}S#{5Jrmbp2SQ19#rem9~U$X1MbewHHNM5n(mNdPF476F>^@7A))3Y0O(+Sj)6rg>D>IA;grg?{F`sg%}>Ld3o{pB``d-s8j{*f?AXxTb&5xh+BSUdB_ln6KPp8|)3GKBg%iUrotlOu_$~ z3JT>mI69xL>P;ck=&nWgSajE;dpx=)qI(kWAl6iIrk#4DuyED5GM~GZkNUZ(n+y4N zn)*}u>B8)6uAQN$=|V0)pDz_k?R_D%Fh6zk`pj(pcJ%5(VRky-9-{vB+|+;kTrrwC z4-7YQm*;Nfx7A>%Rku-&!t~5QtD7||NZm4>mX(*XA-B1F5?Bxn3CpcYo0Mc*k!N76 zeF*vJT3)5zkTuY`_bmDKmS;QeWOF^p*lxwFRzXo(re}#UWaiVvUd}S`Pw)iOKjU0~ z$W{GkT+=`0G5x1p*V{a1%napsh;L@ zfo865@=Y`vt=MLUMA_cYqQ1uDvv4a93sB-(v*FrESrBuZj_n0%bwviMUH7(CBEOvK zOtVA~LvFdmg0OiW88i%5(Rka6Xg-curik1W)0oCnT)wiGBrPJVha`Vr*#v?-AmpAh zt-Lkyb-uwjK%snfRhLxs=3=*Nd9nlZUtrpDO$XO zYnGERP@(5Ojzo$TLeGD7ITB0oEK4xp$jn}j>@vN{pVRb!BWiIbh|Pk@7v)LBW3r3U z4q6FNOvm)>dTvKXkxDZ8+90*-%INGawG#|?m1BaJ04tIl2c=V16Y```OOWCCoUn=& z19oF!CK$TWs#nn*(1ujfzaUWs>sW5cbz(-OZo$Y7zdP_?-_C#7Kz5_SHFq{ZN*-iF z4Fpruc!FBF@VOLT9zdacFyya1f>iCH^sLZ;(il?Oc-3b@Uxhg*;y`gJU_~H0HUrMV z4ft$B&LOU^4-iQbP-pG${#?JJe)DXC;64Qp0+w$#$uMmfcfG=&T5_ z6_9Wm??7aQPOI6(d?dtS&-Pi^z6wc7~I`!H$@(K}G z%9$O5LQl3ALme@^v--=*UN6DrFMbjDC9W3cb5|f`3SHO6BNTAOmgcfqH-BRQUhjV) zcwNgac!19050IYvkAsf%*%f?;`u;0nM9$-@H zDZi#HL8KG>Zo*^J5JM-jY0w0*)!}p8JP=LMLl$ZVA06ByYIp_ zs#$+umj`j(?{s(gPIsGwk6!NYlpTNj2ZOlOjjqR)j_M|SFK>kwM5D) zTQ~WyK=E)VF1S#I_5t67EF5O4n@q%3xx9*c?W>TX7dJFt+e+M1wvs{@@q2tj^HN(w zl)ayU>^-)j`!QdGckcQ+X76DJ@9Q+S(mS@cvNlV3eWLvaW#svHJ&aFA3lnxDSDJq+ z6izql&blGO!rK7Z8*bC8+Do=24B$mW;7q$tmB5lMUC*eW#;Vx>ehT;I<4! z8y*Vi7M6J~RYq-gI$)LUbda)POV=}zyD@q{NG_~5!;&yi9jh+U=;Q>-POaJXKo4;W zVo~&$R@1>;M8|2!`t7*}WLJSzaGu+8JU1BW(oyNq5o9{O3LR(!!`){a z0?l3(8Ut=r`d9g96#G$B1T97RBxjr*e5l3J_{6d?tVPmrWw}I~xc^I``#AMT_n~)` z$sohPT&{V_=t)nKmt;MQix}X9!RKU`6?8RU>>{e00}9wP^SK9hD-EA7Q@sN4BT!2#AR_f1lgF^CUgACWcWh0I>gtz>%>@CK zJPOUMgLOs5SSnn3?(*DqG_qy;ZL4l{+)!v?+r0Py@q@}4!-V`xY`%Yow5PzHr02e4 zdn*7$s(_22$6YRzV>MH*x@8S-dpY-*9U+5Kf+D=K*r=shl!^n}An>J_4ho%Oqg>t( zS@*+7>TuV&CptPDN5YFABS8KmHviN?0A%^Y0kRx-R~juxR9sKm%^s|duufoM@<-4v zU};iqQjQ(yIJ@fgdue}7={eq+RXP!8iy||4Rmdy0RPw5aqcaf&{4~f93aJTSjU+hX zGkMk1gt`?&Gu&kFGdviAs3iX!5&sKxa>mU%#u&qE7_xJ6LiPnpY&`Rgjc2xX`Bymm zud(SmFnJoAe+^~(-`Gb%%fG?qZwK%vNy0^{kFriQBXs^uPXoN*0svibx1|eCEdNBb3*oz5$6H>dkPHw~@yvLVe)r|y% z?YN(~$NX4$hj4t`hYiPWg?7_N%eS+gA|w7vCLSroWH7a;&@Eb*DHQVZb`^pdC1gW%!Z zezr$WyUsI4$wWQKej6h`I$h;}La9A#e~TR9v;~+#W?&iilHtA6Fz8gWX)araDdF-A z$1)*5xp05xDI-E}(ir^3z!2avjCV}eSPs8hKv<-lh&G~B2hY812$j2NjXW}w<78+% z-0ou$mipZ{ZzGG)>=hl{=|efrIwx|w&$`36`&cxa2PJhb=H?di%@$w9qYA-mz9@JGFcP>J(puLSzrN^m&7tzRUTjP z<5&p69n*`W8%aOmC*iM-D_B5mr2Le73Y_qHmp3z6JOO~0bTe6Me^JLp%8#)bMwQqn zPqR*>oy6XAWXRY&j}68nc@CTN*kn;BW27tPWT-M$U6j++me-B5<*^XZguKi)9nz^v zb!9bRclxxq_q__e<~C7#FQH}(QT>45c}R<~&v_PHX#yN92Opxxvn-|Z&orKSsA;1t zO|T4p2jTJ+Mmg3Wf1#6N3)^6@Ukl@hfrQXk0v%Pe>V|P-|4xb?edwhmB}kGNY&0BK zBC7)~EvnK2-CJ*>pGgxlvB9`4QJ*EIk8(fG+80^{8U^h}d3=z-gK{VYy)d0cPfArE zeI*JH9uDC=6^t&>7GZb#bVnb%D9xZxD)iNX4)N)joKBbNf0UPwQt8~14hiX0j*i0U z?1_$YLT$h!3M&7@_=!%D%C#`uV!lhsCgoI=g9Nc9Fk_FxSm?sFLUCq}{0nIm@x4dR zJzt0}hGoqqOu-)f9yBOZtP;b&0eOy*O0bdraKU|S814zUGSQWcF0H5EccnvkYQlha z^zcYl8_kYpA4Vod(j4@N{|xI?`hS`pQ-0EY>i%_>{_+0;r2vQhhk7+xhk7+yw|X^O zi1rBL2;8O#Lz{QE3M^ci0tZh;>gh3e?dVx6Dm@IsAL=-1q{&JFaTuBHq2{i?Fhb@*^#p^*aOUT zh696XXkzAZhMPaSv`7vn;fIMe60q-XqJjpR-FS6re3ATdpt7XZMbL>^)eA`CELAHN z=_r4z@oLFqb)M3xF)B(X7qqhAReUc@nz=qpiroCBUs`!Vxbd)2|9A++y>+Zcffs^* zOFs|X>&NeUNh=`hJqCTg4%Qs-urYTP{fYEFtaIt|jk#F+K^yGGjmu&*1QU+?Ph-?>vCZ)5y?Ly4*1&q%LVw3AdD2&6A$T$ zCT0<50?c>ihsbdiQwYdGRpLq(afQlsiOB@r_e*q_o+fgApwpvyd>(;OY(ata@UYH( zf>4a{Il$v@$26E|g{U@ka(Jmu>{q2PNYP?TO}_aYoqWDWC%sQYlyR^BB_94`57>WZ zkj9`>2fMo~-<0%JcafqKCH69QSKS5z1j(+4$TGFVAj!oQ%JgMz%RpZqkf+IXW`J^H z?tmt+Wf6H=J0xD3H|6k1dymJMAa<$F$>Ewfe(~WlsOWxz=Hv?T>+6eY12s}}pP(fS znlQH8RL8*ZGy~B2LjISC&8}9d<@JU+m*MozCMi-Tf!c0f6`=OrtFxaC)@?8rju&JNpOAmaak%aW z^%|By6Ipt1gr9^QHBFN~*HjxI5pQDMIYPcm*9zBXt}aBjyf{Y;fo6yQcRbMKSe@<@ zY$39i%3g&%WJz#&B8A~abLE+6VBG`IB~ zP%MOc1p)@|jK>w4G!4q5I&puE3>m$l?EoeC{WKNw4tj)r>Eku z71%Se>r5KZ#l*K1)EwRFfSHMYnAFUz1i&(upf}_Eg?1pNc%u*z;B^< zQn2j*jR#aYIErZDw?eo?4%oQTX&Ae=E++FsGu2bzqrVK%D(~ zw%#viB`(;d`X=1xZAI7@l3XT36!`}7qWkLG+LlVQV)7FWAgenIaBZR3r}@(T!yxRj zG#K0QoBJBn(zh`7pe<>n_*}e>et5rFnRKt9Ku;V70Pw4`a9%;z%?fnY9e>dsk%%uH zpOJw@MTo?}(!1Ff>JxupBfD1Qfj2R6p8pZvJ{fY5&T>Y`flw&d?w*M~tisO3IjVWs zt937F;DXe{^MiGt8u3^GNjNnfJ!b+w@sb)_pBlR8E!EP7w8QCHKu1QJaUqFj<5@VT zwip-xB_Xl^j>eW5YOBEc8z%YL4YKVtpd0JGX>?}*-V<$rq6UAGLW(;w`L{BS4AK#) z<4h`R@iPn5(|a&?8DxI96n|KRHyYM<7DE~D%RqG+v$oI?VTAo_*^gB2z_$nR9$Uo#%j?RVa$A8GRF)y-(xzOxTsVmB0HlB) z5PoGp{xx8p*U^8KB1k>fG2JT6zwk+-Gpyx+mO)NZ4@LS-QU!EQ;Yk~dSp@Oxw88-8 zQ+i=5B?t?Mcr>P{)r2=R_0i;G0x{uJEx9XvWvy=luC$s=1t!X&_(BjCdHB$tz~`=l zG=c{k#m%v_Dkiz0j3*=ww0fEdETI~KC<@B&C7DVo4Ss(iRlU9JI=ZdBB&uFU2&SAz z%maR~j^3lxRNROo)9+$#-|?10+_|gs3n_ps zNKZR30Vq-~Rw|p=Dosby!g`Uf0o3Z4a0!iso=kC&vxa8ITDc~03&Z||TlE^1O?5;F zd(l`+mzoga=&@{OsAJCrLdKw}$A25Q5j9*t0e_)^CCp1xQwwhF$@rrfSz|rtIXqw{ z13$Hgp2MGo!(UP3FrH?pt-m4L7V3`t#r7*@FK`sZZQ<}tTG)P7A`eUKLqH>ANBia^ zX!#}>SD?;-X=Mc?cP1KI!@3Wp?i>nrrhx#Q4nY`)`hAU0Ls?Vg3MAqR#39+5`p5qo z`hPv=q2u7L6hLL)70D_TS-}W5X{97!fGY__QmCPu)q09EUgFDbX;gq>lTewmZ({D2 zehrKbRaGp58Cew!6migV(2I{Ri;ESCnxh*ZZbfFfS1hfxrE10h7Art1$o**$=)z5Z zjNT#_nWO;UdhuR)y}m9D9IQnKAAXI3YJaiIrstOu1s!v$L@*to^p?cUN%#3v7bf0G z)kGFH>CRGC74hFR*|*h1LG(@wpmTy7q+z;{a#FbHfNc%3X<;IddwmAXTQsEjm?{`( z>2Bl{=I5v9MWov)2XQ7=WYzr*UaXPBAhwE$@7nR~MA-y%g4rCSRuRZu0ozt0)qhT+ z@DDnm>SIQT2F!GS61;5{?Q%FcG5-HA#D7%hY~CLV4x=({hty9I_xR@bk!!5#=>J;< z8~H=+n}3gJ!$dWonZ#GDFoU##Pu2|nZfIk?Y1K-C5Lw_w2B?`1v%@|tNj^j?_}ZO+ z-mq9!_{>55)A-+ndzEF$n{4?<;D64MF}pr^`#bd35pNTEJQEI(Li)#`5E|hC(BmIB zjO~5x^w>t3LqwVVAFuSHObT}W^yqTT#f1lBXyMFEr<9Q1Wa_ul@*YC4Qtc5W+mnE> zi%7>}G>JC?=mNd}7`UFkCga#%TVGoLS~NpJ@dCCqGWxk`XGRjwCH@se=YMHM+SL44 z@bEuTOke~cbEJYtses}s-_Le7}Ow>;1|38UGeo@7RCw9AREHa8y^dvqzMSQdP^okmjVM`L~i}j^0 zLD)+8{ZB}P_)yuG5`;*NDPh$AB9^?iB@Y^5&HId@Qgo16N;z#062eEcJ zG)Xw>QrwxrD|bF>n1697EF=#L+*@>Q@fuvi9SJcIq@hJFWka}>;k!B?Zs^!Pknb>v zQWMDcyI~eYn+@dqT`1{vk#8T7Z-xX~C;9#q<=N*aULibs(Cz<2f}w$b3Of0`*!~r@ zO@yJ;njx{Z+ux#qp0erp@USOQSe-;M6_WygvxhC3P15229Dga{C`lubL{bI``O~lT zQx;4@6$3F<2pQCwSJf6l!@Q%|{sbdiq@4{@+yl|6SSnTPe(0hDHOJ4YWJXh*K}O$g z$`-G3)+@9?Hs4__36_ERW>fgFRO*f(U=d2!K1toeq^>KevT&8S& zJO~|`MsO8Vz(K}R1w|5g$9jtoN6T*~i5!_j zvclp8TnLj?^sD~3w_Xc3Q_F&6ie@>a1wtUbOTglMVsjmSIaJG2F2ND<37!zSZ6}0# z2+U&g{(sR59NA_IVgY-8AJ#u(PqUBNa2OK06+XS6kHlVB7_&ya0W3_DZ~|q!1xIeQR*-TYQTou z(j|e=vXE6>5C~wz+ho}pAqb*vuJMuhV2meX*c zq)jFJpk#lezmaY9ZQDD_MdeP|up8MW?F|rDcdjstT=W;U-q?grU6_d?XP~VS$k&0> zFK)`UWUo!nUrBkWg%f^c?%LG&>2qf z{ePoN#Znj?rDq9ikSohvOziZ?Pb}87xj4y5Gf=SXi{7G=$h?5knn%3ca?XA0D3(1s z<{m{I6wkP-_UJpKxlXBr{KxZgMHk?jl%JazkHwD`U9k)R9q$`e*Q`4=3?SUG* zDTMwKuw#ZWMS!&E>>4djl9h3&v={*^Ab(bmN#8b*3?rut!Gei}^~E&Y{8FVZyLGq7 z%OsXtUY;0~%tNk7Iop29ZQkMFg%nAZ?zpB)X=hAuoYlqXDF zfr8?LbF@}ZDvP5aD@JW``pUeP zq@+nVtt0GUe7SdGcdm12m}VwL8YLSZ#q=`FkfHPqO$_Xchs*L?1G{o{`l>7QtTf`e z6K7At;p9nvPEBbl@$$vq17Xx^K0S~j)zHL1#LKpU;2;uT8|76B&;A^(E`L*yi{1jo z-GJ_|IebP139Ksb9cgH*8p`TaHXTUv_etdk?yY@IyRE#b-1+Kl#qWm}(a--?W^bu1 zOM044s*g@{>@n0XpL}QUk{dhW`B+7r46>IB?%)osG^vYIxK~oErlDD>H=Fb|C0}&e~q8R zFo{rsFjl^$hZ>^$ydrVoNaEomE+hk(31-Y+&&QYn_;Bj9ME1xOY5jWH596HNUr*da z_qzwnpN6;91T}O-jUh?AL1$`z8-^e2F+$;n4URA!a9cy%ru>O#Uw^~Yh}1kL@myT& zwN$TET3Slec=+!`4v)@x>(#qnJ3<H+VOHlJ89 zuF^8=DalBH_K*avDt|%y1u2JPg#mLxQF^s{80oXOuJC`Q#yTIyb@;#N1*_Ty`=A9Y zCj~2bvv*I2+j}ZklQsm*o_f6=$NXtAX=hSFWW0X!`T~HCh?T;?J^IEmIQyX%uRfp{ ztiVxRn%b2XY{y-@0*Cip%){EEWblF}vp}9iT#fw^n6t7)S$|yx!RoSTfFz4z#Xz2) z>d}4j72tYFQprfU@HfL1x>%$|^I>iVko00QxLZmqPJ1za&^cNx`7JHUjM6Y02P4gz zIEz3bffH!FV*%u@O8@ENd2#><55})`aY@%NaQp^;6c5PmqD-N{s-;3fc%o^QBm%mC znPwu!o_X!k?SJX(GgpOspfw0uuSZdT@@_whct%nD2|S#~15OI9ZR89O=qZj&T0X|> z_@K24g|by~Wr4^Krc41!Uj0KnkX$E>Y2~D0_JGJYz*xBOVmwP=QDZeKkB6cvt#=;c z)z|RwEj;`!JmB6R{I^xf82R_{@cVf952{2%F^|3W8h=6D#PkS~nYLyOr{lf!rx_MV z6GeOAWNpKCoI`fT&KMdVZO69k{q`XIW#DJRpJNZeU%zwSF`UEj_q6kb^AtSK+WQ8N zKq(vE+BUY7wXKrU@ec*xOV}GU7!5S&?@?t7TRHmK7#?MTgI-jyZ;x*Sr+`6L< zrZ_Y~O--D_oxm#PQW^JZ0PCR6V=IVu2&sa$TYs&j46}rwr6FFd;~p1bxl|O(jgzAD z>9#u3vf|aDf!G=hI^*3-I#CSP+6z}9f5qCzd@YD~)Bq}8`xyyIE?c<+tR z5bEv4!df79LBm(wJE3(IPPRP5UB_tOvLsak1`@9%PXks06c^h8Fj|29%p0I}btM4| z^nV3~KOhb*lqli)i4ORuK6~;cZ7C<`MXb>c#H#bz9$)F+Z*9*F*W|Y=Ez2_AfGxiN z+#9j|qz&xR!e`r^`|Mrm+OVx>6Q6D4ww_IVwhi3kw?BoA+~Pue zZs-;lNN`*3?3SvS-r+4(ynRoFnUa$dCVzcOD&q93sPJWI^N>RgQ=CK4lgL;X&rdci zafat&F%^{yUXst>0HLE)RC2_DaUbf;q(#6cEzQH7VN7bt<_)=5hYe3n+@S+Q$M8Oj zyK)qquy4D+L0NR@6hz0}PDU|Yxr>aIeSo2cymG-)rGYXs&-MUPyItR{G4?^JJ@z=^?Z5AaJ>}ru6*N!r> z&1<^@{1-?e+bD8e-xEXzUPb$_$hLvm-4d_(U!cD7BML+YK_wb4#CiT91HvfCk4Am) zvViNwpepU5Lr*gW!FNfeA^mN)FMqZ8q9gMy`4l%nX-y@0KIpcDsIl*(ZaYHS`jBdC z@&~#tsz!#?a?$M8er)M@N12rSNm`; zoYj7yB(a-~N{bvPaQBOPEf%baJWnY`u}d4e{v3cO*L>ts1!JVC=S}<4&4pJ|S5R(O zjrPfv4Dp6HluCnPhxKHA{C{A_4DfzDAhL4IidL@u0?&Aq*f4V zcLFzC={01O^fD#~pym%+{+&UQ#0y5HLz}7`5Q`pYj&Sn#wtP=^Oi_@UqHR-53%xr z8$zs5)5JCda-lhm8Q$+bWU+}%D%(I2!^B*ILcCD;$#!h&T)oh=W-rg@-IH*JS#@U< z^WW0;=(8o*(Vr*Yi9VbxOJqq;iiH+Mq9oWR9dK}}Wr9d{N!#5AaV`)oq?{vN- zAb(zIUz43|@221qIdX_9$!hZqu4PQEyEbMx?lvKo)&Dy&0)NUsNLCQH77p`2=t1P@ zCper8Lle3BLv0M0mI}unl;p60Zjqr5w+R0eHI@yJrdd&8YWn)snFV4}DQCyCF`MDf z;9(pOr?q%~{;<8ftv>%5y!~}eQW*fLCnD}l+1+RngPkWV6Pc*ezBDIU_aj`~oU&V95O-yQK<|M<1@1)}{4%IjqyFVwe|hG{+|{W|^H(GD()`r*>yf!$1P;!>hx(Pd%&Ya< zt}YzV*AYk5_0Fkvq2#C@Z`oj?%41VBK~o%1c^vW&QK_~`ZCf1tjsN?kp6i}eIh|%Q zoztNu>VLq5;wm?tS=%;k`axlGTyPO);XZ>Y8O(lBp}Q>JiJUK7%SS<)UrnLF#Kie7 z6reSd?I=(z4z zd$_nKR}69@lp7out1h1&6|v`B5+a#6FVNs=nt%PVhaM@6#J>xNPiSL~O+*nVMiFQV zP=qF$zlw)xO=y5c4k+P}Fd&o&L3yn(BEBctLi zg^|f|o7u?3IR8U1IiZHTS4cBxtu3_2{nHu$?9w6c}Ow6dwElQ9||kKj|^6{{{*y zx6kU33?SIa-vL#l*{0H6dp;)H?qNT~EUIxJ>)9(Z)h%&)wi4FDcq_porJ>?Rc(fP+ zPCZr>VCY}@nw~^8>7K?Psn^@=bANOlC5A1Ab{cwMka;5+8JxBoc3X*`mnCTZ8?;4d+ECnXK08&d z#W_jnV#l;1&>6?$#ZiP&z(H0#o@<)4JcRF4G4F&jjob1yPEDL89i(ZJK7Rz<;NzIL zizpTau!t>C7Ht;y9mUO0^Nu)Es)7|3`LY-09dRZj`e&huxDYa`_!_xW-U_GQE=7f`2pGipVxrwPd~h9BxNO8yV8mFDZ8>lJ~k?NQIkly`MZ) z;!oaI-aF8+w+ApiuI+Y zT+)Ro+sL4QlX@xpenoj_dn?<>CL?rce}H$P#t=M}rLZMGOqDXJ)OT3lmeVQ)Pky=K zuznD^$uoeb18qIhaA2%`{z-T%(w=fDJaX2eE&Tt@g8h*w>HL zJLlldFcAg@^@f`7FMnVp2ZZS|FUs^;3QtXvZ~v`v_6{8QTSz(Yyd(CGd277#7I4vb z@C{3@YH*-ZZZ0QdUE>V7t+=dE>_uGH+&B$eY&DMFQJMQgOja9b@Z(~8nX^;LDt+2I zJr*4U4J-Dm!Eq@LFM zum-tHN(aj(>t)OPW7|R{uIOjyH(0qc-Yjc9H<-sKeTRp@)!LNuz9j&{cH}WY&;o zsoDca8&olypLQ`;2bBZ3#thy$s-mEw8;GxidR8dJ``O$@KgTn|5~rOwXMz<(bf{VA6C9|)1`)qA*^047S(3I-C!?SFgi(F};)8ZpQrR@{-NfhLJe z{=VxJT@`acYahtj_GfWwW@OLLPm8y&Xwul@x3!qhqvAz!S_nvFr!++2W9Z=si0q5v ze=GAM3iBW0IE^oo7Ki?T2L}Gr3}Z-@f2Lyq{Pn?~Q^a3hqebP8W@$qWM;+7+&E5~c z1NN|e&FA&zbD$q{pwGD`)t6V+7c|2m z@heEfJl}QsWa=)n{6@=z74B+PI-HpXA<%U@Ol#YQUvpVYt9E>jno)J1L^G~;3}!%> zP@+PN&|S;(7d35@(nxM#TptQ@KSp|n;~BosEPoh-dT6X>ft(8??lcU4sGuR7o@N5X z;B4FQJTM93i1a+J-g_V1yP>^RL)Wz(7&7vN*p#iVXt0zIC-~)VF&;<9e2lpK(cMi<08~(Iusm+ofEBevL>)p zV1K~2aY~-;?jZEwWYzKq;Nxz4bGU!JXox8GTGVg2#Ji!wj_b4`jOiT4^85|$=lpH3 zGm_1>14#15Y8TLksYbD{y-(W|XK(fD1K-c47CJ zV8}5zHf{~p&pv66uMDeqFb%-`z-5KF=OpEb2f@L$`;Ek8Sb9=VLTZ zjt0B7W-!gbY!n%Y(BK0%=V(zZY9hULYX4Z|7jL8<^4PL2uw61Ril z1c253#sVVa8<4gjIk=A9#eoe%O{-#?pMWv4uz!o% z2MuemIXV$KC%vMznq^u5I*bpwzTJsKB$}Pay@q(eZ2?;k;uAMUd@7u@7Uy8i>r^8c zAX4wcMuUlAj$gn9a;rG$Z&}G0J#BWwt-7QO2E8^9aXc2hw$W-?Fhd5h>0202vye=2 z;9IwD;W6SeUyBd1L32xcEoocid0%(fvls_T_42XdE}tsIy*$N<=cJQR;Z4=qt=(#s zZ0%k*w|3W8w{{8e%XDkkC~xhW*Wn$1G~$hAkb(Z%68vggyY%{OoS7j|2z6iyM`oK$ zDLy++OyS#|T^tE;ZkHUXTs432uU`yPfNCh?Sr%p@Z=z>;jXxo`@h2p3FC!I za(X2kXer6*6?3SW8=PJV3zB^~OhK{_r%pXx!pYN)mN4J0Hc4$oZ?p`P6`=BDV@Qff z#*vheoI#=@$pbOPV-+hDOTrzjTEB!IU+9T}cpwJCq1clGi3rUcyAXd!n^0@*y%9h~ z+sv@L1lnz>mkLtbDOm_alDdghz6ny!3`nIxs==k?o*c;AX)cxFQrVk=^9{%-AoC@c z$@J1edOOQya$H6Qn%-7;OP;qBKq+(<3KapdEQduEoVUM z*Pt~4T1Q-~(8~td?J;%>8rZg+Mq5 zwf1Ks5umnxapNlq7cvbblsDhJz5EQ9k)2N(d3Tt4_imZV*mi#j336W{2{WJq!N#(K zmzAq5gEB86;oOTzvWW^)5>W_UmP=kBqS@u7o4t%AmkiItEDE?m)J3+AMQ33^p6`gP z3}bh|9Zh!}uhYid2xkC4A^dKeYWW9W3) z=p2_Yt4A9=ntXqD(1g=fl6gT>w9AJxitMd^_qGf3Z}Ciik1>~p>W7Bip`7pMLK#cG zFdccAA90#pLG>RaSwQj%l0_sx0n!)P8bYBaS+m^@&+9tO@H7D4!;QUxF(S&MDk?x_ zpo%!n=_IEU$DXQK;Ibxde7y$%n|^7dM5y z3%=y1h{)qv!Ys27@gImEL0rSGko|N`f;;Hj(Y}bZGO#~3g^vXu`_e|JxNSH)JX`N) z_=4N6+0>J^Q3TidngJ$Qe20o2V-*%}C&f5l1-6WUN^BLy#To}TBG<4bhV_&Ieu1+r zaaa{e5hZ`In94{Q0Fd$dV}~h?pp%M!?<9J@fb$E)nixo*13L5KQUCjHor7{IxpeYs zD=K{lcRzj#I{dCTI5J+<+%}$(a|&9*)o+%4!3++7AII0O$8NN@`yYarY;h28L|X6YDizna zh5cVkN3L$rUo?rr0dCYX>S4p-R;PnX?gCx*6ZC;Sg)Ly{0O&IL>hY`?TTN@aOhf?1#)&dZ8&M^$7wXHIxe4@0k?aq#j* zuI#&8ycXM;$Z2%;-XXFh6e`ANuG9|k!>qkq%$deitR~V{XhYt+d&&t(gYh?(G~w^h zy6oyMS6bGdUOa2l*0UqI{lGuXVrTY%FGjbT|EyAl`gDF%`r$#s4gRmQu_K|?SK-1W zZ)>ukzifjreuq2hK~T;*(>>!KuT7GvVYuJJ1aM}FevDypWnB8Tx^d9Gi^mW;x;DJY zBm|4#v=YdW=On8pXzE!)&)&=91`*l7ow;^hb#`FZUf%=mahkyuq#w*e>Nvs!{Z=@ zVfcNRO%aV)n4w%*EeTZzPe)`@uZ2~G;}lMIkD>y*)#x!K-~?+HYMX+Nn{h3{*pxqL zQ%K4jmL|*88mV*eUFL2mq%S5aKOv<9H;3}i!oQr^*t*-B)6Vx@>>XH9?zavdqNS5S zgI3-+eH&%P-&tCFpQZb~g2!#HbJze)@9>T;?*xg&s#l1tc=)1XpOMZ*=aa|mB zaBDxI_WkY9qZM#ttz3d;B5_BUoT^|{Uo{o|>3w*MPRtM+5xk>%S`hzIR6vhe7qOAU z{Xli3IU-$NikRW$v(T=r*YWR)72aThuv>9Ug(*LD{=-w+skUj!VL_SsFsVlc zDdQ3q73Bmo$F!N8oq@t0gnp@CXk_&r2c5S^Q{NqQn^M>Os*yGCd!k169(Z)Jia;sG0ePC7l7Y>f*W7N(jg*tnRUVU&9pRH5-(MXy z=j=*X1WJ;4(634Q5!86WG`~?d*>k42)V^nQ>{Q`D!{M&OKU2fldY*?E!Qb(9 z!scf!^c24Ru-`f{rAPL(hW3qL&+nYF)%YjkB>V0$7geKBly@c{>+{PE*gSt$`oPKy zh>D#Im3~#Lod&8eMGCx``8KpsY47V|RldII?|FqETLpbbO|HB3G<9D*#9ll}U!V8W z>MPzBY&sM5C9B7(GKyo04;k98a^TZmgOsDiwmY>Zk-o4gS;xlTk~Fhcd{>niXfblK z&*JA{54(8hp%$wo>?!N`sHMHH)gNB8Qr+KSNaOX_7Z)ZzGnMMRZ*}j>&PZk{LdOI1 zYH57l=~W~S&3N|g;Y27aPt`i?f_^Nu&a%qXq7TaQG_lqmQQOEqWO^1M&WO%KbM{4H z1;S|L(p{5JSMYkAyixm0#fZUi66wRbAQUN_l@T-rretX5CHG0vMZo4R=S}eH`FJjt zC&LIWzF~;j)OWfatE}JdZJ1PFh?yyt;|T;Ig0VB$q{){3&uFRzwPw%@oZf*3+`1vD z)l$&xKr`u{F!Gq6<9McDKG$6fgb*`PDd01!GDHe$TH=BR8KNb~DnnRHMKMg;zZVRh z4A6(V9(-s#LSE0+9gr0gO}&`Hke|HhK#9vc^{i31 zA!$9fB1lrqd2jDFn46%&+hrEFzt9*5Ie-hD?pNJ`zi<`mDzk3+z=v*hrNH+gUpj7& zyRS;7$+xdesmdoYpE0Y{er+esqM_+`x@!67*$ERd*RP7sNwYT;+M(%}p``+k{Omd+ z!RDIct%+yZT%8Tgr&)t%IA{v0Z?J)vVo{MiR8XfPWsBgndeVz6q@a~bx-~Wv*|WC| z?f5;=-+y0xGX0S6PRMRNUgP}J{M(o{28U7nZKk2fsf;YiGthSuIxvQE;0BU@?ZyFm z5LHnbmYZC$4VE_Z3*;GN*z*d98p}da^jF4JeKS59J37%!du5&v@ug_I`^2H1@G*u- z*5>^?r-3gey|FCnHS7H~j=JxvW18vqp|o&rzE>$ekl)8nj;SsQsAV}6d=B->iXeGC zOuJEf42L}DkUQ@APjPK>@9iIpir59`Fqe?^kJZYa%YOa;&_L^iv&KQ2&ehTppoiiDs zBM!GCdL7Wa_{){tWI?zqe&*`kbLz9YWih6xMd9zFf?=6^c5(0aQU$rZvzyVlYuy71 zE@*x{4w|F?U5BK4EL=Jlc{kU!w{;ISb(K|?A$s%V2m`kJum=b0s^v|K^h&J3?wB(y z>BS=Fen-Y!<6h%;^BP&A49U6!lJieyT^BC~XRxrXU&{KoFmyks_isJTXC-`d{lG`8 z@WJgJ<*PwjW8CH7qX!!Y%R#!=*}lYkkNsbvK8m4vNMyC9<*qRLejy8Ot#f4{1R9tk z-r(|G_39D1%7SMX^NQ|ZgNddS_*MEve|oJrSFBaHc}~{onM|!Z9Nh4dWnV9*(3q&n z_+=J>j?tuGDFn>e6qT94Zm4DAhWqxZT|{gSp4=uNMQh z*RyUeOJpzKI}Se=?ay0C=#wXFQHH(-HaBVH3&_Q!*=T=EmGXYp|IJC(cOLKd6SQbW z$m)CAHy;15#t9JErTk~U;&vz9D-r(VCsm9)<04ST4AZKIb*6+(7_FvSuh)+i%!D2F zhf@aLKdnfPwduFjt@tp&ji5o{G_5(QnXWMSHMY1|&x1Ace9LKgk~ciyZqWq#i#;sP z;K_66odNd7$KS*^vA)~GR9ip!#_jQlj+!2ZbMW|&@niljr1IAl$tb#d`OIZ|Gv_PMBXF-NglgmV?zj|Ip zO_9D_@G$W4yN^5AEw|OgO+n1^3>qrMOUc?V_zgI2m`EH^a0CNhLFQw zgr~&s8VALCYTe3<&A)JKTbc-3oKEYHZC%RSsb#^e^(gV}oE>J$+i-yZLX$@mYs~4{ zL&=Zz4i4I-?(~jufPhfIEfq)y%qIPKCC;oBd6q_Cfd-dA65*5+EfaXUdTcu z*Y%p5pRCV5RsC74O2DjkL0+aZZAZ&ytbtyv=u`{dG}svUs=A=b=_gU3xP2l?Yd*l> zkdxVsv)9mRA!ZC2cz0^c46V%`@^-=_{T0ZfApX_qiRi&VQ~rlpinFG0X-Qt|D&j}W z4TeO+IGeEU9g&3DoX-NLgNdn|=uc|Cgj_rnc-&6Bv?1wMv5iiC3(EOAPgfj#&sLmK z@{I;1ujLYUBV)Oi!mIPSK>s(|98oAQ>DnmQVES=T*t@GXsj@&O?+WOz9FjR+F{*bz zXEMc#DBUn|I#%igJO%L>+R-Z~CF%nxND2mSSrd3JzXBpg(g-&xr3j zP;y+HuJV?4`9f{Rme}*sFtF8F>ubT4LST4#&}NpI7-#J#D9*U08HvHOM9FdI^o zWPb+ReB$aXoTfjOGqHOKwfnL7=J2#-MQH6X_M>@UnS5fH95p-pQHC1KU5dTn;VNfM zoHpCWS{nOY+-E)q0)`&2WAAjLc8%{7qmLiocYnGvL}tAubFPFr+Lh4Gemu%j< z?r8>|30C<1Owf++;$i3$&xYmbI?TQPG`@)w{Xsq5+?S#6vctEl_n=V%B+AMkKM7Ci z)DmStHm*al-&2;1npPQ?Tvjs#5bR!!8@j_wE6yShp+w^75?_dCG^Ke(#hNP0*yepRK$c8INia(M*1j5u5VDTF{4WhC)&s#!Sc# zWLwc+%O}R_LKQ2{mI6A4u*SFg&_mGUc7nnD(Q56`TW4c1!+ePXscheCu`u|>NBWn` z(hu_Eu+|ii}>if>jxT};h1FM6N9gV?&@k> zOhvGVU=MwQPxQ2*fd>97s7>{lbtvJI@2Vk`%)+shR#3L?IiFJ<{OTw(t!II{CFVzl zYV0Fiu|9-ikMhFr%HC?5*$U|SDQYNMGMTiLmt6*v?l#UQNH)iw)|8t9kN3D0R>=zr z%qyXc3P{{{CX{zaN)(UMyrXdMk5)^L{0U~(i@{M5*I+Y+E|9wUO!)=OE_+Q8lACoV zDe!?c$gC_3GfXqqMAy)5z16Y=moCgnUkprq{Vqnq{v4FPY|^p+z1r+Oc+G9LLFQIZ z@Yd~U?|WUt$DQvHw;^QRcl%gqSIrybVO9krD-HDe- z*AR=~t6Nogk%{{U=UX#d8tQet4@NA?K{BHyp92qyW8nHaqM}cmhoFgFD;)3j=%(UM z+rmE6bjO8h;Qp{A=<{9ysRgJU)<=EGln7!sPUdV?^n@Bod)hXN;iv;|PcEtn`28zj z=kpls>Cj+=z{{Uu?uh9%l%$4{x7oiHEVqp-U2i#Y@EpyzPMr_7SH~6N(dt1pQ2wcD z`GDNvHuJe}CxyTl=fIv|(8l zxK#A1dJbJ;i)^buZ9&VGh3I-|-1YcaYyB0;*f9}Qjc>u^s=6zP1{e5qN%NIEDfpIO zaavqJ`!Bo)^~Rr9(75h;tkQdmmHM+^YXv+#UZa0@Lxpv=5W@Ny7|7+1sm^Lj73>lr|uOSwpF2-*0oT zJQm~1ci-c(RB0$*e6*7j9|$L5fjyK<2rZ*sS&OQIKF8aytFhY&)VhD$M56KfNFuL?5l7EhEut}x=pbH3S9ViM~a;;%IfnN#_eBI6iZD}L}i zQ2&$vQ6S|!gyGwpEQdHR{{CQ!`A7M#sn4=zA6VN4z)PaA*_rtZFWyQ6JJ+&$#|9F| z8lf5D9qd<0pWJ-q8PTvLY4G|7^eg#vdGh9mlJ}F7w2u{Q_XC%^Nn|WSdnt>u2k4Un zTb{0^HcaDj5Zs)xIn1O$?mf-v;b9q;v^;Vt$Gc{S)_ad4WC#^bUi&J$*1y>%I97k- zknyNHrb#;DQh3F%_``wAgd&`%E;o8DxdJ->vmwACfq%rP0^dJ6AfBQ?EW{%6gFF_` zRvXD@H1+;T)(0=d)y3)@d8N&yn`@1~hu2cRD4z6|e-feFY+gDUZlr|T^9D;x?5 z_O!-cFWkd@zB%c&$FdjtEw_oa3&D{p6=dHi@SBXKsxl2|`M!%6R)i)FJD`-({A}cV zJU#K4v|-xwlIzA@RKbZuxL?wa<%4c{XV1D!2g6o6q2GxuY)1GYJ_=fv>8l|S0h#Vk z#&le~T0F9K`O(LmPbA)vKCX3$k;(Y*7|MB{@ZqkVy_xzahQi~x7{S#u`JeB!3(jMn zw7&RQrZqiQ;<&Y?*$l!ayj*i74*9wL<*Vm49DejXJAY}`lBnP(mf!Qvqv=z~LNH6D?7Ixs7}Kp44)l?<;dX-9 ze5O>ANLxxinlP$4)O@u4#-6u)u^n$?m4gQS1c^DB(qTZCtAoXW&SS*;aZ;!*hw3yxVOL8pU!exH*jW?6Nw}C$<$G(R@ z?3@#Gr}=Q*zsQ&!bi7z}N3Y+c{T+&h->?9qMyjqqq}Xfxz}(JPZOzrtL~7KUDn9b2 z5R`nCw^-ONJ6_O~oC%1b=HYWzZU?ki*(=qIc#nSrjCL@TyO4{iuBdWP- z9Xw|vEZ7}abtYOQ+e7GZs=NRf6V@80Tjm{^4Uwq*4C`NnfpDJo{|aUmuJ!LR0$<)UsGLdQLq_FV7dD`8d4LLwg`{I^6%OT+U76jFC6a zL-56PmE?f?kDaO*8XRUO73Me4?Jt6JHV@Bcy32z#4VHhsz+qa*GG6TIXz;IQdq>bk zBapI9`875|v0QE86(aN-dJ-M*p2=N;&hv{(H_&-ph>ar`si zlf%nib8kcN#|K}&>{fP3LaWd?yg1Wll+e6j)RNTYtj4Y$4l9*ae|pL)55i`JfchG zZm~;X3248 zTu_WT`a9R+MkFNV{ytp8ESne`#es=D{fG_EOt@-Y*=G5S>A@1UQ zx&prX_3py`b}!)W+VSN2{QBVM2Gm>Oeh|8SdqlnP6B_taw)OkHV@fMD{rTNqT+8b* z`hydw)J|jFuI$xE=*F|}?w50QH^UkI2M0t@sk!^z7gy)|l;;V?l zH79mi(~2bI#(b8azpl><%2_p7Wla<&WziE>QOkGagAb0(e{VEg>kWs$f(pN9X{LO9 zT)O6l1TTbbSg;T|E-X({6!fatInFA{;8L=uTWi{_+L-*T{S@2tF~hm`or|RThlFj1 z7<0w7m@fTl=knE5N3=-nou~8h2`{^gycP09Ov9Z-`5Q&%Z7xzrjg^x@31D>_Q(LlA zN=&0x>k}{dqkf~FnoBU83%bpbtQ+qXGqycc8~v?e=h20^awv$Em+M`oBvXgY#l+Mo zhiP}v)Qmv(CtjgZY74C*JMK4yxz-cHpuJzeuI+^_%-O5T@3dNt%Rkk{?jcQ`&+Zm# zkx8@#L5Ajh-(puO?v=;P4O|KPZob9Vk=3^KC1<`gyX6C`4{ouo=0ic!HZ%Fgxdr${ zLYRGr$yKwHM|W8X%%0mWAAk6Rwxvs#=UT#$-_4&_K(Ij3xn+X-QO&P_C0Bv4%hIn} zmDW7@ld~?D1 zo&06DCbxGCNLJMOCgWvY>ROE;X^-Y3z1=BS&8t+-XBItuB|)?ViVV0fBQwZ+iVQx( zosU}*KemCmLh$s_4GPg+bU?)+kA3By7h+DflRC&fEyOU_c_jEt&g?MCUx%JLgh)6- zd4wu32S+#(vV?`q!Kgup+F_LC5TMJMU`Kej8L`(zTW&o_(MOo^qaS*4_@!{q~j2$Vd}$-lo@L$OgQ{tZjP8hQE-&E1S<(QM!;w zW(n_U4(LMO!w!YFo!(g9(GCq|gaS2(7F|97JBpAPm6nmLgMmg;9^Erabqm!j=g~~g z?swK{rq(6ib&#R*<5>2X92FYyEtZZ6?* zgz_&-nT9;8$4*(|uE)3NB)`Bc?+~dcTvPxBVl8$Ox#0yzO1dcg0o}-hz-&h0ux`My z*_^`R8zZR33fy)C&I}KJpoFEoLYVPNV_RF%u(bQ8Vka_y*#36Rwg4WalO`4K#8QSQ z1m6(*y``W{$3sKhb43cN2LpdQ>yWB6B*i1ij46dU-;5U;+lJ*v7TX@}Mx)iH;`UG` zis=GftKD84ElWW#5cActhd9<>9-z!7r-M4Jz3 zZHqf3osY;`rno_^TQ;~L*bgcDvV=ZFjFK=y>n}&9q^P}x(aeZ>)oDqEs>n#VA8O^s z4~ulKgrXlWo6QhmWfRA?`_(^al_<9$FQ->h@YzE7(_EhCG`c+=SIClrC-ieX(LqPB z_=89{;)U=|H~gVajCzdLHs=fS;PA&wYeT=oUHAzi$P=S0Vqu5I65|4cV9Lhxj9eB#Rc^OajR3`C3Ng|`lRMCW&cipC zTa24fs0c)MaKExonQ6+i zBr`eX*hX{deg6?M<1krtMfNu#LppUWO9TX#RKTAO5)&~qqU?w3#sjdI(hPYkfCIMz zYlf1g;`|%t@l(k1&4i#c)Yw`}_~Z=e3XJ$2IiyN*ETHr=UlVT15;%}xddY+%{D7fN#SSlYgfJ{y`j7b{1;kP4+toP2w3o;- zqJ$1P$vR)TQOHDl9AbQE15o?fjfAiL4?DFJ)Z@sa-5)`PFaH5*!VX4XqW=Pjh*dXK znXtq|L9+ILA-Swhi3?QqB@J<+|8<--R_Kry%X|HU9TXT?I;g1dpsNfxY@KAPp+x{| z|KD*^S}rQb1tCS>C+OjCX7G06#)rfGVm@=S_HkCDlA$rxkivr>bhmwIvxWN{I^X zZzg;|YW0w%(iX&RzxSh4R$Nmo)Xga8u8Ct2Q2QI1&?`rr>n=)!WCBNWKG6fm8lX)8&OEs1u4 z$G4UN%?8N*f`rdyU3{5Z`07dJEt`0#kp2V8LhN!KocV09K8nv_NU;taErzYHQ8}^AXImEm9wZ`H@|H{f6<8SuJC>B4G?Z76_W~vXv(vNh| zq5TWwVjLkpR6tfd`l!3{?1vmK3 zH8X_(>`)!-@bVGbmJmE0T*~E#ffy;vj`gUu#(`@iAf|RgQcEVyFq>3-JqCR7%(A&X!|8}IMn~|J+qHVb%_<+AwVBUg9mt{VMx#~cidNtO!vv_; z7Yp}KB0>Ah4L(BhPgbMc!t|cOt?2OfrS)$6>(^M+Q{>e0)_&1{~3jUC5CZrxs^0@;pB(nr4j6wu0~ztQoaCQ{B0Oa2d)q5YNQq{!x(QKt|lnK7n>B%6^#d3wV(86IUu zdmW-SVLw`8ox$e+Z%MEd>-_J3E~(tY`*kqp+tG>@L<$Krb=e=zT%IC@ZDGtNKzcixQrM}8S=!M#4c1eFZLW9P#I6!=dnMkbSTkCL)^8bHX@xKx_=zmeR{}47HcZ0M$rJ{LQ(G5mp#G~L@k?>%qCjvRQ4vHzD z3kt0NgBK>kul{w3fhKE5$eaB)0RpQG1%{e%hJP|f%I*g<#Xm?8;sUZJp2%y)|6I#5 zA9C*D6EI98PWejsEcjS>oKR7O&DKAzejFdXuW8;71I_9JD8m`Ww^JI zkT_<)WX}x?Hu#!|eDP_UXM1Hu6-uc_^wdC&|EZW7J(3F^jG%*~ASPK9g{4`UMI6*Cn)z)80&Kya@($jLBhZTZ8N(e!DD2;OTx}2*|Z{!J1w^% zhRFQHs}B`v24@#OSIrz9OyQa2`OuW(2mJkf#hU8nbv?5DQqaKcgtSi{QNSAQ7|fMc zc$v1wg7knFAz0_T5u2AY!WzKAe^g~}z9BjVZR&6?^-G#FJdvc&-|zui$i8-TSXi+h zZ{qcPej+BL`82)yCN{r1?|pi3WWwo)XVU4IXX5E-DbserHX|t8=qXrfTo3%LI^U)y zKgFgLLfa?))U^*Cc?DNP$iO)fF)ZUEL99Z;>FN;sD>c4pC&mWjaSO0X_186JC%YlXLXr#i^Oq{i?pRZ6Q0?yOq z${l3dOSVsZX(($QGf5tva!NzrMY15P72a(~Fq%~>^^UBm$$t^nh+IdcL`))5BAt-j z9m>cOh4KwAM(t|N-sz@xm7L3JollqC^pOxIZTXcV3u)GBhb;qb0E46e2DRXWQyDxB zx`~?_y^|SiX$5IqX%%T~Mulm7e)=A@HVGT1ebtB)Rt*s$mI?qbN_~ zsmih00Uct16;0ScHOj9118l;S6;#$>41RH9-zSa~f#VOy(zu_Rn zBLIal01DXv$VIP?&jTpj0AM@^RPWJbu|YApCI$gi`gjB)0sv$N(PTkndI~N@dkT!& zj_m26@t!5?z{S)|#DSW>V+;Rw$z^C>>xN(-1CkWJj9{10M=}vUKOu`Q_KQ-S> z8Gc=e*c8`CJ_M?zqKl3Ca~#Z9bVT?)3K0h4`cE^9m<>)Of%@(ohv4BHhlM2_5$KwZ zh%4~3I^bt>G{qaPG{yO4pZ-D>^nD7m8H=>A8EdofPhVxK|IPu&H+%?lcoo8nWmUMD zl~i~~gU$XA2LRWKr%#gxN1V9QK5w%(m?myk8kKGHrB- z;~xMkUsxhmoS zjp-b4!E3wywd0#|KwI5MlHgFMm0nJG8iGiT!cK;7ds_cs9sU;4$vsduqS=bA0fCB6 zSLDMTg{xWcMCcPw9hQ69S(rt{G`byH_<(@dJFeW2=@UX=u?`3?rkvVu_pSo`_=<&8 zSffD_vFPC?3|;57TS#as+J5%r?#L&vF)sx|(5H%g0a$F0)kFBPD%})*63-Yco@aEI z$tWMh>Zey7m#59GLKu%fLc;_FmHB1a6mK~7i6D$j`=(+|+mj|tzb8%14<=0ne&jAn z>j6Fkhg6ryxKzia{c0}}&@;W-4-pN(pab=i2vMI)+NYFiDGyX$0NhZ@2r8OY2fwIp zwuyzjS+fEnnhBW+w?zc81pW9WuZC$ym;xKu1g_(2CYk1@LH|Ss>o&z!uSx?1p{*L_ zD8ma7VTKKS;{>3r9o9{U7M=!EkCHWiWDq<+gh+K^BG6*2@grR^08^D4IZ~t$5Eizk zUdUp)K(n#cMEq$dR!}a8F)epi?~5idSDyfB4mBt;fOS<^MV-wd7QhYA{ls70e}{Tu zPYoNY@gv!RnWO_V^E0IdI(mY@0)}(oft1{ma6<}fdmx2dmwwqLzxERTGi5QrTO}{n z&2tNwLFKc0VC6sEsHhNrIGv{9lTZ~>11kzWe;otKU$aH>sHNzr$S`kzZcuy;hqSEe zBI{UP?OJ+7@I2PAnxNK5ZNTB$8idn437Qi;tCDsL@lvI;ISA8eHx=(>sT>KNv8ld< zBe*y6+HV$HMTTL!=&~@cZbKOe(Wmed5g&DkV+*ozM5?!OtCXJDRsN(tuL2@?U|6m6 zx;$Uci*YRBkEZ@+B^5EzfH*{{Q`kpoWKIHrn1sQbphY0&?b+`Mx2(6q(SY?AxIrap zZ2{w&$(qv{Txq#|Vv`gO$7WyIg)g;c2M|Q6-@Lq77SVRf8kAqhvn}o-^7`uPh9=h@ z8K*cN^Oo+2TtX(KkafP4h=U{VMu{&K1(rT*l4=1yDt8LX+bPr3QUw_cC62GDu4Z|+ z7gc1TzG{sd*nLV!U3j7}ee&RhX?w|UueF^f#D+^>C*nXg*{)?EU}v*e5$*ygT9An2 z1pGYTNCnLHqP63&1o0NWeM{T$g~H%Rf~-2kL92|}=ZE}N5qp}fLhIde$x-Z$GFb2A zRbNNK)xxjWijTkK+C)KUTK%(H%=$EuAh=0@$T%wzF!Y*Q-B=#DRIZ;g*s6wkSS{bd zd^yH`>O5IU!*fjvXj=xat-7iL!dSGtCk3Q}sS0sWR;RGjN<5{j@KFkWE|g-BzSPTn zQw*uf3;M(y^b0Qqc$*n3lp${`g5E zewXtAsL5t@9ZisjUm_CV1|nGMQ9I*NLrH^^fm&bm$EQ^9(pFVpsiic;dj79e82W!C z!~dqj#DEIt070+}ef#(&n;qA?yL@A}^qU zd_Z*!P(5^HzrS=Ld;(Pe1XR=<$mQsPTyFTtz6E(?PvI7bxRz+ah~-(k5GHaDL_`A; z$_%vAjnzI;1P=6`0zW`Vcz`o&17E+Y4{)IHIG>Oj_^Ee7c0e3 zG7wP77CLV|NQ1?Um7Hz~ofTNLC6 zaY{*W?Iw(!hDia(Pm~+!3F-jb3=!)r*fXJHTT_u$XOP$+N4)zS>~>y;wp6!w&$=7R z=t3_<=y9Fu9x>Mg%bk~j1pcYU0cy2gU#IGJ0R>K=Fysal27!XnpMpD3=l}|SK!Fcv z<{lGJ0a_fGaqK1lx~6cBBzC+Q=oMwwQO*P<+K{Cl!C-T=Wk>H|gF22)Y=Er-d})Oi z5_Dg7Lj#(|1srLB3r^kkAa9`-yMe`0Wa4YA{%b*IRpsD|gG{^Iis5f`9Lzm1K5)NH z-qAEgPlXhFE8He?^BQBvuhUP9Zs)SuFOuU#>&L)cjOaNND6M(T_R<7(n4_fiCUx;3 zv+`C9bY?u|F<`K6MQT2U9dC7Bt4svq`&~)`7=7MN zAhZj1Ngq{=(opnhO2O< z0N=3Zj=(U$eCbs>%4wjqjISUKi5=yQ{b8f@Dj2j{bk%C;2du{iJ+11Qay_U-TvsS_ zLkVfv$%v>*RupDV2P{DgSi&E$0s&yAM}V0`0W+<+y@5C_6C-DabknNRAD4mx8afeG zalnVmc`KyvpBfCH`L#q>_Y}t(U{Z^y3J`toq1Y;mimftu`xeb z&$$W%-QB%*OdoyG?QP+hccRnCHYMI==dggl4-h(;vavz9n{+=HLN)1&c2>@Sp~^Zo zafjb`7rQ=Hw$X5$Pe`y=riwc}5zC5!z1T=pi~0$Z0E3a@469#2n>KkhRmvcKNVhha zFkQDOW*!%1s*ta97zX_Y{)DvSWFCikgQwC3p8-20`kGQNFZmXGE5BBEdx7SV_1||= ztB%asd!W+Z_`{dSZw33VjxnAfl})40@E)JpQhKHFXMk@%+LnstmcYP5n7vQ{mmDB(cE_6z6OY<%SFNGi zM@gkeQbcqmFJt0>IUlih{-kapry=4QA2kEQImovD`PXh#AXcZ2BqvLCIe?*)f&)v^ zDLoS6dd8_uY;2}#x}8C9zm_grj2`)l?%-9yP=!Q$RST_SXn`SCX#>o-0C%5+RjNzb zKnJKhsR+sh)s*u=8W$gxr`*=9JX@v;c{-0=ZhYJ-O$eO1-_p*8HvG9n=_L7sPT0^W9CEu3A(I$Q&Ftc$iG` z3J3=lA;|#_!A?HlRCu;FwO}6>=z_MRBMqdcs@nj3Gl=cwBlT-Ul33ZqaqvTeeK%Jy z`v`TAZ{Evz30h?=kAlKqzDu9H7{IuLGaZW5%%w-gFjFD#UJij=E3Zq_EvE$pY**D0 zKUvqZ8>~#}NMqyq74SH?(I{7pD6_`Ix)vt#v+O7zHV2`JU#75)sj!94AnRFk+hDOG zG;yspgy!8Kp_ewkXEn;-@EbuMzJfx8$C&;`tEu>{3sV=GKzw8ksEXvW5naKml$Ca+fIOBVMZf^(x_szSzn zZ$xsNVKhPtHc%Q-fE^M*(ttkX#^Gn(ZDDu;p8z+=c%F6$UjH9+H| zanS>WUzD5huPq&6NrKZb#ikkJ6HeyNSA`<){Ah)|r@c2Eqhoz+Kcu>ADX%ndlz@o_ zX_L2L2~p*iZ|{x>4lz@27T7ImMYrHsg<$8-zMW?~>gh*Dp@{h!e)I5zR+ zS|&(bKyLgBzIZu`rRYM(sTaQ{P6J!6vWZ(djIF7xD@FXz;mbzfza409SWNCqDhnAK zSs&ZneYB170es*dLFs56vja@(CX!N!*$MX^wOUy?w@hTkb_SWsZQTH56Y~Ph9thKL zt*I@sk60f}RvAGFW~Eh`qm$H|1t+ecKQ=POl#Nn?uCqa9Q;;sVXPiW!7P=|gq^v%Q z6)TNZ*(U`@S?S}{snaW)14o@3V@((9KiZ%Vv>ffsm%QCDOhPY>{PZpoUKLFla^zY@ ziO_BMjFncs0635Gk3)Mqe=?UC)g=Rg-*M4kn^+3uMbCvG103qL-DqGbb`$Gn7@1J* zKra}YD=53m(@E`YQ!1MKP!61&dIC$U-T<}5(^AU;C#RSafKZRhU{XT+K!C0? z$krmKsS9jp(v6r!8^ZP&WgP+6i$N<~R(qmn#<(`A~5lDosZ#(XFAsEMdo{C1qv zKhjim>y=~9W;mt)4sbf_mwol|cWdU0i=8-*bros4$(}B)jnK*~af4vZXYy#xiWq&- zq^z!=6{>c!t$tcxD^WH+A)q0i_V6`bY@KRDNjH1vfD^@EJRX@6>(P|xtZlLp=@qBC%KEzjQi zA%i`zJFIQO@4HKaUI9B&9W*?=TYVe~tk*-m>*9a&Pf3nhDmU6gIN}FD5zURA%3|MUPTRh)zJt(7(K9^~_zatDk zmCR&;cjqZCWqtQ-gGxHJJk%uu*?^zP{hECD>zFxHA?qcIQXt2)a-_uch$)3k`Bl;hV&;T+c?yomhGofL2H~9S&bmWB^MM7dKlZ#!c+cVl zEIwwoZ&3NeizeiqKSmb$vgIHCR&8AGQo2=*u6n%G%p1C4m)*sW6yFw;_3^7S-n+s8 z*NEj{+=FQFpt8_M-NghR^l0IqUVcEr_Td-`+=nlgZ%Nc{@i2GR7gAxWi;r~Glm{Pb zcz~leL(g}X-)x$WJu0bNwOzL@9f(%AtgDB{z%cJ;h0@V{Mh3PZj^Zq zmxuA=TrD1UpOP~!iM?b`rwHsu?_IBu4OOBacDSVr#vp^@73%BA{Cr;jQsJk;_PG~I zD<^q7ufg@w6gfz~Pb=hMOQ%@uTfM6tAgcu+qhIYdTiG| zt-yig1vWY382X!cKfJKcWQD;GX0BC|PlXAKoB0tQ6hV?D% z_*-mP$s~64D}qeSoHgq&YFrcZU1*gZJ}UfFEKbR76VT6i&pwY&tC6F4)CcW{odzGu z@p&F7SaJ%K;D}_coWBxMlyF*dBZ%TvavSMF<~(`BDQ3D$a096(n9hH+(3!As?(d6I zB^{oA7jB+1%%4@geb*Iuv_B;ms_%i@VygPdh%QUT(ER@)>Z`+|dcKDhB$NeIYUxHA z77(OC6a<#;hNT+>k-h=~(%ll$BGNA1F5O5jp_CvED;>Y<=led-`_IhDnYlA(?$o_! zxF?%SDpg(0(uQ0o^^T4)&T3wf+PK>5XUN-)5p3%e$`@3gXcD~i)1b}H z?9BXFk_5Y_%@oQUKa1X|2h!DLn+|hAE{UJC737uD$h&RLBO0%W5mU7lyf(B^fYwv9 zRgvjpE%$lC2g2})-~wiLsXz2{!S`He`~!I98>XG1Ta^`suePm1r(}W&yS5(SKQ6Lw z>)uU`a(LKRNPTaEIxSn0{&^M^ebC_uHxz66BgcTX;XyY`1Z~H2s$*k^=8zXQ)lJGa z4>qQ#3@o!|q*n-U=%v1H(s+OL8xnYj3k{mR`$5{{P6TNfdl+etIj%~v8F!Cw7%u4c z-qpRgH?4@A%y#29s<+aL9f8A%oz~xJ!UW&~xN~>z?6*@@dVgHYe(O($Iz8w>q2S%9=24;}di@$qjea$yO*IOA?0 zKoabGe(!%jIKK2#wKQT-M&ewDMmu+MgTG-@z>uLeRz^R}hGxk}5}nv)}>~m|2N2fvS zek8Izwz^eN8Tsb=Z?y9{_niD0bIh)ZK~2ojj0lpf#tPlBJT|Kf=EV#EmX<~w%1D(f zl^ExB?m6LO5fP*gDABb%F}sw_ioU%18tpvAJ%>E0hapd``cDFHv3rn)sZQt%dLiUg ztrdFYHop360xSCDhNuT=lj*w>r~4C~ z^=?;tkS?iC&F8rQKk_dqT6oK0Ne!m4cT*DMY?bQdca{r7YJe(R!1U}iSkZidt0fw& z=zyz$80T*8xs&5l5oAn_)%GbdKQgA)N_`jNz4iCcfm%U7vR6lWAvXjOw66JX8E z$w?f{Gy?cs9U!EP9K0HgaZcl&t2n3>LdIG5d!+#1s&_M4(Jz3+>HrC4q~n!ijB`Er z9NXm#CHhH?Rr6AN=d2X?K%}?wmY1O2XkBMTJD=WFBkrT15M}_3^)ssO;%wG4T$AT7 zcVUd)2S!b}!Y+7J+gUg3S%B-*{AKj!sn-RMO1t%DJ@@sJZ2S7=spjkcLKP@+J)pK4i$+b^y){9+F=PhSqjG_Yfi|$4`J#Nxf2IWV2p8aP{@y z&0ot`-ulBlGceaG)+@xG0#-q<@zA96PN@Yp?}iWJh56bCY9D6m>6mirYStN4%Q$vV zbPV0NncB0n;dVTJ;Mak$*X#3u8#g$uxze4qi-z~TMWVco?i?}7R>l`AiR5Wz4fjw* zth|)&93PY=jGKNXLedNy-ggx};`MRk2vH_A_WhZNmG+?F-aAL)G}?-1#!d|*ZV|u! zbcKdGK1d^}U@?Bt5a_n`v#b**#1SX$e#Jv$nsy+5nRMvgh!NmFF6E(3;W4$m(wsBs z^pZke*6SI1WEgo|wcFw(PLCcLMG{o)20JxBMDq?IqpEiEotmL&-Vvm7)o!9w zGby?)#(5dUYIg;knz_+!Acid>PE$CvR`!xMk2<|s(6I>g-#IUA+fLio4 z`ft`EUhCproBHf}@v$ALwOt~C=H1rCPMi9WdVre0nYMM2(dN{`^=;`~z;`sQjhDDj zbN8@|t?S$Oa{)ilwDw-j-pvI=dzMRk9yaw~>ZzT*=uf>AvKC#I_Mo+w@9V{UEaFB4W0{_M`zo4`FS@d4V`<3WoP9$T^b-4qnuA|&;hevX1aP8)w?$? z;sEyrFzY2PqIB-FGBj?d}~kT^BOEX4k^W?-`n|6RA+MtKoDhiliMzD%9@6 zocy@abiK&l+THt3eoW|`@5o%+m<=2xa1A0u$damEr~`6wcv^d`sqsTk&F(X#WQ?<# zEn0BaO9HKGjuxCd;YLbkIgeVPJ?2g%kdnF1eCB9^xf3R2Yq~R^1zLITL;%_P(Yewb z%{6zziEPbuep0i`f@}?Qu6zTwPLiDMihPBVykW2EA75l^kTaNNjFUK!;_UhwWQ&9+ zLJ5egCeZig!I#8Wi_Q^o-%o@edzj{Xko8(BTjofws-NO=7x^Xj)Fo8j7iqd{!8)k8@g-Yy;Qa7uehvA%9+pP!ju`D(Ee%TUi8d9BO3wl?PZ-W>`}fv#*XYIN=n#FtU>didsTcChKHF+Gpb$Lge)c7Mae#4 zop%^BdR#<_LB2pkd=>I{akCTc!ezk;zx^0xgcl{I;zcu|FQAq$iQCGj(IiX%s%|Ea zn04NE%pl?<%f>hM>EyAdl-(Fk1QDgDMt(PL0L%EJ5UEu5?mRUXF^92|$JSIBN<;Gs zBt<}hLe`GS>$zi-+mFs>HfX)s6CLC=4!W%e*=~h4tKQvqx^zTd6QXZYoq=9tyDj?G z5-nY|OFwr4s5xEQBCiS1H!04yJxIV74OHz)&z%q=uPM+sSzWHlW zj!NO9Y&b99It%kMYVCohspDECyn8mH!x`C4;^vCaT>j6ZSGmryH*-AZSH z*KgQn;y=|x8`+W^6-9^pPQ%uWV%9Y_?P}2aQj2M;Jx4Om2KSL!O6uWL2~CCTivM>gSih9x%?h)uaDWw{ieA(D7>ms!N-wH61x@M}Rfk+hn_4Q!tD z1FG5bgEFra?ZHQOSXkJ(k9U-)--xPsIz^I zmynx8$qdi#8|@jI442$SyFTV*yg8P z^P?n95G74&RtC9~@I6Lr%-AS@V@dM3ob=$DDac&R>JKQ4rfcF$x>Tf;^aR*0i=yd# z?y^3HYk@V!l0Ok)Ygl*uV-9nQ7hu=lfJ=a)CX2}9nr&erg_xr~i?4BYZBqfnU zEse8z`i~Z=-MUxwKiF%AQ444H3tGKbhD4?@j?I$jf5;H{E)Zg)ShtWjCy*%0mMF@d z=)?5=kR@be@RcqVP$!c=h0BwC$SZKji#X&>WlVHkr~aWZn!4y8vh0!PTJ<8w+cQAf zpjDsE+GChrpLg6QM7M7sv?72tibW%gKkYDxCE_Igp`-qXZ<@kszk;kXaGMU^aDVsZ zSbZkUFZyy|vr9xkRHyK*Ku?~Ez;_!Ggdjon%P^V!>Xd%86=3IyMrX9hg{kt}l|ZTo z-_N3+@1!!?P}V8r&*2sgzBK9;BQ9zg>H};u{8b0IqWyFFDGFN#`Y1B45|T+`u3$;hDFPDdqv`&N1En{)g6B2K z8rPNl=Vf5jZhrKXqdVk0vENLQl5Xe?8^B}j&A-flZp2Z*;orNqUj!lE0N^*{U+8WW zZEh*-iE`KUY;Lm3j`5X zg}whRMBhol-o+`aVQ}B>L3}@|2(I-G?CjQ=SXM{Qn#CM4Y-wOpcLf^DlkGwNdLdj3 z00sE|3B1PPm?ULL;<|qx^E4eqQ{v&w+xP!5bSOpt>16(=^Ayy12d`lLPsN#Ia_wQ# zwo(RLcsdQEwXwOpfT+?yLr3}OnvH50;O28GKXlN?Ak^I*T$hZ~I*@m%&Hb6}6&HD7 z4E_<@@B#n%U4W9=za6>anf);$f-YhM`a`uRYUG5G+|`expmw)oEmpJGhmK8}$vX45 z#cNxRNeSYlx1npB+5}!vJM9?{PRHk*YK6CmT5LK^Gx`|4;~&$)?Am3XlyoI{!dhJ| z#WwHk#dJnkWk|+3d!Ykx{W(x8gw3T;|DSQB-BW$NkpPPFBm%*{r)EIM+X%T?XFh1e z_A5tO)znU{cOvAr$B>6 z9LA8npyg&e-)IL%bqE(z4S7+JU$Z~D78erz4tDW>_0)@h&hnUcaLrvnNQEeL%}A7p zaNHTN73uxuMC3`s_A?s&Bn2y}>m@;<;f2H({v^4J7~|pLJyH!owcrF*HCr57UZ7{h zFL^I;SdMT38BJMZ?Ig%<%Fu)p&+rvVEu@uCi#wc%&-}|NwLtW_R7^y3BRuEHdL!;| z8opi=fqoEo^46}fUBU}Lh#@yP;3>1rJB|UG5&XF|@ce6Bo;3WIwa@cIaKA!6Z6^In z9@m-JsFMA{+Qpx+8T_@HHIcQ7+R>$_c(NL&9dP&IJx|3HM3p; z>?vtCVn-X8ZYFaw-qQ9ZWp(%wCD;E9zzeLAm2%5#`gS%J^nm>1o4n-VDbds~#{zl> zoqYV~`N_XRfbVN@);=A0x9|IN2gZb6cC9IcM*f)13^ekDe_ho+@_qjdXs|5s8>NAN z{7SG#fQasY$o@YB?53UB@mD91>&=c`@~btODsbi+e4EeJUrBUDp*r0T+g`RdC89bf zX1nFkdO*Aoe3y^3xs?onsXH&4dJyv971u%-7yF|M z9RkJo;vS)_NZCcT{%|8rcyjegDFZSxM=hNPaR1xFq4beBXWC z8N<%=XyJpvKY$Aa#J}Io?nGIO+T(zC)<%p;C#T_Gcbh!^1e7v7GLDFR+?i6!67{g+ zg>}SF;H7Q?`*dD2Yp{Zb4wE8pEj`I#>c*vphbAPfW?1|Hmr%TKKfR&cL;(eOmu zh-t|9M*{wcok_$7rM6n}2hp$(3#K!R3IiB8PSRyR{#M2Vwo7X}-{RnY>>~K6Hos3* z@;@4Jf`Ft}=bD9Pu`Or1#Pk2e6#&Hy-mDB79_uD2n2d1Pa zij*O{$M8Vefd=L`M!(g?^{ey+zb${z{Q%38i#^E&`%`j!4IkP_kjI&6=aW6*b zhK<^ndB!78q()vB%ebN3`VEW00LBhGX+}AN&e{BRWb)QHE?WsWyl=6wxq`#{1P^?P zlbX(VLWs>Z>C+Yrk8MBx(|FRJ)e$d8!IQ<|HA#Wjn8Gdi5|=fm@G`x{Y+zH7nEyO4 zd8-qbjXqTX@SR|WkHiZ|o_4IkK@G_bE3==hPIx73rsT!@s~g|BxQq3QqI=cMERVJ| zdsa(a`Oh1Y4`0mRXKUwJH;|X=U#l;SruSbn;_7%^ETruCwbhueRPeu zFq-#Ljx9F@qq}>>X6&v8Q0bKvFPBs4_w+z-o8}u1hNy+2sfXxw~W^u1r`c>9H z%=U<0v-r1Yy1(3j5MC!Z#=%ED_|MHaCXZ?0M1$Sy#G5{`5U zw=Z%&3U6Fu{VIRFmYVV|XWrtqDaWLiIDCZ9+SehxAEyYew#(lL8dM4|8%2tMP!-wr(-IL1$-{E;#!7u|@Ij-3b24XW26TT<8pmW?mt%`rCx&Py;{Npl$+?-_mwnME7uS+boTKPx&a1X6r z2?7y7BIs$<9QRM-9t!@p_(PKDT#GB}p4;BD%IM$2+lNO!l7V_3mIp%Ze1)i+9#V>q zgyIuN4-bA>KUbj`6O1M~c#hS1$cSGex>MjCOj5XBPT);z&h*73w`%?`$Lh;tpB8Va zIO!qpCq1Y9H;-2V*bVXOn`1u-ruJSV*iz;pkQ051Xc1WrfYJ|~vG@EIYzsadj5c$Z zkQi%~DZNu&@vA7gC{1$=PwMM|K$IVQ%fgB+scKzAN!K=apzg1~^F{hJ!8DY28`9fI==fjN5>-s<-iH4tOVE9o8&GK}|LFx_akH)Br} z%ry8=GkV6Vg?u$3T0zw1sy28*=(+q)4p%Kp)gxavvN)tvg;?JaoMtH~}q zR{e1eTHWZW>j<@j-)GRPt>a5q-D}($DuJBC&(Ug@{$i`g(A?28rXC8xwovdGbl=9G zc-4<`x%bSXM-U2x9Ii&^T3zwV8kNxQoR5=lM!5 zMsMw@eefSt;t2;nimDcg8XrBA>3PCWH+Ux0Qz9spb?6h#XXXEBbr5RSe+FJhL#c-F zCtU51b~X2BUd^HeOOLk-gj0@MUFq~Jn_sDb-%tcb9tuXc51xtkj0y(E9JWJ=xrQ9P zEaE7vTkfs0QdahRe|^}#-asZQO&x1g>#@*aEym(?VN~UC$gsK#meE_GM_lmc-l`gG zDf`eC3Zx#IMxRh^@Nv->|Jd zp_E3Qg-7RFUXk=jTV6e0)uU|hIU|m~?K|U(4kxo%RCqKUzz?>5VzhLhw|I{@|5Cys zZ}eNs|FW=z<_`S#>}?+pb)xqzB(e`7J#hj#{b$P2^tM+ltFExX%tK;I>HqhD5r>XI z^litPTJ-IJcSSy((4_aoJmvhY5K!H*@q%f>5;Sh zJ!*oW5k$p?<4L7{+jE;Q>h@*-Vy=y;)h^U?*+VRJ5oE!RrwfA@ z8BrS7V>>SZoZZ6Uk!o3S!K8`-t4~jTK4wT1!BY*A_J#^e1Pq*2 za;(|zT0i#SAW;Kdm4?GU()M_8Z`zT0o)#6@ZCR%G&t|FEX&S8zNu~(^?%{SV-8jLs z_ZX~$AH=&Hz93_egmzG*e;0uLEr!P{atj)iub5d8INaw7B`YV@t;tj5w96-K3d<TvVLud3eTGw>s40Z4D$JTWBSzXbB#((o@)dD4%W4z$# z-y3yY{Mv_a&n?&dLR<;xRr#ZZYV{r^Jtg|JAJ6l3>&Ay>diXrN2;KaiqQdq5MrX1W z9b7T)txXHT|IDg{a=+7?uji6qD(TSRpFQ3E?*(%f*h4H37=4%q1u_ox{&hX@WomgP zvC69C(_;0xJa+u=jMM%3XNdbY!hEiQ~DB9&h@da6zfy!{5+28-K_uEPCJCUwSoHATZ*vlJYj_kUBa% z1^DZ|R6{q~>&@tdN0Gxm;1mfn{WzCqDVze$?em7L+DGpru0(pe_YS;K;`&$7Gd2>z zhvd=qHZ6qUcc%26;5)llfUf&YxaTb_FcIv$!1uF~=rq3HhY!|g$NIn`m|6KhSgnPc zb)0ebBvCGRp7DZqNat13E56ttW(xF_@Pq1n(YM3iNk??9rc0}|l>2Mm-VDY5Rm2~P zPfJ{$rapa^LD*Z9=CPn}bLIbb>2M?KZZ*+RJ;O*)5jot$yb(u`=G8ZbrJz=FmiKo= zOU)|3zxf5%Bk9H_c-}-Cv~o~(@f>wfalwSDy4paX4(N^_qYjvkHBkp_$AAFpfb;k@ z>VWqc{HagiSPA8})uIGz8EG+uwTyn;d{Am2#rclK`u$AC413sV#tdf|MP?G2vanM& z!khn1E5cjgO$fqU=;=$CL{^gqOyXl^88kJv^}3ddZ8xBi=Ugty_} zcL;Cezj+96)4%ZuZ}Y!Z2z{|Dd`ByVlvq41L9*_o&%LDGXd1q1#vtw|9xgaeHnBRo*#tW`E7|x ztO^w@PjpYu*Kwyql_2xkL*w1@&)ApTb{ieCe$e4Li#oTJM+Amq4{g&@8b^cRj^hJC zGu(E&9f}0=&kka7PQ@P@>+Ib%IdhhKw*>f-NbZI_{#4*h@f=CCgVO3D?yn`Kv#T71 z;|17=i5-MU3KEM02T3?_eRb6}a!-6t{DVfyq4ZNFMNv`&aiZ~vq|Gwr8+SZA(I%sF zF~aTN!+~w8yH}#4Gh4-+PvtM4kapYM7P@>;+wz(*sc$aP5rVe+Ju6s121&1WP*Rtb zJP6hJYhX)ioL82H4H%4}g8=T$RT;PQ&uv87HF>#vdl%b41*$U6?%l|aOm?-bm}Lkp ze#K|fF-mGC!3_e4wTfRb$!|k?=R{-oL_(UDrz0Cpv<}l^>QAME ztnd<@xwoyj52~gIzyE?e$K%`bqEMtZgO&x@xAQsdI=I0hwTiky0p2B6wfy1{O?5AA z9_$V4Qofc3mVUn?v3Zhk>MWr0OaN_db@0}!p?u?;&oYPe&zYS>e3xMtit=}aNQLrteJng`vhPe#!gmPhd-`X!7v}eDtfQFLmOUPl{@# zoPcEe#8$woVhU}s)`$I=E~OF?rVLZ0(i2wh0$f1ROZSy zjk5AJD4O(3fb*4j`oa>o)>BknW(R-8c$l~T!!d4{R-7KV;{(h*Gfy|u4N(PUN?JWgGV$9V+9 zUNkws0e8*wyda{Rq~^$$df$s-Q|isfRmoU_Z|P6viB1}^(+*PASzQDu^`^LS71yU; zFnS(4rw6uAj1Nn9V30}*BDV~aXpZbuHCw>fuW0gO3%+0KX(*Gu6~~^ft8VLS3)aaW z_GiSC`YA?n`siblpb`3uH@1yi3lPyfEMDeM*SO9m*^s3#U(w`~ z?xS9qMR7!Rfg15+wV0VPzo>V8m9K4H(E_O-lVDVjvM!U5T>x_OYs zm7VHm=^Oonc+wZt(h&=gj@z0{R;3@aynqxHT=&|}sn~sdVs_#|;*aw>Co4X$>~7O} zMtSCtrr1}mK8&bRNhl7GA*HreSHmz#0TzMW>VgTZ-e9;{zNeva{MMKEOQ$SspY+1@ zF{mp~pOikVa`$WAic!;|Z!75^%O?s@E9q^fTXlvslUm8DgD9A!&Q_f%&7=rdHhHw= zg>KPgq&s}M*wauTc1t{2)v*T_kTzjI{;YUkL+mS6FQ!$g1h8IBZ!_DfbD^0e=FBFK zwY;z>njCP4kAkgD+lzsN#c_uNihmTwc-n_Bddaaa=Q_ph#h#vnm4erVMFmDuBN!4T z1;2o#ttTn5Cl}ozd8*|F9$2UA>4Caib#*k8 zqg>h3set9h%c9AZ*YI2Yt-2k~3R3-SXloXcQjs zTcxeK9-7H^u#p6MF|H}9Uxr}UpbZItEZMDQ*DX#V$^=4_P)5-aodcXetErz)bO`Mv zWs7gYI#rL~YUjw-CAGSsS1Mt}$q1AK+rOA$@)k^uvkwD+sXY*o1YUl!{SMWYfpMp6 ztHXw5C^R9;Y-G9+M>aAINYc(rvhIsD6lr(7dJBTRvQ5U`32(nUO$V9o-X;fwi>7Ho zP9^rVA;ite;4ss?Py}r{c)&~CCQ}q?DhfKS?+=^OhSWX68~_7RXhz|{}wUfzMuaY(SRCqt}JJ`TGb2#5r*5iv-1go9Hh!)wW1}?dmky?8Mk6 z6TSWPWHMJr4ESTnSA41~wh$_{^N~nb?2nlY>_;YwezbZdw|C=T0*g#LN7}mWmjx^<_nT$ z%LB%sa7thx`)pzho%=@)YiF79`>8M6``%Zhdp7{-fW= z-V{mrR}){|Fl8x-9#doK!(MzZzp}JuUbz=j#{C8Ro>`Lhw~&E9Z*+BCt7^n}S0!!2 zfnt&}$WOgCj_~V)4n^yGB}Y7>SK)X|UU|imYj1!2;wc_o&S{G1Qjz$&C9WUy7czKr z$xEEhB>AnQkG_goau7Z`xI@?dw+{#9Ciz-}mK@yKuUkEW9rH_RG#Wowz-+0IDqu2- zJzu2h3s?3r&s(p30e6Gfp{8qZP(NP=0$*dXwl4yivr7*;>Nyz}Q2U;L3kuGcrWOW; zH*cT+l&_Fti;}K7I#bk{f|O}WN0s^dvUQrh(2`wAOeA6BR|ps{5(Ubf0cLYt z?XC9&1FlD5vxdq^JyvC z+)XmH&fX)?wm#IgZINf?%lhjn%&d>~*97-S6Za%tI)wU}afbzan~WTJL&AfW(JRUY zeVio zm@P5hdvGjQt1y#Ic{05|-J5M{mdD5CExn4Z-x>Fy$P=b_kGEK^`Q)>e2W;4>*BeRb zcD}PKEChNYSd?!FJn^E=TD-sHLSiiA*Q_$US2$*|(D$ZtEO2csXV+a_sRF&A*OxXIK(0{7mFjgGaI5AwaM~!|t@2zR}@C-Rp_BVaVSd zbWZ+VylO1?9v-<7|0K8+7Tlx2ltT^B0h(icbrv#$EGx z8gANggma{K!s&8XCkmHJcMNCNJm!JuL#F@~O*#T?>kbw&E7{XL?(1%S^$XXxh$_}p zqM)d@N6azqls5k1f<(xP*F-H&o!Q`V*koBpu-;KVo#eufp4a6sOI(OxUZgF*O~ZYE z5dz~W)KzuNIUSp>2Y}GI6q9+wHa*7ZC{UeB5|TaBO4QoqBwj2*Few+IbC8Ij>r)RIR_5kZT3ww!8tb1k#{;$$> z{Y-qspH&TSG%`n3Mky0Z`K+yfp8N?&c#(uIk57%a$Wqc87pN7SYb1I zCa1P!MR1Xv_cx@jIgc2p-I-S&>ye#Dk1uq3 z6Ydm@%9~XN;R0AT?YT3-*!M03L)>ka_Yu!5EulXtqvhTOnL<|C!(@rp=xkSMhE`sn zAPvt#cn2Pinqy%>{;qtKfkBca&ArVV=sFcPGetG)hcueFb3A@lJinJuTWZ&7hsSBe zFQ3+Sb!UFvF z7*c{h-N}MNajPDo?(lx+iOY6p$J(5!LkgGe?#}7OU33}^;Ktxx{dz3OJPqjk7t99b5eI$`vLXjGJs)8coNWX&#f z+PiyzGi)$ZoHWZ`Ule6S=~aTLCFH7{rRm<&bgHl*Bh9kae~H?l)>VWJ+3M;-NHTRu zyQ4Q2BQ2C_%MjidzzrR$>aoUCRMnaGn|}czs_KW8%D;dI4AxpBEk5_pN3t$W9NW7+ zrS_G2L-1Q-v?NySul}pD3WUCPT@J!Kmp30dV|}V2#^cd}31nR4g@v9c-7xk2z8vd5 zFQPO(rR+dZ7HZBpVLIW&>;YfK!}$YBC+aB!pp!s&IA-(6YrXOj5vJO_5PO{)x-O$| z`S{3#yUi|zj>n|~Q?0ZdcQx1sy7P;Wc??-ul}Ea37F|(Mw`MG1}Q#y z%K2XkfuItw2bV7WPb>UCElIimBn1CMu30~q{L2J*`5(~?T+xGhi6qkj%6Rz}CBbu} zLHaqXH27vepMAl7qWv`QC1HA?=2l(l-G7TV9)}K$7FZb|P5ys0t^a7m$*NIQ{MY3Z z_8Qp5K(5|@#HjxSZ>s-CEb}z{@op>ae}XmtqZN2IC@c$Hix;hWO`XDT6}K?LjgtXE zW>vH;OSegf4sRq(TVs12`Ax$Qo1zu?rDok%OQ#htIKr;Fv!&`d9%{te4N`@E=w;6NOp zU)OT}OMZD+gnm;~VjcS3hPFWs=~_`FB3-G)2qqL!7Wr$H<+RUJ1fkTJS%;40==zhm zD|1}VIHxL9l9{;Mm2AnA(Zg%_Om2?R$=SZ1dNlDzf>$%_si|HK_9pqiwI}y;*!vi5 z$mEblB5jwpUjS+>R9GEiVkg%hYYtqrCP>6GzbdG%8|?VuLW0`7uhAcyzmvrgHglHA zB_HMU$_p}y=D}%BeJAFVi>ONv?>qjM(P!ppUw@B2%Dw;^dm2dTMOoZQAMZ7&-izi8 z3+15GhAjGs_orI+dA};IrukjpT4xkv#6eqV!W3IyfPiMwr&`oA#wdWFLj%6^;2+DaZ{mKNl`E+NsBvmeHM#VFVa_u9IVTNe1E2Y8j@VUxoXG{N>eW-mjYv$BwjEdHccY%UC72 zY+jdu*GyGW^UfJ2Z{efV)f70x#6*>9NHG?pim8!-B8D)GUI8mQxJg(()t+j=y1Y(V z?h^WB&SlNI#cJ!-+hD7@(y>vdnLDH?^{19BS&_xhbZYcH6{-_a-6>I85R+XYRD6#o%8kN5 z%<6taW|SUeSW*_|X)VZ_6;XjmMYvhoaD~~3DAc4h_(|x&Ak4=sMtEtiZBB^o_}@5@ zpNz=|s;I|{xD&mA&zn-@%FQaz6qH%e(Vl5a@@kyiNzr?Kd};P$*}usKh^(tLYa|<< zHYn8uxT)z5o}E~Dze@JHbPr5o5syAHV(zAst^cMwZ@qHGrYvpb|5&Cg-1JHCx2~dpMD&`+SxOn0o*jHexjj-IGv(L5R^T zMllxN%~pzigG4B|FW_hfz3}1)bLH4eb>jImPlq~q^vM&oc^R6>Y6+ctGUvPI({4rW z#!Ji|hV)gh(H=^s(S+yE0t1Xg-nxn9{$>M-oe1HqjUyD#2F8S8+sq z&+|UxAE1oS_J&EjY3nw4ADiX9dBI;$k7>>H1AX*;Tq}}P0V9OlGDGAf|PQQem z3B+;Wnl*hv94OQ4K`d=WQ2bAi-XqeF0yJS~q-q?v^kvP6(p5DsTRut{oNHA+YbDQr&>?_UAHvJfaZR-J|kek=2vAgB!03^0UDPff_EpPnmYs&L^ z8>?^pO}_CTHBdj#S^I~I@_G%KciLWk|L|>^^+3+zvV+h=w6f;tA}B>qUmI#B*J-|?VqVlaq23Zm&YnChzMV6h7W%zu&5Hgk+>7sOpr)aZ+HLqUr!g)t{ z3{7StMp##u@3{G4kiE%K(9Yl`@h(oQ+{FG0NZ}9*A3q~->>Yu+BLk-Kk1vgt3OOCQsC5^cP zVn54&n^us0S{4(VHZpe2x#Z3H7f(n9&zYJPH@v7J*-za`nF5JPF+VM%nB&*Zv}nTp%gcm`a8zuNwmDXDbatTV&Bv{+2sk>ck;;IiGI6B0(DaD0)LB)dt;enbEz*<9A0nskK7Gj+M=R{jJuK?JV|Ib zb)rAt9tHua3X3%kC9?KP>`?B_-!k_JF2voMaRTx7s?FbFPw_xEWoQX-MIYLCnuE)A zqla#J)i`oAb`G8Dc$r50LqVzJkhgg$ILt4;h%7~0FyjceMOzfGWW^YK`pu&Jy#6uI z9Gmgu=+tOBUMlAFLvsi<*PN!YNo4zf!)iU zzS>a$Zj}AJORynY)f;?HL|SVegnepIrM@=Y01e}LjORcD=_V(z0o~cB_9Xx=ciD{7 z27;W~0{*<@U)6^qjeF`JS=T)85h0jzD2jF^;q2h-PyH!>;_%kIXg7%ULBY0`J5L%5 zNqSg_3GM%3burBb3)^k3JS# z<~x;eDhXwpBo>*kycVIp$IrfNaS2VHn3KXSYIULynUHdAm;KHY@TpI)_7k5_q5jBm z=t=D)(emmYbojn|{BHN@v$bOLHe&v9%ue)E{2{vqRCLytrC}KWh#sWZFF$M> zSFR{qJ+UbakUF=%TfpuAvg3lhjnf>Pz>K8oQ)nf@Y+skiJtwDM?sv2Fy`Og!lecX# zeD$Zc*iuvs>BXcLc82((xnes*hHk`{Scl%(z0+DchrXL~RP)2_?l~iT#(Yu3RoyUm zP=Rm@UDASFPhUoU8oU8yV4kP+oMF@tZOOVj0##uP`p+t%Y}b73VK=Awh=xxW2?%Jd zlrF?_{Ym7f{TpqV#E+v4g!kq~qLuq*iL@TXWyu=l#(WxycvhfC*4?s05otkml8JCT zZqtUeb?Qa_DxQ6Va>Kd)hDh(ck%ukhUFyQlaF;p4&e!+Jx&iplG3tK6!5VWEacrW`YW*0N5nUT9I9Fo9qs2XDeF}Ifu4mpB$XDtE%R+n;?xhL{WeRcnm3%Qtnh@9B$<&}SMz+qwpn=Qi?(hMvHBq7BuYm+Q^C01`}Fp6-nw?mgQwPh zPN#j-G!(9_Sq=|I>nJNL+=6%09M~lWoA93MlpPx@R}>|mdq)0TTHuQ6A(Gj7)rD{v6`_J^7xuzo0f`5ulr$)g2L~cfE-`WdDcDSm!+0Qh{f-(LMe>4*;9ymdewX5 z?v}O<6po8DFd~Bxf6x#F*9EnV`Q%U?GSTzpc|e*eYJ z`(5v}HV0Sfz@#8bB>aAC;;^gk(C2PtTAt*ZL{jfo9vvT+&>kOOT3sCFLb!~55fE$p zjVElHQ|9r@(ATa7$x{_}d$-bL-%s8RpflA;MFI%R<#qR*4ECY`@yraWIcx4?>x2LD~eRDg2WHPb*kP>TYJA?{T90rZ7#R( znba4yKl0~5^CSB2=Iv(&I7LyR;W9AJ9{0HrIX}{kyIpqFHg&NW_hois%(&lvs~DkN zK*L>IE%^z7w(sdwe1HExuh-pV zX6L=h?Jfllz-mi-!y;ym*J7oNeE)O>4drvTGOiaWJh$o;(He60SgRW zzAkCjTK4z2i!;Any~uG=C<=w(pSQDDs|lR`q}K@5B%(X{_N&&~VZ7%<1AIL+0eL|4 zBJ#`n9)FU!|Cf%pHY~oqPB!;# zLCWrxm~TVk#V!BpgckngRb>Wh_GAL_U8pJguxeu}Eb`%j3%?$f8~=#Gft~d3t;IfV zYZ=rpmsN26h{5)qjjRGIN?;~y)PqL$v&+agK%Uh zZmK9=_w0^8y46(K(S{cs?~ryeRVhIIo@*RlprYPLnagvz)DB_y;IHa4 zuR){=-gz}eLSmMoZ|SadnxJsHE9KDD3R9@D;LuSK^78Gc;I2a@eq5sNUBf|J=9#O` zDU?l|D26stwiQwthXC;it1WIfPiD|$1BnzR4r(Jx`(`Zt3v8FLO7eKkH_{0lz-0 z?9LE|m~5z1OMU$ZG=_Qx7CidpRG=9hvjf)nvZ+|N&;CwncC+E(sSUjW!0tT&xJ4Gg ztrP)`={OE(On2(DPyoUMKpu&j-vBfV0R9V>{>`{!a*JY%*S|``?x)}1DeA8$1;m&O zB`s=Qge)$635&T4VKrLv%%J{FU*2K8Z(@4~DsMHESipq5-#^YwA-iO-1LBbEV~%^z zQ<$W0Yr`^c-sWA$V<&yHk`(A_nnh+_lxmz3&qAT!Bo-{+B<))oLTWnh#pXIV=?-~i z`_6&bmw=oiyO5wV`!z&G-nzoRNze^d`IW&FJbS+@Gv%9Ss8Cnx?EVgg#%YCrO~-1{ z{+lxU;0KTfL#01=ooxJmbXE%D0#$>dlrnz9a;iQ51Be;AY}%*$Jz@a(wg1Si=dL_6(X z6Sv-cL^pAN)hIB9ZTvE~TVww`i?F;72&7_-*{{yjvc|FvDLLHH_ajmDwQ=)2IA0WV zv)&{S4aw8>&Y*y*XK6mqQuH?p66&g&oiSY-ICo`Q6IlRK=JTu+VpW_CGxon_rc54K zl`k4eNK{K`)K&Y3;e4i_E6q$%Iye;SikxjYl2<4f)syJHn91GO%uMkL7j_I0D%&w< zn8;gyxqrQ&qF%mH;U9KbN;YS%F8xl5sC=W&|Bqtsx)F5$*E{~Mg4t0LTcE%)*!#~@ z)Kr`w_~#gOCB&IEPHX&qm2=mX_J1YucU8}hQrU)xmSqU_1LdPN`E0HOT=0?TDQN5o z`sII6_5VRr{|A+Qg8KJ7@wamS%hspH?i{nPkolDPEhmr}TAup;L7n*Lm1=n^_Wn$T zy3Xz;EeU(o2mwtv@m!H{NZgFI&28e#e_;%s%$i2F(~K1{{j0N*F8;v6CQJ&y;vhoi z>ON}Ubkljj{~$i9QB>~lo1O=_AAYe2g}2P^QikKt?S2oOnRrv_Nl!vi+52ltFg$H` z^uqR5uq?w3I&e;=#=aQ$R8n8@=18)%80744smtatr*jKy{BQrGo?8SL$V3dClm1^? z)&J6ffUu{u+LK>L&)DDpmNUF7=<~q$|7O#1h`BEWh1fW}ZQA$LMrvgb^5&o~6%CeF zb+Gn#sDxUOPAxgiI!?CQe=F-caM^?Uxp04ZP^*~wB=Ar?yYJ_sAq)H}E%lrbP~{Zt zL(2b`2E>cGJ?Wkt5#qu?xY+hEj#*tt6pcI137)vY(Xc&a*l^Iq_Y^JhTC>c4zB@zf z3Vppl(0gbPmQKBn`JvfJi7NRm1Ym1f|!+HQJE< zQ(U-ylC=Y{v|z0z#?gan>NYu_eC*B6;{&VT&o-~HQ=avGs1HuHa#E4qz3>hN)xS*S zKT3j?1LTmo=>^oWQ)tJM5(q%o9v zE!s=<`}px>lDqC;u|AWcL21cZio^UIDqhNVDUDp8b&(`LIv%jY6Dx?5wy?ps&7=A) zXwS>0XizkzE^;IeJ6q6fwu3A?0R$bAWC!VbU1Qe<)fUha==>vWB~XJWCNI#5@d5~W zP7!}4AeD97X$N`ygAUs??5w0LY%i#xTp;{dLRnaztc$BXp>2p;rwrqYGcMgG9f&TR zBORzdo+BG@ixMIokcdSB!vz+OIF--NTybulroj6&nVQH3nvDEN2T<$$$Od-S|B?=r zn*1e$4k#?+u;eq?F98wV-F-kr_tz6USbcdv5YbI}14MKyKMKP3IzS11mKL8V>Dw*8 zP}2WrT1L6PWKv6M6{!J)#l2wTj1yH{;K0~*t+j(pN}38tNw#YVn0d$vNI`n!1t8s= z34MQ8Dk-hLXc*!iE_(sdcbM)*xOG;Zy0{Er26rIwSp{dDv2ZJAoFhsLI4;O8kfY^y z_M=+HMa~SaRW#H*nQ0c7)5t%n;@uLokwE#K4ccEJ3`Xk+A>8q`>gz5h$(v&Jo?z3F zqxMjAKrhhsHZ6EL8!wY!Y=Ztd$Y0^e7;Y-1{I{h4WGqYU0md>msA^zm5cxfap!)TD)5*MM(1cq`h>En(uhAr=@B!ldbBf9*(4^sx!a+7 zhD^jec@KRhp1LX{Zu|u?`q{i%8z{MK4b--)`KynuBv>@dUGnI|tHA&8%G*_U#xA_) z%|>v&K3`$8uB0{~Wb!C{iOffZe-{^#7sQB^T%s({#*bjY4pqd>y@)MqP zq^wMziPVf`Sl9YFG01rJ-hoDE>}RzMX>DD!RQx=q=f3d^9s{Yn8^bbngj7#eX;s`_ zJ$<&jXw@upBhpKG=agj`)OJtLCo@x1sJ@ve_) ztUc6rQS&FP^c3<^p!ot=%$jd|mFaruqP1pdKHPiJ3}?XjLO+|*U3i~FO{s$+ZCP~Y z^GcGPMY2Pf<)``$&-r>8EoWef=rJ=%@hQV)7Tt;zZ6XB(Tp#i9iwm z%fh7Cy)QVT68 zF=KEIOLD*wh|ma#rLces7*W&pm8pFkKl8nApUeCgi&DT#@EqOQJ#Kte@EU?l_lUHN za(JuT;j9*j);+_WvjsgmI&{xVn?F+X)#3vE*JyyuQA zhq0K)$oQunDEN4MHzCIk$M=2bkOH2X2LX?jt2JRV#rW!Gtky#L z!as|9n(~*|HwV8o&l2t&w2w(FqfSgm)T88Ec6PN=_#t2!)8CG$uImy(&sVY=uLcb# z6h67XKccMiN#Op~zV}x|tpyb`pG&9_=Y@X;u=j7HsR)9(?d8(*Im_h7u<9|Wcg%$M z2jQQolP>uOo3CGLut|7L)qZToAhK`#lp(^5De+qJ*B9$}Cff>!ygjkNFUrYU?yc^* zST6UWnLVj_@BBy8r#COvvT=94i~itjh8^bwzf$TDXB?Pq{f)2If-Td_WIF%)UDtrC z$)FEy+5`*!a6aH*{Tyo0XnAHX2t`18aGR)yn-wn8rJmioERLnuDyIHTI3V)5d8m@A z|6)_uj`sDZ05Tx>bG6Hw7L_-8%4XZa^O@*^_qG|+=3Sgr;aiuVrDnsuvDecB-_GQ9 z@({R#W+5u#92{l(>9qs*Bd-zPY+WRoQ=_GtgDgS99Lnfth1CDN>rcT&)KJ51RMYPgFQ5B4JBDFy{`XPeo^mM|(NY4pdT(2?qjy*0FiKe`1O$S`;$b|$Oc6^&)Yd)&Bjv7 z{B8qO?mzcgb}mJWmY5hLDt{m7)66+E0GFKAr4cc8ock@Tt!4hC_ zyBj+baN8L!@7(-cOp?#f2d$lln=1UUF5Y3xzU3N4sV^$koHVDb3E#S!r|&%dWlxLm zDbHHNh<4*A$xHndzu_=wq+Sj6DsQ!}6c^;R?u+h^(E^o84%I&421X(!q!7Fy)fOUT zmOk#a#RF~)o-ba#u)VH?8B6?8z3JnHGvE?7%DWbsG`Uf3v%{@%{EV;;@69dYBPS|fb@9K5JT z>!m-s@QKfjjp_ztf^{Xiv)P-yyX2VL9InMpP7t@s-r;;3?+pgRAMjtfjqXKPc(9c6 z*{$*IFz@bwUbkXHV`q&TFDPZ`Gu;`q%z)qxd5dRKEXRWHl|z?b?v)PGIk>4tI4|oq zqCdN#zcjR&yVwv(L>dSREA>CCoL@6-$iIQ-Lx(%S?*U1%<{^v4^RVZYGS1`idj% zZ2`Zl8i(_|+;zdDmu*(zpDnS~zScFXD~(=cxYPVuv=%Tk(HY9Y->`{jUP%-Z(fR4v zA5HxWyK36QKquN!MP)+`OSOeu=9F+Wed{M~Rse*H?R}hh+`RM~)x2bENsHeswz2!- zDiN`T=cKpu(CD+p!VGDw@EK{dU^$l`rH)G)25$x6_|D!n4nj7fS{MFjbi=^^^os(2 zgSY%(gO6lyH#EJfl8kA(>-3$P=Cbxq3%5RSGCl+r`&U`MJKFVvt!B^N*Pitzx?kMfSXQD!gbf=#TyPr>8bK6JJ_(e;V~Ffw>Pc54yw zseIYr>md2OChRXOWGP)|Pcy;&f@Md|w?(K5*a%IP`NLj5m`YkqQo9j77ykp_@=MwW zl+o;xQp-K!hnW=eMB3}+$r7II;oNvk|Ll?65kAWU6d4E0G)MgACSATDn+$ZYgRlzW zg<9S!l*r;^oi8YVCEb)~xQnta`rTw@*$cJwon`9la5sluwDZqyWoz8mRinI(vhGHU zqY*ehSCB5;HZ=To3>d%2XVn&z$t`6Vzj4|DahEO08cXut&d+>D<-LaQJn5`kdJfgN z`7tswnm;{yEmu9@wY`xZK~($hiN0@zeX2qa7I7xv^e%iH7zy%tc$_hWknYJU53o_r(61r z$^q0W$DPfhP?W{|oqGKa?@Xk~3<>_P#!XEsSDwl9SI)vq)LmsCpOen7OuEFs2vMQ- z7|4@BBt@mV7iN3T-3D-c5TY*G2{rD=J0H0VeVz=Koc_6Tzm3Hy+ppf@q&rSR2M&$KH*oI2mDcBYgRTwjOK*CQ?v`Y- zjc|kRwopeIMKS9~c48@|e`m`WJ`^lZSKNvY-xzeub@z0t86NOiNy@I?F;V~Xptf7s z55)5US(^20U|T7h+sP+2a?fUr|S6NA$h=lrU>EWomJ6>`TbkR}d{~EFMz= z{m1R%TuFO99M$2-*cNNZ`jR0aRna@K>Qzklr|*j1bZ)9K%iSO3Oj;#E+9zJ}1oN9u z+Wu-cR#>&FIkvHiauynCnVg_p2yi6DseFI%IzE!|rNa5|G-6&BO4hCCQ5UQh8ugJe z>d!fPqw3&OqUA7`wf zv)Fz(4=g2^q^uD;5o8KP&yq@@|t;EBo1B#s*^B1y5kJm(R|s zii=UiTYBEvif4+yRb#%41`}_6@K00pj?Z}&Q@v+MyoFnf#bj2z^Bh~k)NDp6L5^Vy zw@fWY%dHwWUcW=Ztgmc^m5BWH^3D**8oFt?puC<#G+QCz=<+cFhj>dkoP{Xil0;Oa zGyU!Je+EB$S-V(>oCbK+(Q;0!6uqyziOV3izj^4YF&x#MWQSd+kHse%unEF=Li+!H z*%e4TtBqpVn%xOS=PNdPEauVu1f3-`yrsY+x);UMrTXWeC6G(Vb-d9yJG(3SFB=-T zi~Qlqi#M|uhHWJ`_Kcu!Z*S#`JYvD9O?ZrX%Snx;E>4xDC@z<9s*bVDLQa9!MjkIM zgbAxv?;!St;(?MdaFTugk@!0PN1|K&5A}PVNiFI!D?PJv-H&C$iXU5F$BTL8c+)s` zH%E~=Q(?90A2^b+j7hSr%4Z`SenW$FUIuZgV_RAE`(wY!iF;-xuR!Xngw8psMtoAb znFT<(h)*hhoGuXdRlCOjIMsc>UBk8o!nU%MZ>(Y3l8<`9Dy3*zRmNz#4&JhDtf^%* zT_8H^H)yP>X8L2Qtw8G(1N`pixXJ)s>XL=|9R6%#*J4K4vW~*wvZ}%$blId|>_9x< zC4RuYib>C_oC&|FJ&Iy;`P($%jr$j-Kfy(DBhFx~3f*iow|MSvGlZt!t>x7oK)_8f z$4k47Cf2I>u>$;ghFQWdt;X;5P8mP6M5=a`#;HEoQiWlZJ;ukWc4Yu(Q&i?{DfROU zUf>*NNvinK!KLaW1LYNB(Dn(OBlMABik>PFEBZmGa-JC{R&s)^cc2a2&`=k#!)z_v zfiKI`oShy1lYZDmY4*EcaUdjh6)_!HGGMn+ji|2w1PTW+4X4V-f+5_E?5LAp9#Mr z#)<|f{yZTkzMp)>a`8YGS(#YB=|sH|Go5O^O(t$jmR^{a!e`3kDBgN`6);%MC#lKI zp>{~3elW`CC$nP0&I`o^5{qes$eyC35~r505x92#FMdtSCOW1}{iYJ;q#6HmWGYYY zc5emwpqTe4H0ld}n4^3RsAx^sFyN5LEp}$_4zhKgl9}OTZ~@e z51P~uMVjC&9I$=hW?t7Is`E2ys+kYL{B2U-7a2_cc`v(7SGhCmxz>EGa|Y@wa`!-+ zT6A+-U@5T?rijV=-@VE>E#mddQOEf1-)!EZu5d5y_u}IOir0@tt>GUv*rZDN-0cmP zNmh3)Kwaxl?|7DWd*yL1CB2uTQ1Km1yr&~IaPY;?642k$K_;S@@jGqh<51bT#SVbQ zn2a>=0+n`Gl!PaJv#g=X5JWnQa!oxxr@(yq`<;9 z4pdstV(tz3pFd?MWj*PoS`wy~Io^Dhv~OyexO-*-&de<_fv~BA&~V~^yS?N%Z>C|l zrJ|W8XBmFM@t4C>!E@W&d^6veEJLIsZ)&~5Y7`#l`?=Loa6h))>DR;g!k+hguV z1nc7J$Jw{uG>+FXapS1AG=iry-I){WjOdG-mtj84p1o(hxKL}wu~mAh>qQk$D&7uxGg zzPjJLOP(3DnSdT7ein;PMteOQm4I*2TAYr$VWP7fdCFb6-TP1N?b=UW*L%p9qg{?Q zE4E#6wV;l_kEONG4C$_yqe5w~=c8Ql?>*%MFdv(X<2+|y&|R-Ync?5N^>yLLWHITi zfQrxq{ACUf!hX!%#82PE`)^jF>q3D=Q1aoJR*ed_sF+bXrg(JEtejr>GD7m^O?I2# zO}^GIm~)a?{tYbsh%<|c2p|)&>^1H`LB*AsTR{BF3R<5rG_a)U$+HMK?TU_wI8PCl zmqU{;i)M_1=q7yP;GmZH#45K3%+rLbz}5*hQI>S%dew;DKM%WVcW!hpVux;YK>mdp zH)eJS_K5ra9uK};cb>{)L+6j${$tO<>N2%tksr!Ng`f2%yP^GHA+kR7b+NrK?T2x# z6ot8Ek@dao6W1NhllchGQ32)R6Or{TdM$#X-)0EEQSZw1!kD#esUq6alXXDSzFmSC z*RxjsQlff;8>oKOq<-pu2bJty!rgno>X5!x6Qr$jC{7OQcm-n|QXVt*=p2^5W&$#v zPyeFCqjh3H$Sf|!t(0B0XLT0RmPRtWcW&@V3yKf%Zm6c{j^>jOk&WoEdYR%4Ui44v zc6;Q|@01Od! z0f}H_+vy_6aASw^ExML9dPV{G3c*utj^@;?-N_u3I6sD7Nolc zhk8Tr>{HLrg% zfrN0yKCT`&q= z?hpL(p|uXXQ^lZTKP&syskPZgoy4pES>gq+Kjs;k2zqoKw$>?5+1$?R>p8bhyPD8| zYcIE0swi#f_WJJOC3zoRhp5F`y|Ft^c}m7hQLMFQ`(3Wym9;prfMB9 zotsR;i|GGKg*z54g4>{_~R%g{i*%8chhoH+Hwpy}Wi_?$J=cJ1GGV@C@tV_bhTNlDsfwEh>?x3r61u zGn$QM)}Ux1I(vsjag25(Qry-2#;f~%vo`p3kz@4%<7UKiXK6$!hCi|QQp99qGy&dT ze}9nURtMH~zx%9ZuMcX7Y8g8&M5|X6NQVv{XPV2RfH!^rCoBoZ>cf(eVlgu2? zHO<(4BQF8wt9LyV={3ItP0BXy7^YOI(J1ah67ixF`QQsULUB@MMSn7LIvdxb6G2`L z{@x8ettM=3*Nv@9l-B457r0txWPko`R}lJGW#tlnpC+e@A~GP{aG)7VNWeCb;IL+40A`q;if-2ieL?3Vme_3%xXx^E8_T!k7W^1PR)FTG> z4?7K0lcX2(Dm-8m*!c0Wo~ZEfMt!K5V#44rSqH9Q!ePrz3J%q8%{cxEb6i{KyCBMK zx6OZ5EXUmrnSDopx_3`(uU?x3ruQD#r}x3UO`&r&S2!b?vS_o*z_MZN>Bw6k>GEg?-Ib{F9 z<@e0Q{ySSmgt(_G4`b82vUYS0s6fCkBL0bpPLvY75q6t6&<*;yU~xpmG6rd;eSlx} zOO(~4>iP(8zcVE?Zs7n@viEEz+wysu6I^rpHclj2vKNjbFvTEIJU(8=e1RKaBLG>IdM=m9tWRI0f+!+$wdww3Npv7OAO0od3AlGI#9vL)pbNNNg@ z8dyMbo2y{9q@=jh6)Z_eGzIwE9`3;xW;8!*NElx>LxtLw6c#!vCZ~cAH?VmxHL9k^ zf7B>r{79tKE8Y$MczpbA(BM8Qf&q7L=b{4?UK=u%0t1F!(9D;+<2Z(Q%dta@dC+$z zdoKzH-_u{P$2H$O+Nt(ie~K&a1`X3Z+kiw2U! z%jK|X1!Z)a*vn-`JYZ;$drwDjT1|`EQ~}+M2Fcl1&|H^pZ-fhofs&AUlNr?sG7tq4 zLJxE5+=FyA7_lBl^I&lMoo7j6O z0!I3qpSeD!AH1&LmPsiyMu_>lFo`!KVa@?B5`i*HRsT{B1Jww7#G#i9WQuFT!VGDpkgx2cZM!*D0j8HzYY zfm1{4736|Z1F{G;oQ!2w3={L{8E4i~p z*bsQc6k4w2AK2WvIAeLo=NojGq_HuP^Wj^BCq@`^@mmlQC4~At<7O}_ zF?y%XB}DHS*<5qvrUnHU7lAggp5;#T80QzgGNby?5<($lAiMnRW_C)XpA=y_`l3`* zbN5IvS4`TA*}=4DY2S%o!4HMPAe8s#p}jyy(5TZVZP7X(Aq5*g0>7cjI9|CCp z#Jf-%8NFKL!pxl1bME)If6`<<_IJ16Z1xP^e~g%-U|Z}G+VRS9*6pm>Mv&IkK~P~d zTuSx;#j-}ug!ExmRH1P|s0rmux0Z6}hY>WAfR50mv&Kt7iq_!vkh zK+CSFV5eLsI9HH;?^I*G&Tretq)?~=QWciN(QSaVPk?@gM4g>QOfmfaiSv7tZ+LK1 zO`B5Tqmu-#&o}muOkc0Ash)o%*wFe;Q!L zwHgTQ%JdWd%~GMV zYYTbH6jvSe#H0d@J+6R7*A(HvJSMIJ!<1wE)&X-IGLK7-xXN0hn$F zfDu!`HMSNQ^bUYV0pC$aMgJ_W-OJ!w@=O1QB`o~4lofCCa5cxe3R1p*05y7UNwOfC zAgBvYh!l=u+TJIOi?2|idR~Zc9}kiE2qd`S5@}mI1HzM5HE!(v@#q$?5y~%=vpQYe zEo(1<7--i7;Un27;p2-BwtMPIK%zZWf6tHrGzOaN{OsR{UO?-3d7)w&B0hixhdQE+{yIa8Bgd9Wwds4GXL|z zC8Jn=i2+`8h5Xmdzl@s(e|S=^Bz|*)_Pe|=hj)6w#~a3M&OW#qC&$Z9@y6=6+=#ri zv9@83xrlA-5&o^dVLyt!${yX`~V+$I)j{1=i;|L$Z!zY{4`II!DcgI)E$AXs! zna6Bxd-|VkNLe!BXX8<)6Az;5V?kB#g|kQR+jb+7nj-P$Es0QtkN$Nzg5u-HP*0kp z=)Sh^Gs@4D@;RjBKTQM*6!YkX%In`5xpfq^+WuN8f4&vifxo)dIiTDoWLuGJ6WrmB zHn8sTi9o=oepoqIWXX+LgZgM^5?6X}$Qx_u`3ukM+0dO=KhNp4>mV2~AucO*zB_T*J?8~+r=|)}$jJl(-TMHTGn7ll8VO6N(+{iO z?jDD)3WcUg3O123*atGMr#QvOOU5zTotVVsR?-a~0=VJE z*-wnnAU}UBz*GnhDjo|1;DSlQ(U-ysxS;~LK7RzFnS8(J;rg@(kSkbtB|F9si#iJp z{>}HJ+%}zuw&MzX5&#_D=&Tl(1p2nzOd!(G+_B z8uk|a*a9>;*_!Ln1P0^#^zEFCYgC~mv&S$_zJaz3Y@wtTwKvxIQ{1k<&mcT7b1vw* z7IKj^)!;s9TbA>UrH{2%>hAbH(jr0BP)ZN^Ek}z@pb`=! z-2JI~9Iw7r0si`xURcC-+EeFJxn0C@0-#>rNLeW&6B3MdJ7c%I@9DkX%f7=Ds=8lj zld(q^e00Q3L-IMtCqdB_9PYtX&v&e0gjD}r<3_F*`4yoc8xo;x4)6qRYSsI<{Us-eN7nV>^4GPBorCkH*fEfU6Gwb z#-dz%66$n-7Su|5MW**)q>AjPpVC>{p(3lRh0wtmj5`aqQGpu`JO>DoSyx|6z^*t> zz$HhY;)kJg;6h!bM#7@e{}om-L;*&_xvqx{Ob9aU%-QDSTGvKKY(J2t8c8W5^Ae`? z!n(J866%caHFO;blnkNde<3M$^iyAe3#4H~Vy1ivAlBQ=z4fW0(T{ej{k2gwZkNBU zLe^7t9S)<&)N?Zaxf88c&Ho7~bY?OyBdBt_isK7+1EULLBqWQP-pgVDuo71<^lcw} zVAguTCNYNE(9|mf;8GsQ7%H!cV5wY>?|}O8PyeY7>a1QhVh{6GpM8cH!#X(E&5;zO zP)nq4!tgT!0%3ZWWQ5ZpPtsGy3aV|bNoUIK>?UU_fZ*f$jG3y$wdH&wQCOXr z&SUZvKkO$A@(py1r=j~UFxch1Mz!4+O^=J*?DNC*AyCwgQ`t;KmF@sG#nHJLV@z$O z|Anj|E&2>;2JUTa9pwdE^gQgMkX;OnO=jQF&@@>D$p{Jsph8E&DSNE8n%z*N@&#qD$X$J6`ird zA0JrHAINf@l$8~P|9yBCY13Kx&RF8`6yD>&$U=tkxS#QPI$7R)!lo=P=hVN7EK0MG zCu(PPtqm6Vaeku>_Q9&JlNe_@;NQ@B8yu11)Gu@8f)D+Z@Nkl#(5&7R8=Ctz81d%Y zpAqO!;&AVCS&w$srR|^}Y4_zRgF!D5M(hSB<=3K5x5o<>ZXMb=w@42>O+4G$0&R$T z+GkjCld<)NH)Jvc#GviJE12FJ&`Dz1?6Y_w#@Z)wAFYiqTaE8Yjq#)r#P+u4hGxBr zxU>5*j3Pb6{*;Al1Wsm$z;5zYGHEZVu@Er&Dh4)=$^wtVv+NLR=5T2a@k&ES4{Qzm-{s$b zF-qw`cSn6+?xvt+tv2}u{c z!08W1#ow0X-I}5o0L2)-St?z#jHC-H0AH4;@pbVSguie?e5m);G;JR?X?Loz@H0B` zG5U%QUQEw&gTbZy;NP4Og${_H^}Zga(Dn+G_P`p8P@|LAMkiE8C#L4@Hrsc}qP#&4 zGZGCh1*Xls+-An)wKRzf1xkl~CDOws7Y;Ka4K7nnE?uV06ei6w+-BC~$4cb242hS- ziR3mjw@og5O)hoyE~qBWkw>1$?Y1NcT)s$%!pGg&;Y1Iz*yfODYR`!7#eS7y-8ekK?qD_hun>J@~|Kub;7EZk6 zNxY;>yp+CMBsj8`ZS-|EX)gi})ApvCRdJ&eDex5zI4Cl!V+3w#hj`)vbq&#v6Zjzobmth7dzyjM&?R}V zhUj%C%&r0akQ};m>%i&IqvES&`EcZ~Vq4(Uk`i};NQqa<7Sal9b|Q+k7(F^g<31;{ zZ)h-Rcjqx#-8m6DB(*B~q2w8an{K}q9+S1u>TssBEUa}ZA2lI4S7x9K*af%Vg~ zIAQS2mMkoSOrp*2a|$RHL0n@YS@vD9S1gc@Vkg+n6qx-&UP&{s)A+nK6H zmw6Lt^8vRR9(gTWqEX`77m*HNtIDsu9s1H`e&OV`pu|g##D({3U(%}T1Pok+|Eedrc>xDx?KC`Rv)J7ccjKr z<|1G0xd6-Uj!JHqNpmg3vay>IwT@g1#AO1ZTh~ij54ALR=0TUO^haJ(K4C|r$Oekx z;azc=%iq`6D8s`tNBQB)qSg)@N5kDW#CJ{+;Z3r@E0M)zx`B!xLFdmXxyKkd-ABt} z?TC18(#}+~s$=9y2^RgB6`GtCT98H42TyiDtlJ>g9T3V5zFxr5SE-H3k8d2 zXVDD9lbsQ4^}Zyg?XPMqNWr3cS^52NO-Dp|gYTSayNeNTTvmP`e8K_Y)Zp7tv+8c- zi4PXd$;uywPdFpU>wR%d+m&io?TkFJz^$2CiS~%>2H!E$cCwmPH6u?laO;OG^8t9R zBVwV!_t3N*uVz)*$dd%znwJG#>4$qbB3c@JS4`XKYF4$3JSo7f`B^Ii@MA~BWrOb> z4}v~7;RmGA2ClADMWGq~WdsyB9eq^%c1fO~DVp9EQyPwci!Zs?aa4TT5KV878D2zp z4)lfu%kr{zm=C#h=OlsC+JIn>`S6kM94By^Z&^OIDf$fzKO~9{dhQlD?IqR>^f6d9 z7SF*!=~$~O5ro3{JatOgsMP#B${fP>Pq zItJknaQMRz{9zLQ&q zq~15kv>gf@p*5@FMw2;m@L1OOzFH`p6oqo|8xqxaVXV&wwxCP|HSUf`Qy*4hZZ9-&oW3 z=QS3(Ku22s{6$b%uc(28JeP)2LPIpUGbT?TzF9h5GpVG@>%eKjqhf-F=xj$!o?(2m zLb`L?z-jEGVzOm!`1a*_Irb&Bw z&8mHkg^Fl+MFZuIpqX>X}n)vvLTH2NwHz7hss;exNY z!Hbbuha>O+JA_1&ucb-**BT2^qpyI zjfJey39AurFZ{w8VdaFdvPEFj`=Xk*%h#;h7@Zgz@kV9Q^uzHS5pfN^1E%eZChd!+ z?SMH_H9EmFI?*)pBn4lQgRexu6r=EDC&Z8mT$-Qki(#`4Q0Mv+%DN34xFvyL>uKas zG0BoVdtQD2e%4h#mKODJT@ahGD z(DB4Lit9md(MVrx)<-SiO?&7piy@2^$PBFXYTb~?sW?8^&IYXAM#T$Ij}zJ>V+HGlo@Ni(Yu=YR|^NE zZUG;@-DWrUSF`o(ym>4PMPi;bGqiI$Utho3roYbP+2%GM6mNrT|;tkYFj$Ji33_`45JHNp7pNJ>tX` zyQ<#N%zc`HJy0>?)ooSpeC9qnkY-|RuO(o~mgRwNV%-_@f;Bxl4mc&={gjVpluElD zC{l%&y<$PkvZed(6TfOdfA`rUPEn87{yAq3XIkdiM^(7vE0#}8ihVgww`9nLN)^ z@bP?&CGs}i9lz|_M6F32co|)2{KO~jdbL0-#%MWacoKD za%V6!&2a_Rye`YQ)`$Nf-IVaXkq@5Wri}Yw)YuAU8n@ zhWt)|}Qj+A{Xq7R$bk%rVU|7Q@Beu%IlvwJimzp-8*cx>*Oe&c<0)LIJ zj_SAJRQRT9?gVP=MkoFrNVWCL?fcE2F=0!dufUxX^wNq2m0;OVE(sWwtMXHntu4u{z(0_sUobG=~%&YSS8Gx;qMmoc`ywda28>g;J-*@mAwbTj*LghzUS=K&~Nq1JQmR_Hlx>$z0xIfdswy63)<=RT|F ze%~`ZW7*PImRMhqRLo=}g)tBfTm> zLcT+Vo+b%FFdR-RJ)~Yjj_y4Z3=E8&4a75kfE3omnLz_jq^`qH8AbU!K-T?tlh8UH z<#<48|CHi%I^Z3g{0b%?u!UlNmfTU=KMO!h5-R>0@ebn$38AB0I7ol>i#%xNyr^6&c5DC8Xg$$sLp+W}(K29O2nX}wh{X%!P@5GuKqC` zy(X|CZHe&~>w2L;*)9MT<@WoWD$4WK*DRpcCz70uhet@5%_hu(YoMUiOwDCSdiC%N zsU{oTnXrvV=2de|lF(`h44wsKL&L_V=z&R557;UAMDh^1vukkUM=$Hww?n}Txi5ik z_kbVYZbLcWm?G~I?s!A)9}?;R=^z!KhP7oZML1QzIyxO#Wok)=2#XecD7WV%ws4Us zZ)6q1%-Hds2+tFtdm_?L1oeq9KM|5ABBT(8%7`<-LoiNSWyF#GM=-XTRnNNoeb%?( zU7kjPL1=jRGSxN^nnn3Up1AfW4)Dg{s0BZ9!B5=H6L<5(p+9lxPh9L17yHC1QPN}e zm!KIdVb}`9UCVg;#I?PyMjL1ln`--o-pI}u4EkEIZAk{zLRuyC+;$8HJ)9uxWq-*1 zd5fJ1g|a0ZA^yCT%Z+%8=M6ae7%k+E??2t%Lqjgg(z2vA_M1`YUoaK`-oMWj)BO>+ zC?Qnub$f*{9Ehj;BF0f9sNO5dQJ^+ryEw>+fNJqZcsDtLF*{^D;v>pWn)m8*;i$ei zE_QPCfHQFf3^)^S(0&Lr_C$QgASIk$jfjE*-a#EzIT}=K_Q=B#acx^Pj_m-uLY=%4 zqrAE6{|B!?P`@HwF?%z70;aeUw*=cpN!vDpr^u>wX<6CLtSqBembI~Cs19rx&~`sleMqK+Sj(VcLH@(eRXZw zoj^Ucf3m)9#bn@aL>0?D_hw;A51RQ%GP$L2LqK_*@pYOt<~QT%r>gU zroe1ta4O6;p0eF4ID{!HY0n<@G<(!Ds`RtAM>&BGYGo((oz7}y7xta5YGpU}o$hL7 z4?9c-M_RSArx$ojn4wp#e4e9YZ+62MROvn(e;xa(mHl{(e2K@%0Efu_c8GKWFRS`q z;pjMky>%c*$3Yw&2Xl0Mm9>muEr+Nk4CUxJjHBalj*hRf!mq3PM)06Gk_W{%cu;&( zKr^G>C{^EEUJsjyD&veM0xMzhvqY^}osV+GVUV4N*@cwoE$H&vP-z)h7VvKdTb ze=~^Ucs*IQdI}GcQ`roru^CKfGl*t0h+#9B!DcYiHiPiMECFto6w9_Sn{8nZ+rnJi z7QzGb1h`q!d^U&$Y!D0C?-!}gTE>blXGK@oiaLRnYV%br=4uvm4U4&!#azc?u2(zQ zz+!G>F*mW8n_0{)Eap}ga~q4foyFY2e`4-rF?X?;yIIUVEaqNI%m?NQ)&EU_xk6$p z%oX;r&+ccRJ-|MDP<+A(T*lu?pA=TyciH0=FMGU-;<1XyDZWMVZHgaN{2j%QEB=+@ zH!gd=8+IkkTxuQZRH+zTcD&`PSPu7=t6|yiEmy~K8gIDoDFIsyC@o-{0c8a2e=y)70lN$+D`1ZS? zV~3oLoE_v9l6cZ{)fELCGoX@y@3V)%BT1mE^V-OufmBuoQbh{84{}!(;6BJ*jdxgG zfcqeK4FT?h+%*Nn8Bj}r`yh910q%p`bp*H%a@Q5$KFD29fcqeKeF5%+f7}fOxDRqa zDqybx4F$LlayJs-KFHlzfcqeK6Yk!o0^A3=9~0m{$lXkU`yh970mlt^T!8x^cMAdT zgWN3zxDRr-65u|_{e-9LOT&Z9t-W>`*`G`Tr=1~vg3E2BKwc+Qpsf@LA3PXUJf#ff z1)S?CL+S6W8}LGK`DL&6e*vid6}21@+;)K4HpbhwPygV$8Abl1v1rQ64Vsor zZMlIH*nGtsSbtHb;k%j?=F%d}jXrR8^c0M-HXgGh_&BHW7i%F zPpNAgKolZ+r2e@8YZ8WQ#F?L8GNBM6H*`aNmKr40B z?Z~ANIoea?z~z*uWg92Z>uQ*sF1)C?@0!O?-thQ$H$47_;+GZwS8?A>kH2=)<8LT_ zTJbZA|E~CDf5opT?)%5%ng8*4cEwvN-cIqZiuY1{lHxInZ&rM(;@cJX-SYUew^jYO zJw8zJ!HSPkJW}zfB>up}qvn?>F!9)!3KNeQCI4Y%7Dp8SK=CgW|4#8UieFOvvf{TC z_ucXMtUDf$Rs2)o;epF{lA^kMe-uV5u0Qbi4>jK;xzi$X| zZ~VR~z`gPN9|7)--?s#~H-6t%M-%i8Ihr%89gnZ^c)dLyZ@kCjMfZBV_+F1M|H9*2 zzwr1^zj^%fZytZ{Pe*#u_m88Kt-ZJvB#apDLvd`j4})~Lu+W_xapQ28ncpsW2$@=% zBo>h;e|KoFY3)LXajQx?i=B@|7M0#+qmc$=u-TaTL6%W=kk9NOlU-;m?mEqEv9mLm z1X&h3gn8IQR;jIksV$pb+j!((*@+=b%|Q%z_2i^I#4bVtO-(_Pmzy@mopgDmCEZGf zT9TJ)n~mH*pS|S-48Hk^g_3By*AF1?ElA~Xe_LH4+3Tz3_zT;6T{m$lvS=xF+a#7n z?W!h?MG9>n=qzkloXSD`5;lvPfD~GG@R~XJQd9`tTiV`1EK-&--iD_A4+$t_Kv@Ar z3@9gHgaPI4eN7#Y%$XP(SwS|eZB95U+J&Y?A$gWU#Z2vwP$8TfRVId{vwv;3OC_Qtu7VBeVO%$;WoPZHj6<&HLzL8 z`5vWmh%*gsHUmk1BVxFnv@zAU{DBEdtvbb0UV@UVRBB65g6C1T^s{hQ*3@RPF*tX! z*=(F^HX{bJZf>(V<8VGC9y`i-Y)dKxf7@?G3?BQ0&E{ehYi+YdbAs$i*+D6@gEmwM zLAu@`LKYKJ=xH*`uz4VWl ztp)6DHX=IqCx-iWU!en7gMtI>f?F^?4MMF!wmg-p4ZRH_ATX=`({cMoK+w)SW?Xn~K;nD+z`s?JiD&t;E{Bl@9 zuAYd@Y`$INA=J2l7$jdvd%@tc$S!vn^)0s95g6qXVhI0BiQz0E&SJle!4WUB_ZxZ| zU^y|Ib*%9E)QmYRsZST;f5c{$y@$}`{%V_zM>tty_5Cm7aW=75_Aov7e=%oNdszxh z$=*zbDcL&FePpSSWvwTJfk|$VLY0j9ZL|wbz<|Gr7-I8gVhD#@Y&H?+6I*2mmCX*e z3HZi@n(g*hlaMCvAciq~r_G{pm1mdDCL{jrw%HW;&mNmi!#?(sf1_=Lv+T1APDP~N zPZc8A9-s;lf6@4iDj!LaeJ9aq+3_Dc02m6i~&ZxepK97be z{$L;eCiLZx_Qp#Q63*Cc39RlXn=L~({VXl6WmwlN-O- zY$d$*g6!d<*~3MFTlos*abHr_WWu0-Bu*l zf7#_WLZHi3;c}d4T(Jvo!l7NYE8K=|xklv>djGcBW^~nc>6XXMxxfu7gvq;`)ROf` zX#Sz(c_+>pe{WIA4KRY+c9o&_-Jycp5eV+HTkS%$^AkfnNn^9!u`OfwG^LIBKb+w^X@YCgMM=pL2) z#E?G~Acl0Jpv^+#WFh+~;$rcJgTi*f@$lFpcEOcV2-`*Nf)f_4a{|S{+&PWn_WDVP z|0U$mf7h8qFKHKwLY`QP_BIc>L}|O=WaI;7h#_xyh&En?$Ir_WjKhdf&fa<&qHuYe zO-HzX*j8dca;yqe4josK$|3wcVwanN)5yxiki}Gye%WODrK(+MCRC_qvssY8y1mnb zFr6B9xmcuKHK_--ViKYj6-4N-O$E0j^Qa@uf2(Q2e_gxO@(CCw>)F-KgO>HFy2BW> z8!$vyJ!->MqcH>B&_28)7yuht>|7+Qqp>t_m+8MIRNGjL2~8Pdz<-S3IAn{>7-IA0 z_VF!3Ab6Y@`k|#XW{+u1D*?Y5@PxfpXePO}eORLrJ)X4L7zBYf)U+6!K(w_hT!wJ; zf0XPsoe`~_fc>T!?d|Hv!mFRA>gQp)?-|+hakJ&KRB8ccbUF}R2&3&No8C9A=wvr_ z4d#qG+YK3qfxe4u*xKx~tG(emn1457xWe6?nz0H-(}UppHNj}rQ$?#@b`wHh)_I;b z+KjgLws*M&I=w&)nSLLtFf;>B6>diqe|yp1cn2J=pS|&9O!dA*=rQ)j zV=!Wkwb?k#HH@>jjlqaAp30$PCRptJdSpivsntsmswOc+$tY^}bj*EBW{8AligfIY zr9vG$)o#orjPBEHb{GTdbo)SNe<0*W+vO%BeUBlA1D-()BjZf_fG1-hpGD;`9T-at zxe<2^)`z|mv&cPC;_pTpI2Tqf8I9+bC5PfR6As|#W073Z+n=M3w^`*V%^*G++a=c#}e__57 zaKeBS0+yH_`I_3W9ol_k*S#Iu#oKHLbV#t-PMlmO+HBXJ2c>Css(e>G<)vxc{=YQs zNuQghE%N>ErfL1245nRekanFU+c=2Ru2VLQi^D*D+7^8e2HS6Kwi{#KcT^6k&i7Pd z$k%?b3m(9H%#UKb@y3|X*juihe~W1P6GIG-KU>vZ8iVT2+H5T1^EsQ1Ln3jWDqIBD z{e=p`@-NtI5+*G!+H4A9%OzsCbn&arqR?5t*(@4S?suETV0`?88n^{P=uf-g94PXa z9Y$7Tg9 z?6$pS==nFtF1P~2X1K-9ZA5e+PNyS=ks`glk1ZI&Gf)FJ z!s{|7!HA#TX94WmwqaHvf3wYYAcM?e?_me_kd+u*E}OmWE*wR6yCv(#V&fdNG2A96 z6&wfS$VG4xw$4p3l>6tAgNrw#TwZ%0yF!!YQs}fPl;3Xg0rY19n;k?u3KGMdQXyj4 zL1Ed!8MA{T)Yf^CcwFVSqaJ$+m&Z?9=L+|piOc2jt))Ef3(M+@f0*n(x`My|n`hAK zRBc`&I0WG(3;(m@?al~a8K1B1x^Ab_4jnN#Ft8t9tnG_PgC9J(eL7Rmp2Pb_3<(Sx z*t6&9@W8;Kr^AN~jfl8{0-vE1#yi2EoA~J;R3st+KRtt$L|np8hhR++2k}!nEgoya z&sF?%O&9!m2R{|le+PdS;K#{;TJUoUKOHg#e?G-elT5*%5ApLz=HSm<{G<&^9q|@^ zuHz> z2e(1z#a(0g$&(Lj@pBhHQFtZNHT?7}5d8T7Ka~mwe`4`-e+NIk3k82Z#!r>PXfA&4 z;iqpA^csGu7sWy2C#)FSj30dCG4yq%&<7Mk??w*2vM}^6qR>kRLJt6jZn6*E))l&h z7@DUFWkDe+Pp26=Z15|6PiGi5bV!X_eV!ls{QqmA=^G3f)MwZ$eH%jVYnOvU=1$`e zuNe5B|F69hf94PK-*+7UJty4%ujBXMb<+6nIBA0cKAr!TlivT2lfi$}$>_h~Wb$8k zGW-8_viPq#S^Za?Z2l`wcK>B3hyO1pr~gkUm;VnZxBqu1kN-C(um4vkpZ}7R-+$35 z;J@G$^#9@%@}GAK`_DN={AZn_{-2#<{-2!U{xePqfB%n8N&gQ{DgXCQY5#Xl8UMG= zL;llFS^p`god2X#-k<0^>`!ni_~V_5{%@R0{;!=!{3o2s{;!-W{^L$n|CdfR{})bm z|L0B(|7T83|EEqZ|0hmu|Hn=p|3^+;|A$UJ{|8Qe|NBk@|1sxL|9ehD|GQ2j|2s}& z|52xjNdJh_)PLA{%zwyf=0E5(_aAT`_wRRF`1d(2{d=8O{yokU{@qS%|1RfA|4yfk ze}~i7zukGtzs+gq-|DpYZ*lJb9}eGX%!d(OUbhilUvQv*8&kqkP5?^6OwV);*$`|hU&`<$Ia+tWwtU$yh7 z2jz`S{dYe5?o1~0lZ~6}to9S@fwj>U&LCtrJNJ1qH)QL6XoZgN)!F6kFdVG>;0N~u z-)s6}>uu%)%woZ?6Y!Avy-KQcF!DlckJYYUefPJq{$J_@f0RiW2b~`QC~~?TGrPJ+Rp^n!ptLMoOx{Q&w5L`&#lnhFN_O4&>UySxp9769GAxB zam6-2EsbaX-2B9d`;2F=W$w-GpBfvFvg1>a4I}gZ2eyIaCi~gn6f>C(y}~(bw_#cB zw#q)_>Q`Ate@Nh620gOzcDpw~qnahnsoiew3ap=6z1?02h6D1DWL!PRf(p5+FJ zeUf>VSP`lS7>OjLxOxarMRxMvDokmeMmvrcWbgfkCV=G>Zx9 zZgP2Qxl3I&*-i8iyAH7dyGF*@-ArD&X%Ae;teu7bO{3x7O9TH@u$XIpIiiF)2<7 zMmaYn6-!#2$G0&01I}nGVT%hbCdr;9gf(K^<$XCElvSBvHrD6;4%t&I&UA2tYImJ* zTP;{MD0BG(?l##KPgh7S15?2< ze|i9-Qj(JyYXNhcgfj8ypcHKTL)VsOKz3Dw!|Jz^77g+@lOjBsq!*N{R;?48J@%TK5)H-XQQS& zO3|0(;d8j_AU`1-vb&9`1|Z3`nBZd7e^ew)jcubh^tv>LQlX}=fv7cw0h!+FQMS>O z$s$(eAu!sU5}Mrj8L2iws!^i2*OK`8S`rXqu(kr0-=QT9<4!pvEY^WsuaX9Z4KQU1 zC+&7X6sFl3k$UxDx8+V4d7)tt0=>1{DF{M_GVDma%xb*3)r5g^B@!Rg7LLt>e`J-y z_r{VWG4?s&mQBK+I26lPn|jD#q(cP%vCgDp3b&P=ZIinJtf0WRYl*ENO-$qngAfnx z5bEiyAC!&*DTnZhc$M%{E;`fF9JdtM6;Wk^d?lKS@-mno%tcu!HZpsIW67U8VT{P! z*^Np>lT0PbcejV$&Ot`h@a*Xsf5M@6TP^ZbNJj=Ekwf(!VWVq=m=;Qg`ISkBS@<$J zvV||qtf`LNtXVR02HIutGfcXEk;9V$j$EN+bd41Hnn|OtkkFSAtc^{v1_ZVS1hzKL zOC+_X5!ISTVQU(Nt&PiQUkTP?^tF-EJ=TG}^5Z1XD2x!Q>2yUoy%0 zi(Jn9_X3UsGnz^5l1DG;f5O0WL?EjYj6;94+myv|m3a6|!Z?}xnSEnygvNanN495v zWQbR3w@23HaO7oO(>8To0j0}!b|VuO$C-}|JGYY;AC5D2{#+(#<61bE5qIt4M#e6o zhb#xb!nKU+9DQ~3+(9ru(iPXQUtf2}_)48z{S@{+nP zUV2)l>st$fv-O0qp*T&aSptt`)ncK;)$Q^UZlBQfpJda|-N|#@<|Vy@Qd9{-ON0Sg zRa77|=myd3+Rb-c@7;c9d8xH_Jze^vNony?`WZ@iR??-nqAX$$6lQcbXF8Js4%tX_ z+U6mtFn*)(FQlvUf22L5V4Q(1&`~jR=B!c5o-sd2k?}awGZGw|CoKFa&@5qC=*ax+ z&mi7wJV@bJz57RNTp&b$-Ns)GeDF-JN{xDLzdNK@T31MTf9kz|;*C=)K|5nK8ECID z?UrM|)&=01gj}8mPH@PUH;UPEWt!rucXM1#NMY)_a?n!(S(MjO zs6Z2&lHm!wK9>|#gi1;Bxuw|Dh;K@DDye~x+`y+;OzA^Ik9Zu9 zp|ykf21Ms0L4J0?)UP{I0rN;`ONTW{>4eZWA(ezSDb{z@%a9^DgdDBHgOWI(L@)9a zVx3Mm>2!-u%O`~}at&wUCqAd>mwCAoho&UCo^m4Oe?aoF6Zr!}Ig!x#$Q1K%CZ=sX zHpI`utZl;GXFtk*Xm}T7i(E)y$3!w+uyY7f#rvgSWPXW2^dS=EN9C|0gGTo}IOe?#zB^T)IDNm%>wa*{*z?H8M!k3#$lSb`h!gug9jo=JYkIuX%kf=xZ_f zbvXB^f20y@s(*qsHig&rghay!x5Xepxu|NQ2mqCh2)+1UyP0Sm=UGJ4pNb z-EsOAf=a<(IMWx-^#6u4ZMRd%hSq~Km9(B9e`dX36K7n=p~Xn=s}UWVONYmzZnCve zl6ZwQef&?h5#n7B*|X*ikp+jMu1)TcfTZ8|q`#IQXUZ=wux{lXM6&BM;Uu;{{Y^_V z{ygQ-?DY=ae{t@P_n(_NeUJ9vH*dX<63<+U;qZK8y!w2Trj%3JvL19-$*v{;w>@ALGCkzqQPWbBP&T_T0?GC zN2h|J5dIdp8bCNvDW1pr(|4-zef8v-H0f*P*iHoR`w!GcZZfqWiXRbDGGqcsUot=7 zu7XF)M={dDnW!@POe@NQb#W!5KR1c;auQKFnL<=fHfy4C@|jgsiodgp3fgB9e^!c0 zP%DM(Aj;8QboQE_1?=rl)T7k<8QoKU?Q&3#jNo~I-Th%#zvE$h0h{dkzSFc{ZdiA|}uk;_<#HWn!EBOA`FwplZE?e-jMR?BJ^YDHapM++7$jhA*E@rtg|A2Vvj-_io(n#KyO zxMkFAuJ4rbbuMTqr!Hu<3ZG`ByLxQ~zczkn@mt34+-n+hSn++075RUmyJl^k&+%D4 z!=^qoYmagL-eFeZmHS5RaW>6n*esi4huA!Oj2&i=e`wbh*aAE9zE(TJ7Wo2yd}py~ zvZL(S`+DstFLwTkAFUN6k0&ILW9)eC31;wPJB$1YP(I0?0_E|nZm_4Bi~5t0=owak zL0u!Bc-L?M{ogc@TTC9|msNbicj&X7yFx2pJd71JY)-ucxJ`;ROK~ zcy#D7iiIC+rBh?X>FlU-Nr+ISX5a;>=?Be$bp~Z)a+!>LnOqcH!}4e~gXuMs8O($N zEM}3&HK-rLmIN*9$1aw1wY%A9c~L~-e%EVt)p+hrKi+oZZSH?I!&WQ22?1S?F`p*p zwcL&fJ6yy*kIp%ci%&b+I_Iu|yc;w_(e~n)GnY$FZ5~D57MEl!Y$!6C9@V;}E_ag? z|Bfdj&LmwYj1*lIdm?uIfbm--AbPkrx4Gbwm^w8*zm;`r`2i0?)sLRtMkoZ2I$^+w zG7gEYq-=z(oDhGH-F9#=siL*Uv|Pfsi0?(x^d^eLxFj~Sp=n4FM(RC+f2h+6{@N32or-n zz;bDWr=Nvx_(zmulUubOyI@>XuW|KCb zUhP|H8J&O0lI!&evHQAsik{tJ@eEDD0U>AI2CvtjBmRaQad7NW$#Sx4zepMkyf!M- zza6q}i=Hd>`t`2Y%HEXfbto47NDJcB{;`Jw$US(NMkbT8b<44*`sVHOnU$bPy4XwY z;gebQs)NT*EkE}gOQ*hfVtsx6*4eXX)^EMge0P6opr07%>jVAyfo>1e;2sF zYlvzBcsZ&uYqun-w=1!Zdf~3|4oue4VguNJMPYx2`^BCan`GjNe%HLCOVch@#UZlm z0u_HGKx*8&_CQYH@s;3)*YcUW-o1v8%Yl>~j#V~WTmoS%7IGb;RgdIKrzYss>Q5~8 zbX^%|U9$Uin&g~Z@5B0{Zoo2UV3n3Gs%Tql6vh-YH?Ejpz#_M>r<1}Cb}}glJG?}D z7Sl3%c49MQ*A{1EC<$#PnrdR-Gwy3W`Za&=YwJd@+;ft$xSA9bI5=Q{10@>bw?ELY z|2$Ymt*~o~A0>vk!;1H;#JR8crl8)bTy=qio(}cAK7YGHtyr20obCxIz5vDlQYn5U z12gUzY8jFWEA5&e=)y)%GpV5GG7`HMxZpHy~{w8J<{4_3Qvz~uJ zTbbIJlgwC}sqN|*;YBtje}5WSx)y8@E$AxBl-TsHLGKg~GBfa*Wi!d_u)kolWBpw= zm&`C{QDcW*))G)IY8N!%EsZ@-W5;$fb64+8LpRe(H|(){<)m;Qqe_f8{PEwAyMx1( zeoc8@H-du`uBRN5YFlX)iSl|kj5(gXSa~ft zz&Q7G8Dq)d?LgTw`nFoGGV(E^%+lS6U+?muL1d6dcz%S(5t2(*IAoBgZFgdFS<1jc z4#^bTd_F5p`PhhQR+qh2L~`-~UIfB>t;{E4ONFh`{4g;5tViA-Q}M^Owyb|#<6AuL ziU4$O+{MW!(^4i!KDrctQj-%}l-x#|g}}H*zN|q5nPKJEG=yEEkA(2ruMW%)5TFLb#g_4zr?}s z5I2joP&2!MU$aoW_y{_7_Ufaf=p{nBYlMA{1yr;RN4J5H_!^dOn>K&7=@wdN3>(;~ z(9_Zl&3K5~L)&z+HV0nck-c9;?KqIu#-F2$i1g}w&s~q#gLU!la|6pQJJSt&40h?< z;N-CTj|TZ8K&Ra+1Ad*v0sKxS1*QRPpYjzT>%B^1C*`C}a3cNHbTSP%HpMTK>7=w< z6q^7CP~0^nAeRrICeMHNSBV9_W$^>RI$#zMGoz>oMtmCGl<)r(07~y6&FFnTVr=5r zM`Mu#C`-sJ$FhaM6f>E{_?2WfnI+)cF9|sS0N;tvk~XKoIK|0vZl9x;qZ-W_G@E(* zM62wlpjV9mN3ft=2;Scw_ujYXaYU7}K=L_B`E}(oK>3lb^$vd_20RQ|N}xKlLoP?V zgR{Ul5Ha=+y?5wZ#s|)1HkoT01kkt7DtSonnM|KNDpO8_5sziE8RA&(rh3yE-+YF0 z1wrxk4~*+S367y&hMsU*fozWAy{JiDeYPcx_|a;9l&@yq`}#-9M!@;!<5ofz07s;( z!ptZ>8n+Yail%?mxktiQs`myjT)Nfa4GCshWVPqgQ4&blXoZo2Ulw*ZTbY}Q2Ku?d zkx{Rc=S~84TYj4WeK0$Eaf2L&sLLba>3uy;kM-!6g(pwM5sw*fdfiqmQAi@1prA)^ z2@|Vv*jXW;L2+POkla&?0jT=(X*sF`>+6JsJ49V3M5%v=@L}mxxVeLY>)TnA9RlZWre^(SGzNnONmQ#SS_OSIo2ctsJWlO^---#_(jvk)h@G0dd{5j_ zKrF-~M}Bg&Z_43+k8tIW326XgfH_r~a|S`wjIMqO_N?qzLY+n+XBoCJr#t2X=oaXW zVc^M@wK;!qGGw@O0&ffnck_4xy#&%Ce&>k4ahR*)MKV z6Zs_dM^Dy=MM~(sZ`3Sa*eN!3R$})1dacAN%wbb_vSo5?T99l17znPd`jjP8C*E&u z$8qP}^UqWAU^x_9FK1^*q0X0AxuEk?G?9OYiUkfTEeS!91V-vZFE;nw485|f)UTe| z|Cy}IHc6Q%frg*Ny}B1~<9t2#NfghQ_J1bpvMuAOfNsQ-fYNmj;Q9ZM)1##yle6VV zUz%rjq8{=@-TksWgKm2hhwf8|)R(A^->;0P;9hG9^=2#d;xEZF7F|BR?rZz%UyOfe zQ-)Y0o|pI4zv$c%EspW5hQXJRQf*uez~u8V`B$iE0$Y zZETzwHMyRO+ORc!F_Avq*pLeYA_Z%w-J9EfW1E7{up37{<71IA4kTGPSzQB;{*W+k zN~VJAl1o}v71&QYqaG3KkhHNpW(a?B$uQBAt#@P9W z)a5tj#Qdhu8D{Te={6DcBACWmZkSqEM;0evKZM5o1{ZruF&TE`!89#^A4h-aLov5f z?2vI+9TA6|IxVj;49BzTK%UUbzZ!Zwx(Ca{z(DSd{@8J+hgRrG&o2s0US z`*aP-PMB3FV9lsYV1y3juyTLeJk#EgnbIO?4wP|Hy;00PmTPsW&ml9Z)+YBb0-sc` zpWh5+3eNppH0r)GCPg;BAF2Hbr{)J_NNV7NM2)>&9*x#t_@Tfy-M0#3d+PI>sPYV- zVxkIuF}=-U(r4MdFm%FTfEnN)zuxtsYMOo=4tdGmrvT}746?L*pjm(77fTvK65%p0 z_Ts$`)=Q|XA~9lxrjbOsl|m%H?X{L)RliFIXam;z73snczPKjP_bb)|IPxt@;VDf> zwH!4697#W)63F9>WkS`6`Ke54Cpza2oy2K(^aQ6eu~Q~yC=;Btefg~h@5uX82$Ux> z<)oDNA6Yr2ClMgiRTqD4__689y`&OoY8xqsd`kNIEU}v{&C+R=3eD1mLl$Fc&|DRx zRH$@e*@S^C7avWXj)AdUdzqfQ6-$|Mu8g?S=qNc!HWTGp*0X26_5w5#Z1K}$M$%|? zGxvIOJwAzvor=B9rPHz=oK!yhUs6|eB%YFsM4B9Ve<&nx*N*Gi&7k%x6x=vtcZ~9$@$lHK`sj|) z9E)@c*;gJHE^B|;9ixsIQD-{hL;b$Sj2}}RZ1(7;7ICp^Ma_y)zpL+>;)0BZ=^Z7P zOdJiYK}#jb<&tLMgy0?cwDJEU07Ipv^pwStxymis80|5#9S?$2s(b&%`S_NWH^hBC zHGOt#;9R zi)Z#-cc_1r9j(Lu72bdQ;Rl%v>OV0^9Lgo+0ow;+2cabUjLCU<7$>iw+TPxf)3$d5 zNJ$nE@UR<6vvA3CtGkwQBci-UwQs3R#r{kN4(B6V`CBUfKF?nql&BDYhvJ=~wUiD0 zuuMn{7RIe*WSM>CE7ePB@zpoi&R@Bb7A{{o|JthfOOobmavNO@ zBe;LXv{>a^_#Ithi=WZ!QX_14{1#8AR@dHIslImc^|z~Uq~#0eFTSyQ<^1aF^3F(n zLVy_o>z%bbM6Vc z=`sGNSgIJA61D8_lVZVksBS%UUZUQXg=c@wcFYM z+dGm+ilV3w%juSOEXpQn*>xR(wUs!w6f1FQH)8DiMCQ1>nIo4x?w)7&BvIaLgHSLp z1p>HEinfSdNI(&UZP6A*>)LJF{!;{K5hO+baE(QQ)+i9bMgMbApogaFdvA94ZjXPI z8#{O0xt+H&Z)V=dZ{C~bzbONs5?r5w>w|NuqA;bRFqLTywW3}hgFC&UZRr(5RbEis zV}`CS|^5msa+HpGV62rGZHQ8xB^p;G3f?9h(-l(KxHGRDg{5Akt6wxhD~ zn}_+>E%lbBDlh#lpJ0b~)XEVy!H(QeDwDj>{4YLP$+Jmz6zWI0@v7Q1`O%90IfWf# z$8RX?I6tmzJiMR+s8a?vhvvmb;_Vmw~bzUjFiuHTx^er$5NS zfS12AdwaR7EiJ({1=lKEb+~_AxCC6mUZJZlb=9e^YIfD(NG)~Mk*->N--6EF;!^A7 zGxKL2xz>(!$F0}YKI75g!V#WC13C!>8qW=-4TcjaH`P!Lm0Q|Th3Q8X5RcLQ`7iRI zC0xrUsaS$H1^4@fWn0f}2kUSzS6(Vv@W~8`_Xb>-aL6(gffB+{Ouc`l9>+nn1)&3V zPm4lg;hwKAp@x*6?a}!#_6{_YjkE)Vv%u(*4#dR8?P`h6gm9ERc0HaS+dYaZp^F zVwjqE2!4MmVLy=w+qHk5xb)=3i?g2F*#7u}$Dz$c@Lz!f#IB&&+v@dF0K*>#hrR^5 z2{dr%>(ZeEJydtpwiaqk+f>A7nSRpYm(+bOfM)|DL)>#4S z^4?%3^w2}&mL~g1cwo51qEz+!XcXdZx_cK2M6~yB>sb9~(D8qGYQJ#v5Z&zM1j<_6 zgQ_sUz_-r};fYB11dH-@Pk@a;ll!pA8Em4uk>)=H*TVyPB;7uO0+}RRDXAJcIod=)|2_pXoEEQSmey(;)O06X;)nf-4mj z;9p~EMMr37dL@6y43?v>!SeJiylyg+6>n$&nE=25nFR!4_%+!WLNP#Lk>x=*hoYfA z;CrtEGdX`P;I8kiHn=px$JT?OIsf2;=!0{fSUYFMj%a}j5_4pBV53d8YGBLUpOc1p zsnu+HBJizXokQzJ!@CL#x4hL2UIVJ_GAr0_a^G6rwith}+pR`0FMB>PyZwbN*0~+3^KHj&hr9zBp={e&(J1O1gPhoJHMxJFIT9x)8%9mz;%w}?va$${O?bVs zayo{Ct~LYLymeu5Vb6?Af75Ah@@+pF2D|~(kboGKYwNtWS*S^VLPN1+;W&F>eEcpOsYK}noxs#KvVs_?-gJq&y`5%Nr>zN z*cquWKLOZy!U|NA{g9=SWi^gOJ0pDr{X@3G|LfN`SOvoB+ z!7VTn#D&$oQyVxdG=4SFp-)S}BiYcaWA1cIUu~ws1wR=g!hjYt`0)K`r3Ix42)kaT1vo z3{Ija#bg#W2)Ak;7_Q?U$Tz#FtVw2;yh6|bR^iqi7j%QL(h@%T;nj5q6m~WC-4-|` zG<^077ohd4WIEuJ39n}pho1pSNLAC!tN@Z3-=csgD~{A72PCmzFU(jM<$SiKC}xvt zvg)j%!s>0G#smc}B0jG2b^D6rk&u7UVreJ$o4n@KotlIhFo$Nt0Rx&znXO900*(5h z4U`O-&z9!{2m6YBsV1CeU}5ydlK4f!EaS3rpgf!)RhDf%Z#P;!zmrU)xX70Voj8H2 z0U7n#Ab2Pm4J^qP4)^y-2wA{%Avgj)zaX~{_ycv;TMe=r!Pg+#BAo{iR{DQ(Vrcs* z6LNnk#AF}95q$G$ZGm@ z2DR3!p6+P`BS13ubOXTYOrM&u@NeEabsBf%`{m;9$7d@mIBD3aL3}A6=#aKgH|;qJ zIM#Tue|ZO_lsyO9_FBnmCruAshvF1F z8>#dyXrZgl>=ngxn8f`O7GJ~yvud%3#g{O#D`!<6jbv0VUcfA|7#Tiq)IXe)cpi%v z4#*wNY8CObT3yEg<`{p5H4o&~-q)l&7Js`FeUZjo(ygWqoJ|->Fm#MgWtbYO8|sGk zErn@s=sW6HRi@*)#Cr{BoF0=&@QLF~2j!i{s)T@~H7AWaQz>Sn&wY{S3~B<6L3$&? z^FU15v-UK$v=5Fh@pA##@oP46m_eiUWdaIdwCV)H7TXxaNZ)^*A(OA65%mBjU2bB) z4QG?n+UMtcqu>V`B#ov~y|9wg^O+W8%wl^#kw(I4phO<0+iCCgzGnPdjl-6euJm9= z%_J1hbcJZ=;O4QrV8}9^%whk~_gK%w074p(dQLWzgZ5-tS8m( z=(DkN*6CEh>K=d3#sGbWw6Lc~#dO@L2xg9RtX9!oTziXGt9zQL(xH$yco>9Uc2h|X z4i9$^A27d+*XaFTvp`-Gs)4$r2`f}KG;vHGpIuS{L;eCa7pi#f_jRqUL2E6@2Zg$} zqxnw-`B1~7Hm2V+@raGi0RJg_;2LM}A9DPcJ#XprfOCK6&RKN(=VP_6(h;SnvRv;k}Pc20O^;JT%lv9Wdw9_a@8)jr|c#gZLlU79oo91ilEqBu& zM9jSG{U(2EYm5%iN{Ek|X_N^oyW{-|myK(BpT2P(Ly5k>jVYtDp@?BeY3r`R)HWoI z8>%=NXl=ta0=*6C)N;m$+~rkxulOglG< za1FsV4A%%;W#qL}Z0Ftkg3(O7+`g9DPN|)TgjIiK#ty#M$aUY9t0K2tgTTy95EsL) zZHL2#$!&n^`1H8vrx` zBtya6RRKMwiCG^wEYxy+3d$>eFBd*f3JR4?U6esNIrm6@B3$uy`NWTij_faO#piD{-7l9bu5nZa2SM*fn>HyCb{h-O=5#-9x+MyN7otc8}D@3C+x}6%S}#+8x>*KA_JLd?f*W zOz5LhuiPE^AHo+F(6-Pifcu#ccUzg=7Z32z9Dfeib5liUfA_)BpU3ymfB>CQTHT|a zA#`MXh1D6|%!|1W#Ixko&?3|xQ^5W8j!tdY5ivi7Z{%_v*tsW^qe|Q8twzDCNiH3%}uou6B93d)Jfu&a@zi z3;_Q*>#CRE$5UEy9E!yYk%5Qo0D7Xu0c`NJuB$GSKS0Q!Hy{c)QmwTFFbS$MFRoJ3 zADI#@92V)Tt$I|B)BU(nRP5zuxw<1TnjpLuA+jD99h}2&p&J*g2^xam#=Y@|D5KSE zq9=cTTY^~+5UO~RlciAbVjx}oIyTpElE6^3aL{X5{3aGxu-MM}|98=eK|miMbSNr< znL)2BW)_O2zLno?REkB4~8}z@; zn6XwpuaUgdn4xeiQrmmEC@+svqa3}%5O|a#94v4L-z!Br11J3>B>XWJf09Nne~QK5 z;kJWR(y($Hy3b_WAaHtNgg;hFso2b9wkuuQ}>fUk$K1^PRMDzlRDd5>56`kI@>>B@k1rfAf#u0_}Y5QdOMZor0m!m>i_p^ zIfoynbNEOCC0YIknmx*L7-cy+4lX)(_L1ji?xrVu_lldSP)$HsRK+75%FLqUwLASk zQ8aXs&Uz@@lqV{O4`_cZFsc^c#K#3pR-FbHvq<_J+0WBYT&jL)@xod8uU9!rcO%uo zx9ve}T9IB`7vj_Dg1>1GVyXs(74r zRb5XTM--iz{q%Zc2sDLAQ52<01w_!KP1Ay+kf1oKBjQLvn%01<&CZw@+q>3yserDf zDo*9K)Q9{8=u`b4`Xl;0uYIzVx4cwV)%MQrngVJ)nxmO>&&=MrbMN?fbna(De*pdc zE&xR(L@_0GT*7~c<1kX{q@k2lj9wsbT18B&S^N%0vQbh}zeOJT22phfmvn}Y45~4_ zYeLVgAV6yc9g|X)>eP6HN;XrQl-VVPl65p|4kw?iKPz4f{2KGFwOq&Z7`Fz}rD7io zyW!MWIi~MBwetBkj=~lRTdwy|yi_Xo?&TK7g(VKs>%QKrSzr8tsb9*_Sy7<%q z33MB}A`kf;K!|oxF9V2s8X)OefwHUiFpRZc7EtdQfJV;*GR|aQ zGD20(n|JBh6p~!?fgE*k+wjcD3{^P_4cI|B9{Dm3U&Z{V)R&8?FB1tH>2#u#@~M6@ zw)~pvKS=eL5*GBAIw_y(Ka4H!QvFn_pH5iNPj^yY>XZ9?4L1sjak)6e*9S6X1^#}B zHwAz82CAH?-d?>fa3Iux@39SmD+5^wLaR9S7JDo}UmVD^7D~}63S1b-gc4@Kt5m&e za4^L4gN&@4%>0PztHLUHl4za}oGlcrPUt%S-p9o}MPhjZsZ|~hiHkzg0$ER?EJ{pegwtR0ZeNz^i2Ydm7b4AwQV_A`yU>oP~I5F`!Hep0i-2Q)7 zftkQpz$*JSY!eGxV7KvAut;Wn)XDIp=0W-N+qH17?z?bb_ZR*R%$bLPoPG$d0vzTd zl$65@^mAMsN9Y(H0eEO-x?uS{YHpo5yifQISinC9fU!Id|3t!~ge92_nUjw`l>6)H zL33ny{eK-jS<<)pUAfbz626GHD?WdJx{_ZjujPdnUoQVr+U`jBT*7A(Zb`U3@}^IO z0XG;x{_vF(@8(Zj96RU8m~`|??5O@on%wUIV%wdOW%wmUX%wvaY%w&gZ%w@M~%x1tif8|=ubKAxh zC%{ipv?71RjuSUoJ8dMT6x~ibNk@~9I+h%}jVO&JPZ}j13gRv$NFcy0K+8<2nNFQ+ zdg-ATAM8#qy7ktcd+Gmxo2RFob1Ktm`g@B72vT&KNvDT4atH#ui??sz?)$ypd(7W5 zV}C__ev-);pZ^gzJi`qqf73R$41?}X$K1-Q@7z`n-&rT$E^HOhm*aV-*e-3A)P2F3 zYL~al>b~eqw<}wf_NlE?>bd01w4d5~3ingH#@4LJ?VrZy3_fSYIrVf-Jl!%cX6SP< zgO>9r+v&4);hhXG^QliD>At!33^zA23)7#`8jg){+Hzeluman2fBib1r@GP+Zqwu9 zGb0*NZfw54zS4MmZTWpX&D`AFT)!zSF66S^435pP67}D>wes%rMtCuLxzX-Af!(oW z&}ezG&8@(~%d>A=z90d&h2O!1BAmG`KI#fTSQWvZ$NlEGmCLb}e~%lH*)n)$%j5>E zYw|2vbB`>1g%^2=e@{IyvCipF@>_ZSB0q(HGiZN`&+^m!3_tsz#Lw}k(Ocl()xGD@ ze?j#=gWik$S@ah9_f+q5=sSg;OAiYCJN$X{l=w@k=e(9my)WQB#xJ9HiWgwlIe8k2 zKK@e{sx$mu_uRX}wP6&&+V(x$WiSV8I+pJXpB?Ub%x-raf6*3hz$~`Zh8dQ&u?1d7 zxZA9)tWsrux4EapSw34*FRMY0z4J?1(+DL?jRAC|8%=VRzzHpT& zJw#d47tut}N(vo=dE zexkD8Rm<%$-0;-)RGA&HL)&qf<9P?H+adj;6W8fTuOn?M5X0Rg&8&cSo_3LWu85ap z?Ra+u3l6>Hcwnb7ZzL?WXszlk*A8sUu|F1)VeJ;)64GDN>rgFhPoWJOnf{C5M~SxG zrqksDf4T=S3-ph-qsqFjBYYfNOe$j;v@dMehD#>G#J!GVH|@ab)l^$ph|WTo#qkJp zbUec1+WO|LwfaVV@B+>?EKpm8UGV*ZA4s@oAb-L7tPVSbIl2NBi+aYeAVtuXZqrPm znyEk63E5_F(>FQ=JJZiJ5Iuk*29Q`jNAPQge>q<`t>_^mFXL;NhTW%TNnL0PZ-n%k4Jq)jO- zMDvDOC`51Yp3*a%9ghLwnPE8C@wzUzWG^%i4&@~bZx&OQDQV06j4V^ZO@PRH-}tqm zf9zt`2dmdLc8Ys}_Q27_!H?ilLsZ4~+md;QF56CkHAdDNV$#{V7uCzcYVhY``J*e@{*B z;rJ|69{2J(&eGp1UJjTa_ZNera!Mk;|MJ|R?Im00->@8EcA8g zP2l=)Pq++Z0?-L3ji?9WO(IO&b3$CMKA}%V&FWAa$pnlOnZP@wopR9NjPF#+usRMz zDh|Vd3I!(_$yj_(1xXP!YYQjDV!~0Go0=!UMjat3){R7K&poLct#MSye=-;^Ng$dK zNB>v?jfOV1icB#_1JsfU_0vu-5Pr&PDiphj(n4B0jtaNw7q5=JM^?7LMI5o{*zgK( zXCM6Vq~6gHpR9SbeJaSO7eSVR^wG6&(a~V+xhW4hIpK*|u4c3qcg1<5bv1$CUNSPa zVR91L9bd@BYr8<}QS;nte=QPJF0NWZb1&L#v?=(kvJS%82nkTWOZ}aQ0P|5{SSg52 z`~r9|0z@F39@gD)tfo*Tii9pE9;64KTr+|5*E2Cz_tTBFdIVB;Hg7DB(Z{sWYbVa^ z_VyJd0*H#i;wISl6(CfkQ^f3mAifA_S_}mGf%PZ=xk~zB@Q6H3f1dQ>2>s}=9@@m& z<1zKYomin=FJN~q2lt9-?qD>VBQ59D;^t_IxfH?ENdj#|y9*!#@kc-hmGi;P29>5> z1|<=L*>PP5mGm-?&4E!J7)v+6mCC-LIRX#7t0G*#D@DWdo3=g3cZ1gAk5%YAHsu>} zG(VmR^W6@-Je(p~e=7J#AvN2!I`SpD%M(h;Fn1t&zMNJq4Ha+myxZ=8;6ettne^(kngHiHwTu7~9sJ_x% zk&^sa4J8+ol4T+#IYl;R5co4kIgYSz8%KqH;i1vbKQfF=KP!LKN9G@x{p@|?Lguy1 zk%_TcO%e)34Hj~bkIZjO3sPZ!=zNJR8i99eNvsEqw7QNu^y7K40^SoTW&}+COR?>n z#fWbw^e51$e@^|tc7IFDehnGLc<+tSQ zlsIOdB?m7VWiw~YnuE)eoi>F&Bbmf-%3)SB^wf0vFrD_)PbPS3VDxkM4R~t_KDy6A z@z%zjaOdP#YD>G5Bu{)?Wj!tB>}_3>)VxTn8I%zAr!JU4!0Q+5S( znCGHpp>d%~a}O0+YIWV_u!Q%-^6IwMkq`ZHWHBA9=Xe&MoB-*7tEzT2wid_w$x75P zFL*#wf0-K29LrALn@h*;dy5mQT63dw56!ijl*5wjOl9_QBBTkU8^rAqNtY^ z7<7R|HFk|94^g%`PtPu-frsNDRN3mS)fHvV1r`m1t>oxwNQRJzSic&(LD|_oiy&`l zsXPLUy0G~M`{hWp+U1t#%`JiOS#qvAp%-pRDq_ey4W;{9a4(pvvN^r^s=BPZ<`yQ% zf51*Si44q>l0j}gKOC?C(6jjb!XzoQV4f25u@bXmyNMXxmPk1%WK5*pwsytU{f^k3 zsJH9U#^@?nY<+X!#TPXiFNeBahdq5CX->_Ra;yM`Oj8m}nyMzFU zvFg~(rJ4I&Iz36G!M{B?;i0qxjKpKp(k>e%nSNY|;XSMv+DUl5M=5wzSJW<)$cr+K z6gE;sr%HW{@MG2Zn&L=fLWj<;gvS+`VeMF@R;kc(vfi2Y`TuwRH=3t@8;Riff11a` z_R^Tzj95T5w&xfUWJue-C23a-A;3vlVft`a+;-n&b(SpMElvAEVW+q%{OY*&LGiD5+P;JJR$@zJMgYkS~Gxm(9VIujc-$%3#!w zbM^YBy4LH*W<7o`(+@`!K^l#)+-S5t-gW4{(rA3twH)13Y&5vnY&7J1f28J%u?6G@ zabBWSPc3J-Ci+?Y9IfeP`Z2=DU8RJ_|^N$USWLH*Q4 z>$V&R2FTxW@nTroAltf4e-Y+4DVXX)kt)81Mg7}gc;N|^5@m}?MhZ)>M}~is{@07o zDG95XRKls46{BLz;=6!6?~-x;OPqtkzX0?aFb8;?U60L512GWC^S#@TMMWt12woOx zuSJBi)}qv6TfrcN)e}{Ox@V0&R z7y}77P{5o?C{Y1th@%C2515Qm@P_+iTPYGA4jm zcvV)s)_7f3hv2k!xe3kJ$kEYqUMNS$IxltVqIYE$-g7k}_O1}_==Whmx(_9P0$;S5 zHq+J`Z;=1i)IB!Xf1|%nTrzqXWTJDGb*_8;u48sJ&-IH5iyP|UaIUSx3u|0*pWO|6 zw|y}h4{kEY%ITYWvhF~LiPoi^Sl@6Vgo#2e3y1?MVHIE+!4LR2UYerFr>)1IvD5j= z#qC)smxVeHgKa||0t6Cx2pfo?81AmuZ}Wg?|9G6ed~1*#f5&;)y!Lr}d%Jsw!;1um zc!RuKf)q)SAow@{cLWGv0pbn>IUqRL+n&4IyV>1i&n$pLW+jylmQqe2GfLvBM38-_ zQWTwKC4R_qY*#6^e>s)MFDG&)m6T|!q|k9bU(d`w?jWm@RCa56dV2ct zb@$ibtG}Kl{3wbk07k)^sdhz}V<6pukXXXGdzx0AKJQII8TU~!m# zoh4Y(9;t0Jw!zy3OWC8f?Z$SBr|liJoyJaz57@hEf4hy{6wlZX)E+eUP<+sSsHPh_ z#k2OqwY|pP+CF1nZNIUf(uV8yn2#7otRst$7>{0&>P1bm z#;ox(%eZP7mUtH;}perLwwShtW6nHwU>>TYp0FVwKK*U zdiQ|+O6{z1wsy`qN6!!1=W8XS1Y>@|xL{p0e=b_FwO6f6>#{M;_OOSTeorxGEM@I7 zdzkHIiFMU@%}T6YVf!G*>((1qitS%j3|r-l#Sh!**Gi0|1tO zZJ3VBv1>QWRo9$raFauYm3{&uhXf=85lb>;CIQiqVfYk3bE5260Qe;54PF8WlBQWN z*DTZY)23N#u%?aijA_2zEZgGEhQtp;O%$}ZHMwn9XFu|0B^vDF@(SMv?+(EAz5+o~ zre}aOEqZg}!l^fK(k}AGtreK1f4S;BPKX(f^aYwD2eX*w4GTu6QHOTp{%|m*!6*>a zenAZKMKOvZZMX!WLUj$hiB$y|OV-T}PKdNL!64%K=@rMdYFPP|GOy#5X#T+T*)tc- z(~}dYCNDt_c(^!m;@o7AGVP~39rrcIu}z%%*#=uNVSXwL&H57dqY%vae;ib5@nv4E zyBjfov;q_6T4peYCRF8Gw_HC{biRu z+~nnD(`i(eEO$fkb0?ulb*@^0Rzx4OwX$1TFc%t*i?a!!sh7F^-bI+7_kIsB1qx{k zuDk5VFm&GgZUSD!ai(`)e|>BG;eGoL96a>Mqs6z(>)ywXjz3!-zdbQ-T=Qe)Cab!e zP%jf;;QI%a4(eS79%iVP#+02Ba4Xe{Gwrx!B^Hx#rC4lEotJ?-#UVX$Tw+P!P$`I~ zAwB?HDg*IBh-cwG1os@=^T(0C$JsF4G4BZ6x50fB?%UzM1MWNFf4(bt-VOH|Ymg1F z2dp%N1MIhdmSn5gk z6qFhbo{*+$#&&2qe?`wgS*eX3Q3_C5O4%8uAjQR$T~W#l>_tl1EovnQUSbn>GR6b! zHGpdmgTGAwAe=iWFH#nl(yWa$9C#}N| zDHPKib^TbyhE;UzIwEGVVppxYTkIwC*Y(+^s{@t2QDv5+m+LyLCSKNIT>+(RR@?@s zDrd`;rJH5WobgJdwhUZjwrW@172PhcSX`gA+?$qF*Bdra6{v*ib?YX?F0Qx>P*E{W zbxbfocxbb1f9p%u%FPC6I?!=gQZ6h~q%c}q)z}A@4-33eU zqMD-C3Nk3Gr><(fVmFy}Otd?$U%&1&n!I9}0fD%F{g^&&xm2HcqX%zv;0dCcCg(6* zo0=1qA+azUg64*mIm=cB35On};{;$$%{mNF_cVVcW`I=5DW3D)%~ z7(MG&f4R17TVr~4PG4y>^_x{^0jsm>0EC5&=w~f!S)Z`0H!J`Who0~PGhs{N0E`8d zVkNce`~u)9VsqG5u?R3RYkby*?jJj*FB7tbZ{hbdjh6nXezj8se}{uvn!a$(oW5}K z?BvXt9wnJ)CnqmXoICT{nO>9Z@;9YhOU zb+u(&O;yL$4_n3g;uy^K)oa(U9}!r`Uqya0;;t-1{^Cho)vuNLRp5!&{7l#}l%n_` zW<1)Tu?vfZJRv$}Ubr}O=0a)unm@Yr=uG+AY@=cO1HfK^X%e!Q+5?!TdwQu+xBNU| ze}LJQ!B+t;KSlH6RBv1DQMU;QaTN#(AO(ON7R~mq%J#v(0nDy)-9Y-=&4sdK28At# zVgv!z-rg@CML>g4AYO!(w9^1y_&Q^{O{mN!rr%Bj%$wfeVEftd$*C+@HS0YT8aLt` zc{pbn%wjMH0ZFpAR{V?@EkWRX724zvf8dNA#M+^ezhMO0X%IaESlWdyVK9VG!*C-7 z5(z-=YlIS8fWzO$fFodWZn;ffuc(0lf~+J37f3OZih>9VI@k#Q`0?!Ha;RRqFb z$~1|K0th6-AHm=g5PS-S^*uObgK=4be-gtV#S?KE{tAWgZ*T9TLt&3LWd66Ha7FG@ zJa8gThRTO0ElO)Llh;Z4c=wk>e-@9wmn|2#oen&2p+RhuTeSv|)N*}A2OeHUim$VV zi}btf!pdVL)e;#BrCFrqKz^oPJyj}pNavZlK5x}6Ube?{P<8Z5Mc0V58A1ySe`Xo^Cor{$ zMd~`NHy{DPfaakdAe!awD#QK;?2pK91KDne*C0u+Sy6SMX`oI(R2w<7bqiRtE5@{9 zA)ngRPXs3voLJY`oo?K;psumrVZI4$wr`vqy#mY^#>&QaP62u2k@oc*Wa%A2yU|!` zE(i5&f~9KPoq=l9AqW-N7N_RTr{VYe*8)oVcoCl;3VbtxmwE@#o7$&))S`kXO z*Rk5`0m`^5UFdrSf6&Eon&Bd%SqPMEoEEW~qRw^X^XGI_G9VjF3sTsqLQw;j6pf1Y zUIppbvTBZw=+~$R;t@6o^>aX=SzhK<3*~X!Zrs$JX4UPCaR~9;O~^4JL>$vg*3HfJbS4fa zjD=jb)XsMB9G6x5K^@sSXs%759*2YSdcfkJZ_7v82d9822_4buf*iEXuI7&E?cr{X zH+ZvA;LoEBkq=BrodSeQ{n7wQZE?{TKM8EcLTeCze>%i1e{h=K1%@^LB&H=UOq0=w ze-xjx=IM!PbNY>GbK>%;GczFWtvLKO#9Ni{7Gx2q!k4W++y&|ZJt6@A05KS=mST#m z$!WOY|KoJLAnS6D#Ey}lD5~;7Ax2M9@tEjMg{F6aT@@JIo>;_*P1|rW-Z;S z64f|_vwjHJiikOf0NrR-e*?!{^V6>(5fu~ke{t+s8W1`V;e~h@6ZE7b9b!rTn;6{b zB`?1V!MAX7$Y7U1*)RQ}rWWM(&b~qKw6USShot7c0SvT$*$-2bAr(3(qtLx5FDfmN z{&3Z@@E}fFD?SE5gX|0&2t|dLBBdQles`7aaO2*bf ze}a^yw~P3e#WC(lYblmkOQSH4&mY6O2H*mkv^dC;ca>KB_CN6AYeVbOn`$f3O14s7 z5@5TZ5tGK;k0;P1Dj-SRsnHF*7!dd=Lu}F-B6JMEI z_LG%{J$4kZf&KWl_P8GYdiA7!Ygbj|qTa*l6AO zanTQA&se(v*iVG!cMZ$?i5lqs<$2IuvF(0RmCydq-K>2yxpPX!`Gne=NZF;7T-M zovdku`6Lgl25E~be>zlrNx_|&+DP)RVn=Xpgd$3M>Gv_XCWU(DbqszX>UD?2{5b@p z0Mq+f0xpe8rJ9UoK(*Y|onYMW-yM<-L78OIQWC(EQH1)+eOmTYRmUU@Vu$2Vg4)bY zqD-4w)xuWybhXN}D3!W0e?0?3xT|DvptRD|cf+zAX&?}70_@@YL5F)ik+J7d1Tanj zB6Do--U7%l?*r>Uo+ZpYet`?|eF_Dy|8c1I$^6hv-k-Q+4TC0tr0$Vx(!!R1GBMJzvx zYZS&Pj8m8h*nv`-+DHowdMjF9_p=9)7{LE?)aO1Xk1vj6A4dpcATU~J)(MO|BmL_T z7X*kA{~Cu(1;xove>qFlWuXax8yQ`s4W1KuFij1EXxrX3cd}uJmdaOe-jw)%*2_}G(|35IA@+b zJ#oprGzn5783p+7;26Z_L9Jg7#I0qJlZD2-5f@wo$B7SPy;0?Uj5b{R=i(uFbr$Dh z6vrryiydU&4>gz(MWX+Qn?$d!_Ei4g5QI4C(avT?8c7yTLIMYUmIj^4Ot}NP+$m`l zmZEbolwIdwe}I2U`3#_G{TWyFWaI{`vKs?=_bsNb#Tm$3cR)9EVN$RxOq}Y1)a9ul zB_)I$%y2=c_;$HZ2vh=490Wrrs&s8fO9py?qO;N%g}bt(yatWGt+0SzseZcZpc$-O zufP=IXgxIr!Hz>Xjj-b^%_H<#gkIq9-&5X3j6_s&2shlSYg_PyM4aZQAJX)3G$rAd;|o>@ zY8*iw`x!uuinb327K~!kt=h#d_XJ^`aGJ|#o^td&=5J$bwc(HO&~S(qje*c>H5(c$%~0yE6@-YV)(&z2B{xEz&AZL<{5gEa|c%?O!qX@TR>AA z1x;&FD}`1Pf1X@tXzBa%Qormw4$1HI5T_%33n2h*E7CM1 zSnPPjVpjzJ+7|K|h!c(@op0w|bU~Z5c$B}Lp9zyD!zvK{+u30CjEmJXHA5yWe@Zzg z)>FFaKq=5>>TWxI8RHWak2T%7@n_ygf#<-j!SsPy&^&SBfPy-h-WU<;Tbk@^!kk2g zsH0LKw)m+z-nean_T&;HN*+ zh%w5tN&gGxxrWHFfasP@%h|LdNBN*3skDCTWau|i2Aw&hrCX%dS_;bBRba~N=Mf6{%>@C7Pk zM^C%HBdB693pfw%3o@#W_K9Y#U?-BHcSpE+ zaN~*M!DLfJ#U&EMRI2FJOO$E-1yefB$ep}6IA2JU0jlsW@Lj&LdAf5uq_~UrI zz2~P793PVU2q>Zn>i8t^`%=I)LFwZ;lsP|1DzmTyn)nX4;H5>4f2cPglO3zYaYw*S zfclhNms%>QQYlYeOs~qQO4VP&eFry#p5FX3GH_Q}y1mC8T+A}f9rA!oFXmPiK*E^d zqojPvE$w4kw2P3(+SUq4%z^tM%ElmN7_Jd_n}`0^$yF7eKs;UC4%ZIk#EU!O+J&{V z)ZI)g?jdrg-$j1Wf4zrINF5r7gr^g2G18W7_olS)|LPrF#KCGkSQnh*egRs$tg%4X zrQPjNG)5P)Zuexg6hqR@1t5bV%tf1-yg#m$QS9-t`#y0&%nO9M$>xHfytw~V% zX<^NxQ=EftWY7|+>41SZs*R@8>2N16MC;5(Wxe0enm{U7e;tbzyN97uNw~KkZ1wl~ zYdH&zrp>SgVXqPHX1E6zu2+!`F%S~1-U;a%jiP=9%Wd`s>#BCMyIUti*9IOLQaK`h zdw*w72i>}17z8)cQEGqwfOF)Se!xL@@uYRDVpc(p^#@I~@0&NAI{I_B<7Dl9aU;`N zxgeL5p_Bi2e|*S>9?@v*tk0v*3+_60c$c3K_o5@mAR*zN!{9tpiQU3}fOa%tT|nJQ zu<5_R09Uop83useMz!q36t(8e^QVZ9&#Wv5e#NTYnD-L_k@81S$}$oAyEmrJlTwT| zBd_K^hmX{w1hj#Bul&u>{kU(+7IH{_O3qa*fm%i zsLPg0WH8@QrlvNOQi-m896jUtK@1L2_f3;EDyHdYQE@Y8R{{?#ZV;I^&91`@rpdoZ z({kqGf5l4|W-gdBColQ~UA~U|O{vFNv>Ss@V3B0FK`wUu;tuVi3!^S>0Pzh>&V<;7 zxGAi=Xu9QX4A9QSV;Bs`p{a=^IFiqh|M1&#Fvx({g1}TP+YbGW4o5RWlYxez8MxlR z1py52j$ADBVJ4Q*G73sINfF{dCVim9Xez{nfBdh5dlWfW07)s8-Ajjke)K>#qht?e z^N<*r?PR+^Cfm*8@PB~96uiwqTAcn5vOV{lmB_3oC-%F!g{GFIF0#Ezz3CDQN*aoc~LZ|q9Dtm-Iitg*=&b=L2WYHg@ zotn-fY5zl_oafQAD{zDE@^&VIIZYBFARO?J<2P@k1%jC zXku^!yT7+*goCj-S9Q^~?<#Ere_U&C1E7k45+?;*!FceS*!k^0tD__h1OH77u@erh-Q*D?5Q4E{xAPzpU!(dfQi60SKU8h>5t_C!U!3B=IQgp>r0Y8&nncq6nS zH%ca@LGnt?;4Xoe#$5t$0KHPZVf0G%^5~W770@fy%QoiR%;Ml$*305Hf4e#44K;2B zDMOT!^Kua8y%ZUQzJy!xWD@!%j4c*gsd~~KW+)=3ycFadp?!&M!L9@_h(b{9aazqJg~Br5xTGvE)9pY{qKRRbX>n!8_@ zX}HYt8e4uv|M*Iu#kE=-#InoMh`@(YCMMOJ} zx9P5-{c;4xMsH_2&=XRoyBHnDQN1VC{!`Kxs=dlIK#?a=#fMmmk6~<4YpH-DF{Z7e z=Y~v3Njt`X%7~O2A!VG9GC@cgi;yxFAZ0Q_%4C3)h-!I8TRrX9eo3R(rW%Yhl+!ts13X$$Y6LWq<5l`hNsUffEKVp0pO335xRqo0pL zPijj6?9~=yOL2bMjV~sUyfWpk0{E&imAs6SRKp_0G&i-DUPmmCA-3Ocqa}MC#23KC zOiQDBLDU0{KZM~wkWW#3N#VbNenaG0sjVwv36^NZ(Tp{5o!1WMZI$RIKg=4f2uKjQwz~c;y2XRF%9)jyI%iPT&abG-wa9@$? zmo&+JgwD@@e_foP4@U}8ev#sXy<-J;U>@-H*I=9*Y{|wiuEMqE@I4m4Bi}F6|_NG%)O&iH` zl1bX;f5{8yru_jbVbWoCkQFO$H>=ztTR3XJzfSU=7-KXAq;P+W+ti0k6T$(&NS(-6VP0UPo(aUGC+-I=!H2c+wXwAh;XFd5er;ky8W%?I(gqGTbasc9vxU~aOm ze;_YV(BF&RDQQ*tk(Np;p;e{-uY?ws@5Kul4V~XQ^{2xvkq<#Q(s0W|6Jpc{$aj)T zGM3RsfGmddG(p`QiizqSRU_bmfNwvB=x7iyTVRmvdB z6eD4p3V%0}FMfJ+oklu#D_mEhU(NR;Jnz)~7hB-#pF-Mhn7Q}I2wxH3He*?ke-haB zl)sD*CuQO9)gxYSqD^SeOO?Xk#*RKK9{gcDiFo`zP>X7p_zsKv*TQq>_>Q{#_;|KZ*v z*^f(UYHO3Z4A;v`xIXqu{pK>Je^?-Q9haB}cQlpJwxGY$yu#5Hm`&8#YXKD!OR_D_ zFbA(g!wyN}3l{mtZxZmSKuF7U!TvB4E*jj3a2Co-Vi&RfK+p2mJ-z$8ErfQ07~@Fd zxz4So`CjilbTAONgPv6bCr+9NnbM{75yiX78pw0Xh%m6r%XuWJ_T=>+{$@brhw-62uQy<7oA-dki=9^ z1KKCA%IK2U%GWh7+sca+FK?<|#+mU3@WMSmX9gv43geE!Fh{~mI-Zw;D-BnUdv4Op zv)HP_JufdDCcQyuH^sl^e+{ms(Z9b{0O`2^^8A;*0#m%g+5k(e%Ri^=lv)Kh;}uqA z$XjR)x`Q4b;EkaX1vJUDH|XWPA(p(GZVlgl$II|PceCCwNRKK@-Icuzdg0e!_wtLX zOXmPU0zCmwAa^?_2>ukM45KGYYsAaJ(;gU?ZS{fxM?kp0TL75TOkRaD%YQ{obBDbV zZvdW-L#x|XL8f&_yy2kkZA%KgG2BsTQ)UBql`9~xg0#Jzr0q`x()RG$4(xp>JJT1A zGVeYClX0#wU#-xYkw|3>j@oybx@fZzv|&Q}j`BGcp3EooryVucxQY9Sc=)eZLJE(s zMn?|2&dT=4u~b)ZP~}Fo+=4zRtKuthPy!g ztV-YR060iGcVGbrM?W2GVb+4@Dzrlbz1`5JzE>h$Evv*yVQ z=g(g#nWc&IlYW+3=@@4d3uTA4)CPe1@OQDc7>Ai*d=lF@jS0i%=C2abe&4cXaqPOU z0)F@@`qEYDLTQqt6MvIG)GtFLf%6B0?_s@q`OKxsQ-Xy4SL_LH5^aqBzouZuaP*Cb zjuo0tY)~X!hdC(Q)!P>HlbD0frfFnt7*;mZZIo0_BHjK162u*vaJ~uThxm_^36NW3 z3Y|?;V(}j-N$szdl=fH30LZ*_MvdNR%8!*;@<&P{8AB^bl7HNIB1xn7|HJs8kaW{1 z&1&fnHAVZ0rp7-2o)JS=pWKH~pE!vBffmOY$TJ@#V>w76c-s%%?`veC)thYUWct?l z0i2|~m~hZTqRFGt*d+3zK`=T*iWXB(UXz$`{sk5Q1b5U^Tk`E3iovMJBf+~O)t>>P zrY@!VTY+Q7E`L{Bi!nSRC#{p3?`dZIlYvKkw^K%N%!FqEoc2pypRLkaRrvJ~(gkPP zfyaj(!2R^1-cyF zBDX6Piy2IVE3YX`aaB)RC2#F@1*Qdb2~SyyFCS%EaF5}=rLs8rpC&w&zv9Vck$T0` z>IzHYNn5BxK|7QeGl6fSM@xzSTNF{^SKlg+-@eu!xyc(yTg5h%UT@ZBE#A&G>q~WH zBB3VR9)ICh1;2qLKA{v?9NNEE)Zb_{d7!1BI9C?d(C{3!@cal}w@3&d(_OxTKK%80 zr0Of3@|Q22!?LrYR8gO{V6y3Kd+ySW|}^^QHHMK2kiLch-6P7lI5s9vqPth5zyT2>XK!z2!{}A$tZNG^sRAhwh7wdaY zTz@gy#RHKF?Etlh#3zczgMojHKi<1WItzuI-PQ1LjZDw?|4Ly_>i$Y0st-sR{Gn6L zT5Y9k7kT`0upi7o%&Fi<9>mc`y_4sp9e%8#SV9sgZIf_D<&{HqXNAh!72?swJl z`mOn}q&377VS3-Rl+|E4cX?2H5}ty*=w3LhrbURk|>$slm~QsDlD zLJ+P3A?oS#)f-(R5NNGJ+`_$*ay3|C;u{pW0zxNAyD^U|t0<88Rly$URB*@ehkXEa zB^O%M_xSnV_vl%;q4KjzkXMxN8^>RO7m60RJxj5ILMa>a6spn|eqeI03H^eV!GAFa z|1*>>2D%Qri^Hag0AR7P@f2GUAdWByD7|yV(NS6WI?)c`moU>H z@lFz?&Xiv6cs&`Z$VY(Z@i`wpyOENJpXBv3Aa&TbXu%=3Ch^V0Cpd2N^8bRJ8Kknk z?o$~`3q7Mr>8EXP`XrEO90T$z4}XBc?|X_9gbyMwNroTnq|a*l17`@ugYP>|gx|0b zIZy=ibLMQ>>G?(g8c2k-2EDTVWaMY?ghXD{A+vJmO915UB|a8_p8_DdMut{jBT(^t zjyOev-y{fR*P!dGT2*u`q-nuZo=P@q7<6%^oZWT^Qz2H%mzQQz7!3i=OV(oTf&%Tj>*ei}a} z%4YDhUnJ`ayB4x_K{=705s~n>hlY$k+CYfE6|M1;$HhlhUqJfz{?9{@={P-g{R110 z5)ba;d4%F1BjT}OkUmDW&^X$oCwI{OfkaNusG6|JYFPzBHTQ7||7Ym_aACLdmrr~g z=qg1zIJZC0le@B{Mzout691e#RMLjIrZCjQstu%Vt zmbqH39;9sA(vT4;OB%1z9I~2Z4`-%F)jgu944uHzB~I?LaPEQ)a;GHZ21vjK@&FRt zA-UWk*b6SXOLDnfviYO`NiGi{27(K6iy*+jYvudC>h9@z(B8$7n3}HYdVKZOufA8+ zfBZM8>u(4?mnBL5@m*DtZc9umN=#--MXoAEMaE~fq82sy)+&jrUesmjaSn2cO0t?N zrex`kR6DFm*1%et7i9_m-<6ool20X;w9-%1V(Ok$Q|^kM28)CAohfGMd#E@B->FKr zI$Rv4(FQ8HYOXj!&uMrbEsnzTAj?$te^kecW3promG|;rg||bM@#?FS8f+tK*?2~|klWd&re|suf zC%5w3(xmi6E}pVZQ@{I}{6r0&58(4vsd$DR1bSb9{zdsAEH9p=(ifxBm#Fj{mA)L6 z8dQ3oN?(aeU!~GFsq{6X`>pcZ)*1S~5PZJ_-)FCicN4+$xgh_|SpIxacCoX}){EaF zJ|B+tA8+$!&<@AzF2k|oc^v=Ef7sZ;creB#8sqhg5<61-Hm&&O;uULf>#B8aTP{wr zqwI}mGCRhyPqpGykUP$XA$L8yEIY@}L;g+n7UZV^ z(QmU0fanWPl;Zo=NcjWnee(k-eTPjz=>(MCVBdsR2kHMJ`_?m^U1Hycf3`Q7Iwu{w z{D=Qrlce-bhczmevFvc8;o7woqrNdyw`y~9H;j^Nl#KZsbH-w6Y0av!yfMFOyGB*C zScli#s#p(8HP2YIpaU!Ity+fbm1?ZSnNhJ9d5Lcr3k$AWSy%|$xs7_=;hx2exx(}b zW3k~GHD}%MR!g3-ZXJDSe;JHB^}5Byjn&daoG380*Qj^Sz4Qz04%wy>9hfVhhZ|b zcqf4ec0KAd;z!543}g(fl4F#XfXI?(8A}%T>}7k2o>#4kXNasCzczvrHO@) z8@vKAJeOZ`Y96;2^HJY#e_#jY9E5)Ng& zH$Oj1%z?FcgUx}=Sp-fyHGo?U_79-n_N=9b>p4~Xv9+*}7GOMK0IC7S-8^@@ffAwg|s(Z#XjWNZ!!`lPbORh_Fno&;^#;WJl-HB7D*4Ni#12}wzD#lUJ zt{X4S+YZ%4h_q|004y7eKza4lTA7_9{Ctk~#g6O`mTEP}Bi6bF$ZL<@JpB%QkKL|C z@@eXk2ZTV4rEUX74h@tHJXlgu1`|bLG6+?L4?t02e@FFGrdcahEz|VVrYV*jo-?NT zpi!!bH#-s^hT4?04h1~?PQdB!v>8#~pkB|y=f?^pDVg#>Zu05|2%hN~c+_23a?8U) z1d`M6K37B~t>M`f{Jslw^!M~xH-F4}`W zTR%5@e`{ub=Gx2+6ZFKxGv*mT8$6gdr{>?Ane3@?Hmq?rsIer+I12`!1X@YDhTI*8 z2U}`N_p{$oHswvFsWjzZQXXi)XTdaJvywmU%WJ;;u+2)IgTzl?MCxJj>zD2!<8(-L z_*W!;9N!Pl%$kK66C~-wv+>M1Uxmr~d(GH;e{<$m@GhuGGl0d6=Z0b#-E{r*XO!kpYvaiSP!d)Ux9iESE5ga(xZ5V&k?Y`Rsgw#VBwb6;Jv_BLe?LF2Tyte zNcUtHkbp%rFBb#;<#2+;ZP80@h8 ze|%v__Yay6OBI`e3^#>FvuaDW<(gH?1MGy&ufe83j2@(=Z5Q|&&ehLM&zZCLW@e`f z@G6Fc2oC&3NPZr1kS3VviY}*QUEZAo264cXO$F1kYQhGGoQ5gnv|#S%Z`YUu_C=ck zD4-WNj6ehRQ#1MNg`I>y=5Tw(#Jy>De@&2I!(Z)3KFq z!2|hFQdQo>RaKf2QO>D}t)Rdn{n+nuaSTd?vfSM_) ziQ90X^=C-3e`s+~#Fi_pxMR2%BWi&1}j1uTY5Zdk9TonQ?9Z71}-?w6UrWNK*P^RWm1$0iKb@ymoWgHD{!m91M z!uSzJj)CijdI3=BZRCL_Fku^YXvMIa=NJ#kctiDFv(_!1=Pw{A6DF#V*4)v^Li?$Q z=pEs7{!DCu9ldy{L*3y>`Dl_Zf1g1Dk}&g<=W%~9#yvk95R(@j@IxdvsRcdrWFK%{ zf#h!?xKIL1dPd2~imW`>k{Q@G;+g9Bs_XGq8WN*vkZ4hS4Rss;7QF2d>}rU{i2#jE z1%F0kiKp5o;I1jH>HJVrngirD!3W(W>+kk-c z&{1K9xdIGr%rzEq%U!8>7O#;#OT_@s3Pa`!LzP$2HfFd}p@918aa_Rc!pbYqMXk%x z$P1h5THHXbb6D;rD^3e}P>q_6Mj7&LO6JSq@&Vce7&LE)s9C`z#3it+Lhf9KW_!v_7 z&@LIb=dYi<0R9Ylatv5Oy#cRW=<2qpXkG_O=V<&ZH8uxkEskV^odAvpr~ol3x82{d zfM3(Jl?{XlTFSVa!B~z>jS0GeR-vH?RfcP?z+S0@+zaO?`Vq_Hf37+WSYPPPU9-`9 z3`9f`ZL18iGr%bSPCsm-7@b3G@<>u{%8%b?>ZEl40w7V^lAFr5%(G3Doyrra@pH-n zX%le?l5tyZ%3Eqv+Lrf$3c(1}ob(_YmSIi1D>!4Was z(lR=E=qU+@GcUNmFo8Hi7sh&2uOK2|qeLC8+ZDEi`vch?`a7kEj?DtO4;x^yVpa1| z3lh+U9p$ldJnzeSKT&d*Y#WrmhJ*SbI7+a0(NOT!idFM$rFWEqTwx{ynqIifOJTRgCk}F$daAkP0ncVF#iOp$|6m%6SCvcD7zYjunpl(^9$Y8tnO4bB?21CjEkKqBZ zDs3Zr#{hBimg1>pz-KwJsoarjMNNXd4k&y}pl}6j;(LToC{KDRNC&+1vIaFC%F?DP zOON+^gIgIUH`Q%L)V~8Qz7MEn%BK3UdRGdfsjv^8e@fnvmxVns4E^M`u#ZAX_df)Bf*3SSwU}TY!ieHlhy_}7^6*jS@|o%CsGQ& zI$4+#o{_?jBCPKBYIpFA5N6~V>2l~9;WqiQ^*UNl$Was6Nw{wBjdrWPG`dLRL4x1? zQBdb#Jc9uV)O`pbdk}cXt@QM)afLB%x#)J2e{|-b^r3O!;)+!RA;d2YB8fPFCM#0w z@K+HSHrd%z9EM#NH<|o&%v_oc?VjRz|5fx8utp85I1(9_1;@J%xM9W7$%Y8ZSkXIj z#)}7Ik%M=E5MHWaSMwWn%g+RQQm^?n1>}BInl4ARy z&3>>Q53qxfAAtI4_5$P&u@@nqhP+Psm)OgY9}Gq?*ej6B1i4q)YmgfXa);ULkjt`j zKr6=K6?Tjr2U>^OH|YHdb`sv_Se|mH*lEa(urmPa^Zw8sz!;bua}iOEYVE1;w-XW13XLyIk(CdFLdS8?}(>1~3Lh7<%oq_B*Tstijs zCZW??AiaJa@b`TL7>>vPHV&FHe{IJE?dL9qi4ARXKu}U+h+ga(qTv9+j0Ba|Ue0#ZzZ{00gX^=1=g7Q~t8-9XJ z)5N_@rj^|f{U?r&`%S7&gd=iv=l88E#vD59qFU3pWzBYh^<#=)9U%3ybZ6;TE& zLIW$}Jk(3@$);A;fiVi7e%Bi&Lx;hVCCp@QWqVUf__KW(x1uvc+m5>w`XgNC7Rl=D1QU|e}q2t>vyH5IwzJ~ z2Oxg_9R40>Z==qFoeQ?c)XeoCBaaCVtwU%VaI3@&2SkTB1;EHIL+iekp*LhYOc*wMW}=Q;iAQzTjX*HC6ytCvD)yM zvtIK@ZcSaAn*MNVf6|e|VsQS&7@YqoprId}e;42kW8#Qk3FnZGi4Hg)33?WA)|zSn z=U)2J;72GY3jCjknB~8P$-h8379er}xlPeej!qf>SD5@xqy}iYe-{(71phTA{|1wP zi^=a{LIKf#e-~+w-^T=T#Q!}ee}KtNQ{W3f}&bCSF!uMT30JwRN-|!M!I@C(yXDdb6f4b}qJOSGPv4B{55MoLBSV2rY z2>VGxKff6CbI==XDrImVVK)q6-~@Jq5}_$-c^5u}Cq-z(oopb|Trhgu*ePaF?A+nD zXT{`BHj+E*_@)~vzZ0SCH$td^o+W<&XcwgTITHsq!Bw;?CZ6X0X)QgHPd9j_J8v8h(U{|1j0h)4#}9zW|wjyt^?ASM;Z&}xZdWkJA& zxaR938~`p{qgs!@E)HFvzA-g_Z+6POe==7%QydIkW$3=BTq}^r8_J86-2ceL$5uEn zcKqieQK6<4P1fKus^(<<%kE`}wIQkWvpF&};{!Bf?s(3U6P?S8h-5#%AsN*8ET&Jo zc6LyMf7DHo5+~?je2qb3@$sgN8*DDZtr{b+RH@elm1fOaaXcIN&UizjKov5!f0%Ap z>85!c97r;dW8J`He<=(Mp~KTU+%2B^H7V@K^E>kOol%bBjpIF2o+Y-JAgY(Zr~H8w zxPScDq`=f9qk)t#30nStLlGsmBwWefEm%bR!WVNh5 zdSG;4PR$MGQjkkzlhX6iTvny}e?4&)+|!ql{a59#IE#XDmS+mZShb>NC7>kvOs0qn zcsE7e(#uJzm4;e_QE6C@VlhyXvQkhl8`K*POCgW7a%_a+Eu)a%1MkP!UW&K8&Gy0n zekeWgOk)Sx3r`cpL3V*1qH>kJ2&EW{Nfa~8fcz`aHjKZ#!;Y|{^#2CNe_WpFbOSO` z%m!ngWO=AJ98pTK7oaI;<$@WVf!@wWrD45u>^zl>SR+BbH=*8JVJRC2m`?Dkz|qzZ z#o?4usv4yzRztBEir9#AmoOZ?un?TpFDw|&VsP++O}XXPotkSeR>XNCHRYw6i?`~6 zsIiTq=jGCpWjNv}tj}%9fA(#FXasTM<7qDO)p6j zg=r5+8150m88zlM>dpjdP@MulNiS6%D5v3Rke)z=nM0kype#3#f}?U=P5H^_o`$*P zJ@QkgQ>QyuewHrmnX8WLk+4ET-cQfpnENoe&@ys!x-fn7_Dyr{fA;L`%&qyUNwCSf zZ@rA%ymGgQ=(6l}(_ijqu?%!{lJ9tc_3%!1z`|3$M?$kHrB!@iJ1HmYSpv=*s z>@SJ~R{S7l>FncjWr(tif1?e-vZZ zp&n+%Dz>tCbB^w%Y}|x=57RnsnF&qiDYz9pI_3%)rwKyQRSO7(Nd+^3ImIr-;j3IY z8QiFN9?!qs2X*Ly{#tt?Kf4W$B>DT1BxWs_8kLBL^^&*hfA%#CXQ0Wi$CUoD9_H=V zU28BrJqHsJZLlS~z6x9GYh=seK(=_`@bNJ;4j9N4Fcl<{GIa76Ix{ZR-AVXq+oe0e zH86-M9#FD9=;$^NL^nlVW1bk zkq`JyA*r4ie|i`arD^{HZ9zJn8-+4Om1^7&rJjm$ zBV^GXsdfQ;1g)H)L)$+eg&V;q2hqHHxG{{+sDiz%*BiAGXeQJm6{o~NGd1YOddw1b zCk!y8Bc}U%v0{h?JY^%1!S_hLo=7_m69n?^t7 zz3UYD*R3NxtJR;PqFAvM&V|-2xn^z9LkjO3uREOWzHBNk8_K`Ov+baWEPX1`f?V>H zPeCL+QQYI7N?RH(-d_}ZGVvFrWxB)kG)1S_Sf)3X`uolJ!X?Wo3h{j!EnIqQkZC`~ z!X?DQe|6Y^p{Ch~G~;AG6*57b`O3a*g2pM!9or#wu~MooveKphjO9N>ES&AnS7e{L zv|6%j@l#*Xxb^DoPW*IUzK1pdo{ZS62OF*x_pn5tCN2oSgGBs#xVei%xcz92VED!2 z9&B0XbiE&zP&D~EsI6j`7_<;GZ$r(ILmmuwf6ebd%FzW8bdXad9L5CbjIU!(YlPh7 zm{b&3GyjWcuPI$rSDaZ-B93gjv2i4vy04Tra!lo<10lOD8V$yba0YK)KL>?6d z#ZsW2#G#J33*gK3?j869lK&BEc)S|jdb_WD>~Nyoepdnlr6lBZyLx0_Jnkc>M|->e zfA4LdE-SZQ`zeUIKF{%{BHuz>kH*#{yzPa46y7+(V=q(<9HfWo+RXCzF~?j5>)Tx| ztyv~`&A}O}ILjOkszw$nt*Rbdnp9lw{}&0>9Z7UhaIlujrru0|_yEZbVj;0DyO+FV zGvTE`9iDF{wgyNKB%1nG8sCBd(YFRsf6YJ6z*APa5@F9ukLMn@MYBL!KqGTk9qE>g| z^WeHS*3_Gz!~tMhpi6SXy^bA64KIR7h?q$yQf((7-9Eu4l!%x^zOms!bP9GM5 zQtT#vARweN8U|8XJ0M+^yaYVyfA|zxQeYb<#Wo}pC@}Gb2XXGF^& zu?$@_wF$#0&adE3M4^JgwOmS(bE+nfYQeXfRdY#-uYWN|_ zO)1bUJ35}xipa081KDQHfAI(Kn^|@64F<(+WfL!XiA6}n79kN|1k@Vf4#;at`yfY{ zZ;AF8{GXDUgvmeavko6X*((t~l9b;m5VP^uX3GsA#xhNg0~ZHlcZozOJQKeeCoaN` z^!&bnZng0bvHrjm{h$v6F3F0svSQa(M7%~9M+LrOJHjiVgE!L0e{|F@1=j*7xPI-u zscRoh7vAM}@I4;UVAvJ>WFS=Ng7`1R#A)9U{ru`&_*=3)@fzl}8`D#Tc|Y6v1G8dA z{ANltp`esM4CAza?`N8Ra<$~*ZzVVeWBDtXpufsrqv>9ox;1YWW(rfq!4IcyO<%u9 z8Gne%XJ+T8X9`zte?;$Qr>1TN?`}=~soT@HrY4Io1n;h2nZ998U&mi^VKozL@%M3= z61HbmU49K$_cjiF3X?OKoWtZzOy0&Mk5x`l8}UQ4WcZV^WccH;;NcuU6N!3~^8W`D z`Z3Y_G_e)Sy8-J5xTS6S87BC{DEc)K{h~u$M#d8l(vg0ue+n9vtnjNL@cL~)a5BVi zU2v~TKgRQS{f&&0k~0dPv1gTW4KF)G9{&~m8A(P>X}YA#_|YW&CmH=9)Ps+vi4ywg z&y}BO`lyzLoFXaDv+B4^|0JY7Y*bKjhdlWZ71%}%Pl zTqi^E)6r4ya6iv7*aCOs-8_q7dq>Bn)Y;&CyABKvV;@_755Rvw!|&*nOvs;9vcG6? z-7slQ$RAAdkJdZ-JC(L{l$G)+QesONusvlp_LP&lQ>(@eWvAYh1NLQ8@w73uDVfkW ze$<@U6HBzfQsGNFq!T7C)t-YVNKm(8qt2W?4ClWr8x7uef}$Lcb8U)X)CrbU1rNjH z@c3>pD7B6=qfUPUGm3*-qt2}$&1I?LASr@Do{ke0%iy=fjDq=hVQ?77kAjggG{(N|zye~L+4o3ejn*jr!4mCw<9iObs;>T4gP zmo|ZYRa9F~pY^(;_v^vY!T!Os!`CeSjI! zcfifBE>~Y7xt*5+B%Bx_!tsfAVSO9M8Riq_QJ*sE|I6JLUH&bHIn=Q{`ag-HJlRU3 zJpdAfiFbc;N+@CrFssE#C9j3aYHY(@wNZ@50fD(-iSVQYGNYnVdkZ|u&F$)4WO5J9 zCulxHa}68vu#xut@czu#*D<<&CHgBgoA-c>>l*G}3YtuOuq&PAiqSeE5WE@l$ji4$4AWRp$2K@calV>gcC+KM+B%b}<_ltgJX93OIQD?8c( zwVQun9}=fP-_}K?EecdEuxNok6x$2XhXQ@-LxEmEv_Q87+6L`Iu_}^cwypd9|KVIE zqbOFykmnqp%YXj!|KES1{!ttFOXK&3rs-Rwx~2(D=v8e+FY7v$jjB;L_?arF_-U3+ zex}Q5ep+RVpP6!&pSk3j$1^3&>d;D|T)=-^DUq%YuN2EgE?d=+l~TF1va7s{>zV54 z%I@-RE@!J_D|^a&bj>T3$31I(ugGoa<$a#9zTZ25(qmp~{c({;=?N|kq4cCEh+$ED zV2BY>x@VRTa(x%-qhdGe_S>2m6MODyVvlDnJ>~7&uiZ_RpGNDr*o)S^UJ3PQP~U$i z_M^Vv+k^TcVO-UY9{7^Dw5i8KZmkwXZsZ5GaOz7#HRhe^4=4qLnam5SkSl5g7>8;1G^hej9dgg!7;UmvJ|H90%$&Z}b=66pVd(}Pm@r@S_Z9R|o z*Jn=5+&Mu%7e6s0XKFW^A6>VpFcaNqc1nlh^xSIXg|Rso1XWOM*4z~@wxky|WUZq2 zND7rr{N5sIDWVW*k-ly;wGI8Q4o>MmehFO3+xUC>OwIOJ>Q!$ATVs~l(V~AF*|*%P zFI+5V&--3ggtl9$1XB351v?7R#k0W~zveTOZNFw;Rs0Bf)|Vzv+HOtY`H~&X+t-OP zH|(HRUA1eTN3+#zR|p>MR_)57S6No;@@h8iEVM;n;~aTHzgDR>gl9MEbx&5nYK(EE zTZudwPCjivw-`nB@bvNH^t^w)Fd4{&<6+&agvaH4<<*lXUz}WwR;tg`j`8%zcyoTV zdNj|I&(f&LO4SDoCLKR?s@{TIbrxAX9HM0ww16N`(_swrpiAvG{_xDSZ~G*eLBveh zVPN0(Xj{D1MNfJY#JV;oXe6_OW|upW915gbz^u`u=9OvybEsCe&{bI!%9&ZTp2pSk2* zICtjkxhu}pnRm~{=@mDsEN<#@FX^2o58}~!tRbsaf9}N@;`FJRN=JPr>#Ome9a;Va z#%+=AY6bZeO=ZMsP}YC&A+8qOU;%=0B3E}iH1F5cq|Dz211u)#NgVQOYfhHt^x=0HPwj@pV3bm}rp=OD^ z7)q>$RWOF?DX6YtF}K`ej#L0ekR*texiI%rp_ZWtzN>kDX|%PQ^9 z`xQIjQP7}8A4lZcRm?S+D5+;J1OPZvbsGu`?W)V*7G|Ic7f2s>>@?lN#AfVQBEA0^Vqy5ikYRIRu*2)djgS*$E30w1y(B^$yb zY8MH9z-|$PV$(sh+@*|j3gwE?bIL~YW0f9bm0s63w5H}5O&xdmIHcH9n`WF-y8~v% z=__=O@+5zW*(rq?X6RMtuYYe@`!M98erkgxs~NSlk|Oc%|f$?eds;mCAT16G8~yU)DPI3+@eFzmi4%X~5MPHeH?4dGBcA1p=6mizP8=1_-^-K> zJ(Rv6CP3-%rx1m55hs39dD5r4F7i~I3M1Ld19aMAn1^^lVJFYjR^>%f2s1VpgD{HC zdLX0NTE6Ydg;0rGYCznmK13|O#^ScFF)V=51P%)tgM;2oEnDFcVbD`fMlcL_^Q&U%^=+Hy`_K_8R)u-K-j;xzE<&T3rXhXc%;_ZM1+E~DlX{7bL) zEPxmu8VL3h%S;sXur&1`ah4eGhL;AZyPUDH63}ad< zuUoohl=Q4IY5;)t4V-8P61%qFLfu?SH+7NvOgVDq)byra9#WpV6T*yQKbAV1O)EAQPs#6Kp7IEazO#e&FS8zZ(733#9^b}{o0AW3RYJ@u_Oc!PI)?8E&dYkE^( zPjOveH#fkIHA9}lyY#x%G&Ufg-_~BzeqOtxeb9l^jI1-9CYzB}+VF0U#Ne|#-95$y zIPtC%1x^TC4?{>+H$!Da3ow66wB^{O{_>Y-r(yrb@8RaRVUNsE7FPkrXmI<(R2{i?ZU*2a@|i`y5uJ+)>k)>2M_kATWUV10jPLz_2x+6ql` zTibBc=xfW~FRi7U>Gd4LPrm1%2n9!4Kdd*Pz&9ISs63@^(B|FpRbWj%8hJ{@(Jn)6 z#YK2w3pE$+6ghb{xcG=1Yu+si;XDE@>#={?PI-0^!QwG~rn-EP=`a64 zCl@WuKnzZY2z(LqlXuUN$riUNR2%$V7N<6cWT22QVYLI%i;GS> zgmtJ_4+PezvqdgFG{RysJ*7d9Q?jQ9x7KlQxqj81g9D)u*ztdbTp{SR6iR$Xx6j*v z8s|E6$?t8)k2v2I1Jc{ACrJzPS=Od3ur-h00b|@K=woylS-o{&P{X=Yw1z+vj3_69 zHdC>sjxn}4c1jFpuOCgQMeKT;^z9Rdpr#(_cMUlTxi>bn8vN-t3;}b^CXhCKB}xnQ zqB8WxP~4(1NF!)z_#mn?(*C`LyK* z9bIAze~WIvO}Cw5(j54#R=rOrHOe+>oKI>L=R&1Xy|sUThtpA`5N#A7!XW}8XD$${ zJD*0bZSiOm%1RS49t>D@_^Vq-ZnE}waJ(D-&VQ+wr^L6?of*G z$joi$b-I_=OM1dhj*HjOXz`{#+&9SZxF}V(~7H*Ygi;m`)`t!Ak^Q`VMWaF z^3BhqT+@v5csB=YF$C=~ab^WRGn4$~|M+8WE28Zuoi%h}ZCm5td)KJF(bS={lm7=@U-i-TRX<&|Bc>LOEa$(_Wm(tg zibg~xDiJb_YsAA3fdC)$x+&zRWm~^|mC{voGVOG6=*e5X24|LD&QeChp7T!Ivk~!m363M*_ zql)KsW*=_tJOpU(n%_TS^Q%m~(%AHX#&&WE1-4ZR6B)~lsn)kt;M7ffw@*FvqKJPS zokkr3pkg4(c?FFH%2#m&hZ84Hq0P#En&jW?1W=eY38?;>*h#LdmH|^9ZU>}p*LaxU zwZ8)O#RG+2NE+jhcrdw$2>?I{eeVD58X{MQmwzE>T1ODRp+ia2^3P#x&1M?lV>K-( z^{=dDqI5G8SxcFvEMVb_D2G|H&CGvN9&cZsG1hWx`DRX}mJJz2L(TkpVFT*Arr*5Q z%tFC)>jhzM=+sWn4Fjrw?dB_;Ig1QG2Id?2CQ+AKFQL2(zftbn?YSF0UlHjw^X4n) zHO8PaB*&TlJf$vPWnqr@OmM7>B) z!_>1{_F>j6q8;xw^Pz>Z1;E*dpTQSK|5xj=LCxt|X&Tz!iVYC{P<06~{aE zaj!NX$V#UnVPk7o_w#OoJp74bGuQRk>BA|!GT#4Jbo-ia|EVROd_N#1StbT04px7t zaj=?2*qLQl!dTA173Xv(NxKRQ*He^TA{}X(^;14M1tvxI(8`InR+0n9nmN(++8Ro>lh_)HM{T0e+jrK1``+W2&6!9l| zt)|>zg?JC;o}?#y7;PA|pu$P(+0L4J>zV#FckKVO5y5I#=~;4j|B{KupNB!+LBr!L zoa{PWl~r|=$J>f5_v?L2b=8-&;4H02wjrC3j@6wGN0k&ar-fLrS$iZKnZF?`0zMRBkf%F%g!G9&oP(XJLJ}G_fj&nG^OW2Ah znU!%0`=WgQN*xiVe4N&Lj&79H;zU-QdE0-3KjT;UI|c)oas_wzTp4FyQ=dOyr{mu` zfg2gbcEVBJ3k>jN7EMHjl!DBsN+YHG_`%XIX!ZXE6?wprc$}40&2JM&6rY*>@OqP& z)P%I4w%VeqpQ+mhl}ac=KuCi`$if*otP!}#<| zlh5!P?AiQ;)|usRz^XE|Q0FIMQpfsT)TDa#^Mc`ZHVPCYKy*6SV59STg7w` z;f7x1#msQ^I83@CFU)3^3W&y*LUm;t(XkkC&fvd{ah!pPB75`|>5+iNC=GutO-{fA z+U#3JRkfuEd7N$*<{I249Z-^06mFR`GZ#s#Pvjgd2lHK-B=N?%`)#EGsoJ!At|4`*27k%?l3(3VMtn%R+;WjY%IL** zjeKK*yqt+khSLE9s8@*nc zyDSQ{s?+RyjR`-?WAX5rUx5lA@V#E0c_Q^RFIMkr8QY?C;7NUW&%$$`|2A|_3Ecss zD+TF`#0<_2mMig>>A=pSAu>T_8_rQJ_EREWQwV_uW|k@388RCK`ppPeg|$~hux&q_ zVsjGSE)jEr;|vb7eYcquJY6qx5#bq}cmjHy@H<%fPg^ZPZ`Sh1_K7-rk-Y;3#fn@9 zDtFf>tLX@n4PEm`@IwwGbB?%zu>d7R)jb8g9j){)nYUg1sQ_g@0-% ztOAjEpq~9A5*YFLs)vzDR3yL%9jUVD6Q9%-*`~_e+qX?Hdmxk>%bNateK zByjhvAvD^m!5^EDOEF3vE4Pi>lr(oRsFVhYULKm<{?M(9&vL7#>#3?Km&k&}^dkhQ zyDB(+pM9EEArOTD|Hm1ZJS!Zfz7whL!8ZJqb9<2EI1yzur8tz}7l|PrUc`&%n~l>~ zyG(=iLeOIfb+Rym6Fa*mG&J3hdta%ke%>Y|4Idn7$M@-Tf(*PcY zNa|y(-d8lot-GiYSiZlTF2;P9qf;$8=@NxUsrTodXW7x4@qips`iYXM?Xe#I2%axSMEfW0IpP>m65oPJkc;^+o#2ijHO7#S$vU|+Riu2w3)3iBO1Y~0 zKQRc2hnHV>>6(~(4!5HE_APqOT79YMEt@Fnnt!_nhY?yin{K5LfCvzP4|ogAb^i2P zD^$bw;58@;%9Ofh&hEo!`Pxmrc0D9*c0%yx^-fi4=R4pPggYwSXKj5ZnIOGlxcV_k z8CXvlT>n)?1@;Ndr|3Zbt(P~dA*Q)ujp-edY}yl3R47N#Te;b_bz8?vfgD9EcE~)Z;KQfLjke8|4*;;mAJBMTSKG`rP{2vGXfKVm2lco*rYC)4|S)HgWvFeGsK2!F-@noDAU-hmaDt)C zb<#vfZm4jau%|X7qYpwv%={|DXgV_nX$hM6Cejlm8~#Iu9qwUzE<>-m;EtkBHGTIB^^ql z1Ln=~-92{35A_H;p;TE0G^)-I^}3Bq}Sw`Hi$3{Ujx(%(zi3hwNzXm zpQsmU$?{U!q@@lt!%ml}bF>$z+i8MAjq~XF>QhkWTTgdJ&ATl37l{3DO!Rd?v5(xY zd&l=#Ua#&I30{Rh<$h$^{2by`>*9`9sY;5L=blN6tP5ez~T&h;I zkeRvlLP#=U0$-s4f&MXVZbr> zHy-8Mx4#icb00~g4&Q0e2_EFV5>7iYiYYlCUI*XlAbVS&lxoYDcbxYmH~HZLMzg&7 z!<756ufr%m`>MO40{bNK<8|rn89yKeaxAa&dfSFxQp0op5#P<$aba3yo7`hkY)PSi4?&E1uPM0txpWJ=MR$nq_(H z%%$>VWevx_Ut`~?EV`*9d`Hpb0mIGoB-VZjhb=NY3}?4?R={F^r=|UDYxnf&r#b%y zricXbJ#6_|sNj*C%)z%gp*>}eW=LS*gDPVIQ)_}>8SG{`O&coR_vqI}VJPk@J!R@# z=P1u(!;H!K){X8bkUq;|j0R*iD;HSEyptdaqp5a*9X)%#PVLtCMF+Nrc_%E$x~i5n z)cQ^0)Xyxi#iHr4>+!c!k?l!c=!2o<&RlM=P}aZ#|0vIa51Pv3uM<}tXBgI-R=@GBW}@%D);NROP?W z4bNxqq3OPDBTU)wvwB|E-ktFsT$kqX8o6(<4r%-y*0&I~rRuY4PUzR9v$?#tmV}(~ zs*SguMGI!@mw8{!%FPWLA^UJEKk#15>LbVk$k4J9MhsWn_(|yuENfZS(YQ!}am4x5 zM0Zb;P4RmxK3yuH)hD&WLOc0110O?xggT4WUx>h+5W0T&{!4Fycbc$*}t4owVuE;N4XUR>U zskd6f|9%u<=B!%m&=Nc-ufLT(c-$P$$0}P$Zv+pIJ7ug)OZZU?=Be1+fgrdVv(wp9 zO!C1>G_2h@(oEVUo2ChmMlHFodW0Bd(GC^l_;^r!JlK{#W*3j8y1}~bQRw54OlN6A zzBS=anX0wcBhLz*#7|X~E-*N*=lFB(yTh7wmOWs7Ze0I~PTQ_ki?AMuB17$t82lWC z8*p7wDf~-I7g@sr`PWVkW(1yyE0+!{^cUpNIk75Jc$3kO=5%Ck)m*C&PIS~IaBQQm zKbmv9RNHUAue4YD!^(0}sC#&H=;+fC0tp?~$x?*GMUf>+OGlXvATzy@ch=F_QCFMF z)>53}ZfHgg{tRJUzIc@%>iwO2Kgy{91+hfhB-yh_iP#Dr0J@2MAqWWwGq9os`2i&cR_v5g?*(FdzYHX) z9x&{)V$Y~uH|y)j#l?omIj_k-Qn~`S238iJSir#0N>fmijw1LI2TU8M4%Kw)AfkyM zb&{Ao9J;t$hNqmUrYIvCOX%v3s=LU9oUIsD;?=&6#`lEYCQ$K)K5%AeMGi^@FpR7y zLHq!lk(D+qWfu@(WMv341NM!qm>>NT50~PKxzF%*8QGuH~ zg?gTMPSS;Gb{iyEubP=sSBF0(RJA}5;a9oJ^90D>8>4r2xCONET_|)L!$L0cw>JEb z81n~b(&b$=ybw{RbZhd9QPm2nZ4-hLJ82a9TfLNe?KugVBu-$CzHsVWx_zw>b)1)b zs}@*9j^t=Y!_#6#j!08vlMg+=_)E$ffzTuH5$+l(kq0t?4{k5>kEfB&fBlUa+aisq zBzH%wNDC|09NlEU1a$^Sbq0d>>z!xP^leGOGq)v-!j5tR#y3{Tm%ejuEwvGGv7XNZ z?~|F5Fzu@OD{)tr##DDu{_jS1*wAzcc;QkyiEnct zm)BOPXoNY%|7qx461snNAC_A+n_;4L>qe)58OyrI`HfAB@e@a>d^%&dE3u%Z4p`zn z3qEttT{Svh!RUL^wqQzT!(lm(5jl0U+}n;JDs4$d0sK~Rg6f1~mz)f>M?_jXsj=e5 z?T8-<<&cMt;r;pj+=*X^?J$XN>Qx#DO|4#0LhNkG`n*;v9@Z~BzZW^kC-PU*90m)1 zm=33xaZ*T5k=7M_Lr1?vT3Wg@lF+cZdIENj$D1*S`+WM9033tY|Fxfeh5!M%7L0cF ze*F1$RNlKq#F2LUB|7_Y7>PjG&_IHp1*&Tv79I{>c_*;aAC`|tkB^18&sr$Q9!8(l z4k7nT2<@8CU68g5SUxn+)8H&59#&Hic~-oQ$~`Z&E_y5>CTX{bL2tK+Wo_S$A#2}_ z71mQPEHvOm6_cbTE^IL1iMkg3hIOc&M(Sog};n~~AJ-v|1m=f1yxw_Pf1LKawxIUPsZcLY7P_L|zX$iM5Y>N{{|+1ED^ zr5R|cGK`R+aA_vQ*>fPy?1IMDV6OXl{ipCWrj8r=W5%B{}TOI}SP z3FnP$Yte%td6!842zh@m=6}9)CX2BHvGWJYJXCt0X~$nsuQcbKCcct!hxG$7xZ6LS z!qAD$^T0_?qi+?Jh`NJN9j{m%tx}kxS&m15fe-5s%+B{!a$y6+>wkDZGFT2Y_Mr+W z%j7)c7oBZfqixen8&Vt60(URw25kyIghvxg&90teF4S|LS<>m}))&lIB~uI`8y*!2 z6-k-{^INaHVq@CBg0zXYp7uoRUSQJKpBT5E&7NHz4Eox}f4f;Vf@-p996HJjgViw; z_;dY}mxJ!#He#e0gw+q78|*lRDI^nnIs`GfOb!SstG3r~SI$}U=&fDaHEgKotWH@^ z?@RU>==qcwVbL%1cQ1$AxXh41%BPkvDrRh(h70M2$3|8%&4$gD%_lAb{wyBP-))Z! zGzz#_?~a<#UeI?GLnx8{>Q_Np$#cf_(GOs@Ey zu^e4Cz3Ok<9s(8Jhuwb}gu^J{&@^gUeia(|z&bp`TCqEirfXf4G8U>03Fk|D)R{LG zkY}%X((#iwK?<<)QH~ZEKkI5{TXSE%7Vcx^pX=)4HPL)3(RFAGY84%jNK~&L!;5SU zc>PJ4McM5q%8Xzm{4L|T!EftXucDTyR8}<^c705BEDLU{(ROZb@M?Ny)|ZSQpFgD@ zO`QafH5>#QIFa&96X?w?Kqk9Z+*=P|qDf7-hr`qhjh#Z@VA;5vPGETO&Slu_))%mT z^N;2&v5rblkI2nTKkHJ2ad*)+hU<_p7vK(e!$15T7(;NbnHoIVgnDZqeQd=7U8O*Z(d3#%dT?!vG`Y4j4j|GP~3S{gXmf^ggTkJ#-K4r&f+ zDr0qDTmR_-lV|HOeSPPl(?BBiRr`zflp(t$Fm-Po`$lJcW9(a-1Am%p!Vjm0jj3?| z#$9jG>TY=AGIk#ZTXm7mgwy7Gx1o!ow!>=k3cYon0^K%C+>++#0jVUAW~X~oEVZGb z{m)X)ANu77OWM#IL`Wv~Fk!9at)6c=YCMx}py=yq?I~T(q9qe=VWC$0KQkmsE0>i* zg=cfDh6;+~!I5v3ZapW;RJmIwYAgXUGhH-ut(^r~gXGc^FSf%hasi0jHobp*8H}Li zkC@DMXXEX|9keATwx(>&9}@)*y!s#QRbE)-5|~DR{bJW^a)hL|<6GYu$@@iR+~Lvh zgDLWbH0_)zG_>Mg3kqQo@&%3ge8d1M->!i@bpkd8HCxKjCG(9LtKK4nPUtqAHV>CA zVF01&P5KBzK_b#l*x@U7i`k9it|QTe?6EPQqi-bT#(8|Ju|iwkRc!CH=%xG~4AAo~ zU|M+5s6HOjQ-qv^wWne{tT5Q+#JxwwJw3AKBrU&(HP`=ST9{j8@$o*Sbk@XAaP%6C z%X1jnk_{>c#p;Y965nbi*ilGw;}-?i=LT66rMml*gu#E9{rYTVWCUZY(fONg*Qd0y z$G2Kn;6|McZ$y?q9<}n>YOr@>v~}QiL>O{0Ii!i8*#r^rfE7UEo3K^UDjCnHo%|dl zSYNk3Zqq+X^P{RTVc>N}*+8gaN8P+2-MG8EzDZxVF*)Y&EI#{{U&%QYgrk+Cmk}F&%hbQezJVQBVrfs#~P?_ zP}v;d_$+)q=fJ@DlP`IQyH@z7y=OoC4MUrW{~{z4x-YS2LzJ=MudIrd?2N2TWULjU zFWj$_JreBr8T!_E`U)LZf^Jz%8yLFvr?@T5NxoQEbh5z(Rx)Mm7WS@XW@0@QS~9#Y z-stkv$FSJBDW7Ao?A{zczIwd6yHdR_IJtQ=a3k&VM zmpm5|P&T|`^Et2}^|x`H;qbNv-SLMo(9b+sWz{n5pZ!`)%1GmdgoLxchxDs>@>Ip@ z%)h%=r8)ajc!|%|_v@09rfjdayjzJM282n^LDCNWX9IyP%(w|NjDrQ2QaXU&c@inI zES{n6Xq9FTr4~$_eQraAodqmHSrDq|tAj_#E8#Ijxl3WRD`#aY2{8`R4mWNrHE#bg z3+jG&&Zt|W)qZN}B&;`IT9xU39{u4AcEBaB{XYKuS@+QC6v@p;)ezQjdi>K6o&hq^ z=3G&n(MT2ZL?Y=;o_?J#iNKeMf}S!#2B{ARCq(y5nqQx8F>bZyy+VjG!F)9yLOE<_j3Hdwy+V~#T#Kc-d=(;)-7&+%Y`#-3 zOd@weI2GK9?QYuRY#ZVA_L6jF$&?@F)nRnG48B{<(8ghTSe?lNW`>xO$Vhw0uZwA- zY^4A}3DD?jwdkKp6otSAO1r&y%p>`8$hMWPXp_1b!s#1gJ3)=qFycP_d{(tUYb|)i zR;MR-^W_#^KHQQ31MReL?-z@L5;1Bz=nwzoYLx2ERE7jhn@q>(s2go*q=`s;xg6T3 zxc>$BNnyU97P%LJwE5!@*B=U!*8Z`Gj|~k(wZd3m3s&zj7fZht(S{0pR9e-^y@BX( zNRPgodLxbSyx~8_ePgHA1yU0l7dJBs&>dS{7o$23BuAR<&xg z70r{DM{2<8Z5zDEbjV%6XX1P{$^f|x7SmKhGBh;Tn7Ud%d~=PPD5zT)5E;?dzuYv= zJ2nye728=@oUl9%E(y*w4i>I#!e>0cWyEt0SHI9iq~4^w%5UXHEL!+8ixR?KXs}}@ z%4OW`#Z};e7U4Y#_xjdy^llI`0grM60RfSIRpVW>xbkr0ea6yeDWZB=P$^{Yj2;&* zFI$-{D0t-|MPTVUp^%?RjCkhnp%p{TZi^y(okD*PML4ahfk!D-a38iTK$F3EwCp^(-@h*6_k&wJD ze=N5)suc3uR*cHDo?Cjn-*Me*gQ2Zpyw&6~s^Lb(xJ;_9$}dz>20uw5J`yTMbGp~t z7!y_^3jC-xNs1?uqW2emp7283eXDwLEdtYiJ(`5-=PU4=+Fp%)uaSsbx(uwOdJJNX zmyzb{mY*JR&GqH2MO23FLLXYCen-;_u~4&aCtb1W<5&}lF*$-h2%hqQBBq8 zM`;Sfi@6vF11ssEav|+g+~cWESuU6})kWn_Crv~?t$&)r)z<;p|j_8EuW zz&{lU4bbF#)u)>ol7K!LNQjc}BSaPBvlJGOZf|)mFv;TU_@iyU3;seK$_) z1;lQeqRsNa%V{BoNV=jw*BCFP3e0;^AW2yqG*^Io8n{xVjK> zwD4~Ox}Q={G+;BDFy4PQtkZ%UjwQ7AB*avbDhuRorKbpe(zh{J{Jyrp|i8egW71VS4%JHsH_=uO+a#S*sUSroe0(}3+WcJ#Zh&3LbEJ^U`4t4@n( zjIO7H-qMGVjxUKnKTqhslj)BlrE7(!F4g&nL?x@9ZT>r>Om>l5G4_YRPnPrTy#?Vh z+SghZybwk9qF~e@{i4!83I@#PNISNe{^N|VEjO})gkeOYVZy3L{gF*mm;6*!XxL9$ zmjV@IVvxQuX$P27q&M86`Wm#M^u}n9&iyg&U2!**GLFMtW(g%p!gT4tF+-9S`iV43 zv`vTlE*`z5((rSK*%o|r;s9*e`xsQ8Z~O`owOtUJ1YWLT9XDc>=mFXYo$jDB&w>@s z4H_{ILsZwTR+@7@_*#1H&@%4)*b{^u0y4(5#= z5v=8a*@5bSX7FSfS<33C)g*RtvKoW?)XAlQLCTif`e{$<{@+}y!N@gOc|@VDNO;`J zbTM4>@5KY(Jt6;&Csnys&%5xHHHHw2JcwRF#t=|@v#Y0>dg^ileh2ETo^?j_aKNje zMTuKT>YicU2WqCrzeq*DVK+4z+LDScoC;T8yh5N^Vo&V$mctCcj`KA3uB7$cr;>8d zp)K+r(ZSj8-$JsVwwBtn8?P_GB^<-)4EG#oS!O7(k;=p&j_Eh-+k(R*?om+kVEyP0 z(Tk37D&-xrmr}9ZYh!-!iGQfeYR=!jG0^0!$&y^Er1rcT#JeBe-uCA*|B#HQP2Yix{OmigL1yI3I`Rff zT$Y^fm%U&FVpsImX07sPvl zz?ZMag25p-V~!fSxhe(Y46gOt;<&V~1ifaVL^j)vJr`<`gSei31>&u)+T!?{(8Q8? zikAW--9txt0(++ftn_(=tGpBWEs2(lVS~;SBpG|tO~2XXjWp8}Ugw02X=<~nh zr6et%DjHM6U!d4}oz}vfB?})_hWu$2yEH#{_kjg}+St2zWueB;9e5>W56M2S*|djK z9!$K#7-VS$APd){H!b+tWCR}mqCt7+Vx1Ul{hcgj!7 z@D7M1J;f*$LoE+k6;d+Sq!*uw5=Coawx;YhHjD0}7(Q;8gAjL;up9QSO_s@9P7vO&q{*+-(u$CLbqRVA&aEadZE(iJaQc~MJzWw|7V&UcrT)mba`B!e+i9W%dO3Uguq7S3!Qrf@g8n#us&ln)}Y8nZu{)Cbv zpg51AQ%03X^tp&8=1x>Ds<&n5H{~%Z*_4bW9qM5fTJq&u^78xAzaXeWr}7jQIp+Sb z=+3A_Xo+~|u;-~!YmxAme)!fbRFcxZyv~?421eQ!uNKmNJuw#M5}{*BcM2ad+EI3;Cq}#%_C7{9ZHyp#^eUe607kew z*Vnom5ZxZ<&eD;QqIFkiFgsyhtUXN^t6g$r<4NyBc{TF>sg zzTL;5mGw6qN}teRz4Cf?Vz7~_S#q%0kM-`oj5s{&0(uOMFDM~;Y`Yi9I8I7k${*v5 zFKo2d_XHo8K3B#=io4qDKbN$yOV|sanejKS!Zbh4V}-)4fRJDAB)8Ggnd4@Ja0Giy zaH8oJ5~8-ff^yqme;`k*r*sG>X~-D}m&y&R`icDTLUPpl$t^QBVurhc^s|nN`SZZc z@3r-FI0OIVo_Iep5kS2cHi;y28?rsJ2bP)tQ`1m-y;{JCVhmVA* zAg=&OXvmAUc|0oUmZN$>w03Tjn)(n9XI|%i!*26LePw z%pzG7e`f_YtlXynK~Gnsmk#z1O3zE-?bO%S)+O{$F9YWU>z2Yxzro5%tz6^$;~YbSpb#NKY*5`&`zANd0LiHr4MvI=N<-bc>9|M>``)4cn`y&}Z>Hu|n^p zP_c8El5VKIigY6Uz>%)Z5#UQ}Wxm zJ~4N%mW6Z&3(K}YBex!>jFTN-qt0}b=-&NdU{NrsW}MlHg0OzlzetIq$+nipS1!+s zwEU4|$}%O~nq9GNJ}^*D=!qaAP@%=og19=Xy-HdPu;kxcnXAPRxnK%xl@6j5JI@b@ zWEh2#H#&#lzfN|LA2y=JqT_QmEG9D_OmeNi`s}%sx`nfJ8{8ka+<`?%@fyYH5D`ms z*`Q=Lv&m%&3-Tparh_&-_r0!j%S_)Jj8B`i8h@ThYi45?7Nl(~+^cNaM$@*oBqL^1 z|D-$XRTE?t4Ls@A&$&|IGR=rrM(J0w2jRXi=~sXibC!1FDZr+}!cQ~3hdXIQ58%_n zQM1Jm$qyIc8|lfc!nxp}r;f6Jv zMal+dwJ=;Y$LGYy0--PNIP~V{=i8XuKTt;=$Nv!jh=B{)$uPC>8D_KRmzcUy+>_*w z(SwYj2Ooyv2L4iDj5)?1!?1}X3L+e_UVl(Zoivc6hDQYg^+>_DHK;4Y6RU;+U&uk8j%+CpzKO^*r`(yGGTK>*9=RB_lNvA@mWo zI>{P}5S*&$x+XEbCN2j=jBv(!W1W@-Vl+vJ1Bp-GiV&qtRXz3{ra~w3z6LM-q29ii z`lwZXW=0qBO*-@KPQ{Qy4~lgbWkl+}!-Tt}AjsvXKwcJZI|hZV z1m5TLjn1;g=k$I(CuI8BFHXGcut}nCn-btf#dbzp3x;sd_0|n*zQLyqFCPTu?!T3U zB$<`}>`Y%Zb0gF4_}IVC!S0IWwz{O-)~sQ53KCo)zuVMyDc#kuF$&@{aajC;lupO4 z`0l)YdrONiYxoP=+fd&T%oCMnbBZgaxEa z7ihBuCym2#WUp&Jp?PX266*X=j^E=NgCxUd6&UwNmHAFKCd?Ec6sDWzE)y%l+X{NQ z#&B+04AF^4)umFMySr3nUqxd43YQ3X5L_-1m+@;p{gq4y+rd`*v$cMga|lI4(jVQl zv@xcCXR-pju~cH4Vn7I6Nd91EIxXy@%>a`No4LNjha=QBYkBiahmxFK-N|pTOprg< zo0wj9m)X{P8fUhaKZD5&ElkGR=7p`glD;=hqYreE(UtiG1#t_Z$q>57YV`#CyyGpT zI6oQsJ+~Ef1U+B9AQDZSTL(>Li^G@|k{C6HqatX4qA|N+1$O4IY@xFHb^cKULxZhs zffTcHM&jrBHd~M;>*rzD63x#%`kj!j^u|PU{T!FC3S%oOuG*SB+Q~d0{(Mh3B0B*B zugDD)q*O8obEp%V3-fX(lLCrbs0ez|Dlj&_TWOEKj|h)>cI2N4bzs5iz7Zm<}GERyseH|fC>Bk`gHLGsd*s!DLx=`he#~Wb?Mo?l* zg!)|kO>T~>DknVBkpx5XHNKN*RokI=9OZe%sbMw;biZ{C(a8qq%T3eF#A$(+@b@K_ zSvcpx_k-@+Av%%iBGX^os?Vke&v-wjH2g<%Dr!N-exvun^N;yQ5!9*{PCotw?|kWWb=B@ z(5jDJwX3M z_>fW+_zxWY1D0Z)K9XB{n)bYJNrm8~G}!xoWq*%S-Lb^F<_rs%Rlc zCPIY8Y$0=Yt@-s=7`7m62)LXqAf+wv*!sQw-b6A)(Yo}Oon78AZ8eo3|Mq)pMkS37 z>dw_C31UG}Ns%;;vt9VKDpkT>$dnuO!K8J!;woO3G_403N{g<(nQ`U1BX&aMhO|Wg zEA^Eh(U@K?*pI$V-zCT6Z{gLG3xBytoGRRqiwQm&Eg4aK_d72>hZH^0+|&v(xtG#U zUbEm=M6B2+Zo1-Eg?Hs7J`zcvqg|^gRP-Vst)?b=%#ct1<{W((P1~bkPzCw!NmxsA zG>e)%|2a|_O!*iFM|i?h@*(f(&r!2?*$mw7I%|k`a{Dvi#g(qwr=?kE23a|ln6xzy|SV4gbwpnmXQ|^w5vf z320Fj90+y2{0r61-k3GaPkLdvg&roNq5wKQvrZ2TX3=)|YK_Ce~&h_Ox1QJy6)a^>JN*oSb8NHr;Q87 zJ9)f|KLu;Sh})Ti5{ z)XUx*<$kT@;VD%S*Rg_jpxfeINaEm4fp=qBX$C0i{(<^@DJUjQCyK`41lzoQ3!X zS?NB;ZKr%HNc;f3F$1qE!8nPsjraXDr!`p}SEx65`|UkqQ1|I0QsDsZM-rP4(0_N+ zRLAp(s&N;nINam;Vqm;_A?u-(Lqdogh(_wmH=Q)lYie+R_2p84C9M1dIV45fCC@<- zM?={ou3+{zNmk{_N_I`_c;k|Q+xU(#3E_mIq;p(~24of&t;Fn3^LyZNkae9Aq%VL;an!_?JL0rV2_=lFW6q%)lD1H~ zcc>+S{3)T7d3UAgXkRHK-iIkpd#$>3@857{K2wUthVqhH%*xf1WA5BAGCebNpKw1d z-zc6FYY`PAx;dq~B)~u6^{iRWp3U_QFJ(=Z5JKiBvUB_GKF;zjOI^8I=nWnY=OjjB z{A}$n7ZT?_B#D0^>e`0n-i4zl_aVmB3iVn3gyo#|cEIY{Ygc{T3Y4!9>6vWrAM6Wf z+f~~bEvJKb3f}m5$&L4tva#9tY?II_Ah=~lZ#Q~!8Y^Y^QM|VbXj&29`8FWJ&%{nK zZ4Rj{{*c)8!;a`NEk;ctO;m8@<6L4(`4O^Q#ds=tdo^n-$5UIU5k@=vE1s}K%F?sI z!`I-v0y-3wHznE1_{6O5I3oKk4lARoKQp!u zhvD_YJoyZn7n06*$@^L}oNuzX;OC3d?!jO6Awt>eS*zyHV(5k@9};(w1(C2X4DfE$ z(aWFmwb4eV0F$u??nh6;!kI6+j-F0;Y=fO-*1=>HLIER?v#Rv7ObRm>Z}0oe^rsJy zEBmwALQ+X1T3_3Q1``dT=VZ_1C6Z5zjcL7*n8N3YBiUiR@3tIu(^t%Ez@os5*`j~2 z>wX)0lz3g5H>CrI{Il*j(>@W;;g|6uVV*(TojLq*HQzdQbJ{Vl*YR{%)Aj6EAHaL> zMm?@k1OcD#XR>xq#&O#fVtjS^(dzAxzUg}Rit$OXsFl^50wQ9eH@$>+?KvWsMJX*V z6;wLk%#u#=^Qzv5=Q({3jJgZmA0fpoJXd~v%MW>O`al!uO26owFza?UFy>J)Ak9z@ z$S4AYyY5(MC%bRRGbMr?&6LXl4mOo_uLC(@0Wm#;OpdY3Xc07O*bN7jDmfhpheG#` z&79?Gu5kENoxlsmAyd>6>U}!REH2l&-Qo9|6*kP|fM|e2C3&CAw4NZAM9F)v z+KflJUg+xkEQs&$QJnB`(_TpYv*S(+68FlUBWk3yMe;Tk2R2T=s7kr`xy+%n?k%2E)g^C zg~%N<47RXTTiZ3>`g)yy33OO0pGH*&yrywuJ?00L4yVCQu+S=>%p2 z9i};hSrKuIKrmoq;Egkw8RQD+IfJP{1c0A2m;!VPWIBV1h)sxLVZe{oN|B@pco;A(-aoZNvaq)^b~Uy7uK{(LP);1_9}dyN)zKDg@*j2c z4N8>*pWMOW_*VZ02;R!h*z`YM3pjHJ6MYyeviFcDqx zGXe~F0rc1VJqp;&-k9Cg!P)#j2SG51FyM8d$OBAEx}sVB641HiB+m=ReD!GJ5U{|N~a*xtp_ z+|>2IvV!XVazX!aC}2lpGc#v%m;a3hE+EGX8W9tq(F;t4Xq|)%1D*obyuhT0BHy9u z@HB5|@>c^inGH~Tg9%7XTA=AYgMZw?+j`smuT38SRc|mkNEC4J1{1>~$pTSOQ@}$7 z1qO@>|BoEe!O_&g?0>NgRfAH9sQ*yN4vwyl#?CJPBcp+JXvwgkBH#(?PT=AYs->3u zSL}uiQZ1-OaU-6>CfJIsVEyK~#8EpT*#;X9zKG2Cn1laq4iTQV;ph9V^e}ztN z4p8ZTK3FoK6h8XDl(VtDnZy6wzXRHQz+|8oV95vCE0X}cFPIfX19165=R+Hy=?m?f zX~5GLI--++3}5JgiU3-Dp~L(d*zkppXeI#B586}G0J|TQTLe`7z_hSPVt~6Jl#B(w z_(9#=1D$@*+3pV<{gnyGse|+XIu33G%4!k+!y>p? z*_wO)*A!jA-XBcDZ+8t97>WPeA{Vfwz46}}{?9@&!iNq6-v2+H;^JUxWB$K@)dB7P zU_v1>Td1N;=Ko}Ng@)Afzs&vBPznz79}3mwAIj0$-0?qp2*80rBd!c^LcpY;aX{fY|_O*Ea%ifzW}F3$O-4S8MJ_EEsSRU=RqV zL|RINrg=d?NFbOB3HvkD*kJ`q1Hp8#*S~;?KrjvL$R%(c2xh||`wb;M|6OJ1(}KVx zz=t3(E^NvbU=Rf6#ux=*!+_@q{;40$KlINaFg9#H5il48=7W_Y1z>}rW#h3xW!nHx zFtmg_SwJTkOb;8U1_TC!sbN1@0pEkcw8GS$Pz}q!O~v>(7ToMsuC9)6puzZOxsmsS zDn#J^DU9gd7U|jZy04V?IpSAcN_y6J99i1Ia{x@ZpQlL6CU?dpY&fRq20$MsO zUn4*e0;YrwI|KMbz$}OZ7f{Vlz%m3(jTHC?n%0H|5<|hb_|E1|Zssok8-|MyP_7DS z2m#Z8HYy+@|g4to=-vI`p&{*iahhF0b5}-V6tR_(R z7b7fy#ZYK$e)*<_f$4~?Ay7%vzr!BZ&F#OzKoz5i(&xnFfbXc{#AoV7+4jA zNTdw|!&V23hJy)URn>sqaA|Zkl`tflL)a(T`VxZd^3xz2_ z<1ZWmX@3C%%*H~c4r~BH9Mp6JH2%T^koFg@fY~@Gxg-h@#6!(>K;tj;0BL`r1DK76 zlFEDl0rbECsHu?vHN)6}w7*!c56u3>0UCfH5lUAA8h_ymNc#)x!0cZr0|=6!8Y^i) zBMHobG6w_eH46iu_zj3l0yDsxmjm@l&={N70lR-?9wz`pGFS{;LyUkpdP){ptksiZ$x*AMhguOoF(W3}ZU< z0F0)9?qHV{x zIPX78tG)1JK@ZR|k?UO8%9u{ZfHYVrScY~Bo^^hxu>y^$GA^?>owx!>T(lKQVgyIN^tso1LecAKonqLCD6gGwi46Fp!V3iFX3y z?PM`Ss7}yFeR#0rGhyG%P}Q z4811m^QDT!KQn>$)HhgckITj!&jae#ybF5-(ii`~00#s3{PtvCdsebu0WOjiOg^X& za7mv_A?W~wtOD=3A@Rc+7MNbW9U|plQ#9~Q_cP=I5LR#1^Mi;v`E7;$ zY(;?;$rukZFfueSIWjacHZU|aGq=g7Y19)5IWjacHZU|aGnb~jX+I#I*i+xyM~q$SGb<>O7=Vll>? ze+%_;z13vt7ni3N&C%J6knXHBc5v!%Q*-<><{{Cz0a7`Of8UAQx1Gyz*VHq% zmu8FQVXulNwhGHgIZj(ZoN5kJ#2~{S2whJ^mx1frX^W zoR*3J4AL{9$jWicWa7$;b>sDe5+j-&f9Ah8z>`RfUjqf`d^Xn?BqB#}&yuffI^5{} z-Nbf9_Lh8iv7*w5vE)WmlXls}iO9gwjuU?`6hG+~Y{cmm*F=Kw{}ZOcjF44&%9>il z{QDuk1f?g@biSOga-&gN=8VG8vc@RwxnDt^?BBe*z?!@JJU1-Db(o!?v&J1Te})&t z_OF9>7qo6BYes47{7ga0$HNBB9#>-crr*e)=VLTj<}?01czs+j$qRhfdn>gc1wjHi zF*u1&%2^X6^+`OWSUoB<44isAsYn%bdx?9nT_PrsmHnhz?jz(#Gurl5JWsFb(e(ak jB}uuzAZIuX47bF&4G{z2IcTLUJ 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ℜ$EH)MSXX$(^NI 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%0Dd72Ui-D$l^nLdmVR=SJ2NH4=G3onat?T{)=}bV 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 Ry6u*mCZ<5$`OnXr@qdjDlHLFS diff --git a/tools/get.py b/tools/get.py index 45f97d62f54..6f42cbaa577 100755 --- a/tools/get.py +++ b/tools/get.py @@ -177,6 +177,7 @@ def is_latest_version(destination, dirname, rename_to, cfile, checksum): def unpack(filename, destination, force_extract, checksum): # noqa: C901 + sys_name = platform.system() dirname = "" cfile = None # Compressed file file_is_corrupted = False @@ -223,6 +224,8 @@ def unpack(filename, destination, force_extract, checksum): # noqa: C901 rename_to = re.match(r"^([a-z][^\-]*\-*)+", dirname).group(0).strip("-") if rename_to == dirname and dirname.startswith("esp32-arduino-libs-"): rename_to = "esp32-arduino-libs" + elif rename_to == dirname and dirname.startswith("esptool-"): + rename_to = "esptool" if not force_extract: if is_latest_version(destination, dirname, rename_to, cfile, checksum): @@ -256,6 +259,11 @@ def unpack(filename, destination, force_extract, checksum): # noqa: C901 print("Renaming {0} to {1} ...".format(dirname, rename_to)) shutil.move(dirname, rename_to) + # Add execute permission to esptool on non-Windows platforms + if rename_to.startswith("esptool") and "CYGWIN_NT" not in sys_name and "Windows" not in sys_name: + st = os.stat(os.path.join(destination, rename_to, "esptool")) + os.chmod(os.path.join(destination, rename_to, "esptool"), st.st_mode | 0o111) + with open(os.path.join(destination, rename_to, ".package_checksum"), "w") as f: f.write(checksum) diff --git a/tools/platformio-build.py b/tools/platformio-build.py index 1ece3afddff..485879944eb 100644 --- a/tools/platformio-build.py +++ b/tools/platformio-build.py @@ -213,7 +213,7 @@ def add_tinyuf2_extra_image(): LIBSOURCE_DIRS=[join(FRAMEWORK_DIR, "libraries")], FLASH_EXTRA_IMAGES=[ ( - "0x1000" if build_mcu in ("esp32", "esp32s2") else "0x0000", + "0x1000" if build_mcu in ["esp32", "esp32s2"] else ("0x2000" if build_mcu in ["esp32p4"] else "0x0000"), get_bootloader_image(variants_dir), ), ("0x8000", join(env.subst("$BUILD_DIR"), "partitions.bin")), From 87c0e7763da8838a4af19ed1196632882e25fea4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 18:19:40 +0000 Subject: [PATCH 011/409] change(tools): Push generated binaries to PR --- tools/get.exe | Bin 6943192 -> 6943192 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tools/get.exe b/tools/get.exe index 2082c7a4b68b6438c4f43a736a9d1b6aedda614f..5a1d7b8e90bdfc4b62f4342528b68561dfeee102 100644 GIT binary patch delta 38672 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 Lb~fNEE&TdF6Wwk$ delta 38673 zcmW*QQ*b3pw*cVSnrLF%wrx8*wr%W~C$^o5ZQFJxp4hf-{`>HCbv0`BOLx^;y|(`c zeCct578fDKg54X{E+-1^+WoH%n#WgazEsMDEv_Tq4Y!fhsqDt zA8J3;TU$#shL1sK!~J43Tm53Rdc~j{XD4?oW|~_?7qr-5LGM~UH?*|afTdfSdT1<3 zgKf#4`Tas|G(HQMSs77AaPfllw3Jo)!0y96UA(8b_%yup|>#X zQ3|HQES-b=pW3ofmd5=7wEY3qe*>!f1B?F#7S+G7b`J(N|DCFqrsqUG;+$ujQq0ce za8dgdX0Y&Tex@j@=&z4IND3r-o-Jv-krEvwNO;N3R#9c!0ZY}VsI%3z*<0%dnvT5z zsye)b@34Q9tzun0C+shM-QO37kgh4*JkQc6mymYkQ{6Is?=Zu&MVI2#oBN+`3VB%9 zBbJC1kfa@%ys)qv%NSnp5LGsoW>QVIzVKQV{!BPI0CNfOL|(_lIfgIfSldgh7Xiyl zR{g@+VECm+zt=&cq>_LF>KJ!zQ%&(3jZA=M7=;=AG!s{VIDS#}XBzI0-a zQsf1kT$a&a*F{VYJAy?_COiK{OcpyW2K&V$cDsS5<@A;atNV(e#AX=|+IE9+QWbsc4r}7Y{ozZkPmtAbVT|7Fcdz!d??J>kXF+Ff zT8G1HHDJeJRtiB!yLdOyzTA7KF6@5K-M|mO^&QlHmcw7af2ZJuJL_g`1rW(zX*S%L=9?6^+SzkcN6jbBR^|R^x8l6rFQ$qwucgwRP`l&| zXj(q;JoZ`X>0f1jc-xt~(JCLa5qQbBjm+WH32gi3pxgh*Q+dl~uU+=#^E~IUpRNA* zl*mo9{vznnnT{iUuJGsaO*xBuP7|1}nDFX#!W9%8_7*&M*7&M%;y>rd>kW0I9u*v# z)x5t?`uG45bTIRa-FGnZi{Gzyt~KqB-oG}p+k2r{X|8I$^{LF=tSQl~ui1Tx`RIzx z0}>t|XKB?Mb*C)Tc(4jO7{)ktsb62>?euwrpKpEmqY3JEB<@##_2lHW=cVd=cK-Ls zv$C9hh3(&yo7c`SOK8$OVuW~(U&ZP27Ou_hXTo}pmVKq*?;o;^V?pp;!r7qnY4tcu zqu?-IYxA1%UVW<_+d5%odgz?0-)|iQ4_tLAXTJg{>Kj~h>g+ol+DvoW_}}{KT2DI= z{J}a#+kagdyC)sl$Jl=wY9ln^>ow*hh}rzYinI9dop|IjM*DuwyXAm6V5rRiN85x?&}4H4t2Qp3JK(=H;p;>H#5O3*0Tv|E0EFr zaCCor>~P34ceo8`!l!7=cg6e@`q}5dRipoo4M2R@s0%^3528}scL{~Wx_ z-dN*RL(s*~gl`t7+SiMJwCeU4=*{NLkL$&UG}{b*6`VUweK+48n{$C&!P>$U7z z$uqQ7X_|z(4RNg$?CY44xk+fN9_-xr_d&B#h5#^=b*fsCgd}KzuXDBUd5)5gYlp9}Ieuz5`ulSIeZp!zreTOf_LEraQLnfZ>{Xn0#Lx@|gGDzIThP>yT^@28GblJoukCSOMFl z*7NvnVdwP{@}+}umE)d3OZL{vS0n}x_*Msu%1k-vmpYe_oX0@gD$&K9O+`R$bGE}` z$_G9nOYYH^Z`l6zfs?k?H1skM`c=s(|CPawLeu4Td1Hx8%_ICbM@8i*qKdu-z5g>c z`{4FgO$`*|cDX$*&C@=+^`?MMLH5dME4x#d^|9n?+3@W=54%4wZ?hq4r}Fj7D7xZ1 zJg&kU*d@&m?3$A4&0KWpsIJf;tksy=FQQcwAk>@Oxi$a1g?rqR#O1;#BoWkU|L)A1L{(}{lZUbqK7u6 ztaHBSP-Y3k>e>$|vlQxB+u?AjOEIkGG17fz-lD0u{Zt;EQ{J#$X>Z`8KK)d_vAqqQ zT$XvMnl{{h2G#z*1r@yeJvK{8G?sbRNBW0(PkPn49A%LWGLaP@(bj*viYwj|J5qXz z;k=cXFNV+6p3BZp2$n5;?3JAx6PIPwHlEA0TP5Ab2!QPJ&urAn7@I}*vp#BrPgTm! zNvP}~K5ElXWs}bY>W%!?Wlx)BV(eydnHN4wDA&s8Mzi=885IWl>UuYY&eHFzI|F|Q zI#S$N&%Ia7SL~{u>jj41V9xieDz!NqwnyGT&e5to8uj}-65YVhgR9Q9t_`<_-pDF5 zBN!cTb%E_Xx(*iIX(^5SHm_fHh#ym1^(oQo-pI6?CbYj>AI&xFk*<~ATb()YWVU-B z6*OwDR?MoNUD^R(D~DAc_43rdR zJde+@4!lt5WnM4QSYl|_@}MECSN;4l{gZjpxdcqyDaYJWXeM*7SZ-0J-^#J}x>8xR zN;~_?nK-^ud0+f8ze+LB6`S7Fo#s3F|F%8TYbmp}?#_}!aB3o{`c+xuYRf#gYML)< zn(yy4UwLM&so#Go7UK7hRho_4V-=aVnL5U`<-;$T&cwA2>ntO3)Hj`7x$(S-u~FS80KFQW0N5lX5wgtK))Z z|GA2!u7KbDXX@%(YP>KB*6%okQP3NzSgvIZ^TrR9$<6v!^7pq>dLHY2lA(o#NW)@y z{VmqW=dW$b^SMX*smuIH?5DpZ^ttdC_*FM9m-`!Lfl#^R_nSD#`nV$PvLHE^>f~wO zZz>wAR00IApyxHV>5S}IyK<(Wv$*;wJ|hn?a=G#wD9pvY2y#`STEvsA`=Zw{L9@HA8YKyhyJ z#^d8D2ClcfWSN%#IFk+qJwt;Y2v?v^(~A2|S*T4_jHa$u1n)yf?t%Nb#mwwzK@xSW zC1)avr@}>1-?|2@+yH~{hyI#}7Tk<0Q}1|enMgFzz5EO{Jwgr<^VJHPt?OgKLl|{+ z$nbG=0w5PxkN}o=ob;W+U2xVZFl}CO0$51LSVluzT}CxUPg7?7j_eCBdk4P^OtNuL z`QBAl(MeHNOIHn4kU}z&z#5R#KPeD2V!hOVB_s*|uP&oY>)E&z!b5c?Qh$)pHwEqu zH-m2KWLJ)*-PAlGL-fdw_mdS7`)#zB>t1q#+%1feh(v$iRR_fY@kHhu=(j|qYoW`j zE9fI45)=dUmy(jMBi~5uCCCl*fX%raZ&~{O_(1-a9_9LGe6^axX{rupSY=q1xopXM zeJzxXgRmSByci$tdSBVjIP&%uiR-2OSR-u??+&kqKH^KTpA49eR}{5H&jWqCnROg` zE?7=LNz=6v`K$a2Oq(kQ4!$oT_%0XiYp%?4!saXjX|_xK6R!#XeXO^9-RFIROME76 zpK%Xy@YU;1^u|B;hxC8Ho&lFMMZZF8zwm(?lx^P|=QrO^jU2)st*d(mpY5DR{k=EK zz(cujj}Psf-8V*?Z(z^ctme8W^ML6^lP@|*4;4JR=jCrRq?6%zi zfKgB%mo{#BWOBbb@=okh=vC;_@RdllD#T5xSio?F_`DA5Ek3#ltEbYg;SP;IUKC&6^=v&F&*^@;n(0W{OcA=_&ncp8WHs?$K;8eY!ys(o|K4ML7JhsZs@qO|&c&BbUM z9cH&7(Ds6m4mNF|Pi0|xr9YFL#kmPj^;OaSqxr8(j5OS;m`Fc3A#IpFdh4|!T~7t{ zj<0GQIP{3ju8i(dcP8$HcEe-Z4HiFmBM7b;VUlUyK#t+wb!#Nk#c*WwMcywn5vlt; z{}r`Chef?qxlp0)HtSkiZ7r&WDzRT`l2vmk!g)HTQDUv3Nrz|9a6aIgZO1RAUw@X$ z)*Xh>q`mPNGz3^|#C2PQT}nKJtPj;#tPffPPV*oPREF2I;?3#!%2EQrsy4w`(Y>N0$~`H{7kJkk7-yXz7cxfzAj_$?#=)}jjYYM?s)Q9;XqDY#!$^vpG^#8psyuAS6|s*;{w38 zmCm)(3*YOHsJ5inZkpg;AeIP}QWF@+kDJK#e`mqL9ddB-g!pb_O7Lm-RM~g%HGb}fXHxP@0`vBmW`lkh8QSgxY^ABKkgRcfiGCMG( zrxHk1WQkucC(=lYme)?&qoU&5G7K5~>#98W$R*Ic#{N#84X1j|JWOnTd$zD=)efv;QofiQ%8-m8X=SGyJ zK&)12#3uS;`iLr^ry-4uo}@CI%wQcNh>z$Xm!-Ok{no9gpHry7*G)Z5JI_U_EwLe$ zT(ECrRR!wfh+gsU%0}v5wbsbAQf3(2`DE(6mQF)u%PAI>rinC%b(j^f&E0Rk{=XUw zxdj^WIml+>P`-eJA=}xC_6;4WFGml1NOK5kovt98)FdXQf@6VLu_z3YSvPJ}*&8}p zrrohA{n!hZ?(w|EhX7J*CyI#apz+^_(nBT<(ep?;uu5{H4;S9{k`f6rEU$lwn$IUr zE*P585Ij;$g3>@}6Y-#dC8`=|cg0Gw@p~`Xbx|1L?j}YQSRL~fn)7&bVQLG#M9Pro zTJ~dZ#uCN${bNYIyf=nBGiyTbMg8m^96~Y#rXq+Cs*9dMI_)>@==uag1wKp%wR}Np zmjw@1a{&ujDt|qfEkq1Lxhek%IZ+#m6Y+3>&-5d{*ow{&*VG~dQKV6oJXUR@5s#_{CKqgLgz6B; zQQmm9aRQD|@~y-fYj=BK2gpR6oKT`Vr#3WOl6|7G9);}!bBc<&49|Ww4z@YL!OW2~ zzhdzZeedE3zMTvLIec2C8JgFJLjzI-NBRSHEc?_$Wdm+U>{jhE)uYj6w@--8{Xv+m z4%(O5sA1!ImrO-1$e&dPz01el%L7xlRHaU;VCpgA9dWLOOhXka*N1$`hKy#PwAXsz zq-756RR10on!L6#P@*5a5ovq@KZAH4|FYk~{nDJszz-GyDz^L<#b@qne4CumXY4;@ z^#AojUW0k$qDf>1r?)ynitad^deorJ2{ZxGzXlR}>P^xg)O_Z7R*SsV!FhhpfOPpk zM)%3~!jYG9GnN7Zaf^zxYNB2qVwq?@t;gHrvMztFM-2lINUHLswwCQ{0 zY;<<-1tC!fwAB1I1yShzZ0G8}arw8zwR0YR=+J+DxhGn@0TUtXs4%! zZR?()gtm52-`zY&6;P8HcXoerL?5nhXS|cZQ00uex0Ft}812J;z+@3cluA!68r<)- zea5EeP6H}+LlJqc|E{Up>2=`?X-36>hYrBkrf=Le|4RV z4}6CXZd;0}8BK|846jSE_jGe1A+ z0X@bE6pe5{{s>->247;6b*l(bJR}?#^Be9Hqn2u0(V48!tTr5LmebZN?^+GWOeLG~ zv5b`bJ>O6gk`Xk@(Vlht@;;?H=sU95g#~4<_$;i;`C2P<>qyDarWE=Fx)VZ&XI_yd zH>Ad8#QRMfnkFV%GP(@cXxjQfLg1@EUo!KDRKkFZEePVc1aK#qsa_1~5_ax9hAEe>@eM|@ zz*W|SPG)aGDTXS}!9*q{{7Q!TlLLqeh3fT3A!H{wW95f5jm3U|*r?Um+hyAa!_zlb zrZb+YW}v!b?uIiTC)VkL^6A_!Q=V=(d`pPIEel+*X?+YFaC@~k%~uQbcV#sQdhu5> zi)?(~vf+i7p$6tE@dZb-cCoCsZ`p!(AlIYRbAd^PuFJ<7zu44-cLsa3GqHROpM8 z<9kUM#PoF#v;ogU6Ng?>4WRgUnxHDSPQlRVPI8XH&`QNlB^LjLtMly9$4dT`dpkp& z=a)q^39G027;TH%T}5~i>o3R;wlQS5a#({HGOj&VujR#%4h&J&P19>uKCGZJvTwX! z-|()^Bhx%1Sc5iL4KB_iz$ZugFSS52<>+WJ!-CNG>UAfnm(&YGm~WN-hG z1N050^niFpT!R7|sR#J47#q65LrSs|BHRvzUDIOe;O6ehocrR-EVyFAF=Wyuw+N&B zRke2<8)`l{QTp&9GDs)dDXV;;MX+Va%=(4UCE*Am7u!|vAb%MGV5l?1^E`&5>&?E# z^xHaqq0(g?%n{#o$pjS-vRip=dN*?PXQAR#=A8pgj>`6QA+#J%oCrW3UWD+b*#>b*OJQ5IsscE=-XQW1v*tdHS7lwFqp zJmgljka~55w2HGMI11IEXS;1-QaUYT_*jzmO)YshuS|ZWzHMF=3S zqm_KP@Xwng(o%9sxtW}pY{SA3O?FYJKbP_e?_c?G!m;B4#*7tGE&IZoR&de=4U#nP$xP3c zg=#4BKtW=In|&>qe*DGgB3x;~J<7e>SXwP1+v1O8AGqurFF|p2Xprb+#Ynxo${#o zL|i?#M9LbaVxvNF&d|1t>DU@y9O4M67gE;!nyE6SNiprAX&H-#Uh?8{>S|2mVLi$m zFr;gW1An1h#?6e~(BrMC^|>3a`-nr?hq1sMLHRRa$4e@@e%1>UUDdZtr^#utDyN%? zNU*1Bv9SXu7m=~fB6fYGa5Ue8FOdof6U|JU#yzs*6o+cb!4UQ2OeS#yS|Gd0N2o^B!apRmf9SM+Na%*1Atvm~hIsNM5K${b2crCmWd?u( z1-*1{k*Wx$kVU7B+)=Cv9tc8PkiABp_Ahp0D`@`FDxKXVf*LGD2@WFFj|wW?N$$SE zx~G3400hTl>nL|W(0vm5AuZC{FW?=&z;Mk**H{V5UW+cGFSz);{_>7UtTe@`2^{nL z<$1Hz{+IjWxvi8e+v8(rv_h{wkxMv`hR6!Q1p*NGjx_u{uKp(b>|KOPKkKyrYlrVT zftFQrPt_c>F4u9A%wL~p_HbJCV?UnJ2%f7{8g%45wtHKKgU35Q>;C6m{ZF1}CYrJ5 zgyHtAqZ56F=1{z~OTY3C<()!5l>J%OlhYZG!KHcHvE=Ny!uR#1?7d01;;ly$ZmaIB z2H2N20yv__I8T`y=J@y4F5}jI5ohT2>ODn&+_hP(i=4kN-h1Xyqj}z+t_x0NTep&w zmc5VmN3nx(wVTMb9HX^^;|Noh965h@kD3u4qx%*Eh+BxHj335sO>E&(A;5 zTbEjtwQ8zhRJ|uM2O0D!5KUvyc({9)3E1Nl7q<_rITyITvu1a_-5H63W=j56$jRo~ z@6mbCduH1Nv^kDU`&~uhvr`JVO%FGGdsTWHjT`MNxsjGfxpYY`dm-!RxGCo3^11w_ ze=j-nUN`tc$jdF?{u%qDm(Z_CP~-nBhXx=6+gN8f zM_#$U!o_veli=Sx-j+gq%6tAJ7h6WG1tWcOKJRBS{5RB&+1zhJls6}9w3*}0jfXw# z{AV+*QoW^(dWUC*e3dbck5h~dNi&K#|4Oe`3l^eYGi|rv_)Wh}`OqdHUtH+1w|YezX18dJ_2^-B5O291u!{g2{d#pagXG54`e39((~0G&1kj2}h-v_0SV z4vPR?Q&}blOe_XcN)V3^5+XcE1bi(QGefgJGDDBQ0Uolq?Fs`fL6zz!+0pI}TKxlFz%=fLJ640?xu0gV~L*aD{N-yncR3Zk~=@F47i8Ys5>{g#v8Kz6_} z=)K|2ni1%-^7XrQ;ke}c>3o)GEXv#U6->LJ`Dc&@u}wL7!H)Bc6zeFZ3k8P(T!Q^Q zeX)sZz)XD7@-KvU66wc%TQQkOG)IAnTr(4@#dWU9{#PuY*c@QUJ?jN}R>1x5b>0g$ zUhr<7nVyN61{X*60k{i3AA%Z*^-kNwZV*jMtpq(&gP=-_brPQhKkS+jt;p^nhW=%) z&Z*M;X1vaUnt@kt_n2;k<0Lr)ja0TLxK5-Jg?i0(&D~RoEc4p_SGFu8&RyTI>4w!k z-_+@PFRnZj_zNIK_G}~P8a0|K9>Wb!x?`HsuF)ZCxhA+ z>T^`VF{Vj5va`n&B!wFB6FFPDH^?36H8|B++W9$^AtgTNqaqa?)tgD6A}W4v=%HJ! z4)P&%!E^}=^jC{o^}U9PBc%MGr1H!AWIlVobE8VvIXQ4*bjuiW?f7<|+ghsStY)>K zT70*04yg=LO@0MNDKMk_Emv3H*$)MFjWI4p`O~fTBw84B|EW^i2iNQbqUpCMafO*U zFbTp+iN4xvPl`zmSY`kv$gi!60aEAJE?|SP1J`kfB%YkWIxh6$eeeQ{8Y* zyx`Fgb{-f-7$V+#aEQA53S)c%Fr%hChG(mbac%>9tY@+0BjZOwD83y=v6ttnw0}vl z{)Ntx9vLN>v{DY3*3(OOiR+wIfj!tP0<)g0ZzH3k74N|Y@|Pv2X%0+KjJ1=;7e`o( zZyx<)T(#lv#SPe|=;6fyf)EZ9q8MyzQKxA@hyVj{K>F@}o-r&kLT5>^S<(13Zm{l) zG}vr4zxm2OS0clV-FgBOzZI2wSXI7gp84*T+#sJz6uBO^jOk7kT1ve%SD^WhFS7 z!8AN>06u7A8V@(X2RJ9G0V-sp{dML;xqU9lbS1xYMU7-ff$fCsk9}DM^GR891fX_)|X#> zzlI3oJ8rHZcB571aG+QX4QDwK+Q30YKpb-S!MwL?Lbf$-%W#Kb9}Lhcx6}!vIBpX{zd}%g^g@WR0J-hHZ4F#zTV3a zmdvz8Ne-;t4HqFIH*O7h;63w`A3o-(Se*7Scp7q@6bJ_U1u<-<=&5b_#pl1eUyY3w zi2(|NhNeKY`#akQ1KFN4D(hrQI^@NY)klQG4{XgV)hqhZYOyub4X`-m;s)3Lp5NYINWpilndt$wkCb-pphmCBHMR z;jxAexH$F%KOQa;9p;Ey#8Opqsi!llTeXI)kP3T##V_d?`a5pOgXlp82pUk7dZ>d2 z=yU^Q=@Q+l2Kl(CQWD>o~!vT9T{Gu*DWy~Ln|Ot_0eGQtDeW*m15>#O!t8$;`R zk_jOB_^>>VG-VZZAR@XY(Zd@jDz+K>GilX^0T9abJ0>e1vw)8wxFWcMBpwqG$bAX> zS%MXGMa_>XY%|uXgb2P2H?pO&5Sl3NA3Xgqe_eOA((iRVoWWx4~= zF)Fkm%zK^a3Ik5%_k2y+#~k7sZO{}5=><&r6?~{pyaqxA)b;^@CYaw&67#KVV5^jN zl$31a5Iro3PJkW~1*w?83GkQMmJ=s;#2K<%2naiW6ZqF!{e#&og%!>6XqN@t4Al^v z=ATJmQo2SUTrI!UFi8A?O3=A76}P1PMtWMNh-E28su(SPh?Q=(`HPl&&wv-OS_ZVy zU>aiM1AkUd_c!n}KwP#%9Dy(q#;7d_x*!jT(y#fu$Pj8AXi* zZ5og{m!qmbf+bo*>-0;whx%($d=0$O4jDZk+WT`wtvekqnp@|?&xX|)R(g^HD zs|!ePNVvg8zZ3lnpW16HY^ypwr1#NSZhs{M2K(t6<5;ZS{t_4%p_;pzkTwy%GG<<% z+ObG*0wzZlk#S!NYzIMMz_1YM#tfOLa`1ZVqyPXL6cjG)P!K?cpeTNJDwPwl#G2sk zo`x+1kN|dTih>uVQ&IIv3HK61qqR%MD&oz;{{8nYMcfjuM_$`x8u;PiqZI7dsv{xa z`}A9e&Vnr~JwKlH_PpByC@jp4Mxzo`W{O7ui7>ap1Y$bLF=bX?)}qmL=HHB!xt=7aqxuT6b+<7zCBM<;m=3<(u%~l;2RiEIt>hy$mn)k4~Ky zZzx-X+#X1joF8nQ3|PyT%L+FP2I=$s$QuLo%b@1~B~ z1LHIDfxpV-^e(1d>s=W4VkBnLnC)P=uQkZ%sYuQB+!x#R4;pL8J=oS`WTcBH7w)MA z#muES>A7>7r!XK6lqC&D1fUL<$&_Xw0?-2mPwN%|kODFCpSCI+^AK0;m@s31nx1nr8?g=xW01NPrRLt`;MQuAA4@+SFYhB3+aqDqMqwa4 zqhf1)#0M(Tg?K}PL0$hhijm2NI8nso6oY`>U2q9P{_@F&afjshU;ZESSGXoI0!b2Y z;a`9L{Hw!QW34}z!+Fw64l;M)7SnOy9)5$&(jj7E#FVv3Ib-QwzeKAejK88M=75lT z7qaPdDDY6JyZDZQR^#T1vfOJGX%jTCrvP~3~MF01Yq^&-q4G|{Z*6kdjN z3*(zBokO>5Gg^={td+b`Y#!T*ul-I0P>7o@xt8N@O|_ zN1E?zbNy+-`u$B#+yD|gl8S9z+4qV|@wyH~Y`A30$35@1afeeE)C%FmS#ie{#lD^t3jcO1JHDXWInZtS_$&B= zZtxyVVDK*d(Hz#jC27*wGWW|Uyd?MRfHxN@TmH2R>6wm<# za7A2#6bBHZ_?roSu^Z;D&Zm$_@vks%(M=leI=8FS#(_olpz9be8T28xxW%=M>)fIAN&f@ zeZ)zTcN2s0nb(p{%iKGuw>2*_nS~G;$uA!T;v!q3h`p6JQhGc)A>=x%Q9>4FDIP!# z^Ty9N|0fzt&9kYjoDF|KdOBdoz8AYzMhYQUEVaS)A3}C@szg8y^v-V*=yua>2~**o z^}~=G6F!h-cO0*s=&{8o?7ml^5)w8tojmFC^mxAB7BUdar+hxzYLlncdrYdcjIAW1+>!KncIQ*X%VPfFPao5PGj4w@Ch2jRbhK=LVBRaJQV zi}9BtENv71V{Se}3UI;Z@Z7*4QoLgxiNH&r%R`{D=jH0Nv z>H!?tKe!>{^~|@?Z=5&&1!HStAfP+Vxy(h!F-AvYL}eD?655NKw`Hg?oO7ZUeX^fC(=XE`Xwo|iGCS;Z9G6sWj@@MUjl(q*+Q6NI7-+!co^ z%Rp)z6rht95Tkwhn*-dg)6#gE68>C#*$MGUF&odaeU;puNnq|2@O_-)g( z)`dF)kvf&jUt}9e0d>(*qsDBJKu)j|uArQZ?yvUq&_)!+XPh)!nHL=hSey;9L zzi2HLDz_k2z=K&;*b{bdu?(SpCfRE;PBbBjuw6NYZ&^-;x%9t%K?xE(plHKcD|KZx zAvi-tDdITR5>bK~Ua-g=ABoFCB8QAd6whUoYsEvN0)^BcO_cW%SFlC6;ze0Qw$m7d z6xJ7FCNx$R4Q#T?yMpyP5pYXVWb$eT?UaOuGqACzR}^rs1^MqqO!a$sPVcCS5}cl4 z#aK-xmr913!jeW}XGA4q-Twl}sN)f^-2#a;D)J=WP?VF17brYZt?73Z*{kncKW#WS zLYQdy0VtoQ#R!+r7qH6Coe%U3M!bhZAE(3zI*;Fik&^z(!=aS!owjr=QK}DQ0=(kB zjV}*TX_m48eo*eTQdxj4I&ppT#!g{CZo}#GO&z7OR*o1mMjC}2KpeCp%~lRT1{9Fq z8Yr%zo!}MCud$X(vcmd{@1xys3F3~arkNtLWO;BlJ!u>TN^SLvib+*W2fzs$7gAK( z%;ZX@9WfuZ|KAY__;Oq6SrGYq$4z4Z(qZFTdNET|{|DMosmaR5!;)FQ$ovmx{^f6yg} z_0tE-k(HrPf{;hX8i6%tCZN>Tj}HbvL&6b5wNH3N1yUTLCv|->MBmgE!?V<9ktyLeMQ*|=PG|HU27zims)Ggch z&)3)m-=AA;Qk9|q*BxvwO1m9ph!4z^@!i)v9NwSUt^s>)6CFg?4q9?n|wY^ft7O zW@#zabZh#lj(rXma}ptUSE-AR`Ni_&@A;;{qTU3%2fGd43GqXPwL08&@=HV%O^+I; zXu!ko=Iyl*1-Z_HWA;1f1G}FsKoKEVHFVs4dFedSUrjrXCdWFOkr?Mt2P+B65IO!dZ zcm&cv@cluNp^w9Cn;$AA44rPRW0Pd5y85|T$y1^=QrsK<6L#BovnI*D!$o~!0Lp^T z6cQDdkuk4F`-~F#rBW9YcO!yZ(7_!>Hr5F2D^_9CUC3XBL}^iq0BvBxNnCs%$C4;n zHX?~P!XMllTp2PjOox3CyMm3R$TOPm!Sq!Wi#&Y9!z}|thzk<9K z&F$UrHn`D}wE%xS@$%e|(9mQ{;4TrW0q&tX-0T-#HG^t=^fuV=R=`y)x32^wY!%Hl zzLjMq&cvA-2fozZv-BbKRkfddXLVQk=Ifc=@O3!m{Oq^7xdX7APS!h9p(0Mf<$^8z zk4Ds21Lc4r?C&Y|X1p>MRZaVu1=rcJh(&D>7}zGl-3MIN)|%amB#x|@VQs#5Y|9u& zeFNlFAM==#62z7=a#&K1vcmKv9=gyh`cT~DGcaA2?0QLlSWTTI8Nbv z7m3rJ)W1Da1~MRcI;{DW!R%-{=!@f7li1T3y49!mI`V$@rh($7=yNCZWL{Y7G6cJ; zSPZdrm#~F35I2nQoLOWq3^A4o-%(d|v-BgwLLWpH~FOrB=`BHSzC+<7c&g2daUE!K%(L&NI;K1dco{rkVwobLw%afTwtf zY8v5pNa}EtP*4|PW$$KhtkcHUnwvBp6#xt9Tbi8;fDjZcEk*@EL3%dtcZad-Ev+&x z)qcY{h|!@{EPiif4;BAl%+jVSL#yD!oVKC@ki%QJJUwUC4E4!phta8(R0iJJ3r2ZL zD1X56Wsjx_r~)!Ux6{^D0roKb-?t86aDc)zMKu7$?^(HQp1cO(f9$K`n;k_+rCe;n z^77dOY5%DKihw?MWOhGgUh%4V#G#7&bpnIaZ3nwq#MOgVTKY+r?Ew0o?@iqL&tk-j z`2mZK^h-)xFiuO^%okWr>-P)2)4z4q7HD~P`z^WhzAcEG|5^n@V>bVZ_}HId{+4po zy}C%PNZ;P0SMTyu49!SPLZ$GNq51bvS$1P)c^@x|s0z#$ol6?i`aP@2LFW{9Y|M<2 z0buct5$A;X>)Jep)tO{ z_oqUFM+|6!!YFaMGQVbH5Mn~cheAXKAcZ; zSs<#&3fb==T|)e6*UH%ZQb>AF|BB8jY$Z?bB>+5W2`Q_;F0$tp`TG`cZF2|RL0=&e zw&Xm2vEpxg>M5C#Le-t<=YjdOO$YTj8P<;+-qa0WnzyqWG?;!A2j^#Lugg4efo0sA z^WOp_uS&E=q{%mpIK<9DhJ;)JcUs|jS+gE zoAo;iVK`!}U%kRpTtESkkNePm1X7wqsTBKAUS7_SEie3EpNo|uYp)tj0j@}u(jst( z1KhcQI|h6En%}fOQjTUr=-1#7AV{Q3>1EvA_6*QH*JRE(d%Tt87^dxJfp)*M@O08h zzBZpnxg9BxO($zAt@KAcu>0LlNSc>AJvB47sG*e&);KAJfPW-cL2us#`P#T#QIVUv zgGbByKD3pdA&UqwAdgB#4)`N3)dmDe>{Bwyn_&D_S{Q*LH2y#j!KWvfH-8b1DZCyk z9D5*VLZ$T=NuuL5*R5Wi8L9x}0#b-H%#AtM6nTNxzf z*j|_JqH;S&(2QH(Bh;A5Rd;fjb6s%|r!If$B?|_Q{T~2GK)1iPoeY)Tdp*2Z6xX(z z{}6I2vF{3H&Rzs-U#)0j0VC$;1BR)qf97RnM=RpqEFdL?Q#Y7F7g(5SXxlckc7*3K z)BKfLbi$GyeEihelgC>LCnD}l+1+RngPkWV6Pc*ezBDIU_aj`~oU&V95O-yQK<|M<1@1)}{4%IjqyFVwe|hG{+|{W|^H(GD()`r*>yf!$1P;!>hx(Pd%&Ya< zt}YzV*AYk5_0Fkvq2#C@Z`oj?%41VBK~o%1c^vW&QK_~`ZCf1tjsN?kp6i}eIh|%Q zoztNu>cE8JDmR^3+cs_bL1A)Se{d0I;XZ>Y8O(lBp}Q>JiJUK7%SS<)UrnLF#Kie7 z6reSd?I=(z4z zd$_nKR}69@lp7out1h1&6|v`B5+a#6FVNs=n*Fhd9x05(zYB*?Xk(5|CPWb@MiFQV zP=qF$zlw)xO=y5c4k+P}Fd&o&L&eX z=3HDS0o#`jU0hNDRhMC1TqXleoF$ivU0j+0l9wf3TulMqmvdfRF#$!FrCwY&e@S>V zKy|+dPxm*B)kph9>%(w=fDJaX2eE&Tt@g8h*w>HLJLlldFcAg@^@f`7FJL4Ggy}Lb z%Jf+ZPfe0<|E+QM4jlMfNICDkBleDYYrOInaM5@04NIr*4U4J-Dm!Ee-!iBEZ;o4+?octCyEwTtfkCm)l=lp#jyGePCQ56zddS z6>~sqAIRDEXK`v~WY5n}idm5P}Q+A9gbimXR+6fAstw=%OgL5p-|U!>>v1v+yRHLifh1+GzzH27RERxZ+u2bai;bmmZh zO00Y#KEC`&d^Gc@_(*+}f0QFro5K9%zppBS&@jA)ZB@0FOFA~yUeRuArrT<{j%GPN zWi`X3n(t~Y!|7@$tJOM=>07SjEvl+Rcjg?UMHe(;_{MA1+1Ul{%9ZAh!Rp>T*kaW0 zFvrsj4J0FVx4KPDU$a_mo3^OqTTWen^BYvvzUQxQJ)zF?9=r-JTE1o2)?RFd_kXXc zj+cl>Myr-%ur8kh%xMGWLjVKE^I6CAT{fJtW-zK5w&!Zb6T`BNstq#-J09gdHNykM zRKH<3@fZm{^EXtrMapyY3!2w3mgDEj%GHD`uf^QzdeT;2UO}#E8%?@W9kL#OuqsOG zpdabzpdWLfA9JA3xhB<@SJoFa!y)l2NW(neb@^oKF0=eb%Yzl}YE?R%nFb-ybvsOJ z+lF6rSxc*Se2$t?b)Q5tu6GP(K$uXXLX6N|%kvjCZIjYSZeUy=3UWV2dWPc}zRxTe zgL-JJW`UdwBknW|f2g1#oStTX0>t2K+weRv3F3(KJg(k*AKbg4y;VckwH+8T@`Tuw zt*&UWm?krUc|MX+rW-Bpz#Gd^QFCv&H^BOxhU>y&b6B1;q3u{6wYxZZw}oK{05u(V z$ALhyZOh{#)Mz>s9EP0}t#q;`uvB2cwsA_H?d~A-;AGYE2jJswdvmydf4pdjDE3;^ zZ@9#}p~8;qv>}Y?9LDne4ejUrZLl+v&9?(c^2TZx(1xi-v9G;P+Z5y>`VHImPVOT_ zh(7LEPYjzPvak;{jB|hsHHLO!_n2VFF*r7E4c5;-X^yW9t9LLB!2G~_V%4eV&w=Oo z_dd@aTrBE9OGCGZi;r!8@xyv9Xg+YF|x3W+6N75usJ#rIw!rNwVGvG06L6+54pbGi9;lsoyWa~ zc))D|TMyzBH%5FaoU|6_V9o1PBN!l3@54reiD8akzy)%vIO%U$$rwFtcEhc@qzeYU zHV<(;7QD96YFRKt2C?Z|7*Dg1OmW~_w{GDv;xb>053xaWOM5M8TjY6n*s~Z1O7-%w z;Vz#l#JxPliRYw$lThJJ)!D7xYL#s5UN^UP*H^c83GmBwYu6}m?V8u&9e*_9jb)I5 z{@N1!YFoSX`fQw;Ay5c)U|kysF@p_UI`15eK|})vJax=EZAEXi43ib0@?>L3ib%$hl#rZ3q9VxyF~wsQD-=t@9jscvgdSh$iGg?^2Ew7( zlLCnd%^bUb5J;O)Ywf)eKtZK;jT&vK_2HEX@G3YxB64~t{aFZZa1*xfK2CB|A zE;rs&0%f}dz0)A4Y@Y${9Oov0o8jD9;Ld~Yk3jbV*WDV?orKuFCpRFi%7DG3R4nM2wj#-ULc~`<)oXvj3k!~ z&%-PVxIxrKwvI(-VL+bmh^!1_cfcJ@cO0+N#@q;J06!u8ZkuZTned{nS38ysb+g}n>D*A1bWMUg=-bi0h_o`W zKQ@Jr1s?m-MyR-LI6FLB?`Qae+pgKvleSR=*ZGRbw;^+(fXaFLHqUsR%e3ErglK(c>5@y58>U;PG#NaOxbB zG<$FwK1zbmgJJZ{L~$_0X|L!@2dMz!=1@u^2cqWwXw*Pt4I>A!m5zRY65Ib8(GzHL z4E{$%zXQ#Ueww|8cp;|jr%28s!PsPP4bU7ys_HzR5!BxzUYLOdSxJ{L4#i@c{R~Af z0NH?*nm%o(BHkwIPIIh3E#iKEB*JasLqPGd6ruKP3r+BW`%)+^E`{RmabI#b>(rsU zZFcJqXbv-~3?r~lfO!VC{@apXz0O1@(h$ zQ)U77!<%%FJLJ_ANd7`x~X(YH-2x8hG_;$4-0v zV@9h3TRHv?mY70WxUtrUqKkvRP>s$e50b*O*D(zFHZW5oQJUtVD*#B)y@Z=VJP;sa zQh~&ua*&FuLWl={8MxGebeOyWhiAq{KNZS&c@8tt%`VJDx1oL-t}ix-3wIFYLzTucqcENEO=01Q5EvkRgJOze1d>D)w-B4|R(U!})Pb|6brNt_|4o9iAz}d^B?od6=>sKU8bXZRydNitol;8no)PKVHd2 zNfe7PC0W9X>>0LSQ7wQg3b0C=G|`cX`5Cq()UL^=z#l~jZp3w|8+0_P{8)+$NGoWkp|3{nXzw+!}41?W|z z39R2FZm%!GwbW$Ywtw`J=@QCglb6Ro^t2s_dB^pkt>chII1%n~jrg(Ae*ubHow%m1 zS0;4buy>5Erw^)ZSVZcxN%VY5;Ds=V*t*W&QcaoKjK})PW@|vE_{TAJUkI$--QR$--TS$--WT$--Z^$--cN z7Y1ztHwe5#w@%t%BLV@Sw{qNIbO8dE{kQ1dU>b{m2)m^B>d>(=-K6C;U2$0NH~JXR zv)F)wx_8BjbC09}2ipw7m#k>5s@AjXcMQ>wY3wr|0~3<_Jr0a0G5o2P={*@(g8j2W zM#hhD(jL6W8AOfnJS6)!os*hy`}19p#`c*jvw`Qz5JCl061bzpN;MM`&AARx6CHyc zm?Now(j=|s`iG>&j;Ta!vP=7fyKHy6Uur-ATb79+%h9HXaG|#M&omp4c0Vg!Q!9=5 zTMIKAPRenb#Hg@XiXHT%?+#n0MLSLX0*b^l@E3Gm8)|=xe!FIb7B&c6NT%81@D#cG z&WNta5b6w`oq+Kx%e>U|~*Wl9rm)OwX)7r)G6M-m0U1>#lRy zJ$La;ywf>^!|@hTLJuKzN!Dx%r&5Wo-)Az<`g6KW;n{SOyuZ|k@Mk;#_eM;%G7|Xg zr;-vlR~Q_E7zL-LX%=tRzgs$^7R>d2EHqx-L-v+HG(zbM6e*eJwvOzC@ ziI`&}ah5>Yiz9QDv=e2d%&j!4EJi{INZ6wbz^45YkaUnl!JJkGPuvPH5vef7nPyRH zF16cnRD@_YT$NsRz0g5v7m4I!F_I zl@+yaVHIr+rc+4X2JNYk+=abz_1$i6`uUWyFkO%QT; z_x|aq@AxQR8TQ4wIi@eK^@seS{0oA;V4%e@1e zuZiAah334s%pWb7_ozZLwt0+g-s>3KZ}(#|{I*~0Gd8{v>K;cORPEFlah!|B80~|U zkexsg9hn&1!mdIV5uhxqSgmhNZng z(5N+8pZ2br@yEJYpAK_>vn#Or64}8ASE@}&525WMc+Tffs1Ql(v6-Q%U$f%CDCORK zTP=kibsIC8*HZC1fF`qI{j=L8-mGhvsG8h^?{5(6mV5CjQRqVhAWG1X$)ng`AJn)a zh^ESzDK^Q(RTBV(hBr%Ovdl7z!6U)<>ng&V>!S+faYyEW{=)=+fkqHTA_-Y^x92NE z@pzBK-dvi$oWhg8Q|&xqAO>n6D9+y7^xyDEA%jeF zcNDlW>-{T$V8aZ5^Gog$DWTVE?hT0y8Ez+1!Yxq=Dxt-<`$1-iYfBvXgTw-bK*9E? zj4ns(!_yedmS4+j$2w_E#|$aqKzIKwhT)RG7C2S zWuN2E10czR&YZI{>_3OpfOQfhgUp>gKCGojp{y5T2%eyI61a)=C<*(Qs+fvsmGeUC z1N_HIabTr?FKtm9>b7XSfr57gm0xZ=TRw6A)bWd%Pitbhi-z~?C)jU)hMf|mUZ<Ob)w-+pHfEW49Qq*kBJN#kmdVgEbyBqX?xO`q?NXChk4V^t%Q zU-J1zNA|h6bG-AD>hdJ5GFYrSGS z=bYdszhZOH-xNmp>Wa6s4z^V6#PQ2cp>0NK5iG`O}+wM-{*V6qb z;x!^+CsN|P$`^{r87Z;=NiwX{UGb;MN}A-|I{0HTB+9~LO(H}Z9z7P@wP^K3mWDh7 zyD<-f)deEd-JgkU4H>ysM)^Bs3RLnlHiPxg!TzxnWuNW~inLjqQ_W-Q5wT7VYut2y z^1o}4>WLdi`>qUz<=_GB-ef?mUVne*nvk0DH@YOy3bHyIGA%_}wIWB!y{wF0*t7=0 z1~;DWS{M>G{Jo>WRO7&1s7B=L0Gz%ID_CmYS%posIpsl<<4_EuBV9aor?^y+-~EX! zjkJCuYwQ#?oyxajf)cj_Ez(;iD7qqlG2h+#_Ow!unj%1kxH5Dm8mxT4C`YrW# z=?UYF4|zSS&G34>haF>&r?F=}f43fqhi)GZfV(F$QA|eO=ENJdcICIFzDd)0;T=xr zB>Pw(akBkxPR3(#W%<#W|3BaT=bN{f8aUs$d%kDBBV*xmy;5}t2Qxf0Xu>&v&VoNU zAPM$g?zZQ~Mwp0p-P`D9nt_ytnx2q5v?lpb6N(=4bB7`avWHMnpN(BGJIa@B$^x3H z;0OLRU!#xJF0WcD2hBZj*dB2-7~4 zIOTGwdvcOyskOuMm4}m{65;xP%QZD4*z31e?bu5tegT`}qkTa+9b}5vD9>VI7Vel$ z`LaoVd%xN2g7PFn3*)AeB!^0%re4nbW)qLE>h)bCxUmq=GOrP}LZT@iXmW!)^mai8 zOR$_btwJQ8(X~~b1YH~@0`_xZvEgHW(inm>IY(&X1ZWnh+x_iO2dKo5m2vdQEZYo zDgo<{vkgh5J+JDwN3a>iI<}lJQlA%jt`mULjVZUKXc>#9SCWZ;U3@i*jY!l{2409o z3GQ!8Dei7{u`}_C;Vq+@mzpaL<&#bTcX7j!A0^?>lYlo!b4BcR5$<&cC7;w9&B&R6 zT47#&OphvsCKpsAzDmbEzF`6-_v6PikyR-(ijOm^{91>5nQ70+I}k`^W@ziGh1&GQWA31 zs%{rx#@_LY-9n@02FtR+FAk)J;}MY3)xV{XdirjVs*>PSsbXuozR=qCj-fR|!$+fP z^#5`ou(n0OO4a_B!fNVnu$n$SeYOie<6kHJpKJc7fq+SW(f_$k1g`%J5IJ&J3Pfn` z23;`O`i^0e16|>!zBUjlBQXKuial_N_bdOHrjpmMzzN8u;cZ%OfTI3&O>%;BKp$#)LGaE+q$Mr6fZi$N1)2K@Szxys($DB{h5wqvf>PKRw z1px)@Q}Pa@xPf97#TzI-i{b}R+(E&yMoIh;HV5#3{t-Wc(|?1bH&Og|6kkIz1eE+l z*VtJ{EqxK$DyNP zl+G4^XG=ckjMDF@v(>qefB9ck>-rDvJgaHlU-gYLH#r^lLExYN&CW5theTMF$J+Dt z)dYe1ffn7}ZL3%UcoBOBZA62f>^tZ|ABiJiHq8R z7ihs$s$b*jenrj0e>)JL6S7quL^*(f585g~3g~U&bBN}~ak&*mj*U{yX5IJxDcUh2 z$GvwJM?Zz57d1|2tTyWiV24|=T$!zUSTEi|6yT~JV$nV5ogTu~JiIP+WPV%IlN&aF zFsWq&11lb^7PB0{;xpetcv#jDqAvs3)74sScI{}GB$;(5*$MZRgcb>0nBa=MC* z_OQ1jzQItb*UM$^5j=!NDe^BwT^#) zu0tW=@Or`z;IAVhASMSSy?>xuzBD7s2mg+MxePA3H5r~F$z95ftxd69E3v~-tI$=V zm4C=_tAN_K&&DQTi)9}kgwo+~9D;|!42|h~cHKI}4WTt$$4-WlhJ%DF&h*HxSS;o} zYGNml$!Lw!B#HMr*dccjP#ZDrz%~f*ubpT;GATXsFj^6vxI120YOoa{DR(raModkw zjZ4MbhExM%Oc29T*~TIuRypyWcdwcp9)AMeTk`8A85D;{Xb3eRq>z*;A##h2uyOwD9v0G0fI+`$F3>qN`#`BGNT_KVya*sB^=elYgPw z(sOcng47)Es-58zRFOfh(kMlvlbFLyhJb4M6_6qD5zzXjC8^xP)0Sp&7SwT}PzpjO zY}MqXAdrG^DSO*8q+gv9N*Q>PH*$uUT`b7?jc8a>;eG zj)aQ>KmI95IO#j2H3malU-l;|(0`pYr!XOL0P!QNre3o6nBt?&Mfyg zmh=8u1T|Pr&JuIhb^{IsJ%18Lut0;^3~8Uq+fTsQG9=mG7cH-D=J@{;Js7u@Yk?M; zk6Ks_YEB!{&Bc~GU&3whwqZh54MDDL3>vm{FO~wipBV1R#o~(}^EY=&13gT!LUXo4R z$)pjHh2?ldo+Mcrl9PoG)|Wv0BqIvQZODyP)Jra zbG;Bs+sAh$$2H}>h&9XxH@}A~jI8(jX6#RnQ4G?mDRMZ^t~UV)vg#wK|6a1=04W?< z7eh-(Yp`Q*DQg?*Y8zh&f7k+m_`Alqz)oF=SZoRSC0RH1VGVo8hhFzIrY7sv*+mNW z5m@lhuVCa?Y=4oG=}3`*cM;~i^}e%m|KP$*88X~5uSKt+0#RU-rvkOKQsvcN_tlJ8 zEPH-qqLqI9z`^FWC+`pR?#3YvO^IHb+Kc^o<%%YVZGMg@=gWqic7Z;Dtt4y@9OUAf z;ho12-0sr7nFAMG_%C<|zt2{Z5NNGh4@DrdQLYh>b$`PxU9Hqa{c3}EolTI`Vfl4! zHNv)z$hPJ=E-@`8)zYLX&!2Y@GyNw@TecM=fJRx`S~|EVYDcA7buW~w+@2D3XRT3^ zn~C&;HqBfrFSwj4iyq}3Zb`)s6ppIo*> zH!)MXKYt9f%jK{!tjGLF_o8j!2!IQyl|@UZ^n|Q(IE=8xdN_{4g?RmlLPgUUSB`h2 zX|1U1_Gc@ZrX^!@EhB~%o@M#iGiSb`$-FB$7WyFiu|xIrsv5%SE$dD5PToXk5tU_i zyd#HLFNlA@cYP8&@^wF7rAj!kh4 z1DIg~$U>m?iScEdXf;DPH=%_|`=cvk*y0w(F-a{Olu|t$xMB)Jy49hL{J z=YPRU?Mk^?5hc8>#NeW1z5H-uy%4S6x<8tC?I^X&`fcei5R=VtIA!wo=*${22MBIY zYMFjn3!yq=;eUgx{kVEq=ip>Z9$}!srnW&F&xT!phr-{%VIQwDdcgdV?Or3a(Fh!@ zR7z~ft;W8AC6>ChfbxRTe&gbjU#TM0`+wqfRvjz#T44a7KejhPU{X|gaOza{TMy9Zgey~zR zein?@=mwp7vE%16jh_^RzI=9{yQvdjl=2ouX4$N5ZDM1{{DS4ZEV6W;r~5v>|G4Pk@Hao{ z_tUz{jmiK(SS!7)M~<=rl7$D*A~izxA`IiK1b-dEK51**8a%c{kQQPVrV<`6?C|7{ z6F(-^4DB|K#7?cANfs>fKBR%eHw1>6?GA5MVZLbs;KOUxJ4P&js+8uVQ`<`uEwzyGrm-t| zDN}>h8*~^M-nlsARblg3>f!Vpu4FBQ9AN+0`-xY1vgfh+%{)TfX!HGw+1FMEh}ln- z2&v3x{2@YAUu~u=ZGKn@5`Ta~H%WxUu`sYtI?zT+#kbJrH&e+w4#>Lhr1x$SPUL|q zYu8HsF;b}=@b4o2AVVl1HHh+lnE+IMl+$c8# zaLm(_>}bHt{FYXrX;|N0mPyPUP8YU$sAew7#rAkkupe;#LtH- zLdqGs7@Q?!53Don11{*d;&2_D>9KaX=li6~fHxah!fp87T*Cjg9eTi8;lc|=c!;M7 zdoPw`2h>?a(eqs}EWQ7A~m17+VteD6*O z>~|_XPOKf1;t%CnSuX6Pao#CKAUk<&?u>LX?}N@M^z7t(vA9Mi%U$nS1oQ0lh6F?ArK0sdfvY{b)?Kr}4gF$- zOJi8UXq1s9!vGO3y0x?v5A}C;r!-1zU%=j8YdsUp!GABXr2h)*_iDWv%5{0Q}>zI?sNwTR$G1Cx4QkN0+JXp*yvcGXe z8LQifEPp$n;-meEZ88Xj_kKp09JxcH&y{Q#Wh`FD(iubODq5W><@4udcUY~{Ng+3M z(2$^j8f~KtIh82GaMn_8w2NzF6D$g$8q45qE`eZV z2&fpPtdGJ5nbPKP@Lw@CWlQ{)@#3*)(^^Arc|E2H^C0A;7IvvWs2#zzy_wD&H!V%6 z4nNN%o-;zZ19_|q@O#nc4c}a_8XnX*xbi+l^cJT}YK*Trq&BfEHvQ7I9G((dp!8)h zK7Tfs`-;kItGrGPIqYSJj_Ku$fS*c=MGH!YLqueF+|rr>Ux;2b2o}m zH?3+f81P&{AaQ@hA8q2R#+p5J+}s3X)_;o_adf@|+X7IVdWn_mVGkbUxsx|-)aSR* z@2;k^I=tNXyjH8qEeT>@SO4yHb?ftmF173P_qW`WtKxt@bQ$QmxyBwsFn}{Rzs^FRazn@`!pm!cX@!2gC@C-T++<3XJa{T@CTo z5SQKSKa{MWzi;17eKoT@s%jcd^nVCFQ+E%GQJOiX=kt^O%7=OT%6lT`!!Z?3lD%Kp z4~C^m>{1i&;K&{^yp1Dvz*a%dyu&~N`ZIE?h{=ql*>X0KB6#wMPt#D4X%0VO_DyeXZkMGbQ1-@=y7$LKmIbNGD>A+p;aC-L7Sfizkh0KGN6bwH8Nxub z9M8~Vvzs7)xY5A=*njn!wE1RdTMmKLjbs4v@e}DNdSYIeyU;}+5xSzo`U>W?(#%$$ zTr;Mo*37B!fV=HoBPdE@hlx{MaRkM!xZR1vA9HJP#j3&?92Rl7fdh-2-())gLoIMx zuC9-*R$f9$rvG6N-~~8*1BdtHQ(4punXZ%p@UlLD#eCQbdw=7Er9QvwhENDu^m+Ko z18C7i8L^m{lGe?+A~uI|^3D`Cippl3UMJ&Z3_WYn6w75({WIAIvc1^>O36F-JEKhT z-_Gvi<1Q*Q;#^#3^A-h`YTs-Pfu&@4#yPpw8bUPoazI8MTT$|!Qfc9U3HG2EZ5@+A zmWXdt;Up65n|}(BbLKj66SYFMGUJsAz{kEO*eAGr!EH!;>S?*ZN9W#_(N-$hG|gwv zbZPj2p#N{Cqzp~%lx<+sv?z9gw^<5(d&8*^WJ*vzUxKrc-7VSymk69NQ@4-?KNC$~ z*f-I7ZVjHf-WgJWbud$HI<~&#r+mf0rzpP_X_(Fa0Dp~REZjWgt1Tzw9CyDSoUms+;tazw0L<^<~s*Y+eA2ixoLQB2^bago-@lv z&1%{lhR^Um52-(ua+(G^gKI09CT}YS=?yl~q<1;X8P5Bglow>2A-S!l1J`aMV0wII z7=9CkaDR5CSGoIVk7+M{g$PvDvStspEXQ|wy4DquD!(GfEj=sStxDwZEu8)(*jqJo z9H2h;CJZ3H-OP*L1;hI`%&5JOP><$rLZ9~$Zt1tFrTJz~_8sNLSLM2Y6_x&c_wTy= z?b^?&9KS|6`e@8LzLvi4hrZYM$#zm5U!#^9-hXb@Qlqh3)%~?(Ti?Gx;S%$m~ zIx&bswk562)|+IXoGXMm!$@Te3lgSCg@%iATuDqG65NR8&-CuFTw`e_%mfP+x?1uO z<$tDnow;{py?|3!4WlFR3?HuAvQBE~_lCC5l@( z)#?esH+@_ywWG0TN24`B{RpW_IL#`xz$i;ks$2hX`}Xa?mKoq271z}=QN>+q?|+i+ z?`z$us!pt)IMTs{)E!F42JRXr@D{I+?~-!`A(}XS8@*~;-yeCz8#;pb>^ndK^8tI_B`S~xSMUREbdX5Upj0c-+Szf*F2PSxw z4ut#`Rr^nYkY5Ih&C4x4hIvbmex@$-yuXXZ;;1nu#X&l=K{MwVV>eyLkXv7YLCCB7 ztln=r97_~Avn~v zU<(#u@y0KNuj!lusWT5VF&maAjN9eC!}savKEwCU>j=@KGhTVYw-CA)Dn{>h-y%#z zSMv^ES-4tAd9OpevYc7Y)_z;%wpZb>ggo}T+`mB7LAIG%&eT4uauXfl{R!tuugm=> z&9usWMdfxFXOD0$r!zmEG=Cjc0+f(-Q)2$ie0IJ^WK~EwYC&yGr8%5-0`DQpB`oVS zE&8S`U44>!LzeWSwjaQepUCpBbNTx?CBrG7MqRaG(X*06Dp6-Wes7btO6p6p{3XA~ z?a!|NlE!~R`?<#4n+D&jHgWkp1XUcqhA0=pvHhZ#D3~16V7X=%SAT?E`@RkuUb%3M zhici~A#|5uH1yGuc0duddx|}o%OSR4v?Zf}da(;MF^C>}g8@LXO;HM_U|ZPT7;CGA$nB9o<&Atdx+%UBVEd(*N?A%23)dRxt=9VI=gT82T2V( z>i|9oVq2<2y}k}D!G9S0eQTgsZVYoI0tE1*RrMyT!fX32c*Dat{v};oHj&H6{;w%e zSa$L}}kC^8}mpWKi+mi7OGDpL{m|imoQq?(hr+3A|t`K&RUA$gWh*N@H z0NWs~l7jr1>$1Gs<>xIk<)b0Da~`)L446VjnhccZXc+kc7T!aKT*WjxH0smAoy zt^^yB1m>~fRn)jwA(XSw?J{nb9^@3uBe$=JV)aOm;cdzYtibWdqzhrlBJF&<@O}4q z%WJy)gk>w<>Yy*kR4&1fi$*%I*q~})7Mq`yfa^-qLdx?|EH>}@0o?upZuja+X6BtX zRSyNWG&z@=41Zv;wO+}_eG>or4ip6mCgW`F5OEE56ZaY+9K< zV?z&?S>4Xs*|Y0Zi;>5|peA`*A8SyDeHnWum|uqtUN#Au7~n{9uj*c6^?1WwEPG|? zvCet1QR6iRZS;u1i(5m`eOHnE9v5OwblFcrz=H=5G8sNzQklkg&g>C8ckSY*AKE#y z^Tmzw?SG++d*YmX-XSY;&L#5V6}t=XRQXJldBZFnId~CHt(mllh+y>V^=bpuTD3Ck z2AL8^hw;7ZwALQ#7W*Zv_N)`CVf(#bvo^2`g>Xno1y?kmbz#eN?d@&y-GYfL*od+Z zg2rqtHdM?>4f5B|{qVN5_ znRl9hakh>L08f=aW4rRGtEBNO!#zWh#=K!#$MXGE8fe!E#Z>({hA^DEaUhYz>P1`% z470)UGm6|8MT;O53Wp-PRH-e21A)Uc-4gTddu8I$1mk()k3lcgJ)ziao(rePAKF!@ z)_>~@ON$c8(+B)~9?~-lwJqW_3Xh7{2QI?y-v3 zXf5z(9*zQtQ{!czC!W-9t+51?Q@$ZgS${<|ql64Y#v_jz_eyQHx&(GmS=~gTtYiRi zz2oyDz&xQzx#^1GBO(M5NbFxCV|Pi<62nhn%Q-xgalEFw0*ZBhAUFFOjV{LHYiT)oQnMFnngqQ}Qvg)5Lx0Bi z;f=q>q(F(f413989uPQ9aVRo)UNC?R(&YxfqH{X+wl&~QM_IXR#vtznzHwXE^;}Bz z-rEHp2wz7xOSdlA%CQ?4%MM3X52oa99skh^6&0UGtNy}@W9a-D9(C-8ft)`Qb|`c! ztxau>+%QI2q!`L+a^H1$8{UjI3xE3ks2Sa(-%6Kb*Z=RMHK(^m+Pf#rvTirk$S!HO z7TP6A-#6Y^SZ^8&>H1a#6kD*di=8))UApDQUaf1L8}%})gK(^FgONu$DVvL!A6jee zHmq$K3*%8ppvYaSK}+`Ht`1iV1n9M5*D`k2=27Xvq{~o+rAzSBUk9bAb$|8h6&F+G z(-DkLNxHE$*4A%{tQ&_Gn$lu-9WRf*;XA~DDL_+#fn?hXb0O_b_>9?U!fDb?2F8#p zwhTWMZ*fMBUW_c0&qj(6jR7ieQ1OpTO*^(x8Y`Djh zo)tE%)=rm7*s`t^SXat$tACI?^RAiFhiaG^CU4zlNr43ikIzQTlAYx(D;-mw2lduK zTSp`JTCN+(9ON24@kFyyHp**It_2Lfr>8;}0v&pJGJYdXBq!Jp!sL^nW7}&uqo#e1Kol ztdgb9Kt5^`ih@^OtcdFMF4zXwk^9)=T1ZH&>Yo^9>k_kDlqH|{Eha!{vwb^U=}if8 z(m|HZX0I{h=pYyfB42Ry@?fwOe_V+HOG84-p;Q}~>H-|U8Z9?$`HJN>6xX#ec>Hhq zW!@-SIfes&%~0FdNPpTW@i{!nx_u5F{PMcb8BTmo1as-7-B`hR5^p$b(S&~);ys$R zR?gVV71n_Ifg|tI%6k0qSSS|*yKj8zGvD~s%k;lcp75{viS$pY^qIEpN#gvo zZTZ{FtluFfe&%wyi0j~}F;5gK^$8VAczjp%?8aPTuOnpS-4l|}BNOBCo!ow~KFY=& z%vyP)%rkptyMJV#-8j40<8~?Fwik$y(G!K8<(XOGPSAktl;3)WrJB4?OCz+2mHHy- zcUkcpZgno+Oo@qtsB&l=s8&=meq&DU%`~Z;=sg#@$ty1G)|l0eb_7(4wkt$AfDBa= z=2)zr^24nI$0aqNFxXWV_1vsokH<}+L71VYphXiXPk%5vF=XZFW5*L+K)oi1C(byt zQN|hKYUSIctXOSpmT1AuL_{$W11r<#>%@idtQVClv>H?&)V)NxS!(u7VGoTUw*??480OkRR^`tHJOvK8+gRFlG2qx6+^U@=-K%H+u7B{ z#&K2QnSa^Y_3V00U3WN@?;AhI7P7MU$`+A5%T_8Ygp3Ye4i4u~RwuKp%6wF2_B^(P z2>Hq?Nmh2q$Vf(melLCN_w|S8eV@`{Kp9j6La=DZWXIvr4yrPpisa&pQry+w3tMn;)DPndz6A8cX1tWI2{AS zU7+5}_?k(KcB6(NVk;fHo<6E!ezv4p7JmAHT}uyqt+e|SL%Xwlf#QnM$}{Yif36*y zd^?`TucU@BG8$zlU8!K!c%DF5mcjLG5y_EktBw@2x^Mx~RQuDgR!j z%g1!2{LMc;k^`}NqMxMGMOt3O&NrUzeGYy9b)PSs&J@8IoLpTTT;&rSUg-v{l%3yJ z{fSc{wHv?e78AMXA}2?v{y3reBgwgyl@rZ+V3zD0?7zLjm$n;j5R(*tmC6hL&Jl~h zLy)@A-mK2wAEdZASJ^w7PPF?%aOZNJF2}0Rhj_|5TAALOd=r^p{$lwkm+uAUNps3p z`%qPhPQe_rw;Rv79_rQHhpU^doncLLUunO%4)d-o&^QvD_X7r}p4v{)Wb}7x6Eu4S zX;@m{;dbOdgeX4hms+O1FswQq81q&ef4q6@`}rsD)837J;>wijzV(42{&kbD^hxH# zur>cRj7NO^D8(boA#!8yPlk5JW@_E$!w>PNZRSN>7IY_B-#eA{ge;#kV^66Uk8=C+ zj9rj=-Rbi7=3OgW;rGV6Zbp>6{`+_7mov)eMID|I+^hO&cR|kQ?u-gkpSfF>NIs#RSIj)BuXyWm8Dt`U%7v}O^^n>txWV`k;i`5 z647s4td3Mi+;Hecm?ZonBwMK`Rb>?M=g6Sd$Tp2j;?_0B6;j0<_UxG@K39M5I=1R` z#{BXtCt>#O%XgnnQsQON`h2TDY@Rsdn`K1rs5MhFRby-nahZOGdZS~r$OyYnQM0iq zhE{vJ4q~$Bx5t!o%p@uJ>jzFXG5EJ;-`42wG_ujEH!Yy~c=FMi`WuUmfeMNCS!z9= zk0Yv6_xcCJQj|R#GEA);V!ziu-*Fa1z33IcQ-)o+uVb?5yY=u(hh`O4qwE1$Jic;) zCf47jTK{RJ{j1gljk{jCLyK&lvz{ttk@8K6&iO4DzrH^?lOm$XvUbSUAjJ0aDzQuOjcG!DWY9ve;mFDtm0Pf!4cbm;|P}?{3T_sH;^Z4NcCVi{?Vr>?KaUaH-~Rl-tgRm7hn{6dK3A z6R(ZgPZWd+^C;3%l{TyTIM(Vh$h+#c)nB#4aGNwupB`scQ;Tq)6JXVvPB@5be4e1& zSS!qd4|#v)OS=Q(n$_}%tXI^|S5f^vT=VX^Pc9|9x9Pzj!D5}s>gg|K z(~c^?9{DCIv8%z&Rw}huEzSat9|L(z9?bhDj7`#&F?Q}Grj6U32n&QMWJt!a@QnEE z**4|JawTu83;Hts(uyXGo!yT01mT5MawgMORIM7C@poA8>ipvjQbb-z#lHKMXu zQgPDeB91H}RYI=qgKcG7OD*kOvTx-DanC!x78HV9ZDvJx6LDW+F!nK3qJf#_mrB(o zh;jByIg%;KEm>v!bvCIjuBG1Aj|Tnjr)~5or=#A<)&$&RE%G?q3gzoV+#EyLcWP(} zc4(hvg*VnDA8z_j;V=Gcs=vdoEJOMJJ`J%ET55y zmAZ5bzh2>MIX=<6!hz2^D8u~P;O!PLH=5Q}l4@fa3u%z;O=~H5`S?2i*F14?m{eb? zh=8oPA=fI8VC#1ND87oqM~Z4w^$zq+oP>}!WD%B<-(WCf{xK-?HL+be>8dgHDLw8N z36vj2`lywQW>}m#_E2Ndv?R-MEQmqCn$K-Cq8VYBR-;(AMStD9m#GrnrkiC~vCSA{ zP<5VGJPDQd(=|ir9N!JRvawQoJzM-v@Viex43n3#(@x$zHOx`FpxexCEO6yTm)?bQ zs$xHDOFk*7kDbWcycImAuTyzez(^;K_$_+m_QP)c%LxUUcHJJE;!jTdGy}9AFFIYD zf;GBRYBC|2u-@*->CMPiN$un)J@d=1?!cTEx+zBces+h*Q5 z&)S;#l(U*t+ecfjqSI9xa!&D9OtsIN>g$|cWCO|JbO@RlF;$cZyS1&5< z&ztx{zVWxuZ4NJro8$e>LvmFNUyympq8VOxRAhJE8fm(df542_DxK?|Tz8zma;*8F|Hd7L=Y|c{5F_OulXZfI_nV66@YbZ{# z&u}3*&nH4wZ;`x!V6jM8(S2DqpI@xd!ISZB_SBo0B*~u-gf_&3Qt46<==zOH7r;`->Q}+4Y$IBXqoLyTwlw zH<+RJRnPV5Ka=aO&3>Fh%>=?jsh5_%yF3cExR~(H>K8JUb0yAm3z$BotA zlpz{>f1-Zv>Xwr@sm=E5YzBhKH%2y4ym!_+*5vaCbpHWQyFz_W2sF!&v;gI~kO+Cm z10({1NB|)hVgoz5&~fB4AkBj$Xc!A&z=0lt5GDG~4(RhBMmj%~4;J$B6eac{LLd+j z4mjjNyu8fMVB*NRL*m#mCofMN>Lv~iIsRd-f$Thp)xwdD2mv+F9I=Rh41i6H60y?jUtc^@?ALxRWyFq;nvA=>~&0sK}2Bnu!uWG=W^05iXVn*|U*G8{ZE zfOwJ5K+_>*0?ZV^K4$=FAv}o(CktUF5?m~VCs_ct5H@!O$%ohos5=~#!EhmLhXg+h zAs)E75@!*_!B?9`f`GKhkD@1Y#$o=Gmz^9KDg%~9&>bn)-+3W%^>A?dvp35#qzH(E z>d^E%i7O6=fdNkSFesDwiB!sEgwWI)?GT=H%spf&TA+H5i8beyd69 z?ThmL>v|r32P!UqLgV{wPa;3$8;z;rpR z%UeK6fFzLoK%M|A`W)C0;5@zq!30>P1dvI91-T2_2yl&Vg9QRyjv|1n0v1aL$X3AE z7_g{-F>(-40h`Bxti$0u=&XQ5k+;CcAyWmgR>I6Opi&8O$rJZcAs|b(qnJpsu4vTF zKha)YfDs1T-y6ZY`r;t;AIJmTtAyC)`sAq*&?l0A8D38AsJ~gPRe>QF=_803i~VcK z2|mD<$S$y32}{}on5!Ueu8VJAa>&10;v9UO|C8@G;Bpnji7Wx0hl4wase-r^3tDLq zP_xqSpmARAsJ}PX_3tp^OL~M*93fD^Uxh}&bQOHArcc6G3q zdmy3?Uflo`*1@j%Kwlj!x)E5fgV(zYIO}2Y#)08Gpa|}p5gfOG>SNPgFu z9s#K`gOCP@5qLI0)bQ~QY=Dj2Kz0MftRff=w-8)6A?~5KY(Eubb&`x6u$F_h!E1DqLO5kVv+ih zyEI60qO4F+Zg`3v)OSH9yr5t(awodQOx&P!emBm^H&~iiBO9}1~ak}dFgPr?*KHZ$X;y_^>JbYZW!J@x`j^4(OVmv}6fsI3& zw}3N}xob|Kg=TZ3YdxiAGgyrJwzZ?-i_y79?-FV7_0H#ABHEQdx4kT|@FmmzK6-~> ze}Y~j?$PxVSwhisBsspf6bJk9)K1*HF&C*EB7D;HtLo)ECxwC^ZV810Zk7=DI9P^ zQft%*yorANp3<8Z&e)z~-WXY;6GU%@B6G~{-m0X2?a5l7cyMrI^!9CAAsz|GVS$G8 zs6C-$x2?)2NBa8DT!cT{jH-r_U$PhMtgXw$JYRt6?MO(|2>3xv} zW7F2eZO?1(F4pGO;IH`))a7XxYNd)G7tLqH(5t1dF&npQrveIIDm@(Axo#I|QDuje zN?viWgVv@f&srXy3uGw}^#k2CFGh0qhNY@z09>HM@+kL|A% zbNA{Qv12-HvO`%kq(fO$$c~AVAxV&-3dF=nnNSvScux3l!5mg63oATzf(S`0Lwi_C z_L2HX6fp@ATuRb6$f(5Ve%CQ29g-x=mBd;4I#?Kk_|B>q%v|8%TSA1F60JAzZML&B zr`k1h@y}l~mD@PKEBld%&cbVGE9|b)H;;&Yv`z@qD^}Xm(x>I5l}^ja$V<7%~0$U`|S_@5lOphT>A{1>a1azDgmtoi}$Pe+qSagUEI0JYGX) z(s^qPwWV#y$IFz@6oCj;Aa((?2w4uS7|BH25P$?cK_cx~7SKqa9IQtpoQM@uyB` zEU}?x@$hza_55DIldBOv@=V=6=oXge=v26oYog$wbu4!eg zPBk^QK5G1-svyzko0^_g-N_}5k7ViCA%yv{)OenB*M(Mop4aOBr=6^y`-h)M){#MfyzGz^K3q zTmF*|lJ|41*91Q5%Z}}st6n554SYRt6*6dO;dN1@rmpX3prI%K@l7!)mkQx6CktP+ Hhd=)V1SUr- From 9398d52ddc20f0fe1149280fbe6dbf423a37d5a3 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 25 Sep 2024 00:05:49 +0300 Subject: [PATCH 012/409] Update package_esp32_index.template.json --- package/package_esp32_index.template.json | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 21b3635bfcc..4df82b26bee 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -101,57 +101,57 @@ "host": "i686-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", - "size": "320072134" + "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", + "size": "360076736" }, { "host": "x86_64-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", - "size": "320072134" + "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", + "size": "360076736" }, { "host": "arm64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", - "size": "320072134" + "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", + "size": "360076736" }, { "host": "x86_64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", - "size": "320072134" + "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", + "size": "360076736" }, { "host": "x86_64-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", - "size": "320072134" + "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", + "size": "360076736" }, { "host": "i686-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", - "size": "320072134" + "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", + "size": "360076736" }, { "host": "aarch64-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", - "size": "320072134" + "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", + "size": "360076736" }, { "host": "arm-linux-gnueabihf", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:fba40f59a2c1ed89bb3fb17c655ea312c9d6a9c3be102fbcb25f27e96ddc2bc6", - "size": "320072134" + "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", + "size": "360076736" } ] }, From 4bb287eaf6cb23303bf22bcab228f0e35a3680d9 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Wed, 25 Sep 2024 17:38:21 -0300 Subject: [PATCH 013/409] fix(esp32p4): Fix compilation errors (#10371) * fix(esp32p4): Add missing touchpad definitions * fix(esp32p4): Add missing target in SPI example * fix(esp32p4): Start touch driver fix * fix(esp32p4): Skip touch examples while it is not implemented * fix(esp32p4): Add missing analog pin definitions * refactor(formatting): Fix formatting that was broken in P4 PR * fix(openthread): Add missing targets to skip * fix(esp32p4): Skip ethernet sketches * fix(esp32p4): Disable periman test while touch is not implemented * fix(esp32p4): Disable touch test while touch is not implemented * fix(esp32p4): Fix UART test * fix(esp32p4): Skip Wi-Fi test * fix(esp32): Skip unsupported example * fix(esp32p4): Fix skip files * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- cores/esp32/esp32-hal-i2c-slave.c | 772 +++++++++--------- cores/esp32/esp32-hal-spi.c | 7 +- cores/esp32/esp32-hal-touch.c | 2 +- .../examples/BLE5_multi_advertising/ci.json | 1 + .../BLE5_periodic_advertising/ci.json | 5 +- .../BLE/examples/BLE5_periodic_sync/ci.json | 3 - libraries/BLE/examples/Beacon_Scanner/ci.json | 3 - libraries/BLE/examples/Client/ci.json | 1 - libraries/BLE/examples/Notify/ci.json | 1 - libraries/BLE/examples/Server/ci.json | 6 +- .../BLE/examples/Server_multiconnect/ci.json | 4 - libraries/BLE/examples/UART/ci.json | 3 - libraries/BLE/examples/Write/ci.json | 1 - libraries/BLE/examples/iBeacon/ci.json | 1 - .../examples/DeepSleep/TouchWakeUp/ci.json | 3 +- .../ESP32/examples/Touch/TouchButton/ci.json | 1 + .../examples/Touch/TouchButtonV2/ci.json | 3 +- .../examples/Touch/TouchInterrupt/ci.json | 3 +- .../ESP32/examples/Touch/TouchRead/ci.json | 3 +- .../Ethernet/examples/ETH_LAN8720/ci.json | 1 + .../Ethernet/examples/ETH_TLK110/ci.json | 1 + .../examples/COAP/coap_switch/ci.json | 6 +- .../OpenThread/examples/SimpleCLI/ci.json | 7 +- .../OpenThread/examples/SimpleNode/ci.json | 5 +- .../ExtendedRouterNode/ci.json | 7 +- .../SPI_Multiple_Buses/SPI_Multiple_Buses.ino | 2 +- tests/validation/periman/ci.json | 3 + tests/validation/touch/ci.json | 3 +- tests/validation/uart/uart.ino | 24 +- tests/validation/wifi/ci.json | 3 +- variants/esp32p4/pins_arduino.h | 30 + 31 files changed, 471 insertions(+), 444 deletions(-) diff --git a/cores/esp32/esp32-hal-i2c-slave.c b/cores/esp32/esp32-hal-i2c-slave.c index 14da815455b..85eddcdfcf4 100644 --- a/cores/esp32/esp32-hal-i2c-slave.c +++ b/cores/esp32/esp32-hal-i2c-slave.c @@ -361,155 +361,153 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t if (!i2c->intr_handle) { uint32_t flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED; -#if !defined(CONFIG_IDF_TARGET_ESP32P4) if (i2c->num == 0) { +#if !defined(CONFIG_IDF_TARGET_ESP32P4) ret = esp_intr_alloc(ETS_I2C_EXT0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); +#else + ret = esp_intr_alloc(ETS_I2C0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); +#endif #if SOC_HP_I2C_NUM > 1 } else { +#if !defined(CONFIG_IDF_TARGET_ESP32P4) ret = esp_intr_alloc(ETS_I2C_EXT1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); +#else + ret = esp_intr_alloc(ETS_I2C1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); #endif -#endif // !defined(CONFIG_IDF_TARGET_ESP32P4) -#ifdef CONFIG_IDF_TARGET_ESP32P4 - if (i2c->num == 0) { - ret = esp_intr_alloc(ETS_I2C0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); -#if SOC_I2C_NUM > 1 - } else { - ret = esp_intr_alloc(ETS_I2C1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); #endif -#endif // #ifdef CONFIG_IDF_TARGET_ESP32P4 - } - - if (ret != ESP_OK) { - log_e("install interrupt handler Failed=%d", ret); - goto fail; - } } - i2c_ll_txfifo_rst(i2c->dev); - i2c_ll_rxfifo_rst(i2c->dev); - i2c_ll_slave_enable_rx_it(i2c->dev); - i2c_ll_set_stretch(i2c->dev, 0x3FF); - i2c_ll_update(i2c->dev); - if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_SLAVE_SDA, (void *)(i2c->num + 1), i2c->num, -1) - || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_SLAVE_SCL, (void *)(i2c->num + 1), i2c->num, -1)) { - i2cSlaveDetachBus((void *)(i2c->num + 1)); - ret = ESP_FAIL; + if (ret != ESP_OK) { + log_e("install interrupt handler Failed=%d", ret); + goto fail; } - I2C_SLAVE_MUTEX_UNLOCK(); - return ret; + } -fail: - i2c_slave_free_resources(i2c); - I2C_SLAVE_MUTEX_UNLOCK(); - return ret; + i2c_ll_txfifo_rst(i2c->dev); + i2c_ll_rxfifo_rst(i2c->dev); + i2c_ll_slave_enable_rx_it(i2c->dev); + i2c_ll_set_stretch(i2c->dev, 0x3FF); + i2c_ll_update(i2c->dev); + if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_SLAVE_SDA, (void *)(i2c->num + 1), i2c->num, -1) + || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_SLAVE_SCL, (void *)(i2c->num + 1), i2c->num, -1)) { + i2cSlaveDetachBus((void *)(i2c->num + 1)); + ret = ESP_FAIL; } + I2C_SLAVE_MUTEX_UNLOCK(); + return ret; - esp_err_t i2cSlaveDeinit(uint8_t num) { - if (num >= SOC_HP_I2C_NUM) { - log_e("Invalid port num: %u", num); - return ESP_ERR_INVALID_ARG; - } +fail: + i2c_slave_free_resources(i2c); + I2C_SLAVE_MUTEX_UNLOCK(); + return ret; +} + +esp_err_t i2cSlaveDeinit(uint8_t num) { + if (num >= SOC_HP_I2C_NUM) { + log_e("Invalid port num: %u", num); + return ESP_ERR_INVALID_ARG; + } - i2c_slave_struct_t *i2c = &_i2c_bus_array[num]; + i2c_slave_struct_t *i2c = &_i2c_bus_array[num]; #if !CONFIG_DISABLE_HAL_LOCKS - if (!i2c->lock) { - log_e("Lock is not initialized! Did you call i2c_slave_init()?"); - return ESP_ERR_NO_MEM; - } + if (!i2c->lock) { + log_e("Lock is not initialized! Did you call i2c_slave_init()?"); + return ESP_ERR_NO_MEM; + } #endif - I2C_SLAVE_MUTEX_LOCK(); - int scl = i2c->scl; - int sda = i2c->sda; - i2c_slave_free_resources(i2c); - perimanClearPinBus(scl); - perimanClearPinBus(sda); - I2C_SLAVE_MUTEX_UNLOCK(); - return ESP_OK; - } - - size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms) { - if (num >= SOC_HP_I2C_NUM) { - log_e("Invalid port num: %u", num); - return 0; - } - uint32_t to_queue = 0, to_fifo = 0; - i2c_slave_struct_t *i2c = &_i2c_bus_array[num]; + I2C_SLAVE_MUTEX_LOCK(); + int scl = i2c->scl; + int sda = i2c->sda; + i2c_slave_free_resources(i2c); + perimanClearPinBus(scl); + perimanClearPinBus(sda); + I2C_SLAVE_MUTEX_UNLOCK(); + return ESP_OK; +} + +size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms) { + if (num >= SOC_HP_I2C_NUM) { + log_e("Invalid port num: %u", num); + return 0; + } + uint32_t to_queue = 0, to_fifo = 0; + i2c_slave_struct_t *i2c = &_i2c_bus_array[num]; #if !CONFIG_DISABLE_HAL_LOCKS - if (!i2c->lock) { - log_e("Lock is not initialized! Did you call i2c_slave_init()?"); - return ESP_ERR_NO_MEM; - } + if (!i2c->lock) { + log_e("Lock is not initialized! Did you call i2c_slave_init()?"); + return ESP_ERR_NO_MEM; + } #endif - if (!i2c->tx_queue) { - return 0; - } - I2C_SLAVE_MUTEX_LOCK(); + if (!i2c->tx_queue) { + return 0; + } + I2C_SLAVE_MUTEX_LOCK(); #if CONFIG_IDF_TARGET_ESP32 - i2c_ll_slave_disable_tx_it(i2c->dev); - uint32_t txfifo_len = 0; - i2c_ll_get_txfifo_len(i2c->dev, &txfifo_len); - if (txfifo_len < SOC_I2C_FIFO_LEN) { - i2c_ll_txfifo_rst(i2c->dev); - } + i2c_ll_slave_disable_tx_it(i2c->dev); + uint32_t txfifo_len = 0; + i2c_ll_get_txfifo_len(i2c->dev, &txfifo_len); + if (txfifo_len < SOC_I2C_FIFO_LEN) { + i2c_ll_txfifo_rst(i2c->dev); + } #endif - i2c_ll_get_txfifo_len(i2c->dev, &to_fifo); - if (to_fifo) { - if (len < to_fifo) { - to_fifo = len; + i2c_ll_get_txfifo_len(i2c->dev, &to_fifo); + if (to_fifo) { + if (len < to_fifo) { + to_fifo = len; + } + i2c_ll_write_txfifo(i2c->dev, (uint8_t *)buf, to_fifo); + buf += to_fifo; + len -= to_fifo; + //reset tx_queue + xQueueReset(i2c->tx_queue); + //write the rest of the bytes to the queue + if (len) { + to_queue = uxQueueSpacesAvailable(i2c->tx_queue); + if (len < to_queue) { + to_queue = len; } - i2c_ll_write_txfifo(i2c->dev, (uint8_t *)buf, to_fifo); - buf += to_fifo; - len -= to_fifo; - //reset tx_queue - xQueueReset(i2c->tx_queue); - //write the rest of the bytes to the queue - if (len) { - to_queue = uxQueueSpacesAvailable(i2c->tx_queue); - if (len < to_queue) { - to_queue = len; - } - for (size_t i = 0; i < to_queue; i++) { - if (xQueueSend(i2c->tx_queue, &buf[i], timeout_ms / portTICK_PERIOD_MS) != pdTRUE) { - xQueueReset(i2c->tx_queue); - to_queue = 0; - break; - } - } - //no need to enable TX_EMPTY if tx_queue is empty - if (to_queue) { - i2c_ll_slave_enable_tx_it(i2c->dev); + for (size_t i = 0; i < to_queue; i++) { + if (xQueueSend(i2c->tx_queue, &buf[i], timeout_ms / portTICK_PERIOD_MS) != pdTRUE) { + xQueueReset(i2c->tx_queue); + to_queue = 0; + break; } } + //no need to enable TX_EMPTY if tx_queue is empty + if (to_queue) { + i2c_ll_slave_enable_tx_it(i2c->dev); + } } - I2C_SLAVE_MUTEX_UNLOCK(); - return to_queue + to_fifo; } + I2C_SLAVE_MUTEX_UNLOCK(); + return to_queue + to_fifo; +} - //===================================================================================================================== - //-------------------------------------- Private Functions ------------------------------------------------------------ - //===================================================================================================================== +//===================================================================================================================== +//-------------------------------------- Private Functions ------------------------------------------------------------ +//===================================================================================================================== - static void i2c_slave_free_resources(i2c_slave_struct_t * i2c) { - i2c_slave_detach_gpio(i2c); - i2c_ll_set_slave_addr(i2c->dev, 0, false); - i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK); - i2c_ll_clear_intr_mask(i2c->dev, I2C_LL_INTR_MASK); +static void i2c_slave_free_resources(i2c_slave_struct_t *i2c) { + i2c_slave_detach_gpio(i2c); + i2c_ll_set_slave_addr(i2c->dev, 0, false); + i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK); + i2c_ll_clear_intr_mask(i2c->dev, I2C_LL_INTR_MASK); - if (i2c->intr_handle) { - esp_intr_free(i2c->intr_handle); - i2c->intr_handle = NULL; - } + if (i2c->intr_handle) { + esp_intr_free(i2c->intr_handle); + i2c->intr_handle = NULL; + } - if (i2c->task_handle) { - vTaskDelete(i2c->task_handle); - i2c->task_handle = NULL; - } + if (i2c->task_handle) { + vTaskDelete(i2c->task_handle); + i2c->task_handle = NULL; + } #if I2C_SLAVE_USE_RX_QUEUE - if (i2c->rx_queue) { - vQueueDelete(i2c->rx_queue); - i2c->rx_queue = NULL; - } + if (i2c->rx_queue) { + vQueueDelete(i2c->rx_queue); + i2c->rx_queue = NULL; + } #else if (i2c->rx_ring_buf) { vRingbufferDelete(i2c->rx_ring_buf); @@ -517,202 +515,202 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t } #endif - if (i2c->tx_queue) { - vQueueDelete(i2c->tx_queue); - i2c->tx_queue = NULL; - } - - if (i2c->event_queue) { - vQueueDelete(i2c->event_queue); - i2c->event_queue = NULL; - } + if (i2c->tx_queue) { + vQueueDelete(i2c->tx_queue); + i2c->tx_queue = NULL; + } - i2c->rx_data_count = 0; + if (i2c->event_queue) { + vQueueDelete(i2c->event_queue); + i2c->event_queue = NULL; } - static bool i2c_slave_set_frequency(i2c_slave_struct_t * i2c, uint32_t clk_speed) { - if (i2c == NULL) { - log_e("no control buffer"); - return false; - } - if (clk_speed > 1100000UL) { - clk_speed = 1100000UL; - } + i2c->rx_data_count = 0; +} + +static bool i2c_slave_set_frequency(i2c_slave_struct_t *i2c, uint32_t clk_speed) { + if (i2c == NULL) { + log_e("no control buffer"); + return false; + } + if (clk_speed > 1100000UL) { + clk_speed = 1100000UL; + } - // Adjust Fifo thresholds based on frequency - uint32_t a = (clk_speed / 50000L) + 2; - log_d("Fifo thresholds: rx_fifo_full = %d, tx_fifo_empty = %d", SOC_I2C_FIFO_LEN - a, a); + // Adjust Fifo thresholds based on frequency + uint32_t a = (clk_speed / 50000L) + 2; + log_d("Fifo thresholds: rx_fifo_full = %d, tx_fifo_empty = %d", SOC_I2C_FIFO_LEN - a, a); - i2c_hal_clk_config_t clk_cal; + i2c_hal_clk_config_t clk_cal; #if SOC_I2C_SUPPORT_APB - i2c_ll_master_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal); - I2C_CLOCK_SRC_ATOMIC() { - i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_APB); /*!< I2C source clock from APB, 80M*/ - } + i2c_ll_master_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal); + I2C_CLOCK_SRC_ATOMIC() { + i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_APB); /*!< I2C source clock from APB, 80M*/ + } #elif SOC_I2C_SUPPORT_XTAL i2c_ll_master_cal_bus_clk(XTAL_CLK_FREQ, clk_speed, &clk_cal); I2C_CLOCK_SRC_ATOMIC() { i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_XTAL); /*!< I2C source clock from XTAL, 40M */ } #endif - i2c_ll_set_txfifo_empty_thr(i2c->dev, a); - i2c_ll_set_rxfifo_full_thr(i2c->dev, SOC_I2C_FIFO_LEN - a); - i2c_ll_master_set_bus_timing(i2c->dev, &clk_cal); - i2c_ll_master_set_filter(i2c->dev, 3); - return true; - } + i2c_ll_set_txfifo_empty_thr(i2c->dev, a); + i2c_ll_set_rxfifo_full_thr(i2c->dev, SOC_I2C_FIFO_LEN - a); + i2c_ll_master_set_bus_timing(i2c->dev, &clk_cal); + i2c_ll_master_set_filter(i2c->dev, 3); + return true; +} - static void i2c_slave_delay_us(uint64_t us) { - uint64_t m = esp_timer_get_time(); - if (us) { - uint64_t e = (m + us); - if (m > e) { //overflow - while ((uint64_t)esp_timer_get_time() > e); - } - while ((uint64_t)esp_timer_get_time() < e); +static void i2c_slave_delay_us(uint64_t us) { + uint64_t m = esp_timer_get_time(); + if (us) { + uint64_t e = (m + us); + if (m > e) { //overflow + while ((uint64_t)esp_timer_get_time() > e); } + while ((uint64_t)esp_timer_get_time() < e); } +} - static void i2c_slave_gpio_mode(int8_t pin, gpio_mode_t mode) { - gpio_config_t conf = { - .pin_bit_mask = 1LL << pin, .mode = mode, .pull_up_en = GPIO_PULLUP_ENABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, .intr_type = GPIO_INTR_DISABLE - }; - gpio_config(&conf); - } +static void i2c_slave_gpio_mode(int8_t pin, gpio_mode_t mode) { + gpio_config_t conf = { + .pin_bit_mask = 1LL << pin, .mode = mode, .pull_up_en = GPIO_PULLUP_ENABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, .intr_type = GPIO_INTR_DISABLE + }; + gpio_config(&conf); +} - static bool i2c_slave_check_line_state(int8_t sda, int8_t scl) { - if (sda < 0 || scl < 0) { - return false; //return false since there is nothing to do - } - // if the bus is not 'clear' try the cycling SCL until SDA goes High or 9 cycles - gpio_set_level(sda, 1); - gpio_set_level(scl, 1); - i2c_slave_gpio_mode(sda, GPIO_MODE_INPUT | GPIO_MODE_DEF_OD); - i2c_slave_gpio_mode(scl, GPIO_MODE_INPUT | GPIO_MODE_DEF_OD); - gpio_set_level(scl, 1); - - if (!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state - log_w("invalid state sda(%d)=%d, scl(%d)=%d", sda, gpio_get_level(sda), scl, gpio_get_level(scl)); - for (uint8_t a = 0; a < 9; a++) { +static bool i2c_slave_check_line_state(int8_t sda, int8_t scl) { + if (sda < 0 || scl < 0) { + return false; //return false since there is nothing to do + } + // if the bus is not 'clear' try the cycling SCL until SDA goes High or 9 cycles + gpio_set_level(sda, 1); + gpio_set_level(scl, 1); + i2c_slave_gpio_mode(sda, GPIO_MODE_INPUT | GPIO_MODE_DEF_OD); + i2c_slave_gpio_mode(scl, GPIO_MODE_INPUT | GPIO_MODE_DEF_OD); + gpio_set_level(scl, 1); + + if (!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state + log_w("invalid state sda(%d)=%d, scl(%d)=%d", sda, gpio_get_level(sda), scl, gpio_get_level(scl)); + for (uint8_t a = 0; a < 9; a++) { + i2c_slave_delay_us(5); + if (gpio_get_level(sda) && gpio_get_level(scl)) { // bus recovered + log_w("Recovered after %d Cycles", a); + gpio_set_level(sda, 0); // start i2c_slave_delay_us(5); - if (gpio_get_level(sda) && gpio_get_level(scl)) { // bus recovered - log_w("Recovered after %d Cycles", a); - gpio_set_level(sda, 0); // start - i2c_slave_delay_us(5); - for (uint8_t a = 0; a < 9; a++) { - gpio_set_level(scl, 1); - i2c_slave_delay_us(5); - gpio_set_level(scl, 0); - i2c_slave_delay_us(5); - } + for (uint8_t a = 0; a < 9; a++) { gpio_set_level(scl, 1); i2c_slave_delay_us(5); - gpio_set_level(sda, 1); // stop - break; + gpio_set_level(scl, 0); + i2c_slave_delay_us(5); } - gpio_set_level(scl, 0); - i2c_slave_delay_us(5); gpio_set_level(scl, 1); + i2c_slave_delay_us(5); + gpio_set_level(sda, 1); // stop + break; } + gpio_set_level(scl, 0); + i2c_slave_delay_us(5); + gpio_set_level(scl, 1); } + } - if (!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state - log_e("Bus Invalid State, Can't init sda=%d, scl=%d", gpio_get_level(sda), gpio_get_level(scl)); - return false; // bus is busy - } - return true; + if (!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state + log_e("Bus Invalid State, Can't init sda=%d, scl=%d", gpio_get_level(sda), gpio_get_level(scl)); + return false; // bus is busy } + return true; +} - static bool i2c_slave_attach_gpio(i2c_slave_struct_t * i2c, int8_t sda, int8_t scl) { - if (i2c == NULL) { - log_e("no control block"); - return false; - } +static bool i2c_slave_attach_gpio(i2c_slave_struct_t *i2c, int8_t sda, int8_t scl) { + if (i2c == NULL) { + log_e("no control block"); + return false; + } - if ((sda < 0) || (scl < 0)) { - log_e("bad pins sda=%d, scl=%d", sda, scl); - return false; - } + if ((sda < 0) || (scl < 0)) { + log_e("bad pins sda=%d, scl=%d", sda, scl); + return false; + } - i2c->scl = scl; - gpio_set_level(scl, 1); - i2c_slave_gpio_mode(scl, GPIO_MODE_INPUT_OUTPUT_OD); - gpio_matrix_out(scl, I2C_SCL_IDX(i2c->num), false, false); - gpio_matrix_in(scl, I2C_SCL_IDX(i2c->num), false); + i2c->scl = scl; + gpio_set_level(scl, 1); + i2c_slave_gpio_mode(scl, GPIO_MODE_INPUT_OUTPUT_OD); + gpio_matrix_out(scl, I2C_SCL_IDX(i2c->num), false, false); + gpio_matrix_in(scl, I2C_SCL_IDX(i2c->num), false); - i2c->sda = sda; - gpio_set_level(sda, 1); - i2c_slave_gpio_mode(sda, GPIO_MODE_INPUT_OUTPUT_OD); - gpio_matrix_out(sda, I2C_SDA_IDX(i2c->num), false, false); - gpio_matrix_in(sda, I2C_SDA_IDX(i2c->num), false); + i2c->sda = sda; + gpio_set_level(sda, 1); + i2c_slave_gpio_mode(sda, GPIO_MODE_INPUT_OUTPUT_OD); + gpio_matrix_out(sda, I2C_SDA_IDX(i2c->num), false, false); + gpio_matrix_in(sda, I2C_SDA_IDX(i2c->num), false); - return true; + return true; +} + +static bool i2c_slave_detach_gpio(i2c_slave_struct_t *i2c) { + if (i2c == NULL) { + log_e("no control Block"); + return false; + } + if (i2c->scl >= 0) { + gpio_matrix_out(i2c->scl, 0x100, false, false); + gpio_matrix_in(0x30, I2C_SCL_IDX(i2c->num), false); + i2c_slave_gpio_mode(i2c->scl, GPIO_MODE_INPUT); + i2c->scl = -1; // un attached } + if (i2c->sda >= 0) { + gpio_matrix_out(i2c->sda, 0x100, false, false); + gpio_matrix_in(0x30, I2C_SDA_IDX(i2c->num), false); + i2c_slave_gpio_mode(i2c->sda, GPIO_MODE_INPUT); + i2c->sda = -1; // un attached + } + return true; +} - static bool i2c_slave_detach_gpio(i2c_slave_struct_t * i2c) { - if (i2c == NULL) { - log_e("no control Block"); - return false; - } - if (i2c->scl >= 0) { - gpio_matrix_out(i2c->scl, 0x100, false, false); - gpio_matrix_in(0x30, I2C_SCL_IDX(i2c->num), false); - i2c_slave_gpio_mode(i2c->scl, GPIO_MODE_INPUT); - i2c->scl = -1; // un attached +static bool i2c_slave_send_event(i2c_slave_struct_t *i2c, i2c_slave_queue_event_t *event) { + bool pxHigherPriorityTaskWoken = false; + if (i2c->event_queue) { + if (xQueueSendFromISR(i2c->event_queue, event, (BaseType_t *const)&pxHigherPriorityTaskWoken) != pdTRUE) { + //log_e("event_queue_full"); } - if (i2c->sda >= 0) { - gpio_matrix_out(i2c->sda, 0x100, false, false); - gpio_matrix_in(0x30, I2C_SDA_IDX(i2c->num), false); - i2c_slave_gpio_mode(i2c->sda, GPIO_MODE_INPUT); - i2c->sda = -1; // un attached - } - return true; } + return pxHigherPriorityTaskWoken; +} - static bool i2c_slave_send_event(i2c_slave_struct_t * i2c, i2c_slave_queue_event_t * event) { - bool pxHigherPriorityTaskWoken = false; - if (i2c->event_queue) { - if (xQueueSendFromISR(i2c->event_queue, event, (BaseType_t *const)&pxHigherPriorityTaskWoken) != pdTRUE) { - //log_e("event_queue_full"); - } - } - return pxHigherPriorityTaskWoken; - } - - static bool i2c_slave_handle_tx_fifo_empty(i2c_slave_struct_t * i2c) { - bool pxHigherPriorityTaskWoken = false; - uint32_t d = 0, moveCnt = 0; - i2c_ll_get_txfifo_len(i2c->dev, &moveCnt); - while (moveCnt > 0) { // read tx queue until Fifo is full or queue is empty - if (xQueueReceiveFromISR(i2c->tx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) == pdTRUE) { - i2c_ll_write_txfifo(i2c->dev, (uint8_t *)&d, 1); - moveCnt--; - } else { - i2c_ll_slave_disable_tx_it(i2c->dev); - break; - } +static bool i2c_slave_handle_tx_fifo_empty(i2c_slave_struct_t *i2c) { + bool pxHigherPriorityTaskWoken = false; + uint32_t d = 0, moveCnt = 0; + i2c_ll_get_txfifo_len(i2c->dev, &moveCnt); + while (moveCnt > 0) { // read tx queue until Fifo is full or queue is empty + if (xQueueReceiveFromISR(i2c->tx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) == pdTRUE) { + i2c_ll_write_txfifo(i2c->dev, (uint8_t *)&d, 1); + moveCnt--; + } else { + i2c_ll_slave_disable_tx_it(i2c->dev); + break; } - return pxHigherPriorityTaskWoken; } + return pxHigherPriorityTaskWoken; +} - static bool i2c_slave_handle_rx_fifo_full(i2c_slave_struct_t * i2c, uint32_t len) { +static bool i2c_slave_handle_rx_fifo_full(i2c_slave_struct_t *i2c, uint32_t len) { #if I2C_SLAVE_USE_RX_QUEUE - uint32_t d = 0; + uint32_t d = 0; #else uint8_t data[SOC_I2C_FIFO_LEN]; #endif - bool pxHigherPriorityTaskWoken = false; + bool pxHigherPriorityTaskWoken = false; #if I2C_SLAVE_USE_RX_QUEUE - while (len > 0) { - i2c_ll_read_rxfifo(i2c->dev, (uint8_t *)&d, 1); - if (xQueueSendFromISR(i2c->rx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) != pdTRUE) { - log_e("rx_queue_full"); - } else { - i2c->rx_data_count++; - } - if (--len == 0) { - len = i2c_ll_get_rxfifo_cnt(i2c->dev); - } + while (len > 0) { + i2c_ll_read_rxfifo(i2c->dev, (uint8_t *)&d, 1); + if (xQueueSendFromISR(i2c->rx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) != pdTRUE) { + log_e("rx_queue_full"); + } else { + i2c->rx_data_count++; + } + if (--len == 0) { + len = i2c_ll_get_rxfifo_cnt(i2c->dev); + } #else if (len) { i2c_ll_read_rxfifo(i2c->dev, data, len); @@ -722,109 +720,109 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t i2c->rx_data_count += len; } #endif - } - return pxHigherPriorityTaskWoken; } + return pxHigherPriorityTaskWoken; +} + +static void i2c_slave_isr_handler(void *arg) { + bool pxHigherPriorityTaskWoken = false; + i2c_slave_struct_t *i2c = (i2c_slave_struct_t *)arg; // recover data - static void i2c_slave_isr_handler(void *arg) { - bool pxHigherPriorityTaskWoken = false; - i2c_slave_struct_t *i2c = (i2c_slave_struct_t *)arg; // recover data + uint32_t activeInt = 0; + i2c_ll_get_intr_mask(i2c->dev, &activeInt); + i2c_ll_clear_intr_mask(i2c->dev, activeInt); + uint32_t rx_fifo_len = 0; + i2c_ll_get_rxfifo_cnt(i2c->dev, &rx_fifo_len); + bool slave_rw = i2c_ll_slave_rw(i2c->dev); - uint32_t activeInt = 0; - i2c_ll_get_intr_mask(i2c->dev, &activeInt); - i2c_ll_clear_intr_mask(i2c->dev, activeInt); - uint32_t rx_fifo_len = 0; - i2c_ll_get_rxfifo_cnt(i2c->dev, &rx_fifo_len); - bool slave_rw = i2c_ll_slave_rw(i2c->dev); + if (activeInt & I2C_RXFIFO_WM_INT_ENA) { // RX FiFo Full + pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len); + i2c_ll_slave_enable_rx_it(i2c->dev); //is this necessary? + } - if (activeInt & I2C_RXFIFO_WM_INT_ENA) { // RX FiFo Full + if (activeInt & I2C_TRANS_COMPLETE_INT_ENA) { // STOP + if (rx_fifo_len) { //READ RX FIFO pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len); - i2c_ll_slave_enable_rx_it(i2c->dev); //is this necessary? } - - if (activeInt & I2C_TRANS_COMPLETE_INT_ENA) { // STOP - if (rx_fifo_len) { //READ RX FIFO - pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len); - } - if (i2c->rx_data_count) { //WRITE or RepeatedStart - //SEND RX Event + if (i2c->rx_data_count) { //WRITE or RepeatedStart + //SEND RX Event + i2c_slave_queue_event_t event; + event.event = I2C_SLAVE_EVT_RX; + event.stop = !slave_rw; + event.param = i2c->rx_data_count; + pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event); + //Zero RX count + i2c->rx_data_count = 0; + } + if (slave_rw) { // READ +#if CONFIG_IDF_TARGET_ESP32 + if (i2c->dev->status_reg.scl_main_state_last == 6) { + //SEND TX Event i2c_slave_queue_event_t event; - event.event = I2C_SLAVE_EVT_RX; - event.stop = !slave_rw; - event.param = i2c->rx_data_count; + event.event = I2C_SLAVE_EVT_TX; pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event); - //Zero RX count - i2c->rx_data_count = 0; } - if (slave_rw) { // READ -#if CONFIG_IDF_TARGET_ESP32 - if (i2c->dev->status_reg.scl_main_state_last == 6) { - //SEND TX Event - i2c_slave_queue_event_t event; - event.event = I2C_SLAVE_EVT_TX; - pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event); - } #else //reset TX data i2c_ll_txfifo_rst(i2c->dev); uint8_t d; while (xQueueReceiveFromISR(i2c->tx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) == pdTRUE); //flush partial write #endif - } } + } #ifndef CONFIG_IDF_TARGET_ESP32 - if (activeInt & I2C_SLAVE_STRETCH_INT_ENA) { // STRETCH - i2c_stretch_cause_t cause = i2c_ll_stretch_cause(i2c->dev); - if (cause == I2C_STRETCH_CAUSE_MASTER_READ) { - //on C3 RX data disappears with repeated start, so we need to get it here - if (rx_fifo_len) { - pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len); - } - //SEND TX Event - i2c_slave_queue_event_t event; - event.event = I2C_SLAVE_EVT_TX; - pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event); - //will clear after execution - } else if (cause == I2C_STRETCH_CAUSE_TX_FIFO_EMPTY) { - pxHigherPriorityTaskWoken |= i2c_slave_handle_tx_fifo_empty(i2c); - i2c_ll_stretch_clr(i2c->dev); - } else if (cause == I2C_STRETCH_CAUSE_RX_FIFO_FULL) { + if (activeInt & I2C_SLAVE_STRETCH_INT_ENA) { // STRETCH + i2c_stretch_cause_t cause = i2c_ll_stretch_cause(i2c->dev); + if (cause == I2C_STRETCH_CAUSE_MASTER_READ) { + //on C3 RX data disappears with repeated start, so we need to get it here + if (rx_fifo_len) { pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len); - i2c_ll_stretch_clr(i2c->dev); } + //SEND TX Event + i2c_slave_queue_event_t event; + event.event = I2C_SLAVE_EVT_TX; + pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event); + //will clear after execution + } else if (cause == I2C_STRETCH_CAUSE_TX_FIFO_EMPTY) { + pxHigherPriorityTaskWoken |= i2c_slave_handle_tx_fifo_empty(i2c); + i2c_ll_stretch_clr(i2c->dev); + } else if (cause == I2C_STRETCH_CAUSE_RX_FIFO_FULL) { + pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len); + i2c_ll_stretch_clr(i2c->dev); } + } #endif - if (activeInt & I2C_TXFIFO_WM_INT_ENA) { // TX FiFo Empty - pxHigherPriorityTaskWoken |= i2c_slave_handle_tx_fifo_empty(i2c); - } + if (activeInt & I2C_TXFIFO_WM_INT_ENA) { // TX FiFo Empty + pxHigherPriorityTaskWoken |= i2c_slave_handle_tx_fifo_empty(i2c); + } - if (pxHigherPriorityTaskWoken) { - portYIELD_FROM_ISR(); - } + if (pxHigherPriorityTaskWoken) { + portYIELD_FROM_ISR(); } +} - static size_t i2c_slave_read_rx(i2c_slave_struct_t * i2c, uint8_t * data, size_t len) { - if (!len) { - return 0; - } +static size_t i2c_slave_read_rx(i2c_slave_struct_t *i2c, uint8_t *data, size_t len) { + if (!len) { + return 0; + } #if I2C_SLAVE_USE_RX_QUEUE - uint8_t d = 0; - BaseType_t res = pdTRUE; - for (size_t i = 0; i < len; i++) { - if (data) { - res = xQueueReceive(i2c->rx_queue, &data[i], 0); - } else { - res = xQueueReceive(i2c->rx_queue, &d, 0); - } - if (res != pdTRUE) { - log_e("Read Queue(%u) Failed", i); - len = i; - break; - } + uint8_t d = 0; + BaseType_t res = pdTRUE; + for (size_t i = 0; i < len; i++) { + if (data) { + res = xQueueReceive(i2c->rx_queue, &data[i], 0); + } else { + res = xQueueReceive(i2c->rx_queue, &d, 0); + } + if (res != pdTRUE) { + log_e("Read Queue(%u) Failed", i); + len = i; + break; } - return (data) ? len : 0; + } + return (data) ? len : 0; #else size_t dlen = 0, to_read = len, so_far = 0, available = 0; uint8_t *rx_data = NULL; @@ -851,55 +849,55 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t } return (data) ? so_far : 0; #endif - } +} - static void i2c_slave_task(void *pv_args) { - i2c_slave_struct_t *i2c = (i2c_slave_struct_t *)pv_args; - i2c_slave_queue_event_t event; - size_t len = 0; - bool stop = false; - uint8_t *data = NULL; - for (;;) { - if (xQueueReceive(i2c->event_queue, &event, portMAX_DELAY) == pdTRUE) { - // Write - if (event.event == I2C_SLAVE_EVT_RX) { - len = event.param; - stop = event.stop; - data = (len > 0) ? (uint8_t *)malloc(len) : NULL; - - if (len && data == NULL) { - log_e("Malloc (%u) Failed", len); - } - len = i2c_slave_read_rx(i2c, data, len); - if (i2c->receive_callback) { - i2c->receive_callback(i2c->num, data, len, stop, i2c->arg); - } - free(data); - - // Read - } else if (event.event == I2C_SLAVE_EVT_TX) { - if (i2c->request_callback) { - i2c->request_callback(i2c->num, i2c->arg); - } - i2c_ll_stretch_clr(i2c->dev); +static void i2c_slave_task(void *pv_args) { + i2c_slave_struct_t *i2c = (i2c_slave_struct_t *)pv_args; + i2c_slave_queue_event_t event; + size_t len = 0; + bool stop = false; + uint8_t *data = NULL; + for (;;) { + if (xQueueReceive(i2c->event_queue, &event, portMAX_DELAY) == pdTRUE) { + // Write + if (event.event == I2C_SLAVE_EVT_RX) { + len = event.param; + stop = event.stop; + data = (len > 0) ? (uint8_t *)malloc(len) : NULL; + + if (len && data == NULL) { + log_e("Malloc (%u) Failed", len); } + len = i2c_slave_read_rx(i2c, data, len); + if (i2c->receive_callback) { + i2c->receive_callback(i2c->num, data, len, stop, i2c->arg); + } + free(data); + + // Read + } else if (event.event == I2C_SLAVE_EVT_TX) { + if (i2c->request_callback) { + i2c->request_callback(i2c->num, i2c->arg); + } + i2c_ll_stretch_clr(i2c->dev); } } - vTaskDelete(NULL); } + vTaskDelete(NULL); +} - static bool i2cSlaveDetachBus(void *bus_i2c_num) { - uint8_t num = (int)bus_i2c_num - 1; - i2c_slave_struct_t *i2c = &_i2c_bus_array[num]; - if (i2c->scl == -1 && i2c->sda == -1) { - return true; - } - esp_err_t err = i2cSlaveDeinit(num); - if (err != ESP_OK) { - log_e("i2cSlaveDeinit failed with error: %d", err); - return false; - } +static bool i2cSlaveDetachBus(void *bus_i2c_num) { + uint8_t num = (int)bus_i2c_num - 1; + i2c_slave_struct_t *i2c = &_i2c_bus_array[num]; + if (i2c->scl == -1 && i2c->sda == -1) { return true; } + esp_err_t err = i2cSlaveDeinit(num); + if (err != ESP_OK) { + log_e("i2cSlaveDeinit failed with error: %d", err); + return false; + } + return true; +} #endif /* SOC_I2C_SUPPORT_SLAVE */ diff --git a/cores/esp32/esp32-hal-spi.c b/cores/esp32/esp32-hal-spi.c index 8c8ce0b7705..af3fd7b5f06 100644 --- a/cores/esp32/esp32-hal-spi.c +++ b/cores/esp32/esp32-hal-spi.c @@ -148,13 +148,15 @@ struct spi_struct_t { #if CONFIG_DISABLE_HAL_LOCKS #define SPI_MUTEX_LOCK() #define SPI_MUTEX_UNLOCK() -+ static spi_t _spi_bus_array[] = { +// clang-format off +static spi_t _spi_bus_array[] = { #if CONFIG_IDF_TARGET_ESP32S2 {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 0, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 1, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 2, -1, -1, -1, -1} #elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 1, -1, -1, -1, -1} + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1}, + {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 1, -1, -1, -1, -1} #elif CONFIG_IDF_TARGET_ESP32C2 {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1} #elif CONFIG_IDF_TARGET_ESP32C3 @@ -168,6 +170,7 @@ struct spi_struct_t { {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3, -1, -1, -1, -1} #endif }; +// clang-format on #else #define SPI_MUTEX_LOCK() \ do { \ diff --git a/cores/esp32/esp32-hal-touch.c b/cores/esp32/esp32-hal-touch.c index 4c0ed92656c..93e0cb1c4ac 100644 --- a/cores/esp32/esp32-hal-touch.c +++ b/cores/esp32/esp32-hal-touch.c @@ -29,7 +29,7 @@ #if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 static uint16_t __touchSleepCycles = 0x1000; static uint16_t __touchMeasureCycles = 0x1000; -#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 +#elif SOC_TOUCH_SENSOR_VERSION >= 2 // ESP32S2, ESP32S3, ESP32P4 static uint16_t __touchSleepCycles = TOUCH_PAD_SLEEP_CYCLE_DEFAULT; static uint16_t __touchMeasureCycles = TOUCH_PAD_MEASURE_CYCLE_DEFAULT; #endif diff --git a/libraries/BLE/examples/BLE5_multi_advertising/ci.json b/libraries/BLE/examples/BLE5_multi_advertising/ci.json index fc9f75986fe..e97e4cf7fea 100644 --- a/libraries/BLE/examples/BLE5_multi_advertising/ci.json +++ b/libraries/BLE/examples/BLE5_multi_advertising/ci.json @@ -1,5 +1,6 @@ { "targets": { + "esp32": false, "esp32p4": false, "esp32s2": false } diff --git a/libraries/BLE/examples/BLE5_periodic_advertising/ci.json b/libraries/BLE/examples/BLE5_periodic_advertising/ci.json index a034e239a3f..e97e4cf7fea 100644 --- a/libraries/BLE/examples/BLE5_periodic_advertising/ci.json +++ b/libraries/BLE/examples/BLE5_periodic_advertising/ci.json @@ -1,10 +1,7 @@ { "targets": { "esp32": false, - "esp32c2": false, - "esp32c3": false, "esp32p4": false, - "esp32s2": false, - "esp32s3": false + "esp32s2": false } } diff --git a/libraries/BLE/examples/BLE5_periodic_sync/ci.json b/libraries/BLE/examples/BLE5_periodic_sync/ci.json index 715becda6cb..e97e4cf7fea 100644 --- a/libraries/BLE/examples/BLE5_periodic_sync/ci.json +++ b/libraries/BLE/examples/BLE5_periodic_sync/ci.json @@ -1,9 +1,6 @@ { "targets": { "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, "esp32p4": false, "esp32s2": false } diff --git a/libraries/BLE/examples/Beacon_Scanner/ci.json b/libraries/BLE/examples/Beacon_Scanner/ci.json index ee810400be6..fc9f75986fe 100644 --- a/libraries/BLE/examples/Beacon_Scanner/ci.json +++ b/libraries/BLE/examples/Beacon_Scanner/ci.json @@ -1,8 +1,5 @@ { "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, "esp32p4": false, "esp32s2": false } diff --git a/libraries/BLE/examples/Client/ci.json b/libraries/BLE/examples/Client/ci.json index eb6596c4a37..fc9f75986fe 100644 --- a/libraries/BLE/examples/Client/ci.json +++ b/libraries/BLE/examples/Client/ci.json @@ -1,6 +1,5 @@ { "targets": { - "esp32c3": false, "esp32p4": false, "esp32s2": false } diff --git a/libraries/BLE/examples/Notify/ci.json b/libraries/BLE/examples/Notify/ci.json index 156dda6560c..fc9f75986fe 100644 --- a/libraries/BLE/examples/Notify/ci.json +++ b/libraries/BLE/examples/Notify/ci.json @@ -1,6 +1,5 @@ { "targets": { - "esp32h2": false, "esp32p4": false, "esp32s2": false } diff --git a/libraries/BLE/examples/Server/ci.json b/libraries/BLE/examples/Server/ci.json index a034e239a3f..fc9f75986fe 100644 --- a/libraries/BLE/examples/Server/ci.json +++ b/libraries/BLE/examples/Server/ci.json @@ -1,10 +1,6 @@ { "targets": { - "esp32": false, - "esp32c2": false, - "esp32c3": false, "esp32p4": false, - "esp32s2": false, - "esp32s3": false + "esp32s2": false } } diff --git a/libraries/BLE/examples/Server_multiconnect/ci.json b/libraries/BLE/examples/Server_multiconnect/ci.json index 715becda6cb..fc9f75986fe 100644 --- a/libraries/BLE/examples/Server_multiconnect/ci.json +++ b/libraries/BLE/examples/Server_multiconnect/ci.json @@ -1,9 +1,5 @@ { "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, "esp32p4": false, "esp32s2": false } diff --git a/libraries/BLE/examples/UART/ci.json b/libraries/BLE/examples/UART/ci.json index ee810400be6..fc9f75986fe 100644 --- a/libraries/BLE/examples/UART/ci.json +++ b/libraries/BLE/examples/UART/ci.json @@ -1,8 +1,5 @@ { "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, "esp32p4": false, "esp32s2": false } diff --git a/libraries/BLE/examples/Write/ci.json b/libraries/BLE/examples/Write/ci.json index eb6596c4a37..fc9f75986fe 100644 --- a/libraries/BLE/examples/Write/ci.json +++ b/libraries/BLE/examples/Write/ci.json @@ -1,6 +1,5 @@ { "targets": { - "esp32c3": false, "esp32p4": false, "esp32s2": false } diff --git a/libraries/BLE/examples/iBeacon/ci.json b/libraries/BLE/examples/iBeacon/ci.json index 156dda6560c..fc9f75986fe 100644 --- a/libraries/BLE/examples/iBeacon/ci.json +++ b/libraries/BLE/examples/iBeacon/ci.json @@ -1,6 +1,5 @@ { "targets": { - "esp32h2": false, "esp32p4": false, "esp32s2": false } diff --git a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json index 25c42144223..cd679adefad 100644 --- a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json +++ b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json @@ -2,6 +2,7 @@ "targets": { "esp32c3": false, "esp32c6": false, - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESP32/examples/Touch/TouchButton/ci.json b/libraries/ESP32/examples/Touch/TouchButton/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/ESP32/examples/Touch/TouchButton/ci.json +++ b/libraries/ESP32/examples/Touch/TouchButton/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json b/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json index e7d65393dd6..d87f049685e 100644 --- a/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json +++ b/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json @@ -3,6 +3,7 @@ "esp32": false, "esp32c3": false, "esp32c6": false, - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json b/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json index 25c42144223..cd679adefad 100644 --- a/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json +++ b/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json @@ -2,6 +2,7 @@ "targets": { "esp32c3": false, "esp32c6": false, - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESP32/examples/Touch/TouchRead/ci.json b/libraries/ESP32/examples/Touch/TouchRead/ci.json index 25c42144223..cd679adefad 100644 --- a/libraries/ESP32/examples/Touch/TouchRead/ci.json +++ b/libraries/ESP32/examples/Touch/TouchRead/ci.json @@ -2,6 +2,7 @@ "targets": { "esp32c3": false, "esp32c6": false, - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/Ethernet/examples/ETH_LAN8720/ci.json b/libraries/Ethernet/examples/ETH_LAN8720/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/Ethernet/examples/ETH_LAN8720/ci.json +++ b/libraries/Ethernet/examples/ETH_LAN8720/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/Ethernet/examples/ETH_TLK110/ci.json b/libraries/Ethernet/examples/ETH_TLK110/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/Ethernet/examples/ETH_TLK110/ci.json +++ b/libraries/Ethernet/examples/ETH_TLK110/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/OpenThread/examples/COAP/coap_switch/ci.json b/libraries/OpenThread/examples/COAP/coap_switch/ci.json index 715becda6cb..a034e239a3f 100644 --- a/libraries/OpenThread/examples/COAP/coap_switch/ci.json +++ b/libraries/OpenThread/examples/COAP/coap_switch/ci.json @@ -1,10 +1,10 @@ { "targets": { "esp32": false, + "esp32c2": false, "esp32c3": false, - "esp32c6": false, - "esp32h2": false, "esp32p4": false, - "esp32s2": false + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/OpenThread/examples/SimpleCLI/ci.json b/libraries/OpenThread/examples/SimpleCLI/ci.json index ee810400be6..a034e239a3f 100644 --- a/libraries/OpenThread/examples/SimpleCLI/ci.json +++ b/libraries/OpenThread/examples/SimpleCLI/ci.json @@ -1,9 +1,10 @@ { "targets": { + "esp32": false, + "esp32c2": false, "esp32c3": false, - "esp32c6": false, - "esp32h2": false, "esp32p4": false, - "esp32s2": false + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/OpenThread/examples/SimpleNode/ci.json b/libraries/OpenThread/examples/SimpleNode/ci.json index eb6596c4a37..a034e239a3f 100644 --- a/libraries/OpenThread/examples/SimpleNode/ci.json +++ b/libraries/OpenThread/examples/SimpleNode/ci.json @@ -1,7 +1,10 @@ { "targets": { + "esp32": false, + "esp32c2": false, "esp32c3": false, "esp32p4": false, - "esp32s2": false + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json index 156dda6560c..a034e239a3f 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json @@ -1,7 +1,10 @@ { "targets": { - "esp32h2": false, + "esp32": false, + "esp32c2": false, + "esp32c3": false, "esp32p4": false, - "esp32s2": false + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/SPI/examples/SPI_Multiple_Buses/SPI_Multiple_Buses.ino b/libraries/SPI/examples/SPI_Multiple_Buses/SPI_Multiple_Buses.ino index c73f6078c03..3d3d3e4e38e 100644 --- a/libraries/SPI/examples/SPI_Multiple_Buses/SPI_Multiple_Buses.ino +++ b/libraries/SPI/examples/SPI_Multiple_Buses/SPI_Multiple_Buses.ino @@ -39,7 +39,7 @@ #define HSPI_SS 15 #endif -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 #define VSPI FSPI #endif diff --git a/tests/validation/periman/ci.json b/tests/validation/periman/ci.json index accee2b2135..22ff71c54ff 100644 --- a/tests/validation/periman/ci.json +++ b/tests/validation/periman/ci.json @@ -2,5 +2,8 @@ "platforms": { "qemu": false, "wokwi": false + }, + "targets": { + "esp32p4": false } } diff --git a/tests/validation/touch/ci.json b/tests/validation/touch/ci.json index 8d58dbf5250..d3129f16bae 100644 --- a/tests/validation/touch/ci.json +++ b/tests/validation/touch/ci.json @@ -6,6 +6,7 @@ "targets": { "esp32c3": false, "esp32c6": false, - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/tests/validation/uart/uart.ino b/tests/validation/uart/uart.ino index a68ef879659..e5fa0a8285f 100644 --- a/tests/validation/uart/uart.ino +++ b/tests/validation/uart/uart.ino @@ -100,7 +100,7 @@ void transmit_and_check_msg(const String msg_append, bool perform_assert = true) if (perform_assert) { TEST_ASSERT_EQUAL_STRING(("Hello from Serial1 (UART1) >>> via loopback >>> Serial1 (UART1) " + msg_append).c_str(), recv_msg.c_str()); } -#elif SOC_UART_HP_NUM == 3 +#elif SOC_UART_HP_NUM >= 3 Serial1.print("Hello from Serial1 (UART1) >>> to >>> Serial2 (UART2) " + msg_append); Serial1.flush(); delay(100); @@ -128,7 +128,7 @@ void task_delayed_msg(void *pvParameters) { #if SOC_UART_HP_NUM == 2 selected_serial = &Serial; -#elif SOC_UART_HP_NUM == 3 +#elif SOC_UART_HP_NUM >= 3 selected_serial = &Serial1; #endif @@ -150,7 +150,7 @@ void setUp(void) { onReceive_cb(Serial1); }); uart_internal_loopback(1, RX1); -#elif SOC_UART_HP_NUM == 3 +#elif SOC_UART_HP_NUM >= 3 log_d("Setup internal loop-back between Serial1 (UART1) <<--->> Serial2 (UART2)"); Serial1.onReceive([]() { @@ -225,7 +225,7 @@ void change_baudrate_test(void) { Serial1.updateBaudRate(9600); TEST_ASSERT_UINT_WITHIN(192, 9600, Serial1.baudRate()); -#if SOC_UART_HP_NUM == 3 +#if SOC_UART_HP_NUM >= 3 Serial2.updateBaudRate(9600); TEST_ASSERT_UINT_WITHIN(192, 9600, Serial2.baudRate()); #endif @@ -239,7 +239,7 @@ void change_baudrate_test(void) { //Baudrate error should be within 2% of the target baudrate TEST_ASSERT_UINT_WITHIN(2304, 115200, Serial1.baudRate()); -#if SOC_UART_HP_NUM == 3 +#if SOC_UART_HP_NUM >= 3 TEST_ASSERT_UINT_WITHIN(2304, 115200, Serial2.baudRate()); #endif @@ -421,7 +421,7 @@ void change_pins_test(void) { #if SOC_UART_HP_NUM == 2 esp_rom_gpio_connect_out_signal(SOC_RX0, SIG_GPIO_OUT_IDX, false, false); -#elif SOC_UART_HP_NUM == 3 +#elif SOC_UART_HP_NUM >= 3 esp_rom_gpio_connect_out_signal(RX1, SIG_GPIO_OUT_IDX, false, false); esp_rom_gpio_connect_out_signal(RX2, SIG_GPIO_OUT_IDX, false, false); #endif @@ -432,7 +432,7 @@ void change_pins_test(void) { Serial1.setPins(NEW_RX1, NEW_TX1); TEST_ASSERT_EQUAL(NEW_RX1, uart_get_RxPin(1)); TEST_ASSERT_EQUAL(NEW_TX1, uart_get_TxPin(1)); -#elif SOC_UART_HP_NUM == 3 +#elif SOC_UART_HP_NUM >= 3 Serial1.setPins(RX2, TX2); Serial2.setPins(RX1, TX1); TEST_ASSERT_EQUAL(RX2, uart_get_RxPin(1)); @@ -447,7 +447,7 @@ void change_pins_test(void) { #if SOC_UART_HP_NUM == 2 uart_internal_loopback(1, NEW_RX1); -#elif SOC_UART_HP_NUM == 3 +#elif SOC_UART_HP_NUM >= 3 uart_internal_loopback(1, RX1); uart_internal_loopback(2, RX2); #endif @@ -470,7 +470,7 @@ void auto_baudrate_test(void) { #if SOC_UART_HP_NUM == 2 selected_serial = &Serial1; uart_internal_loopback(0, RX1); -#elif SOC_UART_HP_NUM == 3 +#elif SOC_UART_HP_NUM >= 3 selected_serial = &Serial2; #endif @@ -504,7 +504,7 @@ void periman_test(void) { Wire.begin(RX1, TX1); -#if SOC_UART_HP_NUM == 3 +#if SOC_UART_HP_NUM >= 3 Wire1.begin(RX2, TX2); #endif @@ -518,7 +518,7 @@ void periman_test(void) { Serial1.setPins(RX1, TX1); -#if SOC_UART_HP_NUM == 3 +#if SOC_UART_HP_NUM >= 3 Serial2.setPins(RX2, TX2); uart_internal_loopback(1, RX2); uart_internal_loopback(2, RX1); @@ -577,7 +577,7 @@ void setup() { onReceive_cb(Serial1); }); uart_internal_loopback(1, RX1); -#elif SOC_UART_HP_NUM == 3 +#elif SOC_UART_HP_NUM >= 3 log_d("Setup internal loop-back between Serial1 (UART1) <<--->> Serial2 (UART2)"); Serial1.onReceive([]() { diff --git a/tests/validation/wifi/ci.json b/tests/validation/wifi/ci.json index ff2c1d7c9ce..a51b5669598 100644 --- a/tests/validation/wifi/ci.json +++ b/tests/validation/wifi/ci.json @@ -22,6 +22,7 @@ "qemu": false }, "targets": { - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/variants/esp32p4/pins_arduino.h b/variants/esp32p4/pins_arduino.h index 87d0548cf3c..caba8995222 100644 --- a/variants/esp32p4/pins_arduino.h +++ b/variants/esp32p4/pins_arduino.h @@ -27,4 +27,34 @@ static const uint8_t MOSI = 11; static const uint8_t MISO = 12; static const uint8_t SCK = 13; +static const uint8_t A0 = 16; +static const uint8_t A1 = 17; +static const uint8_t A2 = 18; +static const uint8_t A3 = 19; +static const uint8_t A4 = 20; +static const uint8_t A5 = 21; +static const uint8_t A6 = 22; +static const uint8_t A7 = 23; +static const uint8_t A8 = 49; +static const uint8_t A9 = 50; +static const uint8_t A10 = 51; +static const uint8_t A11 = 52; +static const uint8_t A12 = 53; +static const uint8_t A13 = 54; + +static const uint8_t T0 = 2; +static const uint8_t T1 = 3; +static const uint8_t T2 = 4; +static const uint8_t T3 = 5; +static const uint8_t T4 = 6; +static const uint8_t T5 = 7; +static const uint8_t T6 = 8; +static const uint8_t T7 = 9; +static const uint8_t T8 = 10; +static const uint8_t T9 = 11; +static const uint8_t T10 = 12; +static const uint8_t T11 = 13; +static const uint8_t T12 = 14; +static const uint8_t T13 = 15; + #endif /* Pins_Arduino_h */ From 8422b745c24fe6739956d6a317f34ea8df5242e1 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Mon, 30 Sep 2024 09:27:10 -0300 Subject: [PATCH 014/409] Fix touch examples JSON for P4 --- libraries/ESP32/examples/Touch/TouchInterrupt/ci.json | 5 ++++- libraries/ESP32/examples/Touch/TouchRead/ci.json | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json b/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json index c0ecf9fc0a5..4363987f4d6 100644 --- a/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json +++ b/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json @@ -1,5 +1,8 @@ { "requires": [ "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" - ] + ], + "targets": { + "esp32p4": false + } } diff --git a/libraries/ESP32/examples/Touch/TouchRead/ci.json b/libraries/ESP32/examples/Touch/TouchRead/ci.json index c0ecf9fc0a5..4363987f4d6 100644 --- a/libraries/ESP32/examples/Touch/TouchRead/ci.json +++ b/libraries/ESP32/examples/Touch/TouchRead/ci.json @@ -1,5 +1,8 @@ { "requires": [ "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" - ] + ], + "targets": { + "esp32p4": false + } } From a76b22881a82621e7aaa464e66924690c3e9311c Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Mon, 30 Sep 2024 19:21:46 -0300 Subject: [PATCH 015/409] Fix ethernet examples JSON for P4 --- libraries/Ethernet/examples/ETH_LAN8720/ci.json | 5 ++++- libraries/Ethernet/examples/ETH_TLK110/ci.json | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/Ethernet/examples/ETH_LAN8720/ci.json b/libraries/Ethernet/examples/ETH_LAN8720/ci.json index dcdfd06db51..0eab13b8841 100644 --- a/libraries/Ethernet/examples/ETH_LAN8720/ci.json +++ b/libraries/Ethernet/examples/ETH_LAN8720/ci.json @@ -1,5 +1,8 @@ { "requires": [ "CONFIG_ETH_USE_ESP32_EMAC=y" - ] + ], + "targets": { + "esp32p4": false + } } diff --git a/libraries/Ethernet/examples/ETH_TLK110/ci.json b/libraries/Ethernet/examples/ETH_TLK110/ci.json index dcdfd06db51..0eab13b8841 100644 --- a/libraries/Ethernet/examples/ETH_TLK110/ci.json +++ b/libraries/Ethernet/examples/ETH_TLK110/ci.json @@ -1,5 +1,8 @@ { "requires": [ "CONFIG_ETH_USE_ESP32_EMAC=y" - ] + ], + "targets": { + "esp32p4": false + } } From c980fdc99691fc797f1d56a03ea18c4893c4d598 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 1 Oct 2024 12:34:44 +0300 Subject: [PATCH 016/409] Update early system init function declaration --- cores/esp32/esp32-hal-misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp32/esp32-hal-misc.c b/cores/esp32/esp32-hal-misc.c index acc908d2093..d3782c39aa3 100644 --- a/cores/esp32/esp32-hal-misc.c +++ b/cores/esp32/esp32-hal-misc.c @@ -254,7 +254,7 @@ extern bool btInUse(); #if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM #ifndef CONFIG_SPIRAM_BOOT_INIT -ESP_SYSTEM_INIT_FN(init_psram_new, BIT(0), 99) { +ESP_SYSTEM_INIT_FN(init_psram_new, CORE, BIT(0), 99) { return psramInit() ? ESP_OK : ESP_FAIL; } #endif From 482c0a3c26d9f69a6e4b3cc7da92a5545d16f27a Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 1 Oct 2024 15:43:05 +0300 Subject: [PATCH 017/409] fix(psram): Do not abort if PSRAM is not found Also add to heap in app_main --- cores/esp32/esp32-hal-misc.c | 8 +++++++- cores/esp32/esp32-hal-psram.c | 18 +++++++++++++----- cores/esp32/esp32-hal-psram.h | 1 + 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/cores/esp32/esp32-hal-misc.c b/cores/esp32/esp32-hal-misc.c index d3782c39aa3..1fb1d2af9df 100644 --- a/cores/esp32/esp32-hal-misc.c +++ b/cores/esp32/esp32-hal-misc.c @@ -255,7 +255,8 @@ extern bool btInUse(); #if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM #ifndef CONFIG_SPIRAM_BOOT_INIT ESP_SYSTEM_INIT_FN(init_psram_new, CORE, BIT(0), 99) { - return psramInit() ? ESP_OK : ESP_FAIL; + psramInit(); + return ESP_OK; } #endif #endif @@ -263,6 +264,11 @@ ESP_SYSTEM_INIT_FN(init_psram_new, CORE, BIT(0), 99) { void initArduino() { //init proper ref tick value for PLL (uncomment if REF_TICK is different than 1MHz) //ESP_REG(APB_CTRL_PLL_TICK_CONF_REG) = APB_CLK_FREQ / REF_CLK_FREQ - 1; +#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM +#ifndef CONFIG_SPIRAM_BOOT_INIT + psramAddToHeap(); +#endif +#endif #ifdef CONFIG_APP_ROLLBACK_ENABLE if (!verifyRollbackLater()) { const esp_partition_t *running = esp_ota_get_running_partition(); diff --git a/cores/esp32/esp32-hal-psram.c b/cores/esp32/esp32-hal-psram.c index d2c5ab96fc3..6b0b631791b 100644 --- a/cores/esp32/esp32-hal-psram.c +++ b/cores/esp32/esp32-hal-psram.c @@ -81,17 +81,25 @@ bool psramInit() { ESP_EARLY_LOGE(TAG, "PSRAM test failed!"); return false; } + ESP_EARLY_LOGI(TAG, "PSRAM enabled"); +#endif /* CONFIG_SPIRAM_BOOT_INIT */ + spiramDetected = true; + return true; +} + +bool psramAddToHeap() { + if (!spiramDetected) { + log_e("PSRAM not initialized!"); + return false; + } if (esp_psram_extram_add_to_heap_allocator() != ESP_OK) { - spiramFailed = true; - ESP_EARLY_LOGE(TAG, "PSRAM could not be added to the heap!"); + log_e("PSRAM could not be added to the heap!"); return false; } #if CONFIG_SPIRAM_USE_MALLOC && !CONFIG_ARDUINO_ISR_IRAM heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL); #endif - ESP_EARLY_LOGI(TAG, "PSRAM enabled"); -#endif /* CONFIG_SPIRAM_BOOT_INIT */ - spiramDetected = true; + log_i("PSRAM added to the heap."); return true; } diff --git a/cores/esp32/esp32-hal-psram.h b/cores/esp32/esp32-hal-psram.h index 0ba6763c69f..e82af1342c2 100644 --- a/cores/esp32/esp32-hal-psram.h +++ b/cores/esp32/esp32-hal-psram.h @@ -31,6 +31,7 @@ extern "C" { #endif bool psramInit(); +bool psramAddToHeap(); bool psramFound(); void *ps_malloc(size_t size); From 753e2032e731f7ca1a5318a735f9175babc0aa3f Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 1 Oct 2024 16:11:59 +0300 Subject: [PATCH 018/409] fix(psram): ESP32-S2 does not like to early debug log --- cores/esp32/esp32-hal-psram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp32/esp32-hal-psram.c b/cores/esp32/esp32-hal-psram.c index 6b0b631791b..3c7a51c3343 100644 --- a/cores/esp32/esp32-hal-psram.c +++ b/cores/esp32/esp32-hal-psram.c @@ -81,7 +81,7 @@ bool psramInit() { ESP_EARLY_LOGE(TAG, "PSRAM test failed!"); return false; } - ESP_EARLY_LOGI(TAG, "PSRAM enabled"); + //ESP_EARLY_LOGI(TAG, "PSRAM enabled"); #endif /* CONFIG_SPIRAM_BOOT_INIT */ spiramDetected = true; return true; From 8af91fb4a7fb9554bf776977ebd432ef1de2a473 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 1 Oct 2024 12:50:04 +0300 Subject: [PATCH 019/409] Fix build of camera web server --- .../ESP32/examples/Camera/CameraWebServer/ci.json | 15 +++++++++++++++ .../Camera/CameraWebServer/partitions.csv | 5 +++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/libraries/ESP32/examples/Camera/CameraWebServer/ci.json b/libraries/ESP32/examples/Camera/CameraWebServer/ci.json index 7e0f3c89986..35c3056dda8 100644 --- a/libraries/ESP32/examples/Camera/CameraWebServer/ci.json +++ b/libraries/ESP32/examples/Camera/CameraWebServer/ci.json @@ -1,4 +1,19 @@ { + "fqbn": { + "esp32": [ + "espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=custom,FlashMode=dio", + "espressif:esp32:esp32:PSRAM=disabled,PartitionScheme=custom,FlashMode=dio" + ], + "esp32s2": [ + "espressif:esp32:esp32s2:PSRAM=enabled,PartitionScheme=custom,FlashMode=dio", + "espressif:esp32:esp32s2:PSRAM=disabled,PartitionScheme=custom,FlashMode=dio" + ], + "esp32s3": [ + "espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=custom,FlashMode=qio", + "espressif:esp32:esp32s3:PSRAM=enabled,USBMode=default,PartitionScheme=custom,FlashMode=qio", + "espressif:esp32:esp32s3:PSRAM=disabled,USBMode=default,PartitionScheme=custom,FlashMode=qio" + ] + }, "requires": [ "CONFIG_CAMERA_TASK_STACK_SIZE=[0-9]+" ] diff --git a/libraries/ESP32/examples/Camera/CameraWebServer/partitions.csv b/libraries/ESP32/examples/Camera/CameraWebServer/partitions.csv index 4f76ca6d746..b9f18c465a7 100644 --- a/libraries/ESP32/examples/Camera/CameraWebServer/partitions.csv +++ b/libraries/ESP32/examples/Camera/CameraWebServer/partitions.csv @@ -1,5 +1,6 @@ # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x5000, otadata, data, ota, 0xe000, 0x2000, -app0, app, ota_0, 0x10000, 0x3d0000, -fr, data, , 0x3e0000, 0x20000, +app0, app, ota_0, 0x10000, 0x3c0000, +fr, data, , 0x3d0000, 0x20000, +coredump, data, coredump,0x3f0000, 0x10000, From 58c0bbc0e9a30e7451bcae81a394c05f63541d33 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 2 Oct 2024 16:17:12 +0300 Subject: [PATCH 020/409] fix(usb): Add support for ESP32-P4 to esp32-hal-tinyusb --- CMakeLists.txt | 2 +- cores/esp32/esp32-hal-tinyusb.c | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ae2df0717b..707e3fe6233 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -343,7 +343,7 @@ function(maybe_add_component component_name) endif() endfunction() -if(IDF_TARGET MATCHES "esp32s2|esp32s3" AND CONFIG_TINYUSB_ENABLED) +if(IDF_TARGET MATCHES "esp32s2|esp32s3|esp32p4" AND CONFIG_TINYUSB_ENABLED) maybe_add_component(arduino_tinyusb) endif() if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ArduinoOTA) diff --git a/cores/esp32/esp32-hal-tinyusb.c b/cores/esp32/esp32-hal-tinyusb.c index f7225425913..4247a299df0 100644 --- a/cores/esp32/esp32-hal-tinyusb.c +++ b/cores/esp32/esp32-hal-tinyusb.c @@ -10,12 +10,15 @@ #include "soc/soc.h" #include "soc/efuse_reg.h" +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #include "soc/rtc_cntl_reg.h" #include "soc/usb_struct.h" #include "soc/usb_reg.h" #include "soc/usb_wrap_reg.h" #include "soc/usb_wrap_struct.h" #include "soc/usb_periph.h" +#endif + #include "soc/periph_defs.h" #include "soc/timer_group_struct.h" #include "soc/system_reg.h" @@ -34,8 +37,8 @@ #include "esp32-hal.h" #include "esp32-hal-periman.h" - #include "esp32-hal-tinyusb.h" + #if CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/rom/usb/usb_persist.h" #include "esp32s2/rom/usb/usb_dc.h" @@ -50,6 +53,7 @@ #include "esp32s3/rom/usb/usb_persist.h" #include "esp32s3/rom/usb/usb_dc.h" #include "esp32s3/rom/usb/chip_usb_dw_wrapper.h" +#elif CONFIG_IDF_TARGET_ESP32P4 #endif typedef enum { @@ -467,8 +471,10 @@ __attribute__((weak)) void tud_network_init_cb(void) {} /* * Private API * */ +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 static bool usb_persist_enabled = false; static restart_type_t usb_persist_mode = RESTART_NO_PERSIST; +#endif #if CONFIG_IDF_TARGET_ESP32S3 @@ -549,6 +555,7 @@ static void usb_switch_to_cdc_jtag() { } #endif +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 static void IRAM_ATTR usb_persist_shutdown_handler(void) { if (usb_persist_mode != RESTART_NO_PERSIST) { if (usb_persist_enabled) { @@ -580,8 +587,10 @@ static void IRAM_ATTR usb_persist_shutdown_handler(void) { } } } +#endif void usb_persist_restart(restart_type_t mode) { +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 if (mode < RESTART_TYPE_MAX && esp_register_shutdown_handler(usb_persist_shutdown_handler) == ESP_OK) { usb_persist_mode = mode; #if CONFIG_IDF_TARGET_ESP32S3 @@ -591,6 +600,7 @@ void usb_persist_restart(restart_type_t mode) { #endif esp_restart(); } +#endif } static bool tinyusb_reserve_in_endpoint(uint8_t endpoint) { @@ -674,8 +684,13 @@ static inline char nibble_to_hex_char(uint8_t b) { static void set_usb_serial_num(void) { /* Get the MAC address */ +#if CONFIG_IDF_TARGET_ESP32P4 + const uint32_t mac0 = REG_GET_FIELD(EFUSE_RD_MAC_SYS_0_REG, EFUSE_MAC_0); + const uint32_t mac1 = REG_GET_FIELD(EFUSE_RD_MAC_SYS_0_REG, EFUSE_MAC_1); +#else const uint32_t mac0 = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_0_REG, EFUSE_MAC_0); const uint32_t mac1 = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_1_REG, EFUSE_MAC_1); +#endif uint8_t mac_bytes[6]; memcpy(mac_bytes, &mac0, 4); memcpy(mac_bytes + 4, &mac1, 2); @@ -794,6 +809,7 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) { return ESP_FAIL; } +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 bool usb_did_persist = (USB_WRAP.date.val == USBDC_PERSIST_ENA); //if(usb_did_persist && usb_persist_enabled){ @@ -806,7 +822,8 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) { periph_ll_reset(PERIPH_USB_MODULE); periph_ll_enable_clk_clear_rst(PERIPH_USB_MODULE); } - +#endif + tinyusb_config_t tusb_cfg = { .external_phy = false // In the most cases you need to use a `false` value }; From b067cd6d7f92bd171546a42ec28d646c52a6053c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Wed, 2 Oct 2024 17:25:15 +0200 Subject: [PATCH 021/409] fix(example): Skip zigbee build for P4 --- libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json | 3 ++- libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json | 3 ++- libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json | 3 ++- libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json | 3 ++- libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json | 3 ++- libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json | 3 ++- libraries/Zigbee/examples/Zigbee_Thermostat/ci.json | 3 ++- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json index 3aaf44eb376..f6e4a17c15d 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json @@ -11,6 +11,7 @@ "esp32": false, "esp32c3": false, "esp32s2": false, - "esp32s3": false + "esp32s3": false, + "esp32p4": false } } diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json index c916121b991..e51a291ca49 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json @@ -11,6 +11,7 @@ "esp32": false, "esp32c3": false, "esp32s2": false, - "esp32s3": false + "esp32s3": false, + "esp32p4": false } } diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json b/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json index 3aaf44eb376..f6e4a17c15d 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json @@ -11,6 +11,7 @@ "esp32": false, "esp32c3": false, "esp32s2": false, - "esp32s3": false + "esp32s3": false, + "esp32p4": false } } diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json index c916121b991..e51a291ca49 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json @@ -11,6 +11,7 @@ "esp32": false, "esp32c3": false, "esp32s2": false, - "esp32s3": false + "esp32s3": false, + "esp32p4": false } } diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json b/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json index 3aaf44eb376..f6e4a17c15d 100644 --- a/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json @@ -11,6 +11,7 @@ "esp32": false, "esp32c3": false, "esp32s2": false, - "esp32s3": false + "esp32s3": false, + "esp32p4": false } } diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json index 3aaf44eb376..f6e4a17c15d 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json @@ -11,6 +11,7 @@ "esp32": false, "esp32c3": false, "esp32s2": false, - "esp32s3": false + "esp32s3": false, + "esp32p4": false } } diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json b/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json index c916121b991..e51a291ca49 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json @@ -11,6 +11,7 @@ "esp32": false, "esp32c3": false, "esp32s2": false, - "esp32s3": false + "esp32s3": false, + "esp32p4": false } } From c5047286a1d743e62d441b8bf23cf5aeda74bac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Wed, 2 Oct 2024 18:40:04 +0200 Subject: [PATCH 022/409] fix(example): Use requires instead of target in ci.json --- .../examples/Zigbee_Color_Dimmable_Light/ci.json | 10 +++------- .../Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json | 10 +++------- libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json | 10 +++------- libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json | 10 +++------- libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json | 10 +++------- .../Zigbee/examples/Zigbee_Temperature_Sensor/ci.json | 10 +++------- libraries/Zigbee/examples/Zigbee_Thermostat/ci.json | 10 +++------- 7 files changed, 21 insertions(+), 49 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json index f6e4a17c15d..d3573967de0 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json @@ -7,11 +7,7 @@ "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" ] }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false, - "esp32p4": false - } + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json index e51a291ca49..3a5d7026228 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json @@ -7,11 +7,7 @@ "espressif:esp32:esp32h2:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" ] }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false, - "esp32p4": false - } + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json b/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json index f6e4a17c15d..d3573967de0 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json @@ -7,11 +7,7 @@ "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" ] }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false, - "esp32p4": false - } + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json index e51a291ca49..3a5d7026228 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json @@ -7,11 +7,7 @@ "espressif:esp32:esp32h2:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" ] }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false, - "esp32p4": false - } + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json b/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json index f6e4a17c15d..d3573967de0 100644 --- a/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json @@ -7,11 +7,7 @@ "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" ] }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false, - "esp32p4": false - } + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json index f6e4a17c15d..d3573967de0 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json @@ -7,11 +7,7 @@ "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" ] }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false, - "esp32p4": false - } + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json b/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json index e51a291ca49..3a5d7026228 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json @@ -7,11 +7,7 @@ "espressif:esp32:esp32h2:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" ] }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false, - "esp32p4": false - } + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } From c3aa74f60ab0d6377d17d5ef14a8ddd08c380be1 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 2 Oct 2024 19:26:33 +0300 Subject: [PATCH 023/409] fix(spiram): Fix OPI PSRAM init --- cores/esp32/esp32-hal-misc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/cores/esp32/esp32-hal-misc.c b/cores/esp32/esp32-hal-misc.c index 1fb1d2af9df..0bce548bdd2 100644 --- a/cores/esp32/esp32-hal-misc.c +++ b/cores/esp32/esp32-hal-misc.c @@ -253,13 +253,11 @@ extern bool btInUse(); #endif #if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM -#ifndef CONFIG_SPIRAM_BOOT_INIT ESP_SYSTEM_INIT_FN(init_psram_new, CORE, BIT(0), 99) { psramInit(); return ESP_OK; } #endif -#endif void initArduino() { //init proper ref tick value for PLL (uncomment if REF_TICK is different than 1MHz) From 01b256ca1cd6d341b53758591eaa905818ff4aaa Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 2 Oct 2024 21:08:49 +0300 Subject: [PATCH 024/409] fix(usb): Enable TinyUSB mode for ESP32-P4 --- .github/scripts/sketch_utils.sh | 2 +- boards.txt | 27 ++++++++++++++++++++++----- platform.txt | 2 +- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/.github/scripts/sketch_utils.sh b/.github/scripts/sketch_utils.sh index eae5c139428..b19a0ab67a9 100755 --- a/.github/scripts/sketch_utils.sh +++ b/.github/scripts/sketch_utils.sh @@ -91,7 +91,7 @@ function build_sketch(){ # build_sketch [ex esp32c3_opts="PartitionScheme=huge_app,FlashMode=dio" esp32c6_opts="PartitionScheme=huge_app,FlashMode=dio" esp32h2_opts="PartitionScheme=huge_app,FlashMode=dio" - esp32p4_opts="PartitionScheme=huge_app,FlashMode=dio" + esp32p4_opts="PartitionScheme=huge_app,FlashMode=dio,USBMode=default" # Select the common part of the FQBN based on the target. The rest will be # appended depending on the passed options. diff --git a/boards.txt b/boards.txt index 0ff823bd4e0..51b4adfd868 100644 --- a/boards.txt +++ b/boards.txt @@ -212,21 +212,38 @@ esp32p4.menu.JTAGAdapter.bridge=ESP USB Bridge esp32p4.menu.JTAGAdapter.bridge.build.openocdscript=esp32p4-bridge.cfg esp32p4.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 -esp32p4.menu.CDCOnBoot.default=Disabled -esp32p4.menu.CDCOnBoot.default.build.cdc_on_boot=0 -esp32p4.menu.CDCOnBoot.cdc=Enabled -esp32p4.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 - esp32p4.menu.PSRAM.disabled=Disabled esp32p4.menu.PSRAM.disabled.build.defines= esp32p4.menu.PSRAM.enabled=Enabled esp32p4.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +esp32p4.menu.USBMode.hwcdc=Hardware CDC and JTAG +esp32p4.menu.USBMode.hwcdc.build.usb_mode=1 +esp32p4.menu.USBMode.default=USB-OTG (TinyUSB) +esp32p4.menu.USBMode.default.build.usb_mode=0 + esp32p4.menu.CDCOnBoot.default=Disabled esp32p4.menu.CDCOnBoot.default.build.cdc_on_boot=0 esp32p4.menu.CDCOnBoot.cdc=Enabled esp32p4.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 +esp32p4.menu.MSCOnBoot.default=Disabled +esp32p4.menu.MSCOnBoot.default.build.msc_on_boot=0 +esp32p4.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +esp32p4.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +esp32p4.menu.DFUOnBoot.default=Disabled +esp32p4.menu.DFUOnBoot.default.build.dfu_on_boot=0 +esp32p4.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +esp32p4.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +esp32p4.menu.UploadMode.default=UART0 / Hardware CDC +esp32p4.menu.UploadMode.default.upload.use_1200bps_touch=false +esp32p4.menu.UploadMode.default.upload.wait_for_upload_port=false +esp32p4.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +esp32p4.menu.UploadMode.cdc.upload.use_1200bps_touch=true +esp32p4.menu.UploadMode.cdc.upload.wait_for_upload_port=true + esp32p4.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) esp32p4.menu.PartitionScheme.default.build.partitions=default esp32p4.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) diff --git a/platform.txt b/platform.txt index b9c31d4337f..8d918d3dea7 100644 --- a/platform.txt +++ b/platform.txt @@ -84,7 +84,7 @@ build.extra_flags.esp32c2=-DARDUINO_USB_CDC_ON_BOOT=0 build.extra_flags.esp32c3=-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} build.extra_flags.esp32c6=-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} build.extra_flags.esp32h2=-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} -build.extra_flags.esp32p4=-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} +build.extra_flags.esp32p4=-DARDUINO_USB_MODE={build.usb_mode} -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} -DARDUINO_USB_MSC_ON_BOOT={build.msc_on_boot} -DARDUINO_USB_DFU_ON_BOOT={build.dfu_on_boot} # This can be overriden in boards.txt build.zigbee_mode= From 157b4c864388fe8461471f2abaf85da70259537f Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Wed, 2 Oct 2024 22:26:26 +0300 Subject: [PATCH 025/409] IDF release/v5.3 (#10403) IDF release/v5.3 707d097b --- package/package_esp32_index.template.json | 68 +++++++++++------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 4df82b26bee..ea85072b9cb 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -42,7 +42,7 @@ { "packager": "esp32", "name": "esp32-arduino-libs", - "version": "idf-release_v5.3-4d0db704" + "version": "idf-release_v5.3-707d097b" }, { "packager": "esp32", @@ -95,63 +95,63 @@ "tools": [ { "name": "esp32-arduino-libs", - "version": "idf-release_v5.3-4d0db704", + "version": "idf-release_v5.3-707d097b", "systems": [ { "host": "i686-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", - "size": "360076736" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", + "size": "399730073" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", - "size": "360076736" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", + "size": "399730073" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", - "size": "360076736" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", + "size": "399730073" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", - "size": "360076736" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", + "size": "399730073" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", - "size": "360076736" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", + "size": "399730073" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", - "size": "360076736" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", + "size": "399730073" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", - "size": "360076736" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", + "size": "399730073" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-4d0db704.zip", - "checksum": "SHA-256:645b7579d22e7de73c87cce1d52629f9780de9f18be5b5b066ac0f2c210e9bef", - "size": "360076736" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", + "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", + "size": "399730073" } ] }, From 341dc18079245c62dc66d397825058a5b59805fd Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 3 Oct 2024 13:47:24 +0300 Subject: [PATCH 026/409] fix(usb): Add support for HighSpeed USB This commit adds support for HighSpeed USB as present on ESP32-P4 --- cores/esp32/USBCDC.cpp | 2 +- cores/esp32/USBMSC.cpp | 2 +- cores/esp32/esp32-hal-tinyusb.c | 10 +++++++++- cores/esp32/esp32-hal-tinyusb.h | 8 ++++++++ libraries/USB/src/USBHID.cpp | 2 +- libraries/USB/src/USBMIDI.cpp | 2 +- libraries/USB/src/USBVendor.cpp | 11 +++++++---- libraries/USB/src/USBVendor.h | 2 +- 8 files changed, 29 insertions(+), 10 deletions(-) diff --git a/cores/esp32/USBCDC.cpp b/cores/esp32/USBCDC.cpp index 2689086013a..795a17dc0b8 100644 --- a/cores/esp32/USBCDC.cpp +++ b/cores/esp32/USBCDC.cpp @@ -31,7 +31,7 @@ USBCDC *devices[MAX_USB_CDC_DEVICES] = {NULL, NULL}; static uint16_t load_cdc_descriptor(uint8_t *dst, uint8_t *itf) { uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC"); uint8_t descriptor[TUD_CDC_DESC_LEN] = {// Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, 64, 0x03, 0x84, 64) + TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, CFG_TUD_ENDOINT_SIZE, 0x03, 0x84, CFG_TUD_ENDOINT_SIZE) }; *itf += 2; memcpy(dst, descriptor, TUD_CDC_DESC_LEN); diff --git a/cores/esp32/USBMSC.cpp b/cores/esp32/USBMSC.cpp index eeaf3026535..aeb79883f0d 100644 --- a/cores/esp32/USBMSC.cpp +++ b/cores/esp32/USBMSC.cpp @@ -24,7 +24,7 @@ extern "C" uint16_t tusb_msc_load_descriptor(uint8_t *dst, uint8_t *itf) { uint8_t ep_num = tinyusb_get_free_duplex_endpoint(); TU_VERIFY(ep_num != 0); uint8_t descriptor[TUD_MSC_DESC_LEN] = {// Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(*itf, str_index, ep_num, (uint8_t)(0x80 | ep_num), 64) + TUD_MSC_DESCRIPTOR(*itf, str_index, ep_num, (uint8_t)(0x80 | ep_num), CFG_TUD_ENDOINT_SIZE) }; *itf += 1; memcpy(dst, descriptor, TUD_MSC_DESC_LEN); diff --git a/cores/esp32/esp32-hal-tinyusb.c b/cores/esp32/esp32-hal-tinyusb.c index 4247a299df0..c69fca08fc7 100644 --- a/cores/esp32/esp32-hal-tinyusb.c +++ b/cores/esp32/esp32-hal-tinyusb.c @@ -131,7 +131,11 @@ esp_err_t init_usb_hal(bool external_phy) { .controller = USB_PHY_CTRL_OTG, .target = USB_PHY_TARGET_INT, .otg_mode = USB_OTG_MODE_DEVICE, +#if CONFIG_IDF_TARGET_ESP32P4 + .otg_speed = USB_PHY_SPEED_HIGH, +#else .otg_speed = USB_PHY_SPEED_FULL, +#endif .ext_io_conf = NULL, .otg_io_conf = NULL, }; @@ -169,7 +173,11 @@ void deinit_usb_hal() { esp_err_t tinyusb_driver_install(const tinyusb_config_t *config) { init_usb_hal(config->external_phy); - if (!tusb_init()) { +#if CONFIG_IDF_TARGET_ESP32P4 + if (!tud_init(1)) { +#else + if (!tud_init(0)) { +#endif log_e("Can't initialize the TinyUSB stack."); return ESP_FAIL; } diff --git a/cores/esp32/esp32-hal-tinyusb.h b/cores/esp32/esp32-hal-tinyusb.h index 9e9d044f80e..0b42760e69f 100644 --- a/cores/esp32/esp32-hal-tinyusb.h +++ b/cores/esp32/esp32-hal-tinyusb.h @@ -31,6 +31,14 @@ extern "C" { #define USB_ESPRESSIF_VID 0x303A #define USB_STRING_DESCRIPTOR_ARRAY_SIZE 10 +#ifndef CFG_TUD_ENDOINT_SIZE +#if CONFIG_IDF_TARGET_ESP32P4 +#define CFG_TUD_ENDOINT_SIZE 512 +#else +#define CFG_TUD_ENDOINT_SIZE 64 +#endif +#endif + typedef struct { uint16_t vid; uint16_t pid; diff --git a/libraries/USB/src/USBHID.cpp b/libraries/USB/src/USBHID.cpp index 75f37ef5df3..4bc555b8e30 100644 --- a/libraries/USB/src/USBHID.cpp +++ b/libraries/USB/src/USBHID.cpp @@ -206,7 +206,7 @@ extern "C" uint16_t tusb_hid_load_descriptor(uint8_t *dst, uint8_t *itf) { uint8_t descriptor[TUD_HID_INOUT_DESC_LEN] = { // HID Input & Output descriptor // Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval - TUD_HID_INOUT_DESCRIPTOR(*itf, str_index, tinyusb_interface_protocol, tinyusb_hid_device_descriptor_len, ep_out, (uint8_t)(0x80 | ep_in), 64, 1) + TUD_HID_INOUT_DESCRIPTOR(*itf, str_index, tinyusb_interface_protocol, tinyusb_hid_device_descriptor_len, ep_out, (uint8_t)(0x80 | ep_in), CFG_TUD_ENDOINT_SIZE, 1) }; *itf += 1; memcpy(dst, descriptor, TUD_HID_INOUT_DESC_LEN); diff --git a/libraries/USB/src/USBMIDI.cpp b/libraries/USB/src/USBMIDI.cpp index cfc40e7b154..8a9571855e1 100644 --- a/libraries/USB/src/USBMIDI.cpp +++ b/libraries/USB/src/USBMIDI.cpp @@ -24,7 +24,7 @@ extern "C" uint16_t tusb_midi_load_descriptor(uint8_t *dst, uint8_t *itf) { uint8_t ep_out = tinyusb_get_free_out_endpoint(); TU_VERIFY(ep_out != 0); uint8_t descriptor[TUD_MIDI_DESC_LEN] = { - TUD_MIDI_DESCRIPTOR(*itf, str_index, ep_out, (uint8_t)(0x80 | ep_in), 64), + TUD_MIDI_DESCRIPTOR(*itf, str_index, ep_out, (uint8_t)(0x80 | ep_in), CFG_TUD_ENDOINT_SIZE), }; *itf += 2; memcpy(dst, descriptor, TUD_MIDI_DESC_LEN); diff --git a/libraries/USB/src/USBVendor.cpp b/libraries/USB/src/USBVendor.cpp index 293d5866945..70fac5770ae 100644 --- a/libraries/USB/src/USBVendor.cpp +++ b/libraries/USB/src/USBVendor.cpp @@ -24,7 +24,7 @@ esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, i static USBVendor *_Vendor = NULL; static QueueHandle_t rx_queue = NULL; -static uint8_t USB_VENDOR_ENDPOINT_SIZE = 64; +static uint16_t USB_VENDOR_ENDPOINT_SIZE = CFG_TUD_ENDOINT_SIZE; uint16_t tusb_vendor_load_descriptor(uint8_t *dst, uint8_t *itf) { uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB Vendor"); @@ -68,10 +68,13 @@ extern "C" bool tinyusb_vendor_control_request_cb(uint8_t rhport, uint8_t stage, return false; } -USBVendor::USBVendor(uint8_t endpoint_size) : itf(0), cb(NULL) { +USBVendor::USBVendor(uint16_t endpoint_size) : itf(0), cb(NULL) { if (!_Vendor) { _Vendor = this; - if (endpoint_size <= 64) { + if (endpoint_size == 0) { + endpoint_size = CFG_TUD_ENDOINT_SIZE; + } + if (endpoint_size <= CFG_TUD_ENDOINT_SIZE) { USB_VENDOR_ENDPOINT_SIZE = endpoint_size; } tinyusb_enable_interface(USB_INTERFACE_VENDOR, TUD_VENDOR_DESC_LEN, tusb_vendor_load_descriptor); @@ -97,7 +100,7 @@ size_t USBVendor::setRxBufferSize(size_t rx_queue_len) { } void USBVendor::begin() { - setRxBufferSize(256); //default if not preset + setRxBufferSize(512); //default if not preset } void USBVendor::end() { diff --git a/libraries/USB/src/USBVendor.h b/libraries/USB/src/USBVendor.h index e3e22281939..4990e466321 100644 --- a/libraries/USB/src/USBVendor.h +++ b/libraries/USB/src/USBVendor.h @@ -74,7 +74,7 @@ class USBVendor : public Stream { arduino_usb_vendor_control_request_handler_t cb; public: - USBVendor(uint8_t endpoint_size = 64); + USBVendor(uint16_t endpoint_size = 0); void begin(void); void end(void); size_t setRxBufferSize(size_t); From 6d6a8f8d3207c0f34cb6ad66b92a071fe1215d0b Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Thu, 3 Oct 2024 16:35:39 +0300 Subject: [PATCH 027/409] IDF release/v5.3 707d097b (#10416) --- package/package_esp32_index.template.json | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index ea85072b9cb..ea66c5a816d 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -101,57 +101,57 @@ "host": "i686-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", - "size": "399730073" + "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", + "size": "399729605" }, { "host": "x86_64-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", - "size": "399730073" + "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", + "size": "399729605" }, { "host": "arm64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", - "size": "399730073" + "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", + "size": "399729605" }, { "host": "x86_64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", - "size": "399730073" + "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", + "size": "399729605" }, { "host": "x86_64-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", - "size": "399730073" + "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", + "size": "399729605" }, { "host": "i686-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", - "size": "399730073" + "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", + "size": "399729605" }, { "host": "aarch64-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", - "size": "399730073" + "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", + "size": "399729605" }, { "host": "arm-linux-gnueabihf", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:7af392cc8c0079f3eea5e49706f3ea296bd42c4ce89d48909a135310caa69c96", - "size": "399730073" + "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", + "size": "399729605" } ] }, From 5d873c0787fa96675f74b68d16b9b8a3a2a048ea Mon Sep 17 00:00:00 2001 From: sivar2311 Date: Fri, 4 Oct 2024 12:49:55 +0200 Subject: [PATCH 028/409] Add conditional compilation for second I2C interface based on SOC_I2C_NUM (#10408) The ESP32, ESP32-S and ESP32-H series have two I2C interfaces, while the ESP32-C series has only one. --- libraries/Wire/src/Wire.cpp | 2 ++ libraries/Wire/src/Wire.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index 047795f949a..8ac0c25595d 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -646,6 +646,8 @@ void TwoWire::onRequestService(uint8_t num, void *arg) { #endif /* SOC_I2C_SUPPORT_SLAVE */ TwoWire Wire = TwoWire(0); +#if SOC_I2C_NUM > 1 TwoWire Wire1 = TwoWire(1); +#endif /* SOC_I2C_NUM */ #endif /* SOC_I2C_SUPPORTED */ diff --git a/libraries/Wire/src/Wire.h b/libraries/Wire/src/Wire.h index fcf94313d52..cf720d48234 100644 --- a/libraries/Wire/src/Wire.h +++ b/libraries/Wire/src/Wire.h @@ -144,7 +144,9 @@ class TwoWire : public HardwareI2C { }; extern TwoWire Wire; +#if SOC_I2C_NUM > 1 extern TwoWire Wire1; +#endif /* SOC_I2C_NUM */ #endif /* SOC_I2C_SUPPORTED */ #endif /* TwoWire_h */ From 13511a6b6559634ff77550ed0719114183b8d910 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Fri, 4 Oct 2024 07:51:47 -0300 Subject: [PATCH 029/409] ci(tests): Add linpack FPU tests (#10389) * ci(tests): Add linpack FPU tests * fix(linpack): Change prints to log_d * fix(linpack): Fix number of runs check * ci(pre-commit): Apply automatic fixes * fix(spelling): Correct spelling mistakes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- tests/performance/linpack_double/ci.json | 6 + .../linpack_double/linpack_double.ino | 1094 +++++++++++++++++ .../linpack_double/test_linpack_double.py | 61 + tests/performance/linpack_float/ci.json | 6 + .../linpack_float/linpack_float.ino | 1094 +++++++++++++++++ .../linpack_float/test_linpack_float.py | 61 + 6 files changed, 2322 insertions(+) create mode 100644 tests/performance/linpack_double/ci.json create mode 100644 tests/performance/linpack_double/linpack_double.ino create mode 100644 tests/performance/linpack_double/test_linpack_double.py create mode 100644 tests/performance/linpack_float/ci.json create mode 100644 tests/performance/linpack_float/linpack_float.ino create mode 100644 tests/performance/linpack_float/test_linpack_float.py diff --git a/tests/performance/linpack_double/ci.json b/tests/performance/linpack_double/ci.json new file mode 100644 index 00000000000..accee2b2135 --- /dev/null +++ b/tests/performance/linpack_double/ci.json @@ -0,0 +1,6 @@ +{ + "platforms": { + "qemu": false, + "wokwi": false + } +} diff --git a/tests/performance/linpack_double/linpack_double.ino b/tests/performance/linpack_double/linpack_double.ino new file mode 100644 index 00000000000..5148b6ef591 --- /dev/null +++ b/tests/performance/linpack_double/linpack_double.ino @@ -0,0 +1,1094 @@ +/* + Linpack test for Arduino and ESP32. + Based on https://github.com/VioletGiraffe/EmbeddedLinpack + Created by Violet Giraffe, 2018 + Adapted by Lucas Saavedra Vaz, 2024 +*/ + +#include +#include + +// Number of runs to average +#define N_RUNS 1000 + +using floating_point_t = double; +bool type_float; + +floating_point_t benchmark(void); +floating_point_t cpu_time(void); +void daxpy(int n, floating_point_t da, floating_point_t dx[], int incx, floating_point_t dy[], int incy); +floating_point_t ddot(int n, floating_point_t dx[], int incx, floating_point_t dy[], int incy); +int dgefa(floating_point_t a[], int lda, int n, int ipvt[]); +void dgesl(floating_point_t a[], int lda, int n, int ipvt[], floating_point_t b[], int job); +void dscal(int n, floating_point_t sa, floating_point_t x[], int incx); +int idamax(int n, floating_point_t dx[], int incx); +floating_point_t r8_abs(floating_point_t x); +floating_point_t r8_epsilon(void); +floating_point_t r8_max(floating_point_t x, floating_point_t y); +floating_point_t r8_random(int iseed[4]); +void r8mat_gen(int lda, int n, floating_point_t *a); + +void setup() { + Serial.begin(115200); + while (!Serial) { + delay(10); + } + + String data_type; + + if (sizeof(floating_point_t) == sizeof(float)) { + data_type = "float"; + type_float = true; + } else if (sizeof(floating_point_t) == sizeof(double)) { + data_type = "double"; + type_float = false; + } else { + data_type = "unknown"; + log_e("Unknown data type size. Aborting."); + while (1); + } + + log_d("Starting Linpack %s test", data_type.c_str()); + Serial.printf("Runs: %d\n", N_RUNS); + Serial.printf("Type: %s\n", data_type.c_str()); + Serial.flush(); + int i = 0; + + floating_point_t minMflops = 1000000000.0, maxMflops = 0.0, avgMflops = 0.0; + for (i = 0; i < N_RUNS; ++i) { + Serial.printf("Run %d\n", i); + const auto mflops = benchmark(); + avgMflops += mflops; + minMflops = fmin(mflops, minMflops); + maxMflops = fmax(mflops, maxMflops); + Serial.flush(); + } + + avgMflops /= N_RUNS; + Serial.println(String("Runs completed: ") + i); + Serial.println(String("Average MFLOPS: ") + avgMflops); + Serial.println(String("Min MFLOPS: ") + minMflops); + Serial.println(String("Max MFLOPS: ") + maxMflops); + Serial.flush(); +} + +void loop() { + vTaskDelete(NULL); +} + +/******************************************************************************/ + +floating_point_t benchmark(void) + +/******************************************************************************/ +/* + Purpose: + + MAIN is the main program for LINPACK_BENCH. + + Discussion: + + LINPACK_BENCH drives the floating_point_t precision LINPACK benchmark program. + + Modified: + + 25 July 2008 + + Parameters: + + N is the problem size. +*/ +{ +#define N 8 +#define LDA (N + 1) + + static floating_point_t a[N * LDA]; + static floating_point_t a_max; + static floating_point_t b[N]; + static floating_point_t b_max; + const floating_point_t cray = 0.056; + static floating_point_t eps; + int i; + int info; + static int ipvt[N]; + int j; + int job; + floating_point_t ops; + static floating_point_t resid[N]; + floating_point_t resid_max; + [[maybe_unused]] + floating_point_t residn; + static floating_point_t rhs[N]; + floating_point_t t1; + floating_point_t t2; + static floating_point_t time[6]; + floating_point_t total; + floating_point_t x[N]; + + log_d("LINPACK_BENCH"); + log_d(" C version"); + log_d(" The LINPACK benchmark."); + log_d(" Language: C"); + if (!type_float) { + log_d(" Datatype: Double precision real"); + } else if (type_float) { + log_d(" Datatype: Single precision real"); + } else { + log_d(" Datatype: unknown"); + } + log_d(" Matrix order N = %d", N); + log_d(" Leading matrix dimension LDA = %d", LDA); + + ops = (floating_point_t)(2L * N * N * N) / 3.0 + 2.0 * (floating_point_t)((long)N * N); + + /* + Allocate space for arrays. +*/ + r8mat_gen(LDA, N, a); + + a_max = 0.0; + for (j = 0; j < N; j++) { + for (i = 0; i < N; i++) { + a_max = r8_max(a_max, a[i + j * LDA]); + } + } + + for (i = 0; i < N; i++) { + x[i] = 1.0; + } + + for (i = 0; i < N; i++) { + b[i] = 0.0; + for (j = 0; j < N; j++) { + b[i] = b[i] + a[i + j * LDA] * x[j]; + } + } + t1 = cpu_time(); + + info = dgefa(a, LDA, N, ipvt); + + if (info != 0) { + log_d("LINPACK_BENCH - Fatal error!"); + log_d(" The matrix A is apparently singular."); + log_d(" Abnormal end of execution."); + return 1; + } + + t2 = cpu_time(); + time[0] = t2 - t1; + + t1 = cpu_time(); + + job = 0; + dgesl(a, LDA, N, ipvt, b, job); + + t2 = cpu_time(); + time[1] = t2 - t1; + + total = time[0] + time[1]; + + /* + Compute a residual to verify results. +*/ + r8mat_gen(LDA, N, a); + + for (i = 0; i < N; i++) { + x[i] = 1.0; + } + + for (i = 0; i < N; i++) { + rhs[i] = 0.0; + for (j = 0; j < N; j++) { + rhs[i] = rhs[i] + a[i + j * LDA] * x[j]; + } + } + + for (i = 0; i < N; i++) { + resid[i] = -rhs[i]; + for (j = 0; j < N; j++) { + resid[i] = resid[i] + a[i + j * LDA] * b[j]; + } + } + + resid_max = 0.0; + for (i = 0; i < N; i++) { + resid_max = r8_max(resid_max, r8_abs(resid[i])); + } + + b_max = 0.0; + for (i = 0; i < N; i++) { + b_max = r8_max(b_max, r8_abs(b[i])); + } + + eps = r8_epsilon(); + + residn = resid_max / (floating_point_t)N / a_max / b_max / eps; + + time[2] = total; + if (0.0 < total) { + time[3] = ops / (1.0E+06 * total); + } else { + time[3] = -1.0; + } + time[4] = 2.0 / time[3]; + time[5] = total / cray; + + log_d(""); + log_d(" Norm. Resid Resid MACHEP X[1] X[N]"); + log_d(" %14f %14f %14e %14f %14f", residn, resid_max, eps, b[0], b[N - 1]); + log_d(""); + log_d(" Factor Solve Total MFLOPS Unit Cray-Ratio"); + log_d(" %9f %9f %9f %9f %9f %9f", time[0], time[1], time[2], time[3], time[4], time[5]); + + /* + Terminate. +*/ + log_d(""); + log_d("LINPACK_BENCH"); + log_d(" Normal end of execution."); + log_d(""); + + return time[3]; +#undef LDA +#undef N +} +/******************************************************************************/ + +floating_point_t cpu_time(void) + +/******************************************************************************/ +/* + Purpose: + + CPU_TIME returns the current reading on the CPU clock. + + Discussion: + + The CPU time measurements available through this routine are often + not very accurate. In some cases, the accuracy is no better than + a hundredth of a second. + + Licensing: + + This code is distributed under the GNU LGPL license. + + Modified: + + 06 June 2005 + + Author: + + John Burkardt + + Parameters: + + Output, floating_point_t CPU_TIME, the current reading of the CPU clock, in seconds. +*/ +{ + floating_point_t value; + + value = (floating_point_t)micros() / (floating_point_t)1000000; + + return value; +} +/******************************************************************************/ + +void daxpy(int n, floating_point_t da, floating_point_t dx[], int incx, floating_point_t dy[], int incy) + +/******************************************************************************/ +/* + Purpose: + + DAXPY computes constant times a vector plus a vector. + + Discussion: + + This routine uses unrolled loops for increments equal to one. + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of elements in DX and DY. + + Input, floating_point_t DA, the multiplier of DX. + + Input, floating_point_t DX[*], the first vector. + + Input, int INCX, the increment between successive entries of DX. + + Input/output, floating_point_t DY[*], the second vector. + On output, DY[*] has been replaced by DY[*] + DA * DX[*]. + + Input, int INCY, the increment between successive entries of DY. +*/ +{ + int i; + int ix; + int iy; + int m; + + if (n <= 0) { + return; + } + + if (da == 0.0) { + return; + } + /* + Code for unequal increments or equal increments + not equal to 1. +*/ + if (incx != 1 || incy != 1) { + if (0 <= incx) { + ix = 0; + } else { + ix = (-n + 1) * incx; + } + + if (0 <= incy) { + iy = 0; + } else { + iy = (-n + 1) * incy; + } + + for (i = 0; i < n; i++) { + dy[iy] = dy[iy] + da * dx[ix]; + ix = ix + incx; + iy = iy + incy; + } + } + /* + Code for both increments equal to 1. +*/ + else { + m = n % 4; + + for (i = 0; i < m; i++) { + dy[i] = dy[i] + da * dx[i]; + } + + for (i = m; i < n; i = i + 4) { + dy[i] = dy[i] + da * dx[i]; + dy[i + 1] = dy[i + 1] + da * dx[i + 1]; + dy[i + 2] = dy[i + 2] + da * dx[i + 2]; + dy[i + 3] = dy[i + 3] + da * dx[i + 3]; + } + } + return; +} +/******************************************************************************/ + +floating_point_t ddot(int n, floating_point_t dx[], int incx, floating_point_t dy[], int incy) + +/******************************************************************************/ +/* + Purpose: + + DDOT forms the dot product of two vectors. + + Discussion: + + This routine uses unrolled loops for increments equal to one. + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of entries in the vectors. + + Input, floating_point_t DX[*], the first vector. + + Input, int INCX, the increment between successive entries in DX. + + Input, floating_point_t DY[*], the second vector. + + Input, int INCY, the increment between successive entries in DY. + + Output, floating_point_t DDOT, the sum of the product of the corresponding + entries of DX and DY. +*/ +{ + floating_point_t dtemp; + int i; + int ix; + int iy; + int m; + + dtemp = 0.0; + + if (n <= 0) { + return dtemp; + } + /* + Code for unequal increments or equal increments + not equal to 1. +*/ + if (incx != 1 || incy != 1) { + if (0 <= incx) { + ix = 0; + } else { + ix = (-n + 1) * incx; + } + + if (0 <= incy) { + iy = 0; + } else { + iy = (-n + 1) * incy; + } + + for (i = 0; i < n; i++) { + dtemp = dtemp + dx[ix] * dy[iy]; + ix = ix + incx; + iy = iy + incy; + } + } + /* + Code for both increments equal to 1. +*/ + else { + m = n % 5; + + for (i = 0; i < m; i++) { + dtemp = dtemp + dx[i] * dy[i]; + } + + for (i = m; i < n; i = i + 5) { + dtemp = dtemp + dx[i] * dy[i] + dx[i + 1] * dy[i + 1] + dx[i + 2] * dy[i + 2] + dx[i + 3] * dy[i + 3] + dx[i + 4] * dy[i + 4]; + } + } + return dtemp; +} +/******************************************************************************/ + +int dgefa(floating_point_t a[], int lda, int n, int ipvt[]) + +/******************************************************************************/ +/* + Purpose: + + DGEFA factors a real general matrix. + + Modified: + + 16 May 2005 + + Author: + + C version by John Burkardt. + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart, + LINPACK User's Guide, + SIAM, (Society for Industrial and Applied Mathematics), + 3600 University City Science Center, + Philadelphia, PA, 19104-2688. + ISBN 0-89871-172-X + + Parameters: + + Input/output, floating_point_t A[LDA*N]. + On input, the matrix to be factored. + On output, an upper triangular matrix and the multipliers used to obtain + it. The factorization can be written A=L*U, where L is a product of + permutation and unit lower triangular matrices, and U is upper triangular. + + Input, int LDA, the leading dimension of A. + + Input, int N, the order of the matrix A. + + Output, int IPVT[N], the pivot indices. + + Output, int DGEFA, singularity indicator. + 0, normal value. + K, if U(K,K) == 0. This is not an error condition for this subroutine, + but it does indicate that DGESL or DGEDI will divide by zero if called. + Use RCOND in DGECO for a reliable indication of singularity. +*/ +{ + int info; + int j; + int k; + int l; + floating_point_t t; + /* + Gaussian elimination with partial pivoting. +*/ + info = 0; + + for (k = 1; k <= n - 1; k++) { + /* + Find L = pivot index. +*/ + l = idamax(n - k + 1, a + (k - 1) + (k - 1) * lda, 1) + k - 1; + ipvt[k - 1] = l; + /* + Zero pivot implies this column already triangularized. +*/ + if (a[l - 1 + (k - 1) * lda] == 0.0) { + info = k; + continue; + } + /* + Interchange if necessary. +*/ + if (l != k) { + t = a[l - 1 + (k - 1) * lda]; + a[l - 1 + (k - 1) * lda] = a[k - 1 + (k - 1) * lda]; + a[k - 1 + (k - 1) * lda] = t; + } + /* + Compute multipliers. +*/ + t = -1.0 / a[k - 1 + (k - 1) * lda]; + + dscal(n - k, t, a + k + (k - 1) * lda, 1); + /* + Row elimination with column indexing. +*/ + for (j = k + 1; j <= n; j++) { + t = a[l - 1 + (j - 1) * lda]; + if (l != k) { + a[l - 1 + (j - 1) * lda] = a[k - 1 + (j - 1) * lda]; + a[k - 1 + (j - 1) * lda] = t; + } + daxpy(n - k, t, a + k + (k - 1) * lda, 1, a + k + (j - 1) * lda, 1); + } + } + + ipvt[n - 1] = n; + + if (a[n - 1 + (n - 1) * lda] == 0.0) { + info = n; + } + + return info; +} +/******************************************************************************/ + +void dgesl(floating_point_t a[], int lda, int n, int ipvt[], floating_point_t b[], int job) + +/******************************************************************************/ +/* + Purpose: + + DGESL solves a real general linear system A * X = B. + + Discussion: + + DGESL can solve either of the systems A * X = B or A' * X = B. + + The system matrix must have been factored by DGECO or DGEFA. + + A division by zero will occur if the input factor contains a + zero on the diagonal. Technically this indicates singularity + but it is often caused by improper arguments or improper + setting of LDA. It will not occur if the subroutines are + called correctly and if DGECO has set 0.0 < RCOND + or DGEFA has set INFO == 0. + + Modified: + + 16 May 2005 + + Author: + + C version by John Burkardt. + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart, + LINPACK User's Guide, + SIAM, (Society for Industrial and Applied Mathematics), + 3600 University City Science Center, + Philadelphia, PA, 19104-2688. + ISBN 0-89871-172-X + + Parameters: + + Input, floating_point_t A[LDA*N], the output from DGECO or DGEFA. + + Input, int LDA, the leading dimension of A. + + Input, int N, the order of the matrix A. + + Input, int IPVT[N], the pivot vector from DGECO or DGEFA. + + Input/output, floating_point_t B[N]. + On input, the right hand side vector. + On output, the solution vector. + + Input, int JOB. + 0, solve A * X = B; + nonzero, solve A' * X = B. +*/ +{ + int k; + int l; + floating_point_t t; + /* + Solve A * X = B. +*/ + if (job == 0) { + for (k = 1; k <= n - 1; k++) { + l = ipvt[k - 1]; + t = b[l - 1]; + + if (l != k) { + b[l - 1] = b[k - 1]; + b[k - 1] = t; + } + + daxpy(n - k, t, a + k + (k - 1) * lda, 1, b + k, 1); + } + + for (k = n; 1 <= k; k--) { + b[k - 1] = b[k - 1] / a[k - 1 + (k - 1) * lda]; + t = -b[k - 1]; + daxpy(k - 1, t, a + 0 + (k - 1) * lda, 1, b, 1); + } + } + /* + Solve A' * X = B. +*/ + else { + for (k = 1; k <= n; k++) { + t = ddot(k - 1, a + 0 + (k - 1) * lda, 1, b, 1); + b[k - 1] = (b[k - 1] - t) / a[k - 1 + (k - 1) * lda]; + } + + for (k = n - 1; 1 <= k; k--) { + b[k - 1] = b[k - 1] + ddot(n - k, a + k + (k - 1) * lda, 1, b + k, 1); + l = ipvt[k - 1]; + + if (l != k) { + t = b[l - 1]; + b[l - 1] = b[k - 1]; + b[k - 1] = t; + } + } + } + return; +} +/******************************************************************************/ + +void dscal(int n, floating_point_t sa, floating_point_t x[], int incx) + +/******************************************************************************/ +/* + Purpose: + + DSCAL scales a vector by a constant. + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of entries in the vector. + + Input, floating_point_t SA, the multiplier. + + Input/output, floating_point_t X[*], the vector to be scaled. + + Input, int INCX, the increment between successive entries of X. +*/ +{ + int i; + int ix; + int m; + + if (n <= 0) { + } else if (incx == 1) { + m = n % 5; + + for (i = 0; i < m; i++) { + x[i] = sa * x[i]; + } + + for (i = m; i < n; i = i + 5) { + x[i] = sa * x[i]; + x[i + 1] = sa * x[i + 1]; + x[i + 2] = sa * x[i + 2]; + x[i + 3] = sa * x[i + 3]; + x[i + 4] = sa * x[i + 4]; + } + } else { + if (0 <= incx) { + ix = 0; + } else { + ix = (-n + 1) * incx; + } + + for (i = 0; i < n; i++) { + x[ix] = sa * x[ix]; + ix = ix + incx; + } + } + return; +} +/******************************************************************************/ + +int idamax(int n, floating_point_t dx[], int incx) + +/******************************************************************************/ +/* + Purpose: + + IDAMAX finds the index of the vector element of maximum absolute value. + + Discussion: + + WARNING: This index is a 1-based index, not a 0-based index! + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of entries in the vector. + + Input, floating_point_t X[*], the vector to be examined. + + Input, int INCX, the increment between successive entries of SX. + + Output, int IDAMAX, the index of the element of maximum + absolute value. +*/ +{ + floating_point_t dmax; + int i; + int ix; + int value; + + value = 0; + + if (n < 1 || incx <= 0) { + return value; + } + + value = 1; + + if (n == 1) { + return value; + } + + if (incx == 1) { + dmax = r8_abs(dx[0]); + + for (i = 1; i < n; i++) { + if (dmax < r8_abs(dx[i])) { + value = i + 1; + dmax = r8_abs(dx[i]); + } + } + } else { + ix = 0; + dmax = r8_abs(dx[0]); + ix = ix + incx; + + for (i = 1; i < n; i++) { + if (dmax < r8_abs(dx[ix])) { + value = i + 1; + dmax = r8_abs(dx[ix]); + } + ix = ix + incx; + } + } + + return value; +} +/******************************************************************************/ + +floating_point_t r8_abs(floating_point_t x) + +/******************************************************************************/ +/* + Purpose: + + R8_ABS returns the absolute value of a R8. + + Modified: + + 02 April 2005 + + Author: + + John Burkardt + + Parameters: + + Input, floating_point_t X, the quantity whose absolute value is desired. + + Output, floating_point_t R8_ABS, the absolute value of X. +*/ +{ + floating_point_t value; + + if (0.0 <= x) { + value = x; + } else { + value = -x; + } + return value; +} +/******************************************************************************/ + +floating_point_t r8_epsilon(void) + +/******************************************************************************/ +/* + Purpose: + + R8_EPSILON returns the R8 round off unit. + + Discussion: + + R8_EPSILON is a number R which is a power of 2 with the property that, + to the precision of the computer's arithmetic, + 1 < 1 + R + but + 1 = ( 1 + R / 2 ) + + Licensing: + + This code is distributed under the GNU LGPL license. + + Modified: + + 08 May 2006 + + Author: + + John Burkardt + + Parameters: + + Output, floating_point_t R8_EPSILON, the floating_point_t precision round-off unit. +*/ +{ + floating_point_t r; + + r = 1.0; + + while (1.0 < (floating_point_t)(1.0 + r)) { + r = r / 2.0; + } + r = 2.0 * r; + + return r; +} +/******************************************************************************/ + +floating_point_t r8_max(floating_point_t x, floating_point_t y) + +/******************************************************************************/ +/* + Purpose: + + R8_MAX returns the maximum of two R8's. + + Modified: + + 18 August 2004 + + Author: + + John Burkardt + + Parameters: + + Input, floating_point_t X, Y, the quantities to compare. + + Output, floating_point_t R8_MAX, the maximum of X and Y. +*/ +{ + floating_point_t value; + + if (y < x) { + value = x; + } else { + value = y; + } + return value; +} +/******************************************************************************/ + +floating_point_t r8_random(int iseed[4]) + +/******************************************************************************/ +/* + Purpose: + + R8_RANDOM returns a uniformly distributed random number between 0 and 1. + + Discussion: + + This routine uses a multiplicative congruential method with modulus + 2**48 and multiplier 33952834046453 (see G.S.Fishman, + 'Multiplicative congruential random number generators with modulus + 2**b: an exhaustive analysis for b = 32 and a partial analysis for + b = 48', Math. Comp. 189, pp 331-344, 1990). + + 48-bit integers are stored in 4 integer array elements with 12 bits + per element. Hence the routine is portable across machines with + integers of 32 bits or more. + + Parameters: + + Input/output, integer ISEED(4). + On entry, the seed of the random number generator; the array + elements must be between 0 and 4095, and ISEED(4) must be odd. + On exit, the seed is updated. + + Output, floating_point_t R8_RANDOM, the next pseudorandom number. +*/ +{ + int ipw2 = 4096; + int it1; + int it2; + int it3; + int it4; + int m1 = 494; + int m2 = 322; + int m3 = 2508; + int m4 = 2549; + floating_point_t r = 1.0 / 4096.0; + floating_point_t value; + /* + Multiply the seed by the multiplier modulo 2**48. +*/ + it4 = iseed[3] * m4; + it3 = it4 / ipw2; + it4 = it4 - ipw2 * it3; + it3 = it3 + iseed[2] * m4 + iseed[3] * m3; + it2 = it3 / ipw2; + it3 = it3 - ipw2 * it2; + it2 = it2 + iseed[1] * m4 + iseed[2] * m3 + iseed[3] * m2; + it1 = it2 / ipw2; + it2 = it2 - ipw2 * it1; + it1 = it1 + iseed[0] * m4 + iseed[1] * m3 + iseed[2] * m2 + iseed[3] * m1; + it1 = (it1 % ipw2); + /* + Return updated seed +*/ + iseed[0] = it1; + iseed[1] = it2; + iseed[2] = it3; + iseed[3] = it4; + /* + Convert 48-bit integer to a real number in the interval (0,1) +*/ + value = r * ((floating_point_t)(it1) + r * ((floating_point_t)(it2) + r * ((floating_point_t)(it3) + r * ((floating_point_t)(it4))))); + + return value; +} +/******************************************************************************/ + +void r8mat_gen(int lda, int n, floating_point_t *a) + +/******************************************************************************/ +/* + Purpose: + + R8MAT_GEN generates a random R8MAT. + + Modified: + + 06 June 2005 + + Parameters: + + Input, integer LDA, the leading dimension of the matrix. + + Input, integer N, the order of the matrix. + + Output, floating_point_t R8MAT_GEN[LDA*N], the N by N matrix. +*/ +{ + int i; + int init[4] = {1, 2, 3, 1325}; + int j; + + for (j = 1; j <= n; j++) { + for (i = 1; i <= n; i++) { + a[i - 1 + (j - 1) * lda] = r8_random(init) - 0.5; + } + } +} +/******************************************************************************/ diff --git a/tests/performance/linpack_double/test_linpack_double.py b/tests/performance/linpack_double/test_linpack_double.py new file mode 100644 index 00000000000..0a6e2f90ef3 --- /dev/null +++ b/tests/performance/linpack_double/test_linpack_double.py @@ -0,0 +1,61 @@ +import json +import logging +import os + + +def test_linpack_double(dut, request): + LOGGER = logging.getLogger(__name__) + + # Match "Runs: %d" + res = dut.expect(r"Runs: (\d+)", timeout=60) + runs = int(res.group(0).decode("utf-8").split(" ")[1]) + LOGGER.info("Number of runs: {}".format(runs)) + assert runs > 0, "Invalid number of runs" + + # Match "Type: %s" + res = dut.expect(r"Type: (\w+)", timeout=60) + data_type = res.group(0).decode("utf-8").split(" ")[1] + LOGGER.info("Data type: {}".format(data_type)) + assert data_type == "double", "Invalid data type" + + # Match "Runs completed: %d" + res = dut.expect(r"Runs completed: (\d+)", timeout=120) + runs_completed = int(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Runs completed: {}".format(runs_completed)) + assert runs_completed == runs, "Invalid number of runs completed" + + # Match "Average MFLOPS: %f" + res = dut.expect(r"Average MFLOPS: (\d+\.\d+)", timeout=120) + avg_score = float(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Average MFLOPS: {}".format(avg_score)) + assert avg_score > 0, "Invalid average MFLOPS" + + # Match "Min MFLOPS: %f" + res = dut.expect(r"Min MFLOPS: (\d+\.\d+)", timeout=120) + min_score = float(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Min MFLOPS: {}".format(min_score)) + assert min_score > 0 and min_score < 1000000000.0, "Invalid min MFLOPS" + + # Match "Max MFLOPS: %f" + res = dut.expect(r"Max MFLOPS: (\d+\.\d+)", timeout=120) + max_score = float(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Max MFLOPS: {}".format(max_score)) + assert max_score > 0, "Invalid max MFLOPS" + + # Create JSON with results and write it to file + # Always create a JSON with this format (so it can be merged later on): + # { TEST_NAME_STR: TEST_RESULTS_DICT } + results = {"linpack_double": {"runs": runs, "avg_score": avg_score, "min_score": min_score, "max_score": max_score}} + + current_folder = os.path.dirname(request.path) + file_index = 0 + report_file = os.path.join(current_folder, "result_linpack_double" + str(file_index) + ".json") + while os.path.exists(report_file): + report_file = report_file.replace(str(file_index) + ".json", str(file_index + 1) + ".json") + file_index += 1 + + with open(report_file, "w") as f: + try: + f.write(json.dumps(results)) + except Exception as e: + LOGGER.warning("Failed to write results to file: {}".format(e)) diff --git a/tests/performance/linpack_float/ci.json b/tests/performance/linpack_float/ci.json new file mode 100644 index 00000000000..accee2b2135 --- /dev/null +++ b/tests/performance/linpack_float/ci.json @@ -0,0 +1,6 @@ +{ + "platforms": { + "qemu": false, + "wokwi": false + } +} diff --git a/tests/performance/linpack_float/linpack_float.ino b/tests/performance/linpack_float/linpack_float.ino new file mode 100644 index 00000000000..24dd9e7c461 --- /dev/null +++ b/tests/performance/linpack_float/linpack_float.ino @@ -0,0 +1,1094 @@ +/* + Linpack test for Arduino and ESP32. + Based on https://github.com/VioletGiraffe/EmbeddedLinpack + Created by Violet Giraffe, 2018 + Adapted by Lucas Saavedra Vaz, 2024 +*/ + +#include +#include + +// Number of runs to average +#define N_RUNS 1000 + +using floating_point_t = float; +bool type_float; + +floating_point_t benchmark(void); +floating_point_t cpu_time(void); +void daxpy(int n, floating_point_t da, floating_point_t dx[], int incx, floating_point_t dy[], int incy); +floating_point_t ddot(int n, floating_point_t dx[], int incx, floating_point_t dy[], int incy); +int dgefa(floating_point_t a[], int lda, int n, int ipvt[]); +void dgesl(floating_point_t a[], int lda, int n, int ipvt[], floating_point_t b[], int job); +void dscal(int n, floating_point_t sa, floating_point_t x[], int incx); +int idamax(int n, floating_point_t dx[], int incx); +floating_point_t r8_abs(floating_point_t x); +floating_point_t r8_epsilon(void); +floating_point_t r8_max(floating_point_t x, floating_point_t y); +floating_point_t r8_random(int iseed[4]); +void r8mat_gen(int lda, int n, floating_point_t *a); + +void setup() { + Serial.begin(115200); + while (!Serial) { + delay(10); + } + + String data_type; + + if (sizeof(floating_point_t) == sizeof(float)) { + data_type = "float"; + type_float = true; + } else if (sizeof(floating_point_t) == sizeof(double)) { + data_type = "double"; + type_float = false; + } else { + data_type = "unknown"; + log_e("Unknown data type size. Aborting."); + while (1); + } + + log_d("Starting Linpack %s test", data_type.c_str()); + Serial.printf("Runs: %d\n", N_RUNS); + Serial.printf("Type: %s\n", data_type.c_str()); + Serial.flush(); + int i = 0; + + floating_point_t minMflops = 1000000000.0, maxMflops = 0.0, avgMflops = 0.0; + for (i = 0; i < N_RUNS; ++i) { + Serial.printf("Run %d\n", i); + const auto mflops = benchmark(); + avgMflops += mflops; + minMflops = fmin(mflops, minMflops); + maxMflops = fmax(mflops, maxMflops); + Serial.flush(); + } + + avgMflops /= N_RUNS; + Serial.println(String("Runs completed: ") + i); + Serial.println(String("Average MFLOPS: ") + avgMflops); + Serial.println(String("Min MFLOPS: ") + minMflops); + Serial.println(String("Max MFLOPS: ") + maxMflops); + Serial.flush(); +} + +void loop() { + vTaskDelete(NULL); +} + +/******************************************************************************/ + +floating_point_t benchmark(void) + +/******************************************************************************/ +/* + Purpose: + + MAIN is the main program for LINPACK_BENCH. + + Discussion: + + LINPACK_BENCH drives the floating_point_t precision LINPACK benchmark program. + + Modified: + + 25 July 2008 + + Parameters: + + N is the problem size. +*/ +{ +#define N 8 +#define LDA (N + 1) + + static floating_point_t a[N * LDA]; + static floating_point_t a_max; + static floating_point_t b[N]; + static floating_point_t b_max; + const floating_point_t cray = 0.056; + static floating_point_t eps; + int i; + int info; + static int ipvt[N]; + int j; + int job; + floating_point_t ops; + static floating_point_t resid[N]; + floating_point_t resid_max; + [[maybe_unused]] + floating_point_t residn; + static floating_point_t rhs[N]; + floating_point_t t1; + floating_point_t t2; + static floating_point_t time[6]; + floating_point_t total; + floating_point_t x[N]; + + log_d("LINPACK_BENCH"); + log_d(" C version"); + log_d(" The LINPACK benchmark."); + log_d(" Language: C"); + if (!type_float) { + log_d(" Datatype: Double precision real"); + } else if (type_float) { + log_d(" Datatype: Single precision real"); + } else { + log_d(" Datatype: unknown"); + } + log_d(" Matrix order N = %d", N); + log_d(" Leading matrix dimension LDA = %d", LDA); + + ops = (floating_point_t)(2L * N * N * N) / 3.0 + 2.0 * (floating_point_t)((long)N * N); + + /* + Allocate space for arrays. +*/ + r8mat_gen(LDA, N, a); + + a_max = 0.0; + for (j = 0; j < N; j++) { + for (i = 0; i < N; i++) { + a_max = r8_max(a_max, a[i + j * LDA]); + } + } + + for (i = 0; i < N; i++) { + x[i] = 1.0; + } + + for (i = 0; i < N; i++) { + b[i] = 0.0; + for (j = 0; j < N; j++) { + b[i] = b[i] + a[i + j * LDA] * x[j]; + } + } + t1 = cpu_time(); + + info = dgefa(a, LDA, N, ipvt); + + if (info != 0) { + log_d("LINPACK_BENCH - Fatal error!"); + log_d(" The matrix A is apparently singular."); + log_d(" Abnormal end of execution."); + return 1; + } + + t2 = cpu_time(); + time[0] = t2 - t1; + + t1 = cpu_time(); + + job = 0; + dgesl(a, LDA, N, ipvt, b, job); + + t2 = cpu_time(); + time[1] = t2 - t1; + + total = time[0] + time[1]; + + /* + Compute a residual to verify results. +*/ + r8mat_gen(LDA, N, a); + + for (i = 0; i < N; i++) { + x[i] = 1.0; + } + + for (i = 0; i < N; i++) { + rhs[i] = 0.0; + for (j = 0; j < N; j++) { + rhs[i] = rhs[i] + a[i + j * LDA] * x[j]; + } + } + + for (i = 0; i < N; i++) { + resid[i] = -rhs[i]; + for (j = 0; j < N; j++) { + resid[i] = resid[i] + a[i + j * LDA] * b[j]; + } + } + + resid_max = 0.0; + for (i = 0; i < N; i++) { + resid_max = r8_max(resid_max, r8_abs(resid[i])); + } + + b_max = 0.0; + for (i = 0; i < N; i++) { + b_max = r8_max(b_max, r8_abs(b[i])); + } + + eps = r8_epsilon(); + + residn = resid_max / (floating_point_t)N / a_max / b_max / eps; + + time[2] = total; + if (0.0 < total) { + time[3] = ops / (1.0E+06 * total); + } else { + time[3] = -1.0; + } + time[4] = 2.0 / time[3]; + time[5] = total / cray; + + log_d(""); + log_d(" Norm. Resid Resid MACHEP X[1] X[N]"); + log_d(" %14f %14f %14e %14f %14f", residn, resid_max, eps, b[0], b[N - 1]); + log_d(""); + log_d(" Factor Solve Total MFLOPS Unit Cray-Ratio"); + log_d(" %9f %9f %9f %9f %9f %9f", time[0], time[1], time[2], time[3], time[4], time[5]); + + /* + Terminate. +*/ + log_d(""); + log_d("LINPACK_BENCH"); + log_d(" Normal end of execution."); + log_d(""); + + return time[3]; +#undef LDA +#undef N +} +/******************************************************************************/ + +floating_point_t cpu_time(void) + +/******************************************************************************/ +/* + Purpose: + + CPU_TIME returns the current reading on the CPU clock. + + Discussion: + + The CPU time measurements available through this routine are often + not very accurate. In some cases, the accuracy is no better than + a hundredth of a second. + + Licensing: + + This code is distributed under the GNU LGPL license. + + Modified: + + 06 June 2005 + + Author: + + John Burkardt + + Parameters: + + Output, floating_point_t CPU_TIME, the current reading of the CPU clock, in seconds. +*/ +{ + floating_point_t value; + + value = (floating_point_t)micros() / (floating_point_t)1000000; + + return value; +} +/******************************************************************************/ + +void daxpy(int n, floating_point_t da, floating_point_t dx[], int incx, floating_point_t dy[], int incy) + +/******************************************************************************/ +/* + Purpose: + + DAXPY computes constant times a vector plus a vector. + + Discussion: + + This routine uses unrolled loops for increments equal to one. + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of elements in DX and DY. + + Input, floating_point_t DA, the multiplier of DX. + + Input, floating_point_t DX[*], the first vector. + + Input, int INCX, the increment between successive entries of DX. + + Input/output, floating_point_t DY[*], the second vector. + On output, DY[*] has been replaced by DY[*] + DA * DX[*]. + + Input, int INCY, the increment between successive entries of DY. +*/ +{ + int i; + int ix; + int iy; + int m; + + if (n <= 0) { + return; + } + + if (da == 0.0) { + return; + } + /* + Code for unequal increments or equal increments + not equal to 1. +*/ + if (incx != 1 || incy != 1) { + if (0 <= incx) { + ix = 0; + } else { + ix = (-n + 1) * incx; + } + + if (0 <= incy) { + iy = 0; + } else { + iy = (-n + 1) * incy; + } + + for (i = 0; i < n; i++) { + dy[iy] = dy[iy] + da * dx[ix]; + ix = ix + incx; + iy = iy + incy; + } + } + /* + Code for both increments equal to 1. +*/ + else { + m = n % 4; + + for (i = 0; i < m; i++) { + dy[i] = dy[i] + da * dx[i]; + } + + for (i = m; i < n; i = i + 4) { + dy[i] = dy[i] + da * dx[i]; + dy[i + 1] = dy[i + 1] + da * dx[i + 1]; + dy[i + 2] = dy[i + 2] + da * dx[i + 2]; + dy[i + 3] = dy[i + 3] + da * dx[i + 3]; + } + } + return; +} +/******************************************************************************/ + +floating_point_t ddot(int n, floating_point_t dx[], int incx, floating_point_t dy[], int incy) + +/******************************************************************************/ +/* + Purpose: + + DDOT forms the dot product of two vectors. + + Discussion: + + This routine uses unrolled loops for increments equal to one. + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of entries in the vectors. + + Input, floating_point_t DX[*], the first vector. + + Input, int INCX, the increment between successive entries in DX. + + Input, floating_point_t DY[*], the second vector. + + Input, int INCY, the increment between successive entries in DY. + + Output, floating_point_t DDOT, the sum of the product of the corresponding + entries of DX and DY. +*/ +{ + floating_point_t dtemp; + int i; + int ix; + int iy; + int m; + + dtemp = 0.0; + + if (n <= 0) { + return dtemp; + } + /* + Code for unequal increments or equal increments + not equal to 1. +*/ + if (incx != 1 || incy != 1) { + if (0 <= incx) { + ix = 0; + } else { + ix = (-n + 1) * incx; + } + + if (0 <= incy) { + iy = 0; + } else { + iy = (-n + 1) * incy; + } + + for (i = 0; i < n; i++) { + dtemp = dtemp + dx[ix] * dy[iy]; + ix = ix + incx; + iy = iy + incy; + } + } + /* + Code for both increments equal to 1. +*/ + else { + m = n % 5; + + for (i = 0; i < m; i++) { + dtemp = dtemp + dx[i] * dy[i]; + } + + for (i = m; i < n; i = i + 5) { + dtemp = dtemp + dx[i] * dy[i] + dx[i + 1] * dy[i + 1] + dx[i + 2] * dy[i + 2] + dx[i + 3] * dy[i + 3] + dx[i + 4] * dy[i + 4]; + } + } + return dtemp; +} +/******************************************************************************/ + +int dgefa(floating_point_t a[], int lda, int n, int ipvt[]) + +/******************************************************************************/ +/* + Purpose: + + DGEFA factors a real general matrix. + + Modified: + + 16 May 2005 + + Author: + + C version by John Burkardt. + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart, + LINPACK User's Guide, + SIAM, (Society for Industrial and Applied Mathematics), + 3600 University City Science Center, + Philadelphia, PA, 19104-2688. + ISBN 0-89871-172-X + + Parameters: + + Input/output, floating_point_t A[LDA*N]. + On input, the matrix to be factored. + On output, an upper triangular matrix and the multipliers used to obtain + it. The factorization can be written A=L*U, where L is a product of + permutation and unit lower triangular matrices, and U is upper triangular. + + Input, int LDA, the leading dimension of A. + + Input, int N, the order of the matrix A. + + Output, int IPVT[N], the pivot indices. + + Output, int DGEFA, singularity indicator. + 0, normal value. + K, if U(K,K) == 0. This is not an error condition for this subroutine, + but it does indicate that DGESL or DGEDI will divide by zero if called. + Use RCOND in DGECO for a reliable indication of singularity. +*/ +{ + int info; + int j; + int k; + int l; + floating_point_t t; + /* + Gaussian elimination with partial pivoting. +*/ + info = 0; + + for (k = 1; k <= n - 1; k++) { + /* + Find L = pivot index. +*/ + l = idamax(n - k + 1, a + (k - 1) + (k - 1) * lda, 1) + k - 1; + ipvt[k - 1] = l; + /* + Zero pivot implies this column already triangularized. +*/ + if (a[l - 1 + (k - 1) * lda] == 0.0) { + info = k; + continue; + } + /* + Interchange if necessary. +*/ + if (l != k) { + t = a[l - 1 + (k - 1) * lda]; + a[l - 1 + (k - 1) * lda] = a[k - 1 + (k - 1) * lda]; + a[k - 1 + (k - 1) * lda] = t; + } + /* + Compute multipliers. +*/ + t = -1.0 / a[k - 1 + (k - 1) * lda]; + + dscal(n - k, t, a + k + (k - 1) * lda, 1); + /* + Row elimination with column indexing. +*/ + for (j = k + 1; j <= n; j++) { + t = a[l - 1 + (j - 1) * lda]; + if (l != k) { + a[l - 1 + (j - 1) * lda] = a[k - 1 + (j - 1) * lda]; + a[k - 1 + (j - 1) * lda] = t; + } + daxpy(n - k, t, a + k + (k - 1) * lda, 1, a + k + (j - 1) * lda, 1); + } + } + + ipvt[n - 1] = n; + + if (a[n - 1 + (n - 1) * lda] == 0.0) { + info = n; + } + + return info; +} +/******************************************************************************/ + +void dgesl(floating_point_t a[], int lda, int n, int ipvt[], floating_point_t b[], int job) + +/******************************************************************************/ +/* + Purpose: + + DGESL solves a real general linear system A * X = B. + + Discussion: + + DGESL can solve either of the systems A * X = B or A' * X = B. + + The system matrix must have been factored by DGECO or DGEFA. + + A division by zero will occur if the input factor contains a + zero on the diagonal. Technically this indicates singularity + but it is often caused by improper arguments or improper + setting of LDA. It will not occur if the subroutines are + called correctly and if DGECO has set 0.0 < RCOND + or DGEFA has set INFO == 0. + + Modified: + + 16 May 2005 + + Author: + + C version by John Burkardt. + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart, + LINPACK User's Guide, + SIAM, (Society for Industrial and Applied Mathematics), + 3600 University City Science Center, + Philadelphia, PA, 19104-2688. + ISBN 0-89871-172-X + + Parameters: + + Input, floating_point_t A[LDA*N], the output from DGECO or DGEFA. + + Input, int LDA, the leading dimension of A. + + Input, int N, the order of the matrix A. + + Input, int IPVT[N], the pivot vector from DGECO or DGEFA. + + Input/output, floating_point_t B[N]. + On input, the right hand side vector. + On output, the solution vector. + + Input, int JOB. + 0, solve A * X = B; + nonzero, solve A' * X = B. +*/ +{ + int k; + int l; + floating_point_t t; + /* + Solve A * X = B. +*/ + if (job == 0) { + for (k = 1; k <= n - 1; k++) { + l = ipvt[k - 1]; + t = b[l - 1]; + + if (l != k) { + b[l - 1] = b[k - 1]; + b[k - 1] = t; + } + + daxpy(n - k, t, a + k + (k - 1) * lda, 1, b + k, 1); + } + + for (k = n; 1 <= k; k--) { + b[k - 1] = b[k - 1] / a[k - 1 + (k - 1) * lda]; + t = -b[k - 1]; + daxpy(k - 1, t, a + 0 + (k - 1) * lda, 1, b, 1); + } + } + /* + Solve A' * X = B. +*/ + else { + for (k = 1; k <= n; k++) { + t = ddot(k - 1, a + 0 + (k - 1) * lda, 1, b, 1); + b[k - 1] = (b[k - 1] - t) / a[k - 1 + (k - 1) * lda]; + } + + for (k = n - 1; 1 <= k; k--) { + b[k - 1] = b[k - 1] + ddot(n - k, a + k + (k - 1) * lda, 1, b + k, 1); + l = ipvt[k - 1]; + + if (l != k) { + t = b[l - 1]; + b[l - 1] = b[k - 1]; + b[k - 1] = t; + } + } + } + return; +} +/******************************************************************************/ + +void dscal(int n, floating_point_t sa, floating_point_t x[], int incx) + +/******************************************************************************/ +/* + Purpose: + + DSCAL scales a vector by a constant. + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of entries in the vector. + + Input, floating_point_t SA, the multiplier. + + Input/output, floating_point_t X[*], the vector to be scaled. + + Input, int INCX, the increment between successive entries of X. +*/ +{ + int i; + int ix; + int m; + + if (n <= 0) { + } else if (incx == 1) { + m = n % 5; + + for (i = 0; i < m; i++) { + x[i] = sa * x[i]; + } + + for (i = m; i < n; i = i + 5) { + x[i] = sa * x[i]; + x[i + 1] = sa * x[i + 1]; + x[i + 2] = sa * x[i + 2]; + x[i + 3] = sa * x[i + 3]; + x[i + 4] = sa * x[i + 4]; + } + } else { + if (0 <= incx) { + ix = 0; + } else { + ix = (-n + 1) * incx; + } + + for (i = 0; i < n; i++) { + x[ix] = sa * x[ix]; + ix = ix + incx; + } + } + return; +} +/******************************************************************************/ + +int idamax(int n, floating_point_t dx[], int incx) + +/******************************************************************************/ +/* + Purpose: + + IDAMAX finds the index of the vector element of maximum absolute value. + + Discussion: + + WARNING: This index is a 1-based index, not a 0-based index! + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of entries in the vector. + + Input, floating_point_t X[*], the vector to be examined. + + Input, int INCX, the increment between successive entries of SX. + + Output, int IDAMAX, the index of the element of maximum + absolute value. +*/ +{ + floating_point_t dmax; + int i; + int ix; + int value; + + value = 0; + + if (n < 1 || incx <= 0) { + return value; + } + + value = 1; + + if (n == 1) { + return value; + } + + if (incx == 1) { + dmax = r8_abs(dx[0]); + + for (i = 1; i < n; i++) { + if (dmax < r8_abs(dx[i])) { + value = i + 1; + dmax = r8_abs(dx[i]); + } + } + } else { + ix = 0; + dmax = r8_abs(dx[0]); + ix = ix + incx; + + for (i = 1; i < n; i++) { + if (dmax < r8_abs(dx[ix])) { + value = i + 1; + dmax = r8_abs(dx[ix]); + } + ix = ix + incx; + } + } + + return value; +} +/******************************************************************************/ + +floating_point_t r8_abs(floating_point_t x) + +/******************************************************************************/ +/* + Purpose: + + R8_ABS returns the absolute value of a R8. + + Modified: + + 02 April 2005 + + Author: + + John Burkardt + + Parameters: + + Input, floating_point_t X, the quantity whose absolute value is desired. + + Output, floating_point_t R8_ABS, the absolute value of X. +*/ +{ + floating_point_t value; + + if (0.0 <= x) { + value = x; + } else { + value = -x; + } + return value; +} +/******************************************************************************/ + +floating_point_t r8_epsilon(void) + +/******************************************************************************/ +/* + Purpose: + + R8_EPSILON returns the R8 round off unit. + + Discussion: + + R8_EPSILON is a number R which is a power of 2 with the property that, + to the precision of the computer's arithmetic, + 1 < 1 + R + but + 1 = ( 1 + R / 2 ) + + Licensing: + + This code is distributed under the GNU LGPL license. + + Modified: + + 08 May 2006 + + Author: + + John Burkardt + + Parameters: + + Output, floating_point_t R8_EPSILON, the floating_point_t precision round-off unit. +*/ +{ + floating_point_t r; + + r = 1.0; + + while (1.0 < (floating_point_t)(1.0 + r)) { + r = r / 2.0; + } + r = 2.0 * r; + + return r; +} +/******************************************************************************/ + +floating_point_t r8_max(floating_point_t x, floating_point_t y) + +/******************************************************************************/ +/* + Purpose: + + R8_MAX returns the maximum of two R8's. + + Modified: + + 18 August 2004 + + Author: + + John Burkardt + + Parameters: + + Input, floating_point_t X, Y, the quantities to compare. + + Output, floating_point_t R8_MAX, the maximum of X and Y. +*/ +{ + floating_point_t value; + + if (y < x) { + value = x; + } else { + value = y; + } + return value; +} +/******************************************************************************/ + +floating_point_t r8_random(int iseed[4]) + +/******************************************************************************/ +/* + Purpose: + + R8_RANDOM returns a uniformly distributed random number between 0 and 1. + + Discussion: + + This routine uses a multiplicative congruential method with modulus + 2**48 and multiplier 33952834046453 (see G.S.Fishman, + 'Multiplicative congruential random number generators with modulus + 2**b: an exhaustive analysis for b = 32 and a partial analysis for + b = 48', Math. Comp. 189, pp 331-344, 1990). + + 48-bit integers are stored in 4 integer array elements with 12 bits + per element. Hence the routine is portable across machines with + integers of 32 bits or more. + + Parameters: + + Input/output, integer ISEED(4). + On entry, the seed of the random number generator; the array + elements must be between 0 and 4095, and ISEED(4) must be odd. + On exit, the seed is updated. + + Output, floating_point_t R8_RANDOM, the next pseudorandom number. +*/ +{ + int ipw2 = 4096; + int it1; + int it2; + int it3; + int it4; + int m1 = 494; + int m2 = 322; + int m3 = 2508; + int m4 = 2549; + floating_point_t r = 1.0 / 4096.0; + floating_point_t value; + /* + Multiply the seed by the multiplier modulo 2**48. +*/ + it4 = iseed[3] * m4; + it3 = it4 / ipw2; + it4 = it4 - ipw2 * it3; + it3 = it3 + iseed[2] * m4 + iseed[3] * m3; + it2 = it3 / ipw2; + it3 = it3 - ipw2 * it2; + it2 = it2 + iseed[1] * m4 + iseed[2] * m3 + iseed[3] * m2; + it1 = it2 / ipw2; + it2 = it2 - ipw2 * it1; + it1 = it1 + iseed[0] * m4 + iseed[1] * m3 + iseed[2] * m2 + iseed[3] * m1; + it1 = (it1 % ipw2); + /* + Return updated seed +*/ + iseed[0] = it1; + iseed[1] = it2; + iseed[2] = it3; + iseed[3] = it4; + /* + Convert 48-bit integer to a real number in the interval (0,1) +*/ + value = r * ((floating_point_t)(it1) + r * ((floating_point_t)(it2) + r * ((floating_point_t)(it3) + r * ((floating_point_t)(it4))))); + + return value; +} +/******************************************************************************/ + +void r8mat_gen(int lda, int n, floating_point_t *a) + +/******************************************************************************/ +/* + Purpose: + + R8MAT_GEN generates a random R8MAT. + + Modified: + + 06 June 2005 + + Parameters: + + Input, integer LDA, the leading dimension of the matrix. + + Input, integer N, the order of the matrix. + + Output, floating_point_t R8MAT_GEN[LDA*N], the N by N matrix. +*/ +{ + int i; + int init[4] = {1, 2, 3, 1325}; + int j; + + for (j = 1; j <= n; j++) { + for (i = 1; i <= n; i++) { + a[i - 1 + (j - 1) * lda] = r8_random(init) - 0.5; + } + } +} +/******************************************************************************/ diff --git a/tests/performance/linpack_float/test_linpack_float.py b/tests/performance/linpack_float/test_linpack_float.py new file mode 100644 index 00000000000..d11f6c74136 --- /dev/null +++ b/tests/performance/linpack_float/test_linpack_float.py @@ -0,0 +1,61 @@ +import json +import logging +import os + + +def test_linpack_float(dut, request): + LOGGER = logging.getLogger(__name__) + + # Match "Runs: %d" + res = dut.expect(r"Runs: (\d+)", timeout=60) + runs = int(res.group(0).decode("utf-8").split(" ")[1]) + LOGGER.info("Number of runs: {}".format(runs)) + assert runs > 0, "Invalid number of runs" + + # Match "Type: %s" + res = dut.expect(r"Type: (\w+)", timeout=60) + data_type = res.group(0).decode("utf-8").split(" ")[1] + LOGGER.info("Data type: {}".format(data_type)) + assert data_type == "float", "Invalid data type" + + # Match "Runs completed: %d" + res = dut.expect(r"Runs completed: (\d+)", timeout=120) + runs_completed = int(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Runs completed: {}".format(runs_completed)) + assert runs_completed == runs, "Invalid number of runs completed" + + # Match "Average MFLOPS: %f" + res = dut.expect(r"Average MFLOPS: (\d+\.\d+)", timeout=120) + avg_score = float(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Average MFLOPS: {}".format(avg_score)) + assert avg_score > 0, "Invalid average MFLOPS" + + # Match "Min MFLOPS: %f" + res = dut.expect(r"Min MFLOPS: (\d+\.\d+)", timeout=120) + min_score = float(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Min MFLOPS: {}".format(min_score)) + assert min_score > 0 and min_score < 1000000000.0, "Invalid min MFLOPS" + + # Match "Max MFLOPS: %f" + res = dut.expect(r"Max MFLOPS: (\d+\.\d+)", timeout=120) + max_score = float(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Max MFLOPS: {}".format(max_score)) + assert max_score > 0, "Invalid max MFLOPS" + + # Create JSON with results and write it to file + # Always create a JSON with this format (so it can be merged later on): + # { TEST_NAME_STR: TEST_RESULTS_DICT } + results = {"linpack_float": {"runs": runs, "avg_score": avg_score, "min_score": min_score, "max_score": max_score}} + + current_folder = os.path.dirname(request.path) + file_index = 0 + report_file = os.path.join(current_folder, "result_linpack_float" + str(file_index) + ".json") + while os.path.exists(report_file): + report_file = report_file.replace(str(file_index) + ".json", str(file_index + 1) + ".json") + file_index += 1 + + with open(report_file, "w") as f: + try: + f.write(json.dumps(results)) + except Exception as e: + LOGGER.warning("Failed to write results to file: {}".format(e)) From 5fd7826d9f2847041a1fe5391612f41e6410743e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 4 Oct 2024 12:52:07 +0200 Subject: [PATCH 030/409] fix(boards): Remove partition scheme from FlashSize (#10400) --- boards.txt | 122 ----------------------------------------------------- 1 file changed, 122 deletions(-) diff --git a/boards.txt b/boards.txt index c785e4d80a4..c73d81b6f31 100644 --- a/boards.txt +++ b/boards.txt @@ -123,7 +123,6 @@ esp32c2.menu.FlashFreq.30.build.flash_freq=30m esp32c2.menu.FlashSize.2M=2MB (16Mb) esp32c2.menu.FlashSize.2M.build.flash_size=2MB -esp32c2.menu.FlashSize.2M.build.partitions=minimal esp32c2.menu.FlashSize.4M=4MB (32Mb) esp32c2.menu.FlashSize.4M.build.flash_size=4MB @@ -293,10 +292,8 @@ esp32h2.menu.FlashSize.4M=4MB (32Mb) esp32h2.menu.FlashSize.4M.build.flash_size=4MB esp32h2.menu.FlashSize.8M=8MB (64Mb) esp32h2.menu.FlashSize.8M.build.flash_size=8MB -esp32h2.menu.FlashSize.8M.build.partitions=default_8MB esp32h2.menu.FlashSize.2M=2MB (16Mb) esp32h2.menu.FlashSize.2M.build.flash_size=2MB -esp32h2.menu.FlashSize.2M.build.partitions=minimal esp32h2.menu.FlashSize.16M=16MB (128Mb) esp32h2.menu.FlashSize.16M.build.flash_size=16MB @@ -487,10 +484,8 @@ esp32c6.menu.FlashSize.4M=4MB (32Mb) esp32c6.menu.FlashSize.4M.build.flash_size=4MB esp32c6.menu.FlashSize.8M=8MB (64Mb) esp32c6.menu.FlashSize.8M.build.flash_size=8MB -esp32c6.menu.FlashSize.8M.build.partitions=default_8MB esp32c6.menu.FlashSize.2M=2MB (16Mb) esp32c6.menu.FlashSize.2M.build.flash_size=2MB -esp32c6.menu.FlashSize.2M.build.partitions=minimal esp32c6.menu.FlashSize.16M=16MB (128Mb) esp32c6.menu.FlashSize.16M.build.flash_size=16MB @@ -634,12 +629,10 @@ esp32s3.menu.FlashSize.4M=4MB (32Mb) esp32s3.menu.FlashSize.4M.build.flash_size=4MB esp32s3.menu.FlashSize.8M=8MB (64Mb) esp32s3.menu.FlashSize.8M.build.flash_size=8MB -esp32s3.menu.FlashSize.8M.build.partitions=default_8MB esp32s3.menu.FlashSize.16M=16MB (128Mb) esp32s3.menu.FlashSize.16M.build.flash_size=16MB esp32s3.menu.FlashSize.32M=32MB (256Mb) esp32s3.menu.FlashSize.32M.build.flash_size=32MB -esp32s3.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB esp32s3.menu.LoopCore.1=Core 1 esp32s3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -928,10 +921,8 @@ esp32c3.menu.FlashSize.4M=4MB (32Mb) esp32c3.menu.FlashSize.4M.build.flash_size=4MB esp32c3.menu.FlashSize.8M=8MB (64Mb) esp32c3.menu.FlashSize.8M.build.flash_size=8MB -esp32c3.menu.FlashSize.8M.build.partitions=default_8MB esp32c3.menu.FlashSize.2M=2MB (16Mb) esp32c3.menu.FlashSize.2M.build.flash_size=2MB -esp32c3.menu.FlashSize.2M.build.partitions=minimal esp32c3.menu.FlashSize.16M=16MB (128Mb) esp32c3.menu.FlashSize.16M.build.flash_size=16MB @@ -1137,10 +1128,8 @@ esp32s2.menu.FlashSize.4M=4MB (32Mb) esp32s2.menu.FlashSize.4M.build.flash_size=4MB esp32s2.menu.FlashSize.8M=8MB (64Mb) esp32s2.menu.FlashSize.8M.build.flash_size=8MB -esp32s2.menu.FlashSize.8M.build.partitions=default_8MB esp32s2.menu.FlashSize.2M=2MB (16Mb) esp32s2.menu.FlashSize.2M.build.flash_size=2MB -esp32s2.menu.FlashSize.2M.build.partitions=minimal esp32s2.menu.FlashSize.16M=16MB (128Mb) esp32s2.menu.FlashSize.16M.build.flash_size=16MB @@ -1323,10 +1312,8 @@ esp32.menu.FlashSize.4M=4MB (32Mb) esp32.menu.FlashSize.4M.build.flash_size=4MB esp32.menu.FlashSize.8M=8MB (64Mb) esp32.menu.FlashSize.8M.build.flash_size=8MB -esp32.menu.FlashSize.8M.build.partitions=default_8MB esp32.menu.FlashSize.2M=2MB (16Mb) esp32.menu.FlashSize.2M.build.flash_size=2MB -esp32.menu.FlashSize.2M.build.partitions=minimal esp32.menu.FlashSize.16M=16MB (128Mb) esp32.menu.FlashSize.16M.build.flash_size=16MB @@ -1499,7 +1486,6 @@ esp32da.menu.FlashSize.4M=4MB (32Mb) esp32da.menu.FlashSize.4M.build.flash_size=4MB esp32da.menu.FlashSize.8M=8MB (64Mb) esp32da.menu.FlashSize.8M.build.flash_size=8MB -esp32da.menu.FlashSize.8M.build.partitions=default_8MB esp32da.menu.FlashSize.16M=16MB (128Mb) esp32da.menu.FlashSize.16M.build.flash_size=16MB @@ -1841,12 +1827,10 @@ esp32s3-octal.menu.FlashSize.4M=4MB (32Mb) esp32s3-octal.menu.FlashSize.4M.build.flash_size=4MB esp32s3-octal.menu.FlashSize.8M=8MB (64Mb) esp32s3-octal.menu.FlashSize.8M.build.flash_size=8MB -esp32s3-octal.menu.FlashSize.8M.build.partitions=default_8MB esp32s3-octal.menu.FlashSize.16M=16MB (128Mb) esp32s3-octal.menu.FlashSize.16M.build.flash_size=16MB esp32s3-octal.menu.FlashSize.32M=32MB (256Mb) esp32s3-octal.menu.FlashSize.32M.build.flash_size=32MB -esp32s3-octal.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB esp32s3-octal.menu.LoopCore.1=Core 1 esp32s3-octal.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -2367,7 +2351,6 @@ esp32s2usb.menu.FlashSize.4M=4MB (32Mb) esp32s2usb.menu.FlashSize.4M.build.flash_size=4MB esp32s2usb.menu.FlashSize.8M=8MB (64Mb) esp32s2usb.menu.FlashSize.8M.build.flash_size=8MB -esp32s2usb.menu.FlashSize.8M.build.partitions=default_8MB esp32s2usb.menu.FlashSize.16M=16MB (128Mb) esp32s2usb.menu.FlashSize.16M.build.flash_size=16MB @@ -2461,13 +2444,10 @@ esp32wroverkit.menu.FlashSize.4M=4MB (32Mb) esp32wroverkit.menu.FlashSize.4M.build.flash_size=4MB esp32wroverkit.menu.FlashSize.8M=8MB (64Mb) esp32wroverkit.menu.FlashSize.8M.build.flash_size=8MB -esp32wroverkit.menu.FlashSize.8M.build.partitions=default_8MB esp32wroverkit.menu.FlashSize.2M=2MB (16Mb) esp32wroverkit.menu.FlashSize.2M.build.flash_size=2MB -esp32wroverkit.menu.FlashSize.2M.build.partitions=minimal esp32wroverkit.menu.FlashSize.16M=16MB (128Mb) esp32wroverkit.menu.FlashSize.16M.build.flash_size=16MB -esp32wroverkit.menu.FlashSize.16M.build.partitions=default_16MB esp32wroverkit.menu.PSRAM.enabled=Enabled esp32wroverkit.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw @@ -3069,10 +3049,8 @@ um_feathers2.menu.FlashSize.4M=4MB (32Mb) um_feathers2.menu.FlashSize.4M.build.flash_size=4MB um_feathers2.menu.FlashSize.8M=8MB (64Mb) um_feathers2.menu.FlashSize.8M.build.flash_size=8MB -um_feathers2.menu.FlashSize.8M.build.partitions=default_8MB um_feathers2.menu.FlashSize.2M=2MB (16Mb) um_feathers2.menu.FlashSize.2M.build.flash_size=2MB -um_feathers2.menu.FlashSize.2M.build.partitions=minimal um_feathers2.menu.UploadSpeed.921600=921600 um_feathers2.menu.UploadSpeed.921600.upload.speed=921600 @@ -3211,7 +3189,6 @@ um_feathers2neo.menu.FlashSize.4M=4MB (32Mb) um_feathers2neo.menu.FlashSize.4M.build.flash_size=4MB um_feathers2neo.menu.FlashSize.2M=2MB (16Mb) um_feathers2neo.menu.FlashSize.2M.build.flash_size=2MB -um_feathers2neo.menu.FlashSize.2M.build.partitions=minimal um_feathers2neo.menu.UploadSpeed.921600=921600 um_feathers2neo.menu.UploadSpeed.921600.upload.speed=921600 @@ -4246,7 +4223,6 @@ um_tinyc6.menu.FlashFreq.40.build.flash_freq=40m um_tinyc6.menu.FlashSize.8M=8MB (64Mb) um_tinyc6.menu.FlashSize.8M.build.flash_size=8MB -um_tinyc6.menu.FlashSize.8M.build.partitions=default_8MB um_tinyc6.menu.UploadSpeed.921600=921600 um_tinyc6.menu.UploadSpeed.921600.upload.speed=921600 @@ -4400,7 +4376,6 @@ um_tinys2.menu.FlashSize.4M=4MB (32Mb) um_tinys2.menu.FlashSize.4M.build.flash_size=4MB um_tinys2.menu.FlashSize.2M=2MB (16Mb) um_tinys2.menu.FlashSize.2M.build.flash_size=2MB -um_tinys2.menu.FlashSize.2M.build.partitions=minimal um_tinys2.menu.UploadSpeed.921600=921600 um_tinys2.menu.UploadSpeed.921600.upload.speed=921600 @@ -5669,10 +5644,8 @@ micros2.menu.FlashSize.4M=4MB (32Mb) micros2.menu.FlashSize.4M.build.flash_size=4MB micros2.menu.FlashSize.8M=8MB (64Mb) micros2.menu.FlashSize.8M.build.flash_size=8MB -micros2.menu.FlashSize.8M.build.partitions=default_8MB micros2.menu.FlashSize.2M=2MB (16Mb) micros2.menu.FlashSize.2M.build.flash_size=2MB -micros2.menu.FlashSize.2M.build.partitions=minimal micros2.menu.UploadSpeed.921600=921600 micros2.menu.UploadSpeed.921600.upload.speed=921600 @@ -6003,10 +5976,8 @@ ttgo-t1.menu.FlashSize.4M=4MB (32Mb) ttgo-t1.menu.FlashSize.4M.build.flash_size=4MB ttgo-t1.menu.FlashSize.2M=2MB (16Mb) ttgo-t1.menu.FlashSize.2M.build.flash_size=2MB -ttgo-t1.menu.FlashSize.2M.build.partitions=minimal ttgo-t1.menu.FlashSize.16M=16MB (128Mb) ttgo-t1.menu.FlashSize.16M.build.flash_size=16MB -ttgo-t1.menu.FlashSize.16M.build.partitions=ffat ttgo-t1.menu.UploadSpeed.921600=921600 ttgo-t1.menu.UploadSpeed.921600.upload.speed=921600 @@ -6463,7 +6434,6 @@ cw02.menu.FlashSize.4M=4MB (32Mb) cw02.menu.FlashSize.4M.build.flash_size=4MB cw02.menu.FlashSize.2M=2MB (16Mb) cw02.menu.FlashSize.2M.build.flash_size=2MB -cw02.menu.FlashSize.2M.build.partitions=minimal cw02.menu.UploadSpeed.921600=921600 cw02.menu.UploadSpeed.921600.upload.speed=921600 @@ -6864,10 +6834,8 @@ sparkfun_esp32s2_thing_plus.menu.FlashSize.4M=4MB (32Mb) sparkfun_esp32s2_thing_plus.menu.FlashSize.4M.build.flash_size=4MB sparkfun_esp32s2_thing_plus.menu.FlashSize.8M=8MB (64Mb) sparkfun_esp32s2_thing_plus.menu.FlashSize.8M.build.flash_size=8MB -sparkfun_esp32s2_thing_plus.menu.FlashSize.8M.build.partitions=default_8MB sparkfun_esp32s2_thing_plus.menu.FlashSize.2M=2MB (16Mb) sparkfun_esp32s2_thing_plus.menu.FlashSize.2M.build.flash_size=2MB -sparkfun_esp32s2_thing_plus.menu.FlashSize.2M.build.partitions=minimal sparkfun_esp32s2_thing_plus.menu.FlashSize.16M=16MB (128Mb) sparkfun_esp32s2_thing_plus.menu.FlashSize.16M.build.flash_size=16MB @@ -7256,10 +7224,8 @@ sparkfun_esp32c6_thing_plus.menu.FlashSize.4M=4MB (32Mb) sparkfun_esp32c6_thing_plus.menu.FlashSize.4M.build.flash_size=4MB sparkfun_esp32c6_thing_plus.menu.FlashSize.8M=8MB (64Mb) sparkfun_esp32c6_thing_plus.menu.FlashSize.8M.build.flash_size=8MB -sparkfun_esp32c6_thing_plus.menu.FlashSize.8M.build.partitions=default_8MB sparkfun_esp32c6_thing_plus.menu.FlashSize.2M=2MB (16Mb) sparkfun_esp32c6_thing_plus.menu.FlashSize.2M.build.flash_size=2MB -sparkfun_esp32c6_thing_plus.menu.FlashSize.2M.build.partitions=minimal sparkfun_esp32c6_thing_plus.menu.FlashSize.16M=16MB (128Mb) sparkfun_esp32c6_thing_plus.menu.FlashSize.16M.build.flash_size=16MB @@ -7417,10 +7383,8 @@ esp32micromod.menu.FlashSize.4M=4MB (32Mb) esp32micromod.menu.FlashSize.4M.build.flash_size=4MB esp32micromod.menu.FlashSize.8M=8MB (64Mb) esp32micromod.menu.FlashSize.8M.build.flash_size=8MB -esp32micromod.menu.FlashSize.8M.build.partitions=default_8MB esp32micromod.menu.FlashSize.2M=2MB (16Mb) esp32micromod.menu.FlashSize.2M.build.flash_size=2MB -esp32micromod.menu.FlashSize.2M.build.partitions=minimal esp32micromod.menu.FlashSize.16M=16MB (128Mb) esp32micromod.menu.FlashSize.16M.build.flash_size=16MB @@ -7670,10 +7634,8 @@ sparkfun_esp32_iot_redboard.menu.FlashSize.4M=4MB (32Mb) sparkfun_esp32_iot_redboard.menu.FlashSize.4M.build.flash_size=4MB sparkfun_esp32_iot_redboard.menu.FlashSize.8M=8MB (64Mb) sparkfun_esp32_iot_redboard.menu.FlashSize.8M.build.flash_size=8MB -sparkfun_esp32_iot_redboard.menu.FlashSize.8M.build.partitions=default_8MB sparkfun_esp32_iot_redboard.menu.FlashSize.2M=2MB (16Mb) sparkfun_esp32_iot_redboard.menu.FlashSize.2M.build.flash_size=2MB -sparkfun_esp32_iot_redboard.menu.FlashSize.2M.build.partitions=minimal sparkfun_esp32_iot_redboard.menu.FlashSize.16M=16MB (128Mb) sparkfun_esp32_iot_redboard.menu.FlashSize.16M.build.flash_size=16MB @@ -7855,10 +7817,8 @@ sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.4M=4MB (32Mb) sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.4M.build.flash_size=4MB sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.8M=8MB (64Mb) sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.8M.build.flash_size=8MB -sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.8M.build.partitions=default_8MB sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.2M=2MB (16Mb) sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.2M.build.flash_size=2MB -sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.2M.build.partitions=minimal sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.16M=16MB (128Mb) sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.16M.build.flash_size=16MB @@ -8111,13 +8071,10 @@ nina_w10.menu.UploadSpeed.512000.upload.speed=512000 nina_w10.menu.FlashSize.2M=2MB (16Mb, NINA-W101/W102) nina_w10.menu.FlashSize.2M.build.flash_size=2MB -nina_w10.menu.FlashSize.2M.build.partitions=minimal nina_w10.menu.FlashSize.4M=4MB (32Mb, NINA-W106-00B) nina_w10.menu.FlashSize.4M.build.flash_size=4MB -nina_w10.menu.FlashSize.4M.build.partitions=default nina_w10.menu.FlashSize.8M=8MB (64Mb, NINA-W106-10B) nina_w10.menu.FlashSize.8M.build.flash_size=8MB -nina_w10.menu.FlashSize.8M.build.partitions=default_8MB nina_w10.menu.FlashFreq.80=80MHz nina_w10.menu.FlashFreq.80.build.flash_freq=80m @@ -8287,7 +8244,6 @@ nora_w10.menu.FlashSize.4M=4MB (32Mb) nora_w10.menu.FlashSize.4M.build.flash_size=4MB nora_w10.menu.FlashSize.8M=8MB (64Mb) nora_w10.menu.FlashSize.8M.build.flash_size=8MB -nora_w10.menu.FlashSize.8M.build.partitions=default_8MB #nora_w10.menu.FlashSize.16M=16MB (128Mb) #nora_w10.menu.FlashSize.16M.build.flash_size=16MB #nora_w10.menu.FlashSize.32M=32MB (256Mb) @@ -11261,10 +11217,8 @@ dfrobot_firebeetle2_esp32e.menu.FlashSize.4M=4MB (32Mb) dfrobot_firebeetle2_esp32e.menu.FlashSize.4M.build.flash_size=4MB dfrobot_firebeetle2_esp32e.menu.FlashSize.8M=8MB (64Mb) dfrobot_firebeetle2_esp32e.menu.FlashSize.8M.build.flash_size=8MB -dfrobot_firebeetle2_esp32e.menu.FlashSize.8M.build.partitions=default_8MB dfrobot_firebeetle2_esp32e.menu.FlashSize.2M=2MB (16Mb) dfrobot_firebeetle2_esp32e.menu.FlashSize.2M.build.flash_size=2MB -dfrobot_firebeetle2_esp32e.menu.FlashSize.2M.build.partitions=minimal dfrobot_firebeetle2_esp32e.menu.FlashSize.16M=16MB (128Mb) dfrobot_firebeetle2_esp32e.menu.FlashSize.16M.build.flash_size=16MB @@ -11398,7 +11352,6 @@ dfrobot_firebeetle2_esp32s3.menu.FlashSize.4M=4MB (32Mb) dfrobot_firebeetle2_esp32s3.menu.FlashSize.4M.build.flash_size=4MB dfrobot_firebeetle2_esp32s3.menu.FlashSize.8M=8MB (64Mb) dfrobot_firebeetle2_esp32s3.menu.FlashSize.8M.build.flash_size=8MB -dfrobot_firebeetle2_esp32s3.menu.FlashSize.8M.build.partitions=default_8MB dfrobot_firebeetle2_esp32s3.menu.FlashSize.16M=16MB (128Mb) dfrobot_firebeetle2_esp32s3.menu.FlashSize.16M.build.flash_size=16MB #dfrobot_firebeetle2_esp32s3.menu.FlashSize.32M=32MB (256Mb) @@ -16564,7 +16517,6 @@ nologo_esp32s3_pico.menu.FlashMode.opi.build.flash_freq=80m nologo_esp32s3_pico.menu.FlashSize.8M=8MB (64Mb) nologo_esp32s3_pico.menu.FlashSize.8M.build.flash_size=8MB -nologo_esp32s3_pico.menu.FlashSize.8M.build.partitions=default_8MB nologo_esp32s3_pico.menu.FlashSize.16M=16MB (128Mb) nologo_esp32s3_pico.menu.FlashSize.16M.build.flash_size=16MB @@ -17826,10 +17778,8 @@ esp32s2-devkitlipo.menu.FlashSize.4M=4MB (32Mb) esp32s2-devkitlipo.menu.FlashSize.4M.build.flash_size=4MB esp32s2-devkitlipo.menu.FlashSize.8M=8MB (64Mb) esp32s2-devkitlipo.menu.FlashSize.8M.build.flash_size=8MB -esp32s2-devkitlipo.menu.FlashSize.8M.build.partitions=default_8MB esp32s2-devkitlipo.menu.FlashSize.2M=2MB (16Mb) esp32s2-devkitlipo.menu.FlashSize.2M.build.flash_size=2MB -esp32s2-devkitlipo.menu.FlashSize.2M.build.partitions=minimal esp32s2-devkitlipo.menu.FlashSize.16M=16MB (128Mb) esp32s2-devkitlipo.menu.FlashSize.16M.build.flash_size=16MB @@ -18023,10 +17973,8 @@ esp32s2-devkitlipo-usb.menu.FlashSize.4M=4MB (32Mb) esp32s2-devkitlipo-usb.menu.FlashSize.4M.build.flash_size=4MB esp32s2-devkitlipo-usb.menu.FlashSize.8M=8MB (64Mb) esp32s2-devkitlipo-usb.menu.FlashSize.8M.build.flash_size=8MB -esp32s2-devkitlipo-usb.menu.FlashSize.8M.build.partitions=default_8MB esp32s2-devkitlipo-usb.menu.FlashSize.2M=2MB (16Mb) esp32s2-devkitlipo-usb.menu.FlashSize.2M.build.flash_size=2MB -esp32s2-devkitlipo-usb.menu.FlashSize.2M.build.partitions=minimal esp32s2-devkitlipo-usb.menu.FlashSize.16M=16MB (128Mb) esp32s2-devkitlipo-usb.menu.FlashSize.16M.build.flash_size=16MB @@ -18157,12 +18105,10 @@ esp32s3-devkitlipo.menu.FlashSize.4M=4MB (32Mb) esp32s3-devkitlipo.menu.FlashSize.4M.build.flash_size=4MB esp32s3-devkitlipo.menu.FlashSize.8M=8MB (64Mb) esp32s3-devkitlipo.menu.FlashSize.8M.build.flash_size=8MB -esp32s3-devkitlipo.menu.FlashSize.8M.build.partitions=default_8MB esp32s3-devkitlipo.menu.FlashSize.16M=16MB (128Mb) esp32s3-devkitlipo.menu.FlashSize.16M.build.flash_size=16MB esp32s3-devkitlipo.menu.FlashSize.32M=32MB (256Mb) esp32s3-devkitlipo.menu.FlashSize.32M.build.flash_size=32MB -esp32s3-devkitlipo.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB esp32s3-devkitlipo.menu.LoopCore.1=Core 1 esp32s3-devkitlipo.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -18438,10 +18384,8 @@ esp32c3-devkitlipo.menu.FlashSize.4M=4MB (32Mb) esp32c3-devkitlipo.menu.FlashSize.4M.build.flash_size=4MB esp32c3-devkitlipo.menu.FlashSize.8M=8MB (64Mb) esp32c3-devkitlipo.menu.FlashSize.8M.build.flash_size=8MB -esp32c3-devkitlipo.menu.FlashSize.8M.build.partitions=default_8MB esp32c3-devkitlipo.menu.FlashSize.2M=2MB (16Mb) esp32c3-devkitlipo.menu.FlashSize.2M.build.flash_size=2MB -esp32c3-devkitlipo.menu.FlashSize.2M.build.partitions=minimal esp32c3-devkitlipo.menu.FlashSize.16M=16MB (128Mb) esp32c3-devkitlipo.menu.FlashSize.16M.build.flash_size=16MB @@ -18613,10 +18557,8 @@ esp32c6-evb.menu.FlashSize.4M=4MB (32Mb) esp32c6-evb.menu.FlashSize.4M.build.flash_size=4MB esp32c6-evb.menu.FlashSize.8M=8MB (64Mb) esp32c6-evb.menu.FlashSize.8M.build.flash_size=8MB -esp32c6-evb.menu.FlashSize.8M.build.partitions=default_8MB esp32c6-evb.menu.FlashSize.2M=2MB (16Mb) esp32c6-evb.menu.FlashSize.2M.build.flash_size=2MB -esp32c6-evb.menu.FlashSize.2M.build.partitions=minimal esp32c6-evb.menu.FlashSize.16M=16MB (128Mb) esp32c6-evb.menu.FlashSize.16M.build.flash_size=16MB @@ -18795,10 +18737,8 @@ esp32h2-devkitlipo.menu.FlashSize.4M=4MB (32Mb) esp32h2-devkitlipo.menu.FlashSize.4M.build.flash_size=4MB esp32h2-devkitlipo.menu.FlashSize.8M=8MB (64Mb) esp32h2-devkitlipo.menu.FlashSize.8M.build.flash_size=8MB -esp32h2-devkitlipo.menu.FlashSize.8M.build.partitions=default_8MB esp32h2-devkitlipo.menu.FlashSize.2M=2MB (16Mb) esp32h2-devkitlipo.menu.FlashSize.2M.build.flash_size=2MB -esp32h2-devkitlipo.menu.FlashSize.2M.build.partitions=minimal esp32h2-devkitlipo.menu.FlashSize.16M=16MB (128Mb) esp32h2-devkitlipo.menu.FlashSize.16M.build.flash_size=16MB @@ -18984,10 +18924,8 @@ esp32-sbc-fabgl.menu.FlashSize.4M=4MB (32Mb) esp32-sbc-fabgl.menu.FlashSize.4M.build.flash_size=4MB esp32-sbc-fabgl.menu.FlashSize.8M=8MB (64Mb) esp32-sbc-fabgl.menu.FlashSize.8M.build.flash_size=8MB -esp32-sbc-fabgl.menu.FlashSize.8M.build.partitions=default_8MB esp32-sbc-fabgl.menu.FlashSize.2M=2MB (16Mb) esp32-sbc-fabgl.menu.FlashSize.2M.build.flash_size=2MB -esp32-sbc-fabgl.menu.FlashSize.2M.build.partitions=minimal esp32-sbc-fabgl.menu.FlashSize.16M=16MB (128Mb) esp32-sbc-fabgl.menu.FlashSize.16M.build.flash_size=16MB @@ -20686,7 +20624,6 @@ m5stack_atoms3.menu.FlashMode.opi.build.flash_freq=80m m5stack_atoms3.menu.FlashSize.8M=8MB (64Mb) m5stack_atoms3.menu.FlashSize.8M.build.flash_size=8MB -m5stack_atoms3.menu.FlashSize.8M.build.partitions=default_8MB m5stack_atoms3.menu.LoopCore.1=Core 1 m5stack_atoms3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -20920,7 +20857,6 @@ m5stack_cores3.menu.FlashSize.16M=16MB (128Mb) m5stack_cores3.menu.FlashSize.16M.build.flash_size=16MB m5stack_cores3.menu.FlashSize.32M=32MB (256Mb) m5stack_cores3.menu.FlashSize.32M.build.flash_size=32MB -m5stack_cores3.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_cores3.menu.LoopCore.1=Core 1 m5stack_cores3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -21463,7 +21399,6 @@ m5stack_unit_cams3.menu.FlashSize.16M=16MB (128Mb) m5stack_unit_cams3.menu.FlashSize.16M.build.flash_size=16MB m5stack_unit_cams3.menu.FlashSize.32M=32MB (256Mb) m5stack_unit_cams3.menu.FlashSize.32M.build.flash_size=32MB -m5stack_unit_cams3.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_unit_cams3.menu.LoopCore.1=Core 1 m5stack_unit_cams3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -22475,12 +22410,10 @@ m5stack_stamp_s3.menu.FlashSize.4M=4MB (32Mb) m5stack_stamp_s3.menu.FlashSize.4M.build.flash_size=4MB m5stack_stamp_s3.menu.FlashSize.8M=8MB (64Mb) m5stack_stamp_s3.menu.FlashSize.8M.build.flash_size=8MB -m5stack_stamp_s3.menu.FlashSize.8M.build.partitions=default_8MB m5stack_stamp_s3.menu.FlashSize.16M=16MB (128Mb) m5stack_stamp_s3.menu.FlashSize.16M.build.flash_size=16MB m5stack_stamp_s3.menu.FlashSize.32M=32MB (256Mb) m5stack_stamp_s3.menu.FlashSize.32M.build.flash_size=32MB -m5stack_stamp_s3.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_stamp_s3.menu.LoopCore.1=Core 1 m5stack_stamp_s3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -22714,12 +22647,10 @@ m5stack_capsule.menu.FlashSize.4M=4MB (32Mb) m5stack_capsule.menu.FlashSize.4M.build.flash_size=4MB m5stack_capsule.menu.FlashSize.8M=8MB (64Mb) m5stack_capsule.menu.FlashSize.8M.build.flash_size=8MB -m5stack_capsule.menu.FlashSize.8M.build.partitions=default_8MB m5stack_capsule.menu.FlashSize.16M=16MB (128Mb) m5stack_capsule.menu.FlashSize.16M.build.flash_size=16MB m5stack_capsule.menu.FlashSize.32M=32MB (256Mb) m5stack_capsule.menu.FlashSize.32M.build.flash_size=32MB -m5stack_capsule.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_capsule.menu.LoopCore.1=Core 1 m5stack_capsule.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -22956,12 +22887,10 @@ m5stack_cardputer.menu.FlashSize.4M=4MB (32Mb) m5stack_cardputer.menu.FlashSize.4M.build.flash_size=4MB m5stack_cardputer.menu.FlashSize.8M=8MB (64Mb) m5stack_cardputer.menu.FlashSize.8M.build.flash_size=8MB -m5stack_cardputer.menu.FlashSize.8M.build.partitions=default_8MB m5stack_cardputer.menu.FlashSize.16M=16MB (128Mb) m5stack_cardputer.menu.FlashSize.16M.build.flash_size=16MB m5stack_cardputer.menu.FlashSize.32M=32MB (256Mb) m5stack_cardputer.menu.FlashSize.32M.build.flash_size=32MB -m5stack_cardputer.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_cardputer.menu.LoopCore.1=Core 1 m5stack_cardputer.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -23195,12 +23124,10 @@ m5stack_dial.menu.FlashSize.4M=4MB (32Mb) m5stack_dial.menu.FlashSize.4M.build.flash_size=4MB m5stack_dial.menu.FlashSize.8M=8MB (64Mb) m5stack_dial.menu.FlashSize.8M.build.flash_size=8MB -m5stack_dial.menu.FlashSize.8M.build.partitions=default_8MB m5stack_dial.menu.FlashSize.16M=16MB (128Mb) m5stack_dial.menu.FlashSize.16M.build.flash_size=16MB m5stack_dial.menu.FlashSize.32M=32MB (256Mb) m5stack_dial.menu.FlashSize.32M.build.flash_size=32MB -m5stack_dial.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_dial.menu.LoopCore.1=Core 1 m5stack_dial.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -23434,12 +23361,10 @@ m5stack_dinmeter.menu.FlashSize.4M=4MB (32Mb) m5stack_dinmeter.menu.FlashSize.4M.build.flash_size=4MB m5stack_dinmeter.menu.FlashSize.8M=8MB (64Mb) m5stack_dinmeter.menu.FlashSize.8M.build.flash_size=8MB -m5stack_dinmeter.menu.FlashSize.8M.build.partitions=default_8MB m5stack_dinmeter.menu.FlashSize.16M=16MB (128Mb) m5stack_dinmeter.menu.FlashSize.16M.build.flash_size=16MB m5stack_dinmeter.menu.FlashSize.32M=32MB (256Mb) m5stack_dinmeter.menu.FlashSize.32M.build.flash_size=32MB -m5stack_dinmeter.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_dinmeter.menu.LoopCore.1=Core 1 m5stack_dinmeter.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -26516,7 +26441,6 @@ espectro32.menu.FlashSize.4M=4MB (32Mb) espectro32.menu.FlashSize.4M.build.flash_size=4MB espectro32.menu.FlashSize.2M=2MB (16Mb) espectro32.menu.FlashSize.2M.build.flash_size=2MB -espectro32.menu.FlashSize.2M.build.partitions=minimal espectro32.menu.UploadSpeed.921600=921600 espectro32.menu.UploadSpeed.921600.upload.speed=921600 @@ -26745,10 +26669,8 @@ alksesp32.menu.FlashSize.4M=4MB (32Mb) alksesp32.menu.FlashSize.4M.build.flash_size=4MB alksesp32.menu.FlashSize.2M=2MB (16Mb) alksesp32.menu.FlashSize.2M.build.flash_size=2MB -alksesp32.menu.FlashSize.2M.build.partitions=minimal alksesp32.menu.FlashSize.16M=16MB (128Mb) alksesp32.menu.FlashSize.16M.build.flash_size=16MB -alksesp32.menu.FlashSize.16M.build.partitions=ffat alksesp32.menu.UploadSpeed.921600=921600 alksesp32.menu.UploadSpeed.921600.upload.speed=921600 @@ -27265,7 +27187,6 @@ bpi_leaf_s3.menu.FlashMode.opi.build.flash_freq=80m bpi_leaf_s3.menu.FlashSize.8M=8MB (64Mb) bpi_leaf_s3.menu.FlashSize.8M.build.flash_size=8MB -bpi_leaf_s3.menu.FlashSize.8M.build.partitions=default_8MB bpi_leaf_s3.menu.FlashSize.4M=4MB (32Mb) bpi_leaf_s3.menu.FlashSize.4M.build.flash_size=4MB bpi_leaf_s3.menu.FlashSize.16M=16MB (128Mb) @@ -28222,7 +28143,6 @@ frogboard.menu.FlashSize.4M=4MB (32Mb) frogboard.menu.FlashSize.4M.build.flash_size=4MB frogboard.menu.FlashSize.2M=2MB (16Mb) frogboard.menu.FlashSize.2M.build.flash_size=2MB -frogboard.menu.FlashSize.2M.build.partitions=minimal frogboard.menu.UploadSpeed.921600=921600 frogboard.menu.UploadSpeed.921600.upload.speed=921600 @@ -28819,10 +28739,8 @@ vintlabs-devkit-v1.menu.FlashSize.4M=4MB (32Mb) vintlabs-devkit-v1.menu.FlashSize.4M.build.flash_size=4MB vintlabs-devkit-v1.menu.FlashSize.8M=8MB (64Mb) vintlabs-devkit-v1.menu.FlashSize.8M.build.flash_size=8MB -vintlabs-devkit-v1.menu.FlashSize.8M.build.partitions=default_8MB vintlabs-devkit-v1.menu.FlashSize.2M=2MB (16Mb) vintlabs-devkit-v1.menu.FlashSize.2M.build.flash_size=2MB -vintlabs-devkit-v1.menu.FlashSize.2M.build.partitions=minimal vintlabs-devkit-v1.menu.FlashSize.16M=16MB (128Mb) vintlabs-devkit-v1.menu.FlashSize.16M.build.flash_size=16MB @@ -29023,10 +28941,8 @@ mgbot-iotik32a.menu.FlashSize.4M=4MB (32Mb) mgbot-iotik32a.menu.FlashSize.4M.build.flash_size=4MB mgbot-iotik32a.menu.FlashSize.8M=8MB (64Mb) mgbot-iotik32a.menu.FlashSize.8M.build.flash_size=8MB -mgbot-iotik32a.menu.FlashSize.8M.build.partitions=default_8MB mgbot-iotik32a.menu.FlashSize.2M=2MB (16Mb) mgbot-iotik32a.menu.FlashSize.2M.build.flash_size=2MB -mgbot-iotik32a.menu.FlashSize.2M.build.partitions=minimal mgbot-iotik32a.menu.FlashSize.16M=16MB (128Mb) mgbot-iotik32a.menu.FlashSize.16M.build.flash_size=16MB @@ -29172,10 +29088,8 @@ mgbot-iotik32b.menu.FlashSize.4M=4MB (32Mb) mgbot-iotik32b.menu.FlashSize.4M.build.flash_size=4MB mgbot-iotik32b.menu.FlashSize.8M=8MB (64Mb) mgbot-iotik32b.menu.FlashSize.8M.build.flash_size=8MB -mgbot-iotik32b.menu.FlashSize.8M.build.partitions=default_8MB mgbot-iotik32b.menu.FlashSize.2M=2MB (16Mb) mgbot-iotik32b.menu.FlashSize.2M.build.flash_size=2MB -mgbot-iotik32b.menu.FlashSize.2M.build.partitions=minimal mgbot-iotik32b.menu.FlashSize.16M=16MB (128Mb) mgbot-iotik32b.menu.FlashSize.16M.build.flash_size=16MB @@ -29911,10 +29825,8 @@ wifiduino32c3.menu.FlashSize.4M=4MB (32Mb) wifiduino32c3.menu.FlashSize.4M.build.flash_size=4MB wifiduino32c3.menu.FlashSize.8M=8MB (64Mb) wifiduino32c3.menu.FlashSize.8M.build.flash_size=8MB -wifiduino32c3.menu.FlashSize.8M.build.partitions=default_8MB wifiduino32c3.menu.FlashSize.2M=2MB (16Mb) wifiduino32c3.menu.FlashSize.2M.build.flash_size=2MB -wifiduino32c3.menu.FlashSize.2M.build.partitions=minimal wifiduino32c3.menu.FlashSize.16M=16MB (128Mb) wifiduino32c3.menu.FlashSize.16M.build.flash_size=16MB @@ -30032,7 +29944,6 @@ wifiduino32s3.menu.FlashSize.4M=4MB (32Mb) wifiduino32s3.menu.FlashSize.4M.build.flash_size=4MB wifiduino32s3.menu.FlashSize.8M=8MB (64Mb) wifiduino32s3.menu.FlashSize.8M.build.flash_size=8MB -wifiduino32s3.menu.FlashSize.8M.build.partitions=default_8MB wifiduino32s3.menu.FlashSize.16M=16MB (128Mb) wifiduino32s3.menu.FlashSize.16M.build.flash_size=16MB #wifiduino32s3.menu.FlashSize.32M=32MB (256Mb) @@ -31364,10 +31275,8 @@ kb32.menu.FlashSize.4M=4MB (32Mb) kb32.menu.FlashSize.4M.build.flash_size=4MB kb32.menu.FlashSize.8M=8MB (64Mb) kb32.menu.FlashSize.8M.build.flash_size=8MB -kb32.menu.FlashSize.8M.build.partitions=default_8MB kb32.menu.FlashSize.2M=2MB (16Mb) kb32.menu.FlashSize.2M.build.flash_size=2MB -kb32.menu.FlashSize.2M.build.partitions=minimal kb32.menu.FlashSize.16M=16MB (128Mb) kb32.menu.FlashSize.16M.build.flash_size=16MB @@ -31544,10 +31453,8 @@ deneyapkart.menu.FlashSize.4M=4MB (32Mb) deneyapkart.menu.FlashSize.4M.build.flash_size=4MB deneyapkart.menu.FlashSize.8M=8MB (64Mb) deneyapkart.menu.FlashSize.8M.build.flash_size=8MB -deneyapkart.menu.FlashSize.8M.build.partitions=default_8MB deneyapkart.menu.FlashSize.2M=2MB (16Mb) deneyapkart.menu.FlashSize.2M.build.flash_size=2MB -deneyapkart.menu.FlashSize.2M.build.partitions=minimal deneyapkart.menu.FlashSize.16M=16MB (128Mb) deneyapkart.menu.FlashSize.16M.build.flash_size=16MB @@ -31724,10 +31631,8 @@ deneyapkart1A.menu.FlashSize.4M=4MB (32Mb) deneyapkart1A.menu.FlashSize.4M.build.flash_size=4MB deneyapkart1A.menu.FlashSize.8M=8MB (64Mb) deneyapkart1A.menu.FlashSize.8M.build.flash_size=8MB -deneyapkart1A.menu.FlashSize.8M.build.partitions=default_8MB deneyapkart1A.menu.FlashSize.2M=2MB (16Mb) deneyapkart1A.menu.FlashSize.2M.build.flash_size=2MB -deneyapkart1A.menu.FlashSize.2M.build.partitions=minimal deneyapkart1A.menu.FlashSize.16M=16MB (128Mb) deneyapkart1A.menu.FlashSize.16M.build.flash_size=16MB @@ -31871,7 +31776,6 @@ deneyapkart1Av2.menu.FlashSize.4M=4MB (32Mb) deneyapkart1Av2.menu.FlashSize.4M.build.flash_size=4MB deneyapkart1Av2.menu.FlashSize.8M=8MB (64Mb) deneyapkart1Av2.menu.FlashSize.8M.build.flash_size=8MB -deneyapkart1Av2.menu.FlashSize.8M.build.partitions=default_8MB deneyapkart1Av2.menu.FlashSize.16M=16MB (128Mb) deneyapkart1Av2.menu.FlashSize.16M.build.flash_size=16MB #deneyapkart1Av2.menu.FlashSize.32M=32MB (256Mb) @@ -32155,10 +32059,8 @@ deneyapmini.menu.FlashSize.4M=4MB (32Mb) deneyapmini.menu.FlashSize.4M.build.flash_size=4MB deneyapmini.menu.FlashSize.8M=8MB (64Mb) deneyapmini.menu.FlashSize.8M.build.flash_size=8MB -deneyapmini.menu.FlashSize.8M.build.partitions=default_8MB deneyapmini.menu.FlashSize.2M=2MB (16Mb) deneyapmini.menu.FlashSize.2M.build.flash_size=2MB -deneyapmini.menu.FlashSize.2M.build.partitions=minimal deneyapmini.menu.FlashSize.16M=16MB (128Mb) deneyapmini.menu.FlashSize.16M.build.flash_size=16MB @@ -32347,10 +32249,8 @@ deneyapminiv2.menu.FlashSize.4M=4MB (32Mb) deneyapminiv2.menu.FlashSize.4M.build.flash_size=4MB deneyapminiv2.menu.FlashSize.8M=8MB (64Mb) deneyapminiv2.menu.FlashSize.8M.build.flash_size=8MB -deneyapminiv2.menu.FlashSize.8M.build.partitions=default_8MB deneyapminiv2.menu.FlashSize.2M=2MB (16Mb) deneyapminiv2.menu.FlashSize.2M.build.flash_size=2MB -deneyapminiv2.menu.FlashSize.2M.build.partitions=minimal deneyapminiv2.menu.FlashSize.16M=16MB (128Mb) deneyapminiv2.menu.FlashSize.16M.build.flash_size=16MB @@ -32516,10 +32416,8 @@ deneyapkartg.menu.FlashSize.4M=4MB (32Mb) deneyapkartg.menu.FlashSize.4M.build.flash_size=4MB deneyapkartg.menu.FlashSize.8M=8MB (64Mb) deneyapkartg.menu.FlashSize.8M.build.flash_size=8MB -deneyapkartg.menu.FlashSize.8M.build.partitions=default_8MB deneyapkartg.menu.FlashSize.2M=2MB (16Mb) deneyapkartg.menu.FlashSize.2M.build.flash_size=2MB -deneyapkartg.menu.FlashSize.2M.build.partitions=minimal deneyapkartg.menu.FlashSize.16M=16MB (128Mb) deneyapkartg.menu.FlashSize.16M.build.flash_size=16MB @@ -32823,10 +32721,8 @@ atmegazero_esp32s2.menu.FlashSize.4M=4MB (32Mb) atmegazero_esp32s2.menu.FlashSize.4M.build.flash_size=4MB atmegazero_esp32s2.menu.FlashSize.8M=8MB (64Mb) atmegazero_esp32s2.menu.FlashSize.8M.build.flash_size=8MB -atmegazero_esp32s2.menu.FlashSize.8M.build.partitions=default_8MB atmegazero_esp32s2.menu.FlashSize.2M=2MB (16Mb) atmegazero_esp32s2.menu.FlashSize.2M.build.flash_size=2MB -atmegazero_esp32s2.menu.FlashSize.2M.build.partitions=minimal atmegazero_esp32s2.menu.FlashSize.16M=16MB (128Mb) atmegazero_esp32s2.menu.FlashSize.16M.build.flash_size=16MB @@ -32915,7 +32811,6 @@ franzininho_wifi_esp32s2.menu.FlashSize.4M=4MB (32Mb) franzininho_wifi_esp32s2.menu.FlashSize.4M.build.flash_size=4MB franzininho_wifi_esp32s2.menu.FlashSize.8M=8MB (64Mb) franzininho_wifi_esp32s2.menu.FlashSize.8M.build.flash_size=8MB -franzininho_wifi_esp32s2.menu.FlashSize.8M.build.partitions=default_8MB franzininho_wifi_esp32s2.menu.FlashSize.16M=16MB (128Mb) franzininho_wifi_esp32s2.menu.FlashSize.16M.build.flash_size=16MB @@ -33023,7 +32918,6 @@ franzininho_wifi_msc_esp32s2.menu.FlashSize.4M=4MB (32Mb) franzininho_wifi_msc_esp32s2.menu.FlashSize.4M.build.flash_size=4MB franzininho_wifi_msc_esp32s2.menu.FlashSize.8M=8MB (64Mb) franzininho_wifi_msc_esp32s2.menu.FlashSize.8M.build.flash_size=8MB -franzininho_wifi_msc_esp32s2.menu.FlashSize.8M.build.partitions=default_8MB franzininho_wifi_msc_esp32s2.menu.FlashSize.16M=16MB (128Mb) franzininho_wifi_msc_esp32s2.menu.FlashSize.16M.build.flash_size=16MB @@ -33160,7 +33054,6 @@ tamc_termod_s3.menu.FlashSize.4M=4MB (32Mb) tamc_termod_s3.menu.FlashSize.4M.build.flash_size=4MB tamc_termod_s3.menu.FlashSize.8M=8MB (64Mb) tamc_termod_s3.menu.FlashSize.8M.build.flash_size=8MB -tamc_termod_s3.menu.FlashSize.8M.build.partitions=default_8MB tamc_termod_s3.menu.FlashSize.16M=16MB (128Mb) tamc_termod_s3.menu.FlashSize.16M.build.flash_size=16MB @@ -33622,7 +33515,6 @@ lionbit.menu.FlashFreq.40.build.flash_freq=40m lionbit.menu.FlashSize.4M=4MB (32Mb) lionbit.menu.FlashSize.4M.build.flash_size=4MB -lionbit.menu.FlashSize.4M.build.partitions=default @@ -33970,10 +33862,8 @@ XIAO_ESP32C3.menu.FlashSize.4M=4MB (32Mb) XIAO_ESP32C3.menu.FlashSize.4M.build.flash_size=4MB XIAO_ESP32C3.menu.FlashSize.8M=8MB (64Mb) XIAO_ESP32C3.menu.FlashSize.8M.build.flash_size=8MB -XIAO_ESP32C3.menu.FlashSize.8M.build.partitions=default_8MB XIAO_ESP32C3.menu.FlashSize.2M=2MB (16Mb) XIAO_ESP32C3.menu.FlashSize.2M.build.flash_size=2MB -XIAO_ESP32C3.menu.FlashSize.2M.build.partitions=minimal XIAO_ESP32C3.menu.FlashSize.16M=16MB (128Mb) XIAO_ESP32C3.menu.FlashSize.16M.build.flash_size=16MB @@ -34246,7 +34136,6 @@ XIAO_ESP32S3.menu.FlashMode.dio.build.flash_freq=80m XIAO_ESP32S3.menu.FlashSize.8M=8MB (64Mb) XIAO_ESP32S3.menu.FlashSize.8M.build.flash_size=8MB -XIAO_ESP32S3.menu.FlashSize.8M.build.partitions=default_8MB XIAO_ESP32S3.menu.LoopCore.1=Core 1 XIAO_ESP32S3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -34669,10 +34558,8 @@ department_of_alchemy_minimain_esp32s2.menu.FlashSize.4M=4MB (32Mb) department_of_alchemy_minimain_esp32s2.menu.FlashSize.4M.build.flash_size=4MB department_of_alchemy_minimain_esp32s2.menu.FlashSize.8M=8MB (64Mb) department_of_alchemy_minimain_esp32s2.menu.FlashSize.8M.build.flash_size=8MB -department_of_alchemy_minimain_esp32s2.menu.FlashSize.8M.build.partitions=default_8MB department_of_alchemy_minimain_esp32s2.menu.FlashSize.2M=2MB (16Mb) department_of_alchemy_minimain_esp32s2.menu.FlashSize.2M.build.flash_size=2MB -department_of_alchemy_minimain_esp32s2.menu.FlashSize.2M.build.partitions=minimal department_of_alchemy_minimain_esp32s2.menu.FlashSize.16M=16MB (128Mb) department_of_alchemy_minimain_esp32s2.menu.FlashSize.16M.build.flash_size=16MB @@ -36413,10 +36300,8 @@ VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.4M=4MB (32Mb) VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.4M.build.flash_size=4MB VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.8M=8MB (64Mb) VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.8M.build.flash_size=8MB -VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.8M.build.partitions=default_8MB VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.2M=2MB (16Mb) VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.2M.build.flash_size=2MB -VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.2M.build.partitions=minimal VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.16M=16MB (128Mb) VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.16M.build.flash_size=16MB @@ -36566,10 +36451,8 @@ VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.4M=4MB (32Mb) VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.4M.build.flash_size=4MB VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.8M=8MB (64Mb) VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.8M.build.flash_size=8MB -VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.8M.build.partitions=default_8MB VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.2M=2MB (16Mb) VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.2M.build.flash_size=2MB -VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.2M.build.partitions=minimal VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.16M=16MB (128Mb) VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.16M.build.flash_size=16MB @@ -36687,7 +36570,6 @@ Edgebox-ESP-100.menu.FlashSize.4M=4MB (32Mb) Edgebox-ESP-100.menu.FlashSize.4M.build.flash_size=4MB Edgebox-ESP-100.menu.FlashSize.8M=8MB (64Mb) Edgebox-ESP-100.menu.FlashSize.8M.build.flash_size=8MB -Edgebox-ESP-100.menu.FlashSize.8M.build.partitions=default_8MB Edgebox-ESP-100.menu.FlashSize.16M=16MB (128Mb) Edgebox-ESP-100.menu.FlashSize.16M.build.flash_size=16MB #Edgebox-ESP-100.menu.FlashSize.32M=32MB (256Mb) @@ -37060,7 +36942,6 @@ nebulas3.menu.FlashSize.4M=4MB (32Mb) nebulas3.menu.FlashSize.4M.build.flash_size=4MB nebulas3.menu.FlashSize.8M=8MB (64Mb) nebulas3.menu.FlashSize.8M.build.flash_size=8MB -nebulas3.menu.FlashSize.8M.build.partitions=default_8MB nebulas3.menu.FlashSize.16M=16MB (128Mb) nebulas3.menu.FlashSize.16M.build.flash_size=16MB @@ -37285,7 +37166,6 @@ lionbits3.menu.FlashSize.4M=4MB (32Mb) lionbits3.menu.FlashSize.4M.build.flash_size=4MB lionbits3.menu.FlashSize.8M=8MB (64Mb) lionbits3.menu.FlashSize.8M.build.flash_size=8MB -lionbits3.menu.FlashSize.8M.build.partitions=default_8MB lionbits3.menu.FlashSize.16M=16MB (128Mb) lionbits3.menu.FlashSize.16M.build.flash_size=16MB #lionbits3.menu.FlashSize.32M=32MB (256Mb) @@ -39314,7 +39194,6 @@ epulse_feather_c6.menu.FlashSize.4M=4MB (32Mb) epulse_feather_c6.menu.FlashSize.4M.build.flash_size=4MB epulse_feather_c6.menu.FlashSize.2M=2MB (16Mb) epulse_feather_c6.menu.FlashSize.2M.build.flash_size=2MB -epulse_feather_c6.menu.FlashSize.2M.build.partitions=minimal epulse_feather_c6.menu.UploadSpeed.921600=921600 epulse_feather_c6.menu.UploadSpeed.921600.upload.speed=921600 @@ -39457,7 +39336,6 @@ Geekble_ESP32C3.menu.FlashSize.4M=4MB (Default) Geekble_ESP32C3.menu.FlashSize.4M.build.flash_size=4MB Geekble_ESP32C3.menu.FlashSize.2M=2MB Geekble_ESP32C3.menu.FlashSize.2M.build.flash_size=2MB -Geekble_ESP32C3.menu.FlashSize.2M.build.partitions=minimal Geekble_ESP32C3.menu.UploadSpeed.921600=921600 (Default) Geekble_ESP32C3.menu.UploadSpeed.921600.upload.speed=921600 From 8ce5f775fe928dc4541b0fecaf710de58aa3d198 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:57:08 -0300 Subject: [PATCH 031/409] ci(compilation): Use default partition and add append to FQBN option (#10392) * ci(partitions): Use default partition for compilation in CI * fix(ci): Fix paths for sdkconfig * Fix build of camera web server * fix(ci): Fix test requirements check * ci(append): Add option to append to all FQBNs * fix(json): Fix JSON files to compile examples * fix(example): Use requires instead of target in ci.json fix(zigbee): Improve JSON files Co-authored-by: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> * fix(regex): Trim argument before grep * docs(ci): Add documentation about FQBNs in CI * fix(json): Remove redundant FQBNs * fix(json): Skip requirements if libs are not installed * fix(partitions): Use rainmaker specific partitions --------- Co-authored-by: me-no-dev Co-authored-by: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> --- .github/scripts/install-platformio-esp32.sh | 8 ++- .github/scripts/sketch_utils.sh | 60 ++++++++++++------- .github/scripts/tests_run.sh | 31 ++++++---- .github/workflows/tests_build.yml | 3 + .github/workflows/tests_hw.yml | 4 -- docs/en/contributing.rst | 46 +++++++++++++- .../examples/Camera/CameraWebServer/ci.json | 15 +++++ .../Camera/CameraWebServer/partitions.csv | 5 +- .../RainMaker/examples/RMakerCustom/ci.json | 3 +- .../examples/RMakerCustomAirCooler/ci.json | 3 +- .../examples/RMakerSonoffDualR3/ci.json | 3 +- .../RainMaker/examples/RMakerSwitch/ci.json | 3 +- libraries/WiFiProv/examples/WiFiProv/ci.json | 1 + .../Zigbee_Color_Dimmable_Light/ci.json | 18 ++---- .../Zigbee_Color_Dimmer_Switch/ci.json | 18 ++---- .../examples/Zigbee_On_Off_Light/ci.json | 18 ++---- .../examples/Zigbee_On_Off_Switch/ci.json | 18 ++---- .../examples/Zigbee_Scan_Networks/ci.json | 18 ++---- .../Zigbee_Temperature_Sensor/ci.json | 18 ++---- .../Zigbee/examples/Zigbee_Thermostat/ci.json | 18 ++---- platform.txt | 4 ++ 21 files changed, 168 insertions(+), 147 deletions(-) diff --git a/.github/scripts/install-platformio-esp32.sh b/.github/scripts/install-platformio-esp32.sh index 393c9f3a7d6..a9aab496e19 100755 --- a/.github/scripts/install-platformio-esp32.sh +++ b/.github/scripts/install-platformio-esp32.sh @@ -6,7 +6,7 @@ PLATFORMIO_ESP32_URL="https://github.com/platformio/platform-espressif32.git" TOOLCHAIN_VERSION="12.2.0+20230208" ESPTOOLPY_VERSION="~1.40501.0" ESPRESSIF_ORGANIZATION_NAME="espressif" -LIBS_DIR="tools/esp32-arduino-libs" +SDKCONFIG_DIR="$PLATFORMIO_ESP32_PATH/tools/esp32-arduino-libs" echo "Installing Python Wheel ..." pip install wheel > /dev/null 2>&1 @@ -100,7 +100,8 @@ function count_sketches(){ # count_sketches requirements=$(jq -r '.requires[]? // empty' $sketchdir/ci.json) if [[ "$requirements" != "null" ]] || [[ "$requirements" != "" ]]; then for requirement in $requirements; do - found_line=$(grep -E "^$requirement" $LIBS_DIR/esp32/sdkconfig) + requirement=$(echo $requirement | xargs) + found_line=$(grep -E "^$requirement" "$SDKCONFIG_DIR/esp32/sdkconfig") if [[ "$found_line" == "" ]]; then continue 2 fi @@ -190,7 +191,8 @@ function build_pio_sketches(){ # build_pio_sketches [extra-options] while [ ! -z "$1" ]; do @@ -83,14 +89,21 @@ function build_sketch(){ # build_sketch [ex len=1 + if [ -f $sketchdir/ci.json ]; then + fqbn_append=`jq -r '.fqbn_append' $sketchdir/ci.json` + if [ $fqbn_append == "null" ]; then + fqbn_append="" + fi + fi + # Default FQBN options if none were passed in the command line. - esp32_opts="PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio" - esp32s2_opts="PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio" - esp32s3_opts="PSRAM=opi,USBMode=default,PartitionScheme=huge_app,FlashMode=dio" - esp32c3_opts="PartitionScheme=huge_app,FlashMode=dio" - esp32c6_opts="PartitionScheme=huge_app,FlashMode=dio" - esp32h2_opts="PartitionScheme=huge_app,FlashMode=dio" + esp32_opts="PSRAM=enabled,FlashMode=dio${fqbn_append:+,$fqbn_append}" + esp32s2_opts="PSRAM=enabled,FlashMode=dio${fqbn_append:+,$fqbn_append}" + esp32s3_opts="PSRAM=opi,USBMode=default,FlashMode=dio${fqbn_append:+,$fqbn_append}" + esp32c3_opts="FlashMode=dio${fqbn_append:+,$fqbn_append}" + esp32c6_opts="FlashMode=dio${fqbn_append:+,$fqbn_append}" + esp32h2_opts="FlashMode=dio${fqbn_append:+,$fqbn_append}" # Select the common part of the FQBN based on the target. The rest will be # appended depending on the passed options. @@ -154,7 +167,8 @@ function build_sketch(){ # build_sketch [ex requirements=$(jq -r '.requires[]? // empty' $sketchdir/ci.json) if [[ "$requirements" != "null" ]] || [[ "$requirements" != "" ]]; then for requirement in $requirements; do - found_line=$(grep -E "^$requirement" $LIBS_DIR/$target/sdkconfig) + requirement=$(echo $requirement | xargs) + found_line=$(grep -E "^$requirement" "$SDKCONFIG_DIR/$target/sdkconfig") if [[ "$found_line" == "" ]]; then echo "Target $target does not meet the requirement $requirement for $sketchname. Skipping." exit 0 @@ -270,10 +284,11 @@ function build_sketch(){ # build_sketch [ex unset options } -function count_sketches(){ # count_sketches [target] [file] +function count_sketches(){ # count_sketches [target] [file] [ignore-requirements] local path=$1 local target=$2 - local file=$3 + local ignore_requirements=$3 + local file=$4 if [ $# -lt 1 ]; then echo "ERROR: Illegal number of parameters" @@ -286,7 +301,7 @@ function count_sketches(){ # count_sketches [target] [file] return 0 fi - if [ -n "$file" ]; then + if [ -f "$file" ]; then local sketches=$(cat $file) else local sketches=$(find $path -name *.ino | sort) @@ -306,15 +321,18 @@ function count_sketches(){ # count_sketches [target] [file] continue fi - # Check if the sketch requires any configuration options - requirements=$(jq -r '.requires[]? // empty' $sketchdir/ci.json) - if [[ "$requirements" != "null" ]] || [[ "$requirements" != "" ]]; then - for requirement in $requirements; do - found_line=$(grep -E "^$requirement" $LIBS_DIR/$target/sdkconfig) - if [[ "$found_line" == "" ]]; then - continue 2 - fi - done + if [ "$ignore_requirements" != "1" ]; then + # Check if the sketch requires any configuration options + requirements=$(jq -r '.requires[]? // empty' $sketchdir/ci.json) + if [[ "$requirements" != "null" ]] || [[ "$requirements" != "" ]]; then + for requirement in $requirements; do + requirement=$(echo $requirement | xargs) + found_line=$(grep -E "^$requirement" $SDKCONFIG_DIR/$target/sdkconfig) + if [[ "$found_line" == "" ]]; then + continue 2 + fi + done + fi fi fi echo $sketch >> sketches.txt @@ -392,7 +410,7 @@ function build_sketches(){ # build_sketches `_ - are used if this field is not specified. + are used if this field is not specified. This overrides the default FQBNs and the ``fqbn_append`` field. The ``wifi`` test suite is a good example of how to use the ``ci.json`` file: diff --git a/libraries/ESP32/examples/Camera/CameraWebServer/ci.json b/libraries/ESP32/examples/Camera/CameraWebServer/ci.json index 7e0f3c89986..35c3056dda8 100644 --- a/libraries/ESP32/examples/Camera/CameraWebServer/ci.json +++ b/libraries/ESP32/examples/Camera/CameraWebServer/ci.json @@ -1,4 +1,19 @@ { + "fqbn": { + "esp32": [ + "espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=custom,FlashMode=dio", + "espressif:esp32:esp32:PSRAM=disabled,PartitionScheme=custom,FlashMode=dio" + ], + "esp32s2": [ + "espressif:esp32:esp32s2:PSRAM=enabled,PartitionScheme=custom,FlashMode=dio", + "espressif:esp32:esp32s2:PSRAM=disabled,PartitionScheme=custom,FlashMode=dio" + ], + "esp32s3": [ + "espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=custom,FlashMode=qio", + "espressif:esp32:esp32s3:PSRAM=enabled,USBMode=default,PartitionScheme=custom,FlashMode=qio", + "espressif:esp32:esp32s3:PSRAM=disabled,USBMode=default,PartitionScheme=custom,FlashMode=qio" + ] + }, "requires": [ "CONFIG_CAMERA_TASK_STACK_SIZE=[0-9]+" ] diff --git a/libraries/ESP32/examples/Camera/CameraWebServer/partitions.csv b/libraries/ESP32/examples/Camera/CameraWebServer/partitions.csv index 4f76ca6d746..b9f18c465a7 100644 --- a/libraries/ESP32/examples/Camera/CameraWebServer/partitions.csv +++ b/libraries/ESP32/examples/Camera/CameraWebServer/partitions.csv @@ -1,5 +1,6 @@ # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x5000, otadata, data, ota, 0xe000, 0x2000, -app0, app, ota_0, 0x10000, 0x3d0000, -fr, data, , 0x3e0000, 0x20000, +app0, app, ota_0, 0x10000, 0x3c0000, +fr, data, , 0x3d0000, 0x20000, +coredump, data, coredump,0x3f0000, 0x10000, diff --git a/libraries/RainMaker/examples/RMakerCustom/ci.json b/libraries/RainMaker/examples/RMakerCustom/ci.json index de4e92436d7..833a13f0860 100644 --- a/libraries/RainMaker/examples/RMakerCustom/ci.json +++ b/libraries/RainMaker/examples/RMakerCustom/ci.json @@ -1,6 +1,7 @@ { + "fqbn_append": "PartitionScheme=rainmaker_4MB", "requires": [ "CONFIG_SOC_WIFI_SUPPORTED=y", - "CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK" + "CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK=[1-9][0-9]*" ] } diff --git a/libraries/RainMaker/examples/RMakerCustomAirCooler/ci.json b/libraries/RainMaker/examples/RMakerCustomAirCooler/ci.json index de4e92436d7..833a13f0860 100644 --- a/libraries/RainMaker/examples/RMakerCustomAirCooler/ci.json +++ b/libraries/RainMaker/examples/RMakerCustomAirCooler/ci.json @@ -1,6 +1,7 @@ { + "fqbn_append": "PartitionScheme=rainmaker_4MB", "requires": [ "CONFIG_SOC_WIFI_SUPPORTED=y", - "CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK" + "CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK=[1-9][0-9]*" ] } diff --git a/libraries/RainMaker/examples/RMakerSonoffDualR3/ci.json b/libraries/RainMaker/examples/RMakerSonoffDualR3/ci.json index de4e92436d7..833a13f0860 100644 --- a/libraries/RainMaker/examples/RMakerSonoffDualR3/ci.json +++ b/libraries/RainMaker/examples/RMakerSonoffDualR3/ci.json @@ -1,6 +1,7 @@ { + "fqbn_append": "PartitionScheme=rainmaker_4MB", "requires": [ "CONFIG_SOC_WIFI_SUPPORTED=y", - "CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK" + "CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK=[1-9][0-9]*" ] } diff --git a/libraries/RainMaker/examples/RMakerSwitch/ci.json b/libraries/RainMaker/examples/RMakerSwitch/ci.json index de4e92436d7..833a13f0860 100644 --- a/libraries/RainMaker/examples/RMakerSwitch/ci.json +++ b/libraries/RainMaker/examples/RMakerSwitch/ci.json @@ -1,6 +1,7 @@ { + "fqbn_append": "PartitionScheme=rainmaker_4MB", "requires": [ "CONFIG_SOC_WIFI_SUPPORTED=y", - "CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK" + "CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK=[1-9][0-9]*" ] } diff --git a/libraries/WiFiProv/examples/WiFiProv/ci.json b/libraries/WiFiProv/examples/WiFiProv/ci.json index 36babb82730..04eb62b977a 100644 --- a/libraries/WiFiProv/examples/WiFiProv/ci.json +++ b/libraries/WiFiProv/examples/WiFiProv/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_WIFI_SUPPORTED=y" ] diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json index 3aaf44eb376..7b7ccef8ed7 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json @@ -1,16 +1,6 @@ { - "fqbn": { - "esp32c6": [ - "espressif:esp32:esp32c6:PartitionScheme=zigbee,ZigbeeMode=ed" - ], - "esp32h2": [ - "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" - ] - }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json index c916121b991..e79a477da11 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json @@ -1,16 +1,6 @@ { - "fqbn": { - "esp32c6": [ - "espressif:esp32:esp32c6:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" - ], - "esp32h2": [ - "espressif:esp32:esp32h2:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" - ] - }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=zigbee_zczr,ZigbeeMode=zczr", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json b/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json index 3aaf44eb376..7b7ccef8ed7 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json @@ -1,16 +1,6 @@ { - "fqbn": { - "esp32c6": [ - "espressif:esp32:esp32c6:PartitionScheme=zigbee,ZigbeeMode=ed" - ], - "esp32h2": [ - "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" - ] - }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json index c916121b991..e79a477da11 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json @@ -1,16 +1,6 @@ { - "fqbn": { - "esp32c6": [ - "espressif:esp32:esp32c6:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" - ], - "esp32h2": [ - "espressif:esp32:esp32h2:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" - ] - }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=zigbee_zczr,ZigbeeMode=zczr", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json b/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json index 3aaf44eb376..7b7ccef8ed7 100644 --- a/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json @@ -1,16 +1,6 @@ { - "fqbn": { - "esp32c6": [ - "espressif:esp32:esp32c6:PartitionScheme=zigbee,ZigbeeMode=ed" - ], - "esp32h2": [ - "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" - ] - }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json index 3aaf44eb376..7b7ccef8ed7 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json @@ -1,16 +1,6 @@ { - "fqbn": { - "esp32c6": [ - "espressif:esp32:esp32c6:PartitionScheme=zigbee,ZigbeeMode=ed" - ], - "esp32h2": [ - "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" - ] - }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json b/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json index c916121b991..e79a477da11 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json @@ -1,16 +1,6 @@ { - "fqbn": { - "esp32c6": [ - "espressif:esp32:esp32c6:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" - ], - "esp32h2": [ - "espressif:esp32:esp32h2:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" - ] - }, - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=zigbee_zczr,ZigbeeMode=zczr", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] } diff --git a/platform.txt b/platform.txt index 873e27b0ecb..a1574e2f776 100644 --- a/platform.txt +++ b/platform.txt @@ -143,6 +143,10 @@ recipe.hooks.prebuild.7.pattern.windows=cmd /c type nul > "{file_opts.path}" recipe.hooks.core.prebuild.1.pattern.windows=cmd /c echo "-DARDUINO_CORE_BUILD" > "{file_opts.path}" recipe.hooks.core.postbuild.1.pattern.windows=cmd /c type nul > "{file_opts.path}" +# Copy sdkconfig to build folder +recipe.hooks.prebuild.8.pattern=/usr/bin/env bash -c "cp -f "{runtime.platform.path}"/tools/esp32-arduino-libs/{build.mcu}/sdkconfig "{build.path}"/sdkconfig" +recipe.hooks.prebuild.8.pattern.windows=cmd /c COPY /y "{runtime.platform.path}\tools\esp32-arduino-libs\{build.mcu}\sdkconfig" "{build.path}\sdkconfig" + ## Compile c files recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.extra_flags} {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" -DARDUINO_VARIANT="{build.variant}" -DARDUINO_PARTITION_{build.partitions} {build.extra_flags} {compiler.cpreprocessor.flags} {includes} "@{build.opt.path}" "@{file_opts.path}" "{source_file}" -o "{object_file}" From 765173372f5e1fde9285b4180982589e4289aa9b Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:33:27 -0300 Subject: [PATCH 032/409] Add P4 to chip info --- cores/esp32/Esp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cores/esp32/Esp.cpp b/cores/esp32/Esp.cpp index 6a6ed11e463..aa189516469 100644 --- a/cores/esp32/Esp.cpp +++ b/cores/esp32/Esp.cpp @@ -300,6 +300,7 @@ const char *EspClass::getChipModel(void) { case CHIP_ESP32C2: return "ESP32-C2"; case CHIP_ESP32C6: return "ESP32-C6"; case CHIP_ESP32H2: return "ESP32-H2"; + case CHIP_ESP32P4: return "ESP32-P4"; default: return "UNKNOWN"; } #endif From 630377f7d3f8c859698529e4e1448d4551a9fa67 Mon Sep 17 00:00:00 2001 From: Bharat Pi <133974527+Bharat-Pi@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:13:51 +0530 Subject: [PATCH 033/409] =?UTF-8?q?feat(Variants):=20Add=20Arduino=20libra?= =?UTF-8?q?ries=20for=20Lora=204G=20Module=20and=20Node=20Wifi=20o?= =?UTF-8?q?=E2=80=A6=20(#10402)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(esp32): Added support for BharatPi 4G, LoRa & NodeWifi Boards * fix(variant): Fixed review comments for SPI and I2C Pins * fix(variant): Fixed review comments and Lora build fix * fix(variant): Fixed review comments for board name * fix(review): Fixed review comment for CI * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- boards.txt | 473 +++++++++++++++++++++ variants/BharatPi-A7672S-4G/pins_arduino.h | 31 ++ variants/BharatPi-LoRa/pins_arduino.h | 35 ++ variants/BharatPi-Node-Wifi/pins_arduino.h | 35 ++ 4 files changed, 574 insertions(+) create mode 100644 variants/BharatPi-A7672S-4G/pins_arduino.h create mode 100644 variants/BharatPi-LoRa/pins_arduino.h create mode 100644 variants/BharatPi-Node-Wifi/pins_arduino.h diff --git a/boards.txt b/boards.txt index c73d81b6f31..971f99a0cbc 100644 --- a/boards.txt +++ b/boards.txt @@ -2780,6 +2780,479 @@ aventen_s3_sync.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +BharatPi-Node-Wifi.name=BharatPi Node Wifi Module + +BharatPi-Node-Wifi.bootloader.tool=esptool_py +BharatPi-Node-Wifi.bootloader.tool.default=esptool_py + +BharatPi-Node-Wifi.upload.tool=esptool_py +BharatPi-Node-Wifi.upload.tool.default=esptool_py +BharatPi-Node-Wifi.upload.tool.network=esp_ota + +BharatPi-Node-Wifi.upload.maximum_size=1310720 +BharatPi-Node-Wifi.upload.maximum_data_size=327680 +BharatPi-Node-Wifi.upload.flags= +BharatPi-Node-Wifi.upload.extra_flags= + +BharatPi-Node-Wifi.serial.disableDTR=true +BharatPi-Node-Wifi.serial.disableRTS=true + +BharatPi-Node-Wifi.build.tarch=xtensa +BharatPi-Node-Wifi.build.bootloader_addr=0x1000 +BharatPi-Node-Wifi.build.target=esp32 +BharatPi-Node-Wifi.build.mcu=esp32 +BharatPi-Node-Wifi.build.core=esp32 +BharatPi-Node-Wifi.build.variant=BharatPi-Node-Wifi +BharatPi-Node-Wifi.build.board=BHARATPI_NODE_WIFI + +BharatPi-Node-Wifi.build.f_cpu=240000000L +BharatPi-Node-Wifi.build.flash_size=4MB +BharatPi-Node-Wifi.build.flash_freq=40m +BharatPi-Node-Wifi.build.flash_mode=dio +BharatPi-Node-Wifi.build.boot=dio +BharatPi-Node-Wifi.build.partitions=default +BharatPi-Node-Wifi.build.defines= +BharatPi-Node-Wifi.build.loop_core= +BharatPi-Node-Wifi.build.event_core= + +BharatPi-Node-Wifi.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.default.build.partitions=default +BharatPi-Node-Wifi.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +BharatPi-Node-Wifi.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +BharatPi-Node-Wifi.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +BharatPi-Node-Wifi.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +BharatPi-Node-Wifi.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.minimal.build.partitions=minimal +BharatPi-Node-Wifi.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.no_ota.build.partitions=no_ota +BharatPi-Node-Wifi.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +BharatPi-Node-Wifi.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +BharatPi-Node-Wifi.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +BharatPi-Node-Wifi.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +BharatPi-Node-Wifi.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +BharatPi-Node-Wifi.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +BharatPi-Node-Wifi.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +BharatPi-Node-Wifi.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +BharatPi-Node-Wifi.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +BharatPi-Node-Wifi.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.huge_app.build.partitions=huge_app +BharatPi-Node-Wifi.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +BharatPi-Node-Wifi.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +BharatPi-Node-Wifi.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +BharatPi-Node-Wifi.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +BharatPi-Node-Wifi.menu.PartitionScheme.fatflash.build.partitions=ffat +BharatPi-Node-Wifi.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +BharatPi-Node-Wifi.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +BharatPi-Node-Wifi.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +BharatPi-Node-Wifi.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +BharatPi-Node-Wifi.menu.PartitionScheme.rainmaker=RainMaker +BharatPi-Node-Wifi.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +BharatPi-Node-Wifi.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +BharatPi-Node-Wifi.menu.PartitionScheme.custom=Custom +BharatPi-Node-Wifi.menu.PartitionScheme.custom.build.partitions= +BharatPi-Node-Wifi.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +BharatPi-Node-Wifi.menu.CPUFreq.240=240MHz (WiFi/BT) +BharatPi-Node-Wifi.menu.CPUFreq.240.build.f_cpu=240000000L +BharatPi-Node-Wifi.menu.CPUFreq.160=160MHz (WiFi/BT) +BharatPi-Node-Wifi.menu.CPUFreq.160.build.f_cpu=160000000L +BharatPi-Node-Wifi.menu.CPUFreq.80=80MHz (WiFi/BT) +BharatPi-Node-Wifi.menu.CPUFreq.80.build.f_cpu=80000000L +BharatPi-Node-Wifi.menu.CPUFreq.40=40MHz (40MHz XTAL) +BharatPi-Node-Wifi.menu.CPUFreq.40.build.f_cpu=40000000L +BharatPi-Node-Wifi.menu.CPUFreq.26=26MHz (26MHz XTAL) +BharatPi-Node-Wifi.menu.CPUFreq.26.build.f_cpu=26000000L +BharatPi-Node-Wifi.menu.CPUFreq.20=20MHz (40MHz XTAL) +BharatPi-Node-Wifi.menu.CPUFreq.20.build.f_cpu=20000000L +BharatPi-Node-Wifi.menu.CPUFreq.13=13MHz (26MHz XTAL) +BharatPi-Node-Wifi.menu.CPUFreq.13.build.f_cpu=13000000L +BharatPi-Node-Wifi.menu.CPUFreq.10=10MHz (40MHz XTAL) +BharatPi-Node-Wifi.menu.CPUFreq.10.build.f_cpu=10000000L + +BharatPi-Node-Wifi.menu.FlashMode.qio=QIO +BharatPi-Node-Wifi.menu.FlashMode.qio.build.flash_mode=dio +BharatPi-Node-Wifi.menu.FlashMode.qio.build.boot=qio +BharatPi-Node-Wifi.menu.FlashMode.dio=DIO +BharatPi-Node-Wifi.menu.FlashMode.dio.build.flash_mode=dio +BharatPi-Node-Wifi.menu.FlashMode.dio.build.boot=dio + +BharatPi-Node-Wifi.menu.FlashFreq.80=80MHz +BharatPi-Node-Wifi.menu.FlashFreq.80.build.flash_freq=80m +BharatPi-Node-Wifi.menu.FlashFreq.40=40MHz +BharatPi-Node-Wifi.menu.FlashFreq.40.build.flash_freq=40m + +BharatPi-Node-Wifi.menu.FlashSize.4M=4MB (32Mb) +BharatPi-Node-Wifi.menu.FlashSize.4M.build.flash_size=4MB +BharatPi-Node-Wifi.menu.FlashSize.8M=8MB (64Mb) +BharatPi-Node-Wifi.menu.FlashSize.8M.build.flash_size=8MB +BharatPi-Node-Wifi.menu.FlashSize.8M.build.partitions=default_8MB +BharatPi-Node-Wifi.menu.FlashSize.16M=16MB (128Mb) +BharatPi-Node-Wifi.menu.FlashSize.16M.build.flash_size=16MB + +BharatPi-Node-Wifi.menu.UploadSpeed.921600=921600 +BharatPi-Node-Wifi.menu.UploadSpeed.921600.upload.speed=921600 +BharatPi-Node-Wifi.menu.UploadSpeed.115200=115200 +BharatPi-Node-Wifi.menu.UploadSpeed.115200.upload.speed=115200 +BharatPi-Node-Wifi.menu.UploadSpeed.256000.windows=256000 +BharatPi-Node-Wifi.menu.UploadSpeed.256000.upload.speed=256000 +BharatPi-Node-Wifi.menu.UploadSpeed.230400.windows.upload.speed=256000 +BharatPi-Node-Wifi.menu.UploadSpeed.230400=230400 +BharatPi-Node-Wifi.menu.UploadSpeed.230400.upload.speed=230400 +BharatPi-Node-Wifi.menu.UploadSpeed.460800.linux=460800 +BharatPi-Node-Wifi.menu.UploadSpeed.460800.macosx=460800 +BharatPi-Node-Wifi.menu.UploadSpeed.460800.upload.speed=460800 +BharatPi-Node-Wifi.menu.UploadSpeed.512000.windows=512000 +BharatPi-Node-Wifi.menu.UploadSpeed.512000.upload.speed=512000 + +BharatPi-Node-Wifi.menu.LoopCore.1=Core 1 +BharatPi-Node-Wifi.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +BharatPi-Node-Wifi.menu.LoopCore.0=Core 0 +BharatPi-Node-Wifi.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +BharatPi-Node-Wifi.menu.EventsCore.1=Core 1 +BharatPi-Node-Wifi.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +BharatPi-Node-Wifi.menu.EventsCore.0=Core 0 +BharatPi-Node-Wifi.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +BharatPi-Node-Wifi.menu.DebugLevel.none=None +BharatPi-Node-Wifi.menu.DebugLevel.none.build.code_debug=0 +BharatPi-Node-Wifi.menu.DebugLevel.error=Error +BharatPi-Node-Wifi.menu.DebugLevel.error.build.code_debug=1 +BharatPi-Node-Wifi.menu.DebugLevel.warn=Warn +BharatPi-Node-Wifi.menu.DebugLevel.warn.build.code_debug=2 +BharatPi-Node-Wifi.menu.DebugLevel.info=Info +BharatPi-Node-Wifi.menu.DebugLevel.info.build.code_debug=3 +BharatPi-Node-Wifi.menu.DebugLevel.debug=Debug +BharatPi-Node-Wifi.menu.DebugLevel.debug.build.code_debug=4 +BharatPi-Node-Wifi.menu.DebugLevel.verbose=Verbose +BharatPi-Node-Wifi.menu.DebugLevel.verbose.build.code_debug=5 + +BharatPi-Node-Wifi.menu.EraseFlash.none=Disabled +BharatPi-Node-Wifi.menu.EraseFlash.none.upload.erase_cmd= +BharatPi-Node-Wifi.menu.EraseFlash.all=Enabled +BharatPi-Node-Wifi.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + + +BharatPi-A7672S-4G.name=BharatPi A7672S 4G Module + +BharatPi-A7672S-4G.bootloader.tool=esptool_py +BharatPi-A7672S-4G.bootloader.tool.default=esptool_py + +BharatPi-A7672S-4G.upload.tool=esptool_py +BharatPi-A7672S-4G.upload.tool.default=esptool_py +BharatPi-A7672S-4G.upload.tool.network=esp_ota + +BharatPi-A7672S-4G.upload.maximum_size=1310720 +BharatPi-A7672S-4G.upload.maximum_data_size=327680 +BharatPi-A7672S-4G.upload.flags= +BharatPi-A7672S-4G.upload.extra_flags= + +BharatPi-A7672S-4G.serial.disableDTR=true +BharatPi-A7672S-4G.serial.disableRTS=true + +BharatPi-A7672S-4G.build.tarch=xtensa +BharatPi-A7672S-4G.build.bootloader_addr=0x1000 +BharatPi-A7672S-4G.build.target=esp32 +BharatPi-A7672S-4G.build.mcu=esp32 +BharatPi-A7672S-4G.build.core=esp32 +BharatPi-A7672S-4G.build.variant=BharatPi-A7672S-4G +BharatPi-A7672S-4G.build.board=BHARATPI_A7672S_4G + +BharatPi-A7672S-4G.build.f_cpu=240000000L +BharatPi-A7672S-4G.build.flash_size=4MB +BharatPi-A7672S-4G.build.flash_freq=40m +BharatPi-A7672S-4G.build.flash_mode=dio +BharatPi-A7672S-4G.build.boot=dio +BharatPi-A7672S-4G.build.partitions=default +BharatPi-A7672S-4G.build.defines= +BharatPi-A7672S-4G.build.loop_core= +BharatPi-A7672S-4G.build.event_core= + +BharatPi-A7672S-4G.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.default.build.partitions=default +BharatPi-A7672S-4G.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +BharatPi-A7672S-4G.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +BharatPi-A7672S-4G.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +BharatPi-A7672S-4G.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +BharatPi-A7672S-4G.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.minimal.build.partitions=minimal +BharatPi-A7672S-4G.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.no_ota.build.partitions=no_ota +BharatPi-A7672S-4G.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +BharatPi-A7672S-4G.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +BharatPi-A7672S-4G.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +BharatPi-A7672S-4G.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +BharatPi-A7672S-4G.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +BharatPi-A7672S-4G.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +BharatPi-A7672S-4G.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +BharatPi-A7672S-4G.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +BharatPi-A7672S-4G.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +BharatPi-A7672S-4G.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.huge_app.build.partitions=huge_app +BharatPi-A7672S-4G.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +BharatPi-A7672S-4G.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +BharatPi-A7672S-4G.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +BharatPi-A7672S-4G.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +BharatPi-A7672S-4G.menu.PartitionScheme.fatflash.build.partitions=ffat +BharatPi-A7672S-4G.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +BharatPi-A7672S-4G.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +BharatPi-A7672S-4G.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +BharatPi-A7672S-4G.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +BharatPi-A7672S-4G.menu.PartitionScheme.rainmaker=RainMaker +BharatPi-A7672S-4G.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +BharatPi-A7672S-4G.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +BharatPi-A7672S-4G.menu.PartitionScheme.custom=Custom +BharatPi-A7672S-4G.menu.PartitionScheme.custom.build.partitions= +BharatPi-A7672S-4G.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +BharatPi-A7672S-4G.menu.CPUFreq.240=240MHz (WiFi/BT) +BharatPi-A7672S-4G.menu.CPUFreq.240.build.f_cpu=240000000L +BharatPi-A7672S-4G.menu.CPUFreq.160=160MHz (WiFi/BT) +BharatPi-A7672S-4G.menu.CPUFreq.160.build.f_cpu=160000000L +BharatPi-A7672S-4G.menu.CPUFreq.80=80MHz (WiFi/BT) +BharatPi-A7672S-4G.menu.CPUFreq.80.build.f_cpu=80000000L +BharatPi-A7672S-4G.menu.CPUFreq.40=40MHz (40MHz XTAL) +BharatPi-A7672S-4G.menu.CPUFreq.40.build.f_cpu=40000000L +BharatPi-A7672S-4G.menu.CPUFreq.26=26MHz (26MHz XTAL) +BharatPi-A7672S-4G.menu.CPUFreq.26.build.f_cpu=26000000L +BharatPi-A7672S-4G.menu.CPUFreq.20=20MHz (40MHz XTAL) +BharatPi-A7672S-4G.menu.CPUFreq.20.build.f_cpu=20000000L +BharatPi-A7672S-4G.menu.CPUFreq.13=13MHz (26MHz XTAL) +BharatPi-A7672S-4G.menu.CPUFreq.13.build.f_cpu=13000000L +BharatPi-A7672S-4G.menu.CPUFreq.10=10MHz (40MHz XTAL) +BharatPi-A7672S-4G.menu.CPUFreq.10.build.f_cpu=10000000L + +BharatPi-A7672S-4G.menu.FlashMode.qio=QIO +BharatPi-A7672S-4G.menu.FlashMode.qio.build.flash_mode=dio +BharatPi-A7672S-4G.menu.FlashMode.qio.build.boot=qio +BharatPi-A7672S-4G.menu.FlashMode.dio=DIO +BharatPi-A7672S-4G.menu.FlashMode.dio.build.flash_mode=dio +BharatPi-A7672S-4G.menu.FlashMode.dio.build.boot=dio + +BharatPi-A7672S-4G.menu.FlashFreq.80=80MHz +BharatPi-A7672S-4G.menu.FlashFreq.80.build.flash_freq=80m +BharatPi-A7672S-4G.menu.FlashFreq.40=40MHz +BharatPi-A7672S-4G.menu.FlashFreq.40.build.flash_freq=40m + +BharatPi-A7672S-4G.menu.FlashSize.4M=4MB (32Mb) +BharatPi-A7672S-4G.menu.FlashSize.4M.build.flash_size=4MB +BharatPi-A7672S-4G.menu.FlashSize.8M=8MB (64Mb) +BharatPi-A7672S-4G.menu.FlashSize.8M.build.flash_size=8MB +BharatPi-A7672S-4G.menu.FlashSize.8M.build.partitions=default_8MB +BharatPi-A7672S-4G.menu.FlashSize.16M=16MB (128Mb) +BharatPi-A7672S-4G.menu.FlashSize.16M.build.flash_size=16MB + +BharatPi-A7672S-4G.menu.UploadSpeed.921600=921600 +BharatPi-A7672S-4G.menu.UploadSpeed.921600.upload.speed=921600 +BharatPi-A7672S-4G.menu.UploadSpeed.115200=115200 +BharatPi-A7672S-4G.menu.UploadSpeed.115200.upload.speed=115200 +BharatPi-A7672S-4G.menu.UploadSpeed.256000.windows=256000 +BharatPi-A7672S-4G.menu.UploadSpeed.256000.upload.speed=256000 +BharatPi-A7672S-4G.menu.UploadSpeed.230400.windows.upload.speed=256000 +BharatPi-A7672S-4G.menu.UploadSpeed.230400=230400 +BharatPi-A7672S-4G.menu.UploadSpeed.230400.upload.speed=230400 +BharatPi-A7672S-4G.menu.UploadSpeed.460800.linux=460800 +BharatPi-A7672S-4G.menu.UploadSpeed.460800.macosx=460800 +BharatPi-A7672S-4G.menu.UploadSpeed.460800.upload.speed=460800 +BharatPi-A7672S-4G.menu.UploadSpeed.512000.windows=512000 +BharatPi-A7672S-4G.menu.UploadSpeed.512000.upload.speed=512000 + +BharatPi-A7672S-4G.menu.LoopCore.1=Core 1 +BharatPi-A7672S-4G.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +BharatPi-A7672S-4G.menu.LoopCore.0=Core 0 +BharatPi-A7672S-4G.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +BharatPi-A7672S-4G.menu.EventsCore.1=Core 1 +BharatPi-A7672S-4G.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +BharatPi-A7672S-4G.menu.EventsCore.0=Core 0 +BharatPi-A7672S-4G.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +BharatPi-A7672S-4G.menu.DebugLevel.none=None +BharatPi-A7672S-4G.menu.DebugLevel.none.build.code_debug=0 +BharatPi-A7672S-4G.menu.DebugLevel.error=Error +BharatPi-A7672S-4G.menu.DebugLevel.error.build.code_debug=1 +BharatPi-A7672S-4G.menu.DebugLevel.warn=Warn +BharatPi-A7672S-4G.menu.DebugLevel.warn.build.code_debug=2 +BharatPi-A7672S-4G.menu.DebugLevel.info=Info +BharatPi-A7672S-4G.menu.DebugLevel.info.build.code_debug=3 +BharatPi-A7672S-4G.menu.DebugLevel.debug=Debug +BharatPi-A7672S-4G.menu.DebugLevel.debug.build.code_debug=4 +BharatPi-A7672S-4G.menu.DebugLevel.verbose=Verbose +BharatPi-A7672S-4G.menu.DebugLevel.verbose.build.code_debug=5 + +BharatPi-A7672S-4G.menu.EraseFlash.none=Disabled +BharatPi-A7672S-4G.menu.EraseFlash.none.upload.erase_cmd= +BharatPi-A7672S-4G.menu.EraseFlash.all=Enabled +BharatPi-A7672S-4G.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + + +BharatPi-LoRa.name=BharatPi LoRa Module + +BharatPi-LoRa.bootloader.tool=esptool_py +BharatPi-LoRa.bootloader.tool.default=esptool_py + +BharatPi-LoRa.upload.tool=esptool_py +BharatPi-LoRa.upload.tool.default=esptool_py +BharatPi-LoRa.upload.tool.network=esp_ota + +BharatPi-LoRa.upload.maximum_size=1310720 +BharatPi-LoRa.upload.maximum_data_size=327680 +BharatPi-LoRa.upload.flags= +BharatPi-LoRa.upload.extra_flags= + +BharatPi-LoRa.serial.disableDTR=true +BharatPi-LoRa.serial.disableRTS=true + +BharatPi-LoRa.build.tarch=xtensa +BharatPi-LoRa.build.bootloader_addr=0x1000 +BharatPi-LoRa.build.target=esp32 +BharatPi-LoRa.build.mcu=esp32 +BharatPi-LoRa.build.core=esp32 +BharatPi-LoRa.build.variant=BharatPi-LoRa +BharatPi-LoRa.build.board=BHARATPI_LORA + +BharatPi-LoRa.build.f_cpu=240000000L +BharatPi-LoRa.build.flash_size=4MB +BharatPi-LoRa.build.flash_freq=40m +BharatPi-LoRa.build.flash_mode=dio +BharatPi-LoRa.build.boot=dio +BharatPi-LoRa.build.partitions=default +BharatPi-LoRa.build.defines= +BharatPi-LoRa.build.loop_core= +BharatPi-LoRa.build.event_core= + +BharatPi-LoRa.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.default.build.partitions=default +BharatPi-LoRa.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +BharatPi-LoRa.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +BharatPi-LoRa.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +BharatPi-LoRa.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +BharatPi-LoRa.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.minimal.build.partitions=minimal +BharatPi-LoRa.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.no_ota.build.partitions=no_ota +BharatPi-LoRa.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +BharatPi-LoRa.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +BharatPi-LoRa.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +BharatPi-LoRa.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +BharatPi-LoRa.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +BharatPi-LoRa.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +BharatPi-LoRa.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +BharatPi-LoRa.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +BharatPi-LoRa.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +BharatPi-LoRa.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.huge_app.build.partitions=huge_app +BharatPi-LoRa.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +BharatPi-LoRa.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +BharatPi-LoRa.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +BharatPi-LoRa.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +BharatPi-LoRa.menu.PartitionScheme.fatflash.build.partitions=ffat +BharatPi-LoRa.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +BharatPi-LoRa.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +BharatPi-LoRa.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +BharatPi-LoRa.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +BharatPi-LoRa.menu.PartitionScheme.rainmaker=RainMaker +BharatPi-LoRa.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +BharatPi-LoRa.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +BharatPi-LoRa.menu.PartitionScheme.custom=Custom +BharatPi-LoRa.menu.PartitionScheme.custom.build.partitions= +BharatPi-LoRa.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +BharatPi-LoRa.menu.CPUFreq.240=240MHz (WiFi/BT) +BharatPi-LoRa.menu.CPUFreq.240.build.f_cpu=240000000L +BharatPi-LoRa.menu.CPUFreq.160=160MHz (WiFi/BT) +BharatPi-LoRa.menu.CPUFreq.160.build.f_cpu=160000000L +BharatPi-LoRa.menu.CPUFreq.80=80MHz (WiFi/BT) +BharatPi-LoRa.menu.CPUFreq.80.build.f_cpu=80000000L +BharatPi-LoRa.menu.CPUFreq.40=40MHz (40MHz XTAL) +BharatPi-LoRa.menu.CPUFreq.40.build.f_cpu=40000000L +BharatPi-LoRa.menu.CPUFreq.26=26MHz (26MHz XTAL) +BharatPi-LoRa.menu.CPUFreq.26.build.f_cpu=26000000L +BharatPi-LoRa.menu.CPUFreq.20=20MHz (40MHz XTAL) +BharatPi-LoRa.menu.CPUFreq.20.build.f_cpu=20000000L +BharatPi-LoRa.menu.CPUFreq.13=13MHz (26MHz XTAL) +BharatPi-LoRa.menu.CPUFreq.13.build.f_cpu=13000000L +BharatPi-LoRa.menu.CPUFreq.10=10MHz (40MHz XTAL) +BharatPi-LoRa.menu.CPUFreq.10.build.f_cpu=10000000L + +BharatPi-LoRa.menu.FlashMode.qio=QIO +BharatPi-LoRa.menu.FlashMode.qio.build.flash_mode=dio +BharatPi-LoRa.menu.FlashMode.qio.build.boot=qio +BharatPi-LoRa.menu.FlashMode.dio=DIO +BharatPi-LoRa.menu.FlashMode.dio.build.flash_mode=dio +BharatPi-LoRa.menu.FlashMode.dio.build.boot=dio + +BharatPi-LoRa.menu.FlashFreq.80=80MHz +BharatPi-LoRa.menu.FlashFreq.80.build.flash_freq=80m +BharatPi-LoRa.menu.FlashFreq.40=40MHz +BharatPi-LoRa.menu.FlashFreq.40.build.flash_freq=40m + +BharatPi-LoRa.menu.FlashSize.4M=4MB (32Mb) +BharatPi-LoRa.menu.FlashSize.4M.build.flash_size=4MB +BharatPi-LoRa.menu.FlashSize.8M=8MB (64Mb) +BharatPi-LoRa.menu.FlashSize.8M.build.flash_size=8MB +BharatPi-LoRa.menu.FlashSize.8M.build.partitions=default_8MB +BharatPi-LoRa.menu.FlashSize.16M=16MB (128Mb) +BharatPi-LoRa.menu.FlashSize.16M.build.flash_size=16MB + +BharatPi-LoRa.menu.UploadSpeed.921600=921600 +BharatPi-LoRa.menu.UploadSpeed.921600.upload.speed=921600 +BharatPi-LoRa.menu.UploadSpeed.115200=115200 +BharatPi-LoRa.menu.UploadSpeed.115200.upload.speed=115200 +BharatPi-LoRa.menu.UploadSpeed.256000.windows=256000 +BharatPi-LoRa.menu.UploadSpeed.256000.upload.speed=256000 +BharatPi-LoRa.menu.UploadSpeed.230400.windows.upload.speed=256000 +BharatPi-LoRa.menu.UploadSpeed.230400=230400 +BharatPi-LoRa.menu.UploadSpeed.230400.upload.speed=230400 +BharatPi-LoRa.menu.UploadSpeed.460800.linux=460800 +BharatPi-LoRa.menu.UploadSpeed.460800.macosx=460800 +BharatPi-LoRa.menu.UploadSpeed.460800.upload.speed=460800 +BharatPi-LoRa.menu.UploadSpeed.512000.windows=512000 +BharatPi-LoRa.menu.UploadSpeed.512000.upload.speed=512000 + +BharatPi-LoRa.menu.LoopCore.1=Core 1 +BharatPi-LoRa.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +BharatPi-LoRa.menu.LoopCore.0=Core 0 +BharatPi-LoRa.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +BharatPi-LoRa.menu.EventsCore.1=Core 1 +BharatPi-LoRa.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +BharatPi-LoRa.menu.EventsCore.0=Core 0 +BharatPi-LoRa.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +BharatPi-LoRa.menu.DebugLevel.none=None +BharatPi-LoRa.menu.DebugLevel.none.build.code_debug=0 +BharatPi-LoRa.menu.DebugLevel.error=Error +BharatPi-LoRa.menu.DebugLevel.error.build.code_debug=1 +BharatPi-LoRa.menu.DebugLevel.warn=Warn +BharatPi-LoRa.menu.DebugLevel.warn.build.code_debug=2 +BharatPi-LoRa.menu.DebugLevel.info=Info +BharatPi-LoRa.menu.DebugLevel.info.build.code_debug=3 +BharatPi-LoRa.menu.DebugLevel.debug=Debug +BharatPi-LoRa.menu.DebugLevel.debug.build.code_debug=4 +BharatPi-LoRa.menu.DebugLevel.verbose=Verbose +BharatPi-LoRa.menu.DebugLevel.verbose.build.code_debug=5 + +BharatPi-LoRa.menu.EraseFlash.none=Disabled +BharatPi-LoRa.menu.EraseFlash.none.upload.erase_cmd= +BharatPi-LoRa.menu.EraseFlash.all=Enabled +BharatPi-LoRa.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + um_bling.name=UM BLING um_bling.vid.0=0x303a um_bling.pid.0=0x817F diff --git a/variants/BharatPi-A7672S-4G/pins_arduino.h b/variants/BharatPi-A7672S-4G/pins_arduino.h new file mode 100644 index 00000000000..bf1fab09ddc --- /dev/null +++ b/variants/BharatPi-A7672S-4G/pins_arduino.h @@ -0,0 +1,31 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +static const uint8_t LED_BUILTIN = 2; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t A0 = 14; +static const uint8_t A1 = 13; +static const uint8_t A2 = 12; +static const uint8_t A3 = 4; +static const uint8_t A4 = 2; +static const uint8_t A5 = 0; + +static const uint8_t TX = 1; +static const uint8_t RX = 3; + +static const uint8_t TX_4G = 17; +static const uint8_t RX_4G = 16; + +static const uint8_t SDA = 21; +static const uint8_t SCL = 22; + +static const uint8_t SS = 5; +static const uint8_t MOSI = 23; +static const uint8_t MISO = 19; +static const uint8_t SCK = 18; + +#endif /* Pins_Arduino_h */ diff --git a/variants/BharatPi-LoRa/pins_arduino.h b/variants/BharatPi-LoRa/pins_arduino.h new file mode 100644 index 00000000000..a42e5834a3a --- /dev/null +++ b/variants/BharatPi-LoRa/pins_arduino.h @@ -0,0 +1,35 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +static const uint8_t LED_BUILTIN = 2; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t A0 = 14; +static const uint8_t A1 = 13; +static const uint8_t A2 = 12; +static const uint8_t A3 = 4; +static const uint8_t A4 = 2; +static const uint8_t A5 = 0; + +static const uint8_t TX = 1; +static const uint8_t RX = 3; + +static const uint8_t TX2 = 17; +static const uint8_t RX2 = 16; + +static const uint8_t LORA_SS = 4; +static const uint8_t RST = 14; +static const uint8_t DIO0 = 2; + +static const uint8_t SDA = 21; +static const uint8_t SCL = 22; + +static const uint8_t SS = 5; +static const uint8_t MOSI = 23; +static const uint8_t MISO = 19; +static const uint8_t SCK = 18; + +#endif /* Pins_Arduino_h */ diff --git a/variants/BharatPi-Node-Wifi/pins_arduino.h b/variants/BharatPi-Node-Wifi/pins_arduino.h new file mode 100644 index 00000000000..3b151289f44 --- /dev/null +++ b/variants/BharatPi-Node-Wifi/pins_arduino.h @@ -0,0 +1,35 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +static const uint8_t LED_BUILTIN = 2; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t SAFFRON_LED = 12; +static const uint8_t WHITE_LED = 2; +static const uint8_t GREEN_LED = 13; + +static const uint8_t A0 = 14; +static const uint8_t A1 = 13; +static const uint8_t A2 = 12; +static const uint8_t A3 = 4; +static const uint8_t A4 = 2; +static const uint8_t A5 = 0; + +static const uint8_t TX = 1; +static const uint8_t RX = 3; + +static const uint8_t TX2 = 17; +static const uint8_t RX2 = 16; + +static const uint8_t SDA = 21; +static const uint8_t SCL = 22; + +static const uint8_t SS = 5; +static const uint8_t MOSI = 23; +static const uint8_t MISO = 19; +static const uint8_t SCK = 18; + +#endif /* Pins_Arduino_h */ From 4d1c9bcfa33533946622a9359391150478f38290 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Mon, 7 Oct 2024 09:54:04 -0300 Subject: [PATCH 034/409] Fix partitions for examples --- libraries/BLE/examples/BLE5_extended_scan/ci.json | 1 + libraries/BLE/examples/BLE5_multi_advertising/ci.json | 1 + libraries/BLE/examples/BLE5_periodic_advertising/ci.json | 1 + libraries/BLE/examples/BLE5_periodic_sync/ci.json | 1 + libraries/BLE/examples/Beacon_Scanner/ci.json | 1 + libraries/BLE/examples/Client/ci.json | 1 + libraries/BLE/examples/EddystoneTLM_Beacon/ci.json | 1 + libraries/BLE/examples/EddystoneURL_Beacon/ci.json | 1 + libraries/BLE/examples/Notify/ci.json | 1 + libraries/BLE/examples/Scan/ci.json | 1 + libraries/BLE/examples/Server/ci.json | 1 + libraries/BLE/examples/Server_multiconnect/ci.json | 1 + libraries/BLE/examples/UART/ci.json | 1 + libraries/BLE/examples/Write/ci.json | 1 + libraries/BLE/examples/iBeacon/ci.json | 1 + libraries/BluetoothSerial/examples/DiscoverConnect/ci.json | 1 + libraries/BluetoothSerial/examples/GetLocalMAC/ci.json | 1 + libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json | 1 + libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json | 1 + .../BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json | 1 + libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json | 1 + .../BluetoothSerial/examples/bt_classic_device_discovery/ci.json | 1 + .../BluetoothSerial/examples/bt_remove_paired_devices/ci.json | 1 + libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json | 1 + libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json | 1 + libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json | 1 + .../examples/WiFiClientSecureEnterprise/ci.json | 1 + 27 files changed, 27 insertions(+) diff --git a/libraries/BLE/examples/BLE5_extended_scan/ci.json b/libraries/BLE/examples/BLE5_extended_scan/ci.json index 9f7646a74a6..184cc25a2b0 100644 --- a/libraries/BLE/examples/BLE5_extended_scan/ci.json +++ b/libraries/BLE/examples/BLE5_extended_scan/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_50_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/BLE5_multi_advertising/ci.json b/libraries/BLE/examples/BLE5_multi_advertising/ci.json index 9f7646a74a6..184cc25a2b0 100644 --- a/libraries/BLE/examples/BLE5_multi_advertising/ci.json +++ b/libraries/BLE/examples/BLE5_multi_advertising/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_50_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/BLE5_periodic_advertising/ci.json b/libraries/BLE/examples/BLE5_periodic_advertising/ci.json index 9f7646a74a6..184cc25a2b0 100644 --- a/libraries/BLE/examples/BLE5_periodic_advertising/ci.json +++ b/libraries/BLE/examples/BLE5_periodic_advertising/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_50_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/BLE5_periodic_sync/ci.json b/libraries/BLE/examples/BLE5_periodic_sync/ci.json index 9f7646a74a6..184cc25a2b0 100644 --- a/libraries/BLE/examples/BLE5_periodic_sync/ci.json +++ b/libraries/BLE/examples/BLE5_periodic_sync/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_50_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/Beacon_Scanner/ci.json b/libraries/BLE/examples/Beacon_Scanner/ci.json index c23553ec084..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Beacon_Scanner/ci.json +++ b/libraries/BLE/examples/Beacon_Scanner/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/Client/ci.json b/libraries/BLE/examples/Client/ci.json index c23553ec084..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Client/ci.json +++ b/libraries/BLE/examples/Client/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/EddystoneTLM_Beacon/ci.json b/libraries/BLE/examples/EddystoneTLM_Beacon/ci.json index c23553ec084..abe13a7ebbb 100644 --- a/libraries/BLE/examples/EddystoneTLM_Beacon/ci.json +++ b/libraries/BLE/examples/EddystoneTLM_Beacon/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/EddystoneURL_Beacon/ci.json b/libraries/BLE/examples/EddystoneURL_Beacon/ci.json index c23553ec084..abe13a7ebbb 100644 --- a/libraries/BLE/examples/EddystoneURL_Beacon/ci.json +++ b/libraries/BLE/examples/EddystoneURL_Beacon/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/Notify/ci.json b/libraries/BLE/examples/Notify/ci.json index c23553ec084..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Notify/ci.json +++ b/libraries/BLE/examples/Notify/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/Scan/ci.json b/libraries/BLE/examples/Scan/ci.json index c23553ec084..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Scan/ci.json +++ b/libraries/BLE/examples/Scan/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/Server/ci.json b/libraries/BLE/examples/Server/ci.json index c23553ec084..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Server/ci.json +++ b/libraries/BLE/examples/Server/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/Server_multiconnect/ci.json b/libraries/BLE/examples/Server_multiconnect/ci.json index c23553ec084..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Server_multiconnect/ci.json +++ b/libraries/BLE/examples/Server_multiconnect/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/UART/ci.json b/libraries/BLE/examples/UART/ci.json index c23553ec084..abe13a7ebbb 100644 --- a/libraries/BLE/examples/UART/ci.json +++ b/libraries/BLE/examples/UART/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/Write/ci.json b/libraries/BLE/examples/Write/ci.json index c23553ec084..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Write/ci.json +++ b/libraries/BLE/examples/Write/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_SUPPORTED=y" ] diff --git a/libraries/BLE/examples/iBeacon/ci.json b/libraries/BLE/examples/iBeacon/ci.json index c23553ec084..abe13a7ebbb 100644 --- a/libraries/BLE/examples/iBeacon/ci.json +++ b/libraries/BLE/examples/iBeacon/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_BLE_SUPPORTED=y" ] diff --git a/libraries/BluetoothSerial/examples/DiscoverConnect/ci.json b/libraries/BluetoothSerial/examples/DiscoverConnect/ci.json index 98fda4381b1..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/DiscoverConnect/ci.json +++ b/libraries/BluetoothSerial/examples/DiscoverConnect/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_BT_SPP_ENABLED=y" ] diff --git a/libraries/BluetoothSerial/examples/GetLocalMAC/ci.json b/libraries/BluetoothSerial/examples/GetLocalMAC/ci.json index 98fda4381b1..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/GetLocalMAC/ci.json +++ b/libraries/BluetoothSerial/examples/GetLocalMAC/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_BT_SPP_ENABLED=y" ] diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json b/libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json index 98fda4381b1..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_BT_SPP_ENABLED=y" ] diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json b/libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json index 98fda4381b1..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json +++ b/libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_BT_SPP_ENABLED=y" ] diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json b/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json index 98fda4381b1..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_BT_SPP_ENABLED=y" ] diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json b/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json index 98fda4381b1..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_BT_SPP_ENABLED=y" ] diff --git a/libraries/BluetoothSerial/examples/bt_classic_device_discovery/ci.json b/libraries/BluetoothSerial/examples/bt_classic_device_discovery/ci.json index 98fda4381b1..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/bt_classic_device_discovery/ci.json +++ b/libraries/BluetoothSerial/examples/bt_classic_device_discovery/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_BT_SPP_ENABLED=y" ] diff --git a/libraries/BluetoothSerial/examples/bt_remove_paired_devices/ci.json b/libraries/BluetoothSerial/examples/bt_remove_paired_devices/ci.json index 98fda4381b1..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/bt_remove_paired_devices/ci.json +++ b/libraries/BluetoothSerial/examples/bt_remove_paired_devices/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_BT_SPP_ENABLED=y" ] diff --git a/libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json b/libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json index 36babb82730..04eb62b977a 100644 --- a/libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json +++ b/libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_WIFI_SUPPORTED=y" ] diff --git a/libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json b/libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json index 36babb82730..04eb62b977a 100644 --- a/libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json +++ b/libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_WIFI_SUPPORTED=y" ] diff --git a/libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json index 36babb82730..04eb62b977a 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_WIFI_SUPPORTED=y" ] diff --git a/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/ci.json index 36babb82730..04eb62b977a 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/ci.json @@ -1,4 +1,5 @@ { + "fqbn_append": "PartitionScheme=huge_app", "requires": [ "CONFIG_SOC_WIFI_SUPPORTED=y" ] From 0d5d50eb4186cb5ef0b7c108f87fae1cb688b84f Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 7 Oct 2024 09:56:04 -0300 Subject: [PATCH 035/409] feat(uart): eliminates nonexistent functions (#10428) loop() calls Serial Events functions when those are declared. The way it was declared was forcing to alway call avalable() to then call an empty function. This commit fixes it. --- cores/esp32/HardwareSerial.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index 2e1f2701e9a..c82cbb43d3b 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -24,16 +24,13 @@ #endif void serialEvent(void) __attribute__((weak)); -void serialEvent(void) {} #if SOC_UART_NUM > 1 void serialEvent1(void) __attribute__((weak)); -void serialEvent1(void) {} #endif /* SOC_UART_NUM > 1 */ #if SOC_UART_NUM > 2 void serialEvent2(void) __attribute__((weak)); -void serialEvent2(void) {} #endif /* SOC_UART_NUM > 2 */ #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) @@ -48,37 +45,35 @@ HardwareSerial Serial2(2); #if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event extern void HWCDCSerialEvent(void) __attribute__((weak)); -void HWCDCSerialEvent(void) {} #endif #if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event // Used by Hardware Serial for USB CDC events extern void USBSerialEvent(void) __attribute__((weak)); -void USBSerialEvent(void) {} #endif void serialEventRun(void) { #if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event - if (HWCDCSerial.available()) { + if (HWCDCSerialEvent && HWCDCSerial.available()) { HWCDCSerialEvent(); } #endif #if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event - if (USBSerial.available()) { + if (USBSerialEvent && USBSerial.available()) { USBSerialEvent(); } #endif // UART0 is default serialEvent() - if (Serial0.available()) { + if (serialEvent && Serial0.available()) { serialEvent(); } #if SOC_UART_NUM > 1 - if (Serial1.available()) { + if (serialEvent1 && Serial1.available()) { serialEvent1(); } #endif #if SOC_UART_NUM > 2 - if (Serial2.available()) { + if (serialEvent2 && Serial2.available()) { serialEvent2(); } #endif From 3445164e2d9042189f79f76568a548d4e7ff9a81 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Mon, 7 Oct 2024 09:56:41 -0300 Subject: [PATCH 036/409] test(psram): Add PSRAM test (#10409) * test(psram): Add PSRAM test * fix(test): Hide pointer arithmetic warning * ci(pre-commit): Apply automatic fixes * fix(json): Remove FQBNs for the test --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- tests/validation/psram/ci.json | 14 ++++ tests/validation/psram/psram.ino | 112 +++++++++++++++++++++++++++ tests/validation/psram/test_psram.py | 2 + 3 files changed, 128 insertions(+) create mode 100644 tests/validation/psram/ci.json create mode 100644 tests/validation/psram/psram.ino create mode 100644 tests/validation/psram/test_psram.py diff --git a/tests/validation/psram/ci.json b/tests/validation/psram/ci.json new file mode 100644 index 00000000000..fc34574cf37 --- /dev/null +++ b/tests/validation/psram/ci.json @@ -0,0 +1,14 @@ +{ + "platforms": { + "qemu": false, + "wokwi": false + }, + "requires": [ + "CONFIG_SPIRAM=y" + ], + "targets": { + "esp32c3": false, + "esp32c6": false, + "esp32h2": false + } +} diff --git a/tests/validation/psram/psram.ino b/tests/validation/psram/psram.ino new file mode 100644 index 00000000000..1304fe85cc1 --- /dev/null +++ b/tests/validation/psram/psram.ino @@ -0,0 +1,112 @@ +#include +#include + +#define MAX_TEST_SIZE 512 * 1024 // 512KB + +void *buf = NULL; + +void test_malloc_success(void) { + buf = ps_malloc(MAX_TEST_SIZE); + TEST_ASSERT_NOT_NULL(buf); + free(buf); + buf = NULL; +} + +void test_calloc_success(void) { + buf = ps_calloc(MAX_TEST_SIZE, 1); + TEST_ASSERT_NOT_NULL(buf); + free(buf); + buf = NULL; +} + +void test_realloc_success(void) { + buf = ps_malloc(MAX_TEST_SIZE); + TEST_ASSERT_NOT_NULL(buf); + buf = ps_realloc(buf, MAX_TEST_SIZE + 1024); + TEST_ASSERT_NOT_NULL(buf); + free(buf); + buf = NULL; +} + +void test_malloc_fail(void) { + buf = ps_malloc(0xFFFFFFFF); + TEST_ASSERT_NULL(buf); +} + +void test_memset_all_zeroes(void) { + memset(buf, 0, MAX_TEST_SIZE); + for (size_t i = 0; i < MAX_TEST_SIZE; i++) { + TEST_ASSERT_EQUAL(0, ((uint8_t *)buf)[i]); + } +} + +void test_memset_all_ones(void) { + memset(buf, 0xFF, MAX_TEST_SIZE); + for (size_t i = 0; i < MAX_TEST_SIZE; i++) { + TEST_ASSERT_EQUAL(0xFF, ((uint8_t *)buf)[i]); + } +} + +void test_memset_alternating(void) { + for (size_t i = 0; i < MAX_TEST_SIZE; i++) { + ((uint8_t *)buf)[i] = i % 2 == 0 ? 0x00 : 0xFF; + } + memset(buf, 0xAA, MAX_TEST_SIZE); + for (size_t i = 0; i < MAX_TEST_SIZE; i++) { + TEST_ASSERT_EQUAL(0xAA, ((uint8_t *)buf)[i]); + } +} + +void test_memset_random(void) { + for (size_t i = 0; i < MAX_TEST_SIZE; i++) { + ((uint8_t *)buf)[i] = random(0, 256); + } + memset(buf, 0x55, MAX_TEST_SIZE); + for (size_t i = 0; i < MAX_TEST_SIZE; i++) { + TEST_ASSERT_EQUAL(0x55, ((uint8_t *)buf)[i]); + } +} + +void test_memcpy(void) { + void *buf2 = malloc(1024); // 1KB + TEST_ASSERT_NOT_NULL(buf2); + memset(buf, 0x55, MAX_TEST_SIZE); + memset(buf2, 0xAA, 1024); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpointer-arith" + + for (size_t i = 0; i < MAX_TEST_SIZE; i += 1024) { + memcpy(buf + i, buf2, 1024); + } + + for (size_t i = 0; i < MAX_TEST_SIZE; i += 1024) { + TEST_ASSERT_NULL(memcmp(buf + i, buf2, 1024)); + } + +#pragma GCC diagnostic pop + + free(buf2); +} + +void setup() { + Serial.begin(115200); + while (!Serial) { + delay(10); + } + + UNITY_BEGIN(); + RUN_TEST(test_malloc_success); + RUN_TEST(test_malloc_fail); + RUN_TEST(test_calloc_success); + RUN_TEST(test_realloc_success); + buf = ps_malloc(MAX_TEST_SIZE); + RUN_TEST(test_memset_all_zeroes); + RUN_TEST(test_memset_all_ones); + RUN_TEST(test_memset_alternating); + RUN_TEST(test_memset_random); + RUN_TEST(test_memcpy); + UNITY_END(); +} + +void loop() {} diff --git a/tests/validation/psram/test_psram.py b/tests/validation/psram/test_psram.py new file mode 100644 index 00000000000..7bd1d9d735d --- /dev/null +++ b/tests/validation/psram/test_psram.py @@ -0,0 +1,2 @@ +def test_psram(dut): + dut.expect_unity_test_output(timeout=120) From ba9a3a1dbd5247f662932d4d505b9b1da6ae369c Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 7 Oct 2024 10:58:41 -0300 Subject: [PATCH 037/409] fix(arduino): adds ESP32-P4 to the package description (#10426) * fix(arduino): adds ESP32-P4 to the package description Updates the Package description to add the P4 in 3.1.0 * fix(arduino): update readme title to add the P4 Adds ESP32-P$ to the list of supported SoC in README.md for Core 3.1.0 --- README.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d3dca34aafe..1ee43fa0537 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Arduino core for the ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6 and ESP32-H2 +# Arduino core for the ESP32, ESP32-P4, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6 and ESP32-H2 [![Build Status](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml/badge.svg?branch=master&event=push)](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml) [![External Libraries Test](https://github.com/espressif/arduino-esp32/actions/workflows/lib.yml/badge.svg?branch=master&event=schedule)](https://github.com/espressif/arduino-esp32/blob/gh-pages/LIBRARIES_TEST.md) [![Hardware Tests](https://github.com/espressif/arduino-esp32/blob/gh-pages/runtime-tests-results/badge.svg)](https://github.com/espressif/arduino-esp32/actions/workflows/tests_results.yml) diff --git a/package.json b/package.json index 2e53f41d4c8..e13a446bd98 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "framework-arduinoespressif32", "version": "3.1.0", - "description": "Arduino Wiring-based Framework for the Espressif ESP32, ESP32-S and ESP32-C series of SoCs", + "description": "Arduino Wiring-based Framework for the Espressif ESP32, ESP32-P4, ESP32-S and ESP32-C series of SoCs", "keywords": [ "framework", "arduino", From f083e2df8d9d58a59e86fd2c089ca60490f898b5 Mon Sep 17 00:00:00 2001 From: Hamza Hajeir <32960423+HamzaHajeir@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:15:42 +0300 Subject: [PATCH 038/409] fix(asyncudp): Fixes and implements tcpip thread locking (#10415) * fix(asyncudp): Fixes and implements tcpip thread locking * fix(asyncudp): Adds missing unlock * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- libraries/AsyncUDP/src/AsyncUDP.cpp | 39 ++++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/libraries/AsyncUDP/src/AsyncUDP.cpp b/libraries/AsyncUDP/src/AsyncUDP.cpp index 4f799b4d4a4..5549276de44 100644 --- a/libraries/AsyncUDP/src/AsyncUDP.cpp +++ b/libraries/AsyncUDP/src/AsyncUDP.cpp @@ -15,6 +15,21 @@ extern "C" { #include "lwip/priv/tcpip_priv.h" +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING +#define UDP_MUTEX_LOCK() \ + if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \ + LOCK_TCPIP_CORE(); \ + } + +#define UDP_MUTEX_UNLOCK() \ + if (sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \ + UNLOCK_TCPIP_CORE(); \ + } +#else // CONFIG_LWIP_TCPIP_CORE_LOCKING +#define UDP_MUTEX_LOCK() +#define UDP_MUTEX_UNLOCK() +#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING + static const char *netif_ifkeys[TCPIP_ADAPTER_IF_MAX] = {"WIFI_STA_DEF", "WIFI_AP_DEF", "ETH_DEF", "PPP_DEF"}; static esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void **netif) { @@ -28,7 +43,9 @@ static esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void **net if (netif_index < 0) { return ESP_FAIL; } + UDP_MUTEX_LOCK(); *netif = (void *)netif_get_by_index(netif_index); + UDP_MUTEX_UNLOCK(); } else { *netif = netif_default; } @@ -232,9 +249,6 @@ static bool _udp_task_stop(){ } */ -#define UDP_MUTEX_LOCK() //xSemaphoreTake(_lock, portMAX_DELAY) -#define UDP_MUTEX_UNLOCK() //xSemaphoreGive(_lock) - AsyncUDPMessage::AsyncUDPMessage(size_t size) { _index = 0; if (size > CONFIG_TCP_MSS) { @@ -473,12 +487,14 @@ bool AsyncUDP::_init() { if (_pcb) { return true; } + UDP_MUTEX_LOCK(); _pcb = udp_new(); if (!_pcb) { + UDP_MUTEX_UNLOCK(); return false; } - //_lock = xSemaphoreCreateMutex(); udp_recv(_pcb, &_udp_recv, (void *)this); + UDP_MUTEX_UNLOCK(); return true; } @@ -493,14 +509,12 @@ AsyncUDP::~AsyncUDP() { close(); UDP_MUTEX_LOCK(); udp_recv(_pcb, NULL, NULL); + UDP_MUTEX_UNLOCK(); _udp_remove(_pcb); _pcb = NULL; - UDP_MUTEX_UNLOCK(); - //vSemaphoreDelete(_lock); } void AsyncUDP::close() { - UDP_MUTEX_LOCK(); if (_pcb != NULL) { if (_connected) { _udp_disconnect(_pcb); @@ -508,7 +522,6 @@ void AsyncUDP::close() { _connected = false; //todo: unjoin multicast group } - UDP_MUTEX_UNLOCK(); } bool AsyncUDP::connect(const ip_addr_t *addr, uint16_t port) { @@ -520,14 +533,11 @@ bool AsyncUDP::connect(const ip_addr_t *addr, uint16_t port) { return false; } close(); - UDP_MUTEX_LOCK(); _lastErr = _udp_connect(_pcb, addr, port); if (_lastErr != ERR_OK) { - UDP_MUTEX_UNLOCK(); return false; } _connected = true; - UDP_MUTEX_UNLOCK(); return true; } @@ -544,13 +554,10 @@ bool AsyncUDP::listen(const ip_addr_t *addr, uint16_t port) { IP_SET_TYPE_VAL(_pcb->local_ip, addr->type); IP_SET_TYPE_VAL(_pcb->remote_ip, addr->type); } - UDP_MUTEX_LOCK(); if (_udp_bind(_pcb, addr, port) != ERR_OK) { - UDP_MUTEX_UNLOCK(); return false; } _connected = true; - UDP_MUTEX_UNLOCK(); return true; } @@ -624,12 +631,10 @@ bool AsyncUDP::listenMulticast(const ip_addr_t *addr, uint16_t port, uint8_t ttl return false; } - UDP_MUTEX_LOCK(); _pcb->mcast_ttl = ttl; _pcb->remote_port = port; ip_addr_copy(_pcb->remote_ip, *addr); //ip_addr_copy(_pcb->remote_ip, ip_addr_any_type); - UDP_MUTEX_UNLOCK(); return true; } @@ -651,7 +656,6 @@ size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, const ip_addr_t *addr, if (pbt != NULL) { uint8_t *dst = reinterpret_cast(pbt->payload); memcpy(dst, data, len); - UDP_MUTEX_LOCK(); if (tcpip_if < TCPIP_ADAPTER_IF_MAX) { void *nif = NULL; tcpip_adapter_get_netif((tcpip_adapter_if_t)tcpip_if, &nif); @@ -663,7 +667,6 @@ size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, const ip_addr_t *addr, } else { _lastErr = _udp_sendto(_pcb, pbt, addr, port); } - UDP_MUTEX_UNLOCK(); pbuf_free(pbt); if (_lastErr < ERR_OK) { return 0; From af4099202dba9acbb2653f3579e6441e65556bf4 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Thu, 10 Oct 2024 17:22:39 +0300 Subject: [PATCH 039/409] IDF release/v5.3 (#10444) * IDF release/v5.3 707d097b * fix(camera): Remove support for face detection and recognition --- .../Camera/CameraWebServer/app_httpd.cpp | 520 +----------------- package/package_esp32_index.template.json | 32 +- 2 files changed, 37 insertions(+), 515 deletions(-) diff --git a/libraries/ESP32/examples/Camera/CameraWebServer/app_httpd.cpp b/libraries/ESP32/examples/Camera/CameraWebServer/app_httpd.cpp index af3d38ad544..6b62ee9b6cf 100644 --- a/libraries/ESP32/examples/Camera/CameraWebServer/app_httpd.cpp +++ b/libraries/ESP32/examples/Camera/CameraWebServer/app_httpd.cpp @@ -24,55 +24,6 @@ #include "esp32-hal-log.h" #endif -// Face Detection will not work on boards without (or with disabled) PSRAM -#ifdef BOARD_HAS_PSRAM -// Face Recognition takes upward from 15 seconds per frame on chips other than ESP32S3 -// Makes no sense to have it enabled for them -#if CONFIG_IDF_TARGET_ESP32S3 -#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 1 -#define CONFIG_ESP_FACE_DETECT_ENABLED 1 -#else -#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 0 -#define CONFIG_ESP_FACE_DETECT_ENABLED 0 -#endif -#else -#define CONFIG_ESP_FACE_DETECT_ENABLED 0 -#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 0 -#endif - -#if CONFIG_ESP_FACE_DETECT_ENABLED - -#include -#include "human_face_detect_msr01.hpp" -#include "human_face_detect_mnp01.hpp" - -#define TWO_STAGE 1 /* very large firmware, very slow, reboots when streaming... - -#define FACE_ID_SAVE_NUMBER 7 -#endif - -#define FACE_COLOR_WHITE 0x00FFFFFF -#define FACE_COLOR_BLACK 0x00000000 -#define FACE_COLOR_RED 0x000000FF -#define FACE_COLOR_GREEN 0x0000FF00 -#define FACE_COLOR_BLUE 0x00FF0000 -#define FACE_COLOR_YELLOW (FACE_COLOR_RED | FACE_COLOR_GREEN) -#define FACE_COLOR_CYAN (FACE_COLOR_BLUE | FACE_COLOR_GREEN) -#define FACE_COLOR_PURPLE (FACE_COLOR_BLUE | FACE_COLOR_RED) -#endif - // Enable LED FLASH setting #define CONFIG_LED_ILLUMINATOR_ENABLED 1 @@ -100,32 +51,6 @@ static const char *_STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: % httpd_handle_t stream_httpd = NULL; httpd_handle_t camera_httpd = NULL; -#if CONFIG_ESP_FACE_DETECT_ENABLED - -static int8_t detection_enabled = 0; - -// #if TWO_STAGE -// static HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F); -// static HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5); -// #else -// static HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F); -// #endif - -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED -static int8_t recognition_enabled = 0; -static int8_t is_enrolling = 0; - -#if QUANT_TYPE -// S16 model -FaceRecognition112V1S16 recognizer; -#else -// S8 model -FaceRecognition112V1S8 recognizer; -#endif -#endif - -#endif - typedef struct { size_t size; //number of values used for filtering size_t index; //current value index @@ -166,105 +91,6 @@ static int ra_filter_run(ra_filter_t *filter, int value) { } #endif -#if CONFIG_ESP_FACE_DETECT_ENABLED -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED -static void rgb_print(fb_data_t *fb, uint32_t color, const char *str) { - fb_gfx_print(fb, (fb->width - (strlen(str) * 14)) / 2, 10, color, str); -} - -static int rgb_printf(fb_data_t *fb, uint32_t color, const char *format, ...) { - char loc_buf[64]; - char *temp = loc_buf; - int len; - va_list arg; - va_list copy; - va_start(arg, format); - va_copy(copy, arg); - len = vsnprintf(loc_buf, sizeof(loc_buf), format, arg); - va_end(copy); - if (len >= sizeof(loc_buf)) { - temp = (char *)malloc(len + 1); - if (temp == NULL) { - return 0; - } - } - vsnprintf(temp, len + 1, format, arg); - va_end(arg); - rgb_print(fb, color, temp); - if (len > 64) { - free(temp); - } - return len; -} -#endif -static void draw_face_boxes(fb_data_t *fb, std::list *results, int face_id) { - int x, y, w, h; - uint32_t color = FACE_COLOR_YELLOW; - if (face_id < 0) { - color = FACE_COLOR_RED; - } else if (face_id > 0) { - color = FACE_COLOR_GREEN; - } - if (fb->bytes_per_pixel == 2) { - //color = ((color >> 8) & 0xF800) | ((color >> 3) & 0x07E0) | (color & 0x001F); - color = ((color >> 16) & 0x001F) | ((color >> 3) & 0x07E0) | ((color << 8) & 0xF800); - } - int i = 0; - for (std::list::iterator prediction = results->begin(); prediction != results->end(); prediction++, i++) { - // rectangle box - x = (int)prediction->box[0]; - y = (int)prediction->box[1]; - w = (int)prediction->box[2] - x + 1; - h = (int)prediction->box[3] - y + 1; - if ((x + w) > fb->width) { - w = fb->width - x; - } - if ((y + h) > fb->height) { - h = fb->height - y; - } - fb_gfx_drawFastHLine(fb, x, y, w, color); - fb_gfx_drawFastHLine(fb, x, y + h - 1, w, color); - fb_gfx_drawFastVLine(fb, x, y, h, color); - fb_gfx_drawFastVLine(fb, x + w - 1, y, h, color); -#if TWO_STAGE - // landmarks (left eye, mouth left, nose, right eye, mouth right) - int x0, y0, j; - for (j = 0; j < 10; j += 2) { - x0 = (int)prediction->keypoint[j]; - y0 = (int)prediction->keypoint[j + 1]; - fb_gfx_fillRect(fb, x0, y0, 3, 3, color); - } -#endif - } -} - -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED -static int run_face_recognition(fb_data_t *fb, std::list *results) { - std::vector landmarks = results->front().keypoint; - int id = -1; - - Tensor tensor; - tensor.set_element((uint8_t *)fb->data).set_shape({fb->height, fb->width, 3}).set_auto_free(false); - - int enrolled_count = recognizer.get_enrolled_id_num(); - - if (enrolled_count < FACE_ID_SAVE_NUMBER && is_enrolling) { - id = recognizer.enroll_id(tensor, landmarks, "", true); - log_i("Enrolled ID: %d", id); - rgb_printf(fb, FACE_COLOR_CYAN, "ID[%u]", id); - } - - face_info_t recognize = recognizer.recognize(tensor, landmarks); - if (recognize.id >= 0) { - rgb_printf(fb, FACE_COLOR_GREEN, "ID[%u]: %.2f", recognize.id, recognize.similarity); - } else { - rgb_print(fb, FACE_COLOR_RED, "Intruder Alert!"); - } - return recognize.id; -} -#endif -#endif - #if CONFIG_LED_ILLUMINATOR_ENABLED void enable_led(bool en) { // Turn LED On or Off int duty = en ? led_duty : 0; @@ -359,134 +185,28 @@ static esp_err_t capture_handler(httpd_req_t *req) { snprintf(ts, 32, "%lld.%06ld", fb->timestamp.tv_sec, fb->timestamp.tv_usec); httpd_resp_set_hdr(req, "X-Timestamp", (const char *)ts); -#if CONFIG_ESP_FACE_DETECT_ENABLED - size_t out_len, out_width, out_height; - uint8_t *out_buf; - bool s; -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - bool detected = false; -#endif - int face_id = 0; - if (!detection_enabled || fb->width > 400) { -#endif #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - size_t fb_len = 0; + size_t fb_len = 0; #endif - if (fb->format == PIXFORMAT_JPEG) { + if (fb->format == PIXFORMAT_JPEG) { #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fb_len = fb->len; + fb_len = fb->len; #endif - res = httpd_resp_send(req, (const char *)fb->buf, fb->len); - } else { - jpg_chunking_t jchunk = {req, 0}; - res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk) ? ESP_OK : ESP_FAIL; - httpd_resp_send_chunk(req, NULL, 0); -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fb_len = jchunk.len; -#endif - } - esp_camera_fb_return(fb); -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - int64_t fr_end = esp_timer_get_time(); -#endif - log_i("JPG: %uB %ums", (uint32_t)(fb_len), (uint32_t)((fr_end - fr_start) / 1000)); - return res; -#if CONFIG_ESP_FACE_DETECT_ENABLED - } - - jpg_chunking_t jchunk = {req, 0}; - - if (fb->format == PIXFORMAT_RGB565 -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - && !recognition_enabled -#endif - ) { -#if TWO_STAGE - HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F); - HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5); - std::list &candidates = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}); - std::list &results = s2.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}, candidates); -#else - HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F); - std::list &results = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}); -#endif - if (results.size() > 0) { - fb_data_t rfb; - rfb.width = fb->width; - rfb.height = fb->height; - rfb.data = fb->buf; - rfb.bytes_per_pixel = 2; - rfb.format = FB_RGB565; -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - detected = true; -#endif - draw_face_boxes(&rfb, &results, face_id); - } - s = fmt2jpg_cb(fb->buf, fb->len, fb->width, fb->height, PIXFORMAT_RGB565, 90, jpg_encode_stream, &jchunk); - esp_camera_fb_return(fb); + res = httpd_resp_send(req, (const char *)fb->buf, fb->len); } else { - out_len = fb->width * fb->height * 3; - out_width = fb->width; - out_height = fb->height; - out_buf = (uint8_t *)malloc(out_len); - if (!out_buf) { - log_e("out_buf malloc failed"); - httpd_resp_send_500(req); - return ESP_FAIL; - } - s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf); - esp_camera_fb_return(fb); - if (!s) { - free(out_buf); - log_e("To rgb888 failed"); - httpd_resp_send_500(req); - return ESP_FAIL; - } - - fb_data_t rfb; - rfb.width = out_width; - rfb.height = out_height; - rfb.data = out_buf; - rfb.bytes_per_pixel = 3; - rfb.format = FB_BGR888; - -#if TWO_STAGE - HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F); - HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5); - std::list &candidates = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}); - std::list &results = s2.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}, candidates); -#else - HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F); - std::list &results = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}); -#endif - - if (results.size() > 0) { + jpg_chunking_t jchunk = {req, 0}; + res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk) ? ESP_OK : ESP_FAIL; + httpd_resp_send_chunk(req, NULL, 0); #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - detected = true; + fb_len = jchunk.len; #endif -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - if (recognition_enabled) { - face_id = run_face_recognition(&rfb, &results); - } -#endif - draw_face_boxes(&rfb, &results, face_id); - } - - s = fmt2jpg_cb(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, jpg_encode_stream, &jchunk); - free(out_buf); - } - - if (!s) { - log_e("JPEG compression failed"); - httpd_resp_send_500(req); - return ESP_FAIL; } + esp_camera_fb_return(fb); #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO int64_t fr_end = esp_timer_get_time(); #endif - log_i("FACE: %uB %ums %s%d", (uint32_t)(jchunk.len), (uint32_t)((fr_end - fr_start) / 1000), detected ? "DETECTED " : "", face_id); + log_i("JPG: %uB %ums", (uint32_t)(fb_len), (uint32_t)((fr_end - fr_start) / 1000)); return res; -#endif } static esp_err_t stream_handler(httpd_req_t *req) { @@ -496,26 +216,6 @@ static esp_err_t stream_handler(httpd_req_t *req) { size_t _jpg_buf_len = 0; uint8_t *_jpg_buf = NULL; char *part_buf[128]; -#if CONFIG_ESP_FACE_DETECT_ENABLED -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - bool detected = false; - int64_t fr_ready = 0; - int64_t fr_recognize = 0; - int64_t fr_encode = 0; - int64_t fr_face = 0; - int64_t fr_start = 0; -#endif - int face_id = 0; - size_t out_len = 0, out_width = 0, out_height = 0; - uint8_t *out_buf = NULL; - bool s = false; -#if TWO_STAGE - HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F); - HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5); -#else - HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F); -#endif -#endif static int64_t last_frame = 0; if (!last_frame) { @@ -536,13 +236,6 @@ static esp_err_t stream_handler(httpd_req_t *req) { #endif while (true) { -#if CONFIG_ESP_FACE_DETECT_ENABLED -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - detected = false; -#endif - face_id = 0; -#endif - fb = esp_camera_fb_get(); if (!fb) { log_e("Camera capture failed"); @@ -550,138 +243,18 @@ static esp_err_t stream_handler(httpd_req_t *req) { } else { _timestamp.tv_sec = fb->timestamp.tv_sec; _timestamp.tv_usec = fb->timestamp.tv_usec; -#if CONFIG_ESP_FACE_DETECT_ENABLED -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_start = esp_timer_get_time(); - fr_ready = fr_start; - fr_encode = fr_start; - fr_recognize = fr_start; - fr_face = fr_start; -#endif - if (!detection_enabled || fb->width > 400) { -#endif - if (fb->format != PIXFORMAT_JPEG) { - bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len); - esp_camera_fb_return(fb); - fb = NULL; - if (!jpeg_converted) { - log_e("JPEG compression failed"); - res = ESP_FAIL; - } - } else { - _jpg_buf_len = fb->len; - _jpg_buf = fb->buf; + if (fb->format != PIXFORMAT_JPEG) { + bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len); + esp_camera_fb_return(fb); + fb = NULL; + if (!jpeg_converted) { + log_e("JPEG compression failed"); + res = ESP_FAIL; } -#if CONFIG_ESP_FACE_DETECT_ENABLED } else { - if (fb->format == PIXFORMAT_RGB565 -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - && !recognition_enabled -#endif - ) { -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_ready = esp_timer_get_time(); -#endif -#if TWO_STAGE - std::list &candidates = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}); - std::list &results = s2.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}, candidates); -#else - std::list &results = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}); -#endif -#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_face = esp_timer_get_time(); - fr_recognize = fr_face; -#endif - if (results.size() > 0) { - fb_data_t rfb; - rfb.width = fb->width; - rfb.height = fb->height; - rfb.data = fb->buf; - rfb.bytes_per_pixel = 2; - rfb.format = FB_RGB565; -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - detected = true; -#endif - draw_face_boxes(&rfb, &results, face_id); - } - s = fmt2jpg(fb->buf, fb->len, fb->width, fb->height, PIXFORMAT_RGB565, 80, &_jpg_buf, &_jpg_buf_len); - esp_camera_fb_return(fb); - fb = NULL; - if (!s) { - log_e("fmt2jpg failed"); - res = ESP_FAIL; - } -#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_encode = esp_timer_get_time(); -#endif - } else { - out_len = fb->width * fb->height * 3; - out_width = fb->width; - out_height = fb->height; - out_buf = (uint8_t *)malloc(out_len); - if (!out_buf) { - log_e("out_buf malloc failed"); - res = ESP_FAIL; - } else { - s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf); - esp_camera_fb_return(fb); - fb = NULL; - if (!s) { - free(out_buf); - log_e("To rgb888 failed"); - res = ESP_FAIL; - } else { -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_ready = esp_timer_get_time(); -#endif - - fb_data_t rfb; - rfb.width = out_width; - rfb.height = out_height; - rfb.data = out_buf; - rfb.bytes_per_pixel = 3; - rfb.format = FB_BGR888; - -#if TWO_STAGE - std::list &candidates = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}); - std::list &results = s2.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}, candidates); -#else - std::list &results = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}); -#endif - -#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_face = esp_timer_get_time(); - fr_recognize = fr_face; -#endif - - if (results.size() > 0) { -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - detected = true; -#endif -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - if (recognition_enabled) { - face_id = run_face_recognition(&rfb, &results); -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_recognize = esp_timer_get_time(); -#endif - } -#endif - draw_face_boxes(&rfb, &results, face_id); - } - s = fmt2jpg(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, &_jpg_buf, &_jpg_buf_len); - free(out_buf); - if (!s) { - log_e("fmt2jpg failed"); - res = ESP_FAIL; - } -#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_encode = esp_timer_get_time(); -#endif - } - } - } + _jpg_buf_len = fb->len; + _jpg_buf = fb->buf; } -#endif } if (res == ESP_OK) { res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY)); @@ -707,30 +280,14 @@ static esp_err_t stream_handler(httpd_req_t *req) { } int64_t fr_end = esp_timer_get_time(); -#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - int64_t ready_time = (fr_ready - fr_start) / 1000; - int64_t face_time = (fr_face - fr_ready) / 1000; - int64_t recognize_time = (fr_recognize - fr_face) / 1000; - int64_t encode_time = (fr_encode - fr_recognize) / 1000; - int64_t process_time = (fr_encode - fr_start) / 1000; -#endif - int64_t frame_time = fr_end - last_frame; frame_time /= 1000; #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO uint32_t avg_frame_time = ra_filter_run(&ra_filter, frame_time); #endif log_i( - "MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps)" -#if CONFIG_ESP_FACE_DETECT_ENABLED - ", %u+%u+%u+%u=%u %s%d" -#endif - , - (uint32_t)(_jpg_buf_len), (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time, avg_frame_time, 1000.0 / avg_frame_time -#if CONFIG_ESP_FACE_DETECT_ENABLED - , - (uint32_t)ready_time, (uint32_t)face_time, (uint32_t)recognize_time, (uint32_t)encode_time, (uint32_t)process_time, (detected) ? "DETECTED " : "", face_id -#endif + "MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps)", (uint32_t)(_jpg_buf_len), (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time, avg_frame_time, + 1000.0 / avg_frame_time ); } @@ -841,28 +398,6 @@ static esp_err_t cmd_handler(httpd_req_t *req) { enable_led(true); } } -#endif - -#if CONFIG_ESP_FACE_DETECT_ENABLED - else if (!strcmp(variable, "face_detect")) { - detection_enabled = val; -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - if (!detection_enabled) { - recognition_enabled = 0; - } -#endif - } -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - else if (!strcmp(variable, "face_enroll")) { - is_enrolling = !is_enrolling; - log_i("Enrolling: %s", is_enrolling ? "true" : "false"); - } else if (!strcmp(variable, "face_recognize")) { - recognition_enabled = val; - if (recognition_enabled) { - detection_enabled = val; - } - } -#endif #endif else { log_i("Unknown command: %s", variable); @@ -947,13 +482,6 @@ static esp_err_t status_handler(httpd_req_t *req) { p += sprintf(p, ",\"led_intensity\":%u", led_duty); #else p += sprintf(p, ",\"led_intensity\":%d", -1); -#endif -#if CONFIG_ESP_FACE_DETECT_ENABLED - p += sprintf(p, ",\"face_detect\":%u", detection_enabled); -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - p += sprintf(p, ",\"face_enroll\":%u,", is_enrolling); - p += sprintf(p, "\"face_recognize\":%u", recognition_enabled); -#endif #endif *p++ = '}'; *p++ = 0; @@ -1289,12 +817,6 @@ void startCameraServer() { ra_filter_init(&ra_filter, 20); -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - recognizer.set_partition(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "fr"); - - // load ids from flash partition - recognizer.set_ids_from_flash(); -#endif log_i("Starting web server on port: '%d'", config.server_port); if (httpd_start(&camera_httpd, &config) == ESP_OK) { httpd_register_uri_handler(camera_httpd, &index_uri); diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index ea66c5a816d..413419a9b1c 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -101,57 +101,57 @@ "host": "i686-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", - "size": "399729605" + "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", + "size": "351074410" }, { "host": "x86_64-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", - "size": "399729605" + "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", + "size": "351074410" }, { "host": "arm64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", - "size": "399729605" + "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", + "size": "351074410" }, { "host": "x86_64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", - "size": "399729605" + "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", + "size": "351074410" }, { "host": "x86_64-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", - "size": "399729605" + "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", + "size": "351074410" }, { "host": "i686-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", - "size": "399729605" + "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", + "size": "351074410" }, { "host": "aarch64-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", - "size": "399729605" + "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", + "size": "351074410" }, { "host": "arm-linux-gnueabihf", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:f8624bf7eab91e0a3bb3be4cc385fef5a05a725bc6ff978f3d4e2562f2805b1e", - "size": "399729605" + "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", + "size": "351074410" } ] }, From 81d2cbca961fd7718f7af350677cb5e6561d7784 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Thu, 10 Oct 2024 14:27:04 -0300 Subject: [PATCH 040/409] fix(uart): Add missing HP UARTs for ESP32-P4 (#10447) * fix(uart): Add missing HP UARTs for ESP32-P4 * fix(comment): Fix macro in comment * fix(uart): Fix macro guard --- cores/esp32/HardwareSerial.cpp | 32 ++++++++++++++++++++++++++++---- cores/esp32/HardwareSerial.h | 6 ++++++ cores/esp32/esp32-hal-uart.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index f515e833925..a6a7573f6e3 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -27,11 +27,19 @@ void serialEvent(void) __attribute__((weak)); #if SOC_UART_HP_NUM > 1 void serialEvent1(void) __attribute__((weak)); -#endif /* SOC_UART_NUM > 1 */ +#endif /* SOC_UART_HP_NUM > 1 */ #if SOC_UART_HP_NUM > 2 void serialEvent2(void) __attribute__((weak)); -#endif /* SOC_UART_NUM > 2 */ +#endif /* SOC_UART_HP_NUM > 2 */ + +#if SOC_UART_HP_NUM > 3 +void serialEvent3(void) __attribute__((weak)); +#endif /* SOC_UART_HP_NUM > 3 */ + +#if SOC_UART_HP_NUM > 4 +void serialEvent4(void) __attribute__((weak)); +#endif /* SOC_UART_HP_NUM > 4 */ #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) // There is always Seria0 for UART0 @@ -42,6 +50,12 @@ HardwareSerial Serial1(1); #if SOC_UART_HP_NUM > 2 HardwareSerial Serial2(2); #endif +#if SOC_UART_HP_NUM > 3 +HardwareSerial Serial3(3); +#endif +#if SOC_UART_HP_NUM > 4 +HardwareSerial Serial4(4); +#endif #if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event extern void HWCDCSerialEvent(void) __attribute__((weak)); @@ -67,16 +81,26 @@ void serialEventRun(void) { if (serialEvent && Serial0.available()) { serialEvent(); } -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 if (serialEvent1 && Serial1.available()) { serialEvent1(); } #endif -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 if (serialEvent2 && Serial2.available()) { serialEvent2(); } #endif +#if SOC_UART_HP_NUM > 3 + if (serialEvent3 && Serial3.available()) { + serialEvent3(); + } +#endif +#if SOC_UART_HP_NUM > 4 + if (serialEvent4 && Serial4.available()) { + serialEvent4(); + } +#endif } #endif diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index fc5dd92440d..8eb7f2c91a6 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -375,6 +375,12 @@ extern HardwareSerial Serial1; #if SOC_UART_HP_NUM > 2 extern HardwareSerial Serial2; #endif +#if SOC_UART_HP_NUM > 3 +extern HardwareSerial Serial3; +#endif +#if SOC_UART_HP_NUM > 4 +extern HardwareSerial Serial4; +#endif #endif //!defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) #endif // HardwareSerial_h diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index 82c9d8808d0..706124c7451 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -67,6 +67,12 @@ static uart_t _uart_bus_array[] = { #if SOC_UART_HP_NUM > 2 {2, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, #endif +#if SOC_UART_HP_NUM > 3 + {3, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, +#endif +#if SOC_UART_HP_NUM > 4 + {4, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, +#endif }; #else @@ -87,6 +93,12 @@ static uart_t _uart_bus_array[] = { #if SOC_UART_HP_NUM > 2 {NULL, 2, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, #endif +#if SOC_UART_HP_NUM > 3 + {NULL, 3, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, +#endif +#if SOC_UART_HP_NUM > 4 + {NULL, 4, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, +#endif }; #endif @@ -835,6 +847,20 @@ static void ARDUINO_ISR_ATTR uart2_write_char(char c) { } #endif +#if SOC_UART_HP_NUM > 3 +static void ARDUINO_ISR_ATTR uart3_write_char(char c) { + while (uart_ll_get_txfifo_len(&UART3) == 0); + uart_ll_write_txfifo(&UART3, (const uint8_t *)&c, 1); +} +#endif + +#if SOC_UART_HP_NUM > 4 +static void ARDUINO_ISR_ATTR uart4_write_char(char c) { + while (uart_ll_get_txfifo_len(&UART4) == 0); + uart_ll_write_txfifo(&UART4, (const uint8_t *)&c, 1); +} +#endif + void uart_install_putc() { switch (s_uart_debug_nr) { case 0: ets_install_putc1((void (*)(char)) & uart0_write_char); break; @@ -843,6 +869,12 @@ void uart_install_putc() { #endif #if SOC_UART_HP_NUM > 2 case 2: ets_install_putc1((void (*)(char)) & uart2_write_char); break; +#endif +#if SOC_UART_HP_NUM > 3 + case 3: ets_install_putc1((void (*)(char)) & uart3_write_char); break; +#endif +#if SOC_UART_HP_NUM > 4 + case 4: ets_install_putc1((void (*)(char)) & uart4_write_char); break; #endif default: ets_install_putc1(NULL); break; } From 3733c87c832dd7d2743fda5a42b3ff866f4c47f8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 11 Oct 2024 15:33:49 +0200 Subject: [PATCH 041/409] replace outdated wrong `SOC_I2C_NUM` and use `SOC_HP_I2C_NUM` (#10452) * SOC_HP_I2C_NUM * SOC_HP_I2C_NUM --- libraries/Wire/src/Wire.cpp | 4 ++-- libraries/Wire/src/Wire.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index 8ac0c25595d..24b0eb7c0a3 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -646,8 +646,8 @@ void TwoWire::onRequestService(uint8_t num, void *arg) { #endif /* SOC_I2C_SUPPORT_SLAVE */ TwoWire Wire = TwoWire(0); -#if SOC_I2C_NUM > 1 +#if SOC_HP_I2C_NUM > 1 TwoWire Wire1 = TwoWire(1); -#endif /* SOC_I2C_NUM */ +#endif /* SOC_HP_I2C_NUM */ #endif /* SOC_I2C_SUPPORTED */ diff --git a/libraries/Wire/src/Wire.h b/libraries/Wire/src/Wire.h index cf720d48234..45f30c81ffc 100644 --- a/libraries/Wire/src/Wire.h +++ b/libraries/Wire/src/Wire.h @@ -144,9 +144,9 @@ class TwoWire : public HardwareI2C { }; extern TwoWire Wire; -#if SOC_I2C_NUM > 1 +#if SOC_HP_I2C_NUM > 1 extern TwoWire Wire1; -#endif /* SOC_I2C_NUM */ +#endif /* SOC_HP_I2C_NUM */ #endif /* SOC_I2C_SUPPORTED */ #endif /* TwoWire_h */ From e27a050f5ad72ab2dc666dbe68dc0342c46308e7 Mon Sep 17 00:00:00 2001 From: Y_hsiao_ch'un <66012385+Y1hsiaochunnn@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:35:58 +0800 Subject: [PATCH 042/409] Added variant for Waveshare ESP32-S3-Touch-AMOLED-1.8 (#10433) --- boards.txt | 199 ++++++++++++++++++ .../pins_arduino.h | 87 ++++++++ 2 files changed, 286 insertions(+) create mode 100644 variants/waveshare_esp32_s3_touch_amoled_18/pins_arduino.h diff --git a/boards.txt b/boards.txt index 971f99a0cbc..42070a41a1c 100644 --- a/boards.txt +++ b/boards.txt @@ -40431,6 +40431,205 @@ waveshare_esp32_s3_touch_lcd_169.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +waveshare_esp32_s3_touch_amoled_18.name=Waveshare ESP32-S3-Touch-AMOLED-1.8 +waveshare_esp32_s3_touch_amoled_18.vid.0=0x303a +waveshare_esp32_s3_touch_amoled_18.pid.0=0x8255 +waveshare_esp32_s3_touch_amoled_18.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_amoled_18.upload_port.0.pid=0x8255 + +waveshare_esp32_s3_touch_amoled_18.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_amoled_18.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_amoled_18.upload.tool=esptool_py +waveshare_esp32_s3_touch_amoled_18.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_amoled_18.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_amoled_18.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_amoled_18.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_amoled_18.upload.flags= +waveshare_esp32_s3_touch_amoled_18.upload.extra_flags= +waveshare_esp32_s3_touch_amoled_18.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_18.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_amoled_18.serial.disableDTR=false +waveshare_esp32_s3_touch_amoled_18.serial.disableRTS=false + +waveshare_esp32_s3_touch_amoled_18.build.tarch=xtensa +waveshare_esp32_s3_touch_amoled_18.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_amoled_18.build.target=esp32s3 +waveshare_esp32_s3_touch_amoled_18.build.mcu=esp32s3 +waveshare_esp32_s3_touch_amoled_18.build.core=esp32 +waveshare_esp32_s3_touch_amoled_18.build.variant=waveshare_esp32_s3_touch_amoled_18 +waveshare_esp32_s3_touch_amoled_18.build.board=WAVESHARE_ESP32_S3_TOUCH_AMOLED_18 + +waveshare_esp32_s3_touch_amoled_18.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_18.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_18.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_18.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_18.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_18.build.flash_size=16MB +waveshare_esp32_s3_touch_amoled_18.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_18.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_18.build.boot=qio +waveshare_esp32_s3_touch_amoled_18.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_18.build.partitions=default +waveshare_esp32_s3_touch_amoled_18.build.defines= +waveshare_esp32_s3_touch_amoled_18.build.loop_core= +waveshare_esp32_s3_touch_amoled_18.build.event_core= +waveshare_esp32_s3_touch_amoled_18.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_18.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_amoled_18.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_amoled_18.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_amoled_18.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_18.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_amoled_18.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_amoled_18.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_amoled_18.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_18.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_18.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_18.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_18.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_18.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_18.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_18.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_18.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_amoled_18.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_18.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_amoled_18.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_amoled_18.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_18.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_18.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_amoled_18.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_18.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_18.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_18.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_18.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_18.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_18.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_18.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_18.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_amoled_18.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_amoled_18.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_amoled_18.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_amoled_18.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + waveshare_esp32_s3_lcd_169.name=Waveshare ESP32-S3-LCD-1.69 waveshare_esp32_s3_lcd_169.vid.0=0x303a waveshare_esp32_s3_lcd_169.pid.0=0x8221 diff --git a/variants/waveshare_esp32_s3_touch_amoled_18/pins_arduino.h b/variants/waveshare_esp32_s3_touch_amoled_18/pins_arduino.h new file mode 100644 index 00000000000..de8bcaec2d9 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_amoled_18/pins_arduino.h @@ -0,0 +1,87 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8255 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-AMOLED-1.8" +#define USB_SERIAL "" + +// display for SH8601 +#define WS_LCD_CS 12 +#define WS_QSPI_SIO0 4 +#define WS_QSPI_SI1 5 +#define WS_QSPI_SI2 6 +#define WS_QSPI_SI3 7 +#define WS_QSPI_SCL 11 + +// Touch for FT3168 +#define WS_TP_INT 21 + +// Onboard Electric buzzer & Custom buttons +// GPIO and PSRAM conflict, need to pay attention when using + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 14; +static const uint8_t SCL = 15; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ From 3edf5188250ddb4b4edbb44583b473105fb2e40f Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Tue, 15 Oct 2024 17:25:45 +0300 Subject: [PATCH 043/409] Add support for WiFi to ESP32-P4 (#10463) * feat(p4): Add support for WiFi to ESP32-P4 Implements support for external MCU connected through SDIO * fix(p4): Init SDIO host properly on Network boot esp-hosted has one function marked as "constructor" that did not run in the boot phase of the chip. This calls the function when network is started --- idf_component.yml | 20 ++++++++++++++------ libraries/Network/src/NetworkEvents.cpp | 2 +- libraries/Network/src/NetworkEvents.h | 13 ++++++++----- libraries/Network/src/NetworkManager.cpp | 7 +++++++ libraries/WiFi/src/AP.cpp | 2 +- libraries/WiFi/src/STA.cpp | 2 +- libraries/WiFi/src/WiFi.cpp | 2 +- libraries/WiFi/src/WiFi.h | 3 ++- libraries/WiFi/src/WiFiAP.cpp | 2 +- libraries/WiFi/src/WiFiAP.h | 2 +- libraries/WiFi/src/WiFiGeneric.cpp | 15 +++++++++++++-- libraries/WiFi/src/WiFiGeneric.h | 2 +- libraries/WiFi/src/WiFiMulti.cpp | 2 +- libraries/WiFi/src/WiFiMulti.h | 2 +- libraries/WiFi/src/WiFiSTA.cpp | 2 +- libraries/WiFi/src/WiFiSTA.h | 2 +- libraries/WiFi/src/WiFiScan.cpp | 2 +- libraries/WiFi/src/WiFiScan.h | 2 +- libraries/WiFi/src/WiFiType.h | 2 +- 19 files changed, 58 insertions(+), 28 deletions(-) diff --git a/idf_component.yml b/idf_component.yml index 3b83650bf5b..5570f5d47a5 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -56,11 +56,11 @@ dependencies: espressif/esp-zboss-lib: version: "^1.0.1" rules: - - if: "target != esp32c2" + - if: "target not in [esp32c2, esp32p4]" espressif/esp-zigbee-lib: version: "^1.0.1" rules: - - if: "target != esp32c2" + - if: "target not in [esp32c2, esp32p4]" espressif/esp-dsp: version: "^1.3.4" rules: @@ -68,23 +68,31 @@ dependencies: espressif/esp_rainmaker: version: "^1.0.0" rules: - - if: "target != esp32c2" + - if: "target not in [esp32c2, esp32p4]" espressif/rmaker_common: version: "^1.4.6" rules: - - if: "target != esp32c2" + - if: "target not in [esp32c2, esp32p4]" espressif/esp_insights: version: "^1.0.1" rules: - - if: "target != esp32c2" + - if: "target not in [esp32c2, esp32p4]" espressif/qrcode: version: "^0.1.0~1" rules: - - if: "target != esp32c2" + - if: "target not in [esp32c2, esp32p4]" espressif/esp-sr: version: "^1.4.2" rules: - if: "target in [esp32s3]" + espressif/esp_hosted: + version: "^0.0.22" + rules: + - if: "target == esp32p4" + espressif/esp_wifi_remote: + version: "^0.4.1" + rules: + - if: "target == esp32p4" espressif/libsodium: version: "^1.0.20~1" require: public diff --git a/libraries/Network/src/NetworkEvents.cpp b/libraries/Network/src/NetworkEvents.cpp index bb02282e9b3..4863e346a10 100644 --- a/libraries/Network/src/NetworkEvents.cpp +++ b/libraries/Network/src/NetworkEvents.cpp @@ -423,7 +423,7 @@ const char *NetworkEvents::eventName(arduino_event_id_t id) { case ARDUINO_EVENT_PPP_GOT_IP: return "PPP_GOT_IP"; case ARDUINO_EVENT_PPP_LOST_IP: return "PPP_LOST_IP"; case ARDUINO_EVENT_PPP_GOT_IP6: return "PPP_GOT_IP6"; -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED case ARDUINO_EVENT_WIFI_OFF: return "WIFI_OFF"; case ARDUINO_EVENT_WIFI_READY: return "WIFI_READY"; case ARDUINO_EVENT_WIFI_SCAN_DONE: return "SCAN_DONE"; diff --git a/libraries/Network/src/NetworkEvents.h b/libraries/Network/src/NetworkEvents.h index ac324d19841..b49951b1824 100644 --- a/libraries/Network/src/NetworkEvents.h +++ b/libraries/Network/src/NetworkEvents.h @@ -16,14 +16,15 @@ #include "freertos/queue.h" #include "freertos/semphr.h" #include "freertos/event_groups.h" +#include "sdkconfig.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "esp_wifi_types.h" #include "esp_smartconfig.h" #include "network_provisioning/network_config.h" #endif -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED static const int WIFI_SCANNING_BIT = BIT0; static const int WIFI_SCAN_DONE_BIT = BIT1; #endif @@ -41,7 +42,7 @@ typedef enum { ARDUINO_EVENT_ETH_GOT_IP, ARDUINO_EVENT_ETH_LOST_IP, ARDUINO_EVENT_ETH_GOT_IP6, -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED ARDUINO_EVENT_WIFI_OFF, ARDUINO_EVENT_WIFI_READY, ARDUINO_EVENT_WIFI_SCAN_DONE, @@ -93,7 +94,7 @@ typedef union { ip_event_got_ip_t got_ip; ip_event_got_ip6_t got_ip6; esp_eth_handle_t eth_connected; -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED wifi_event_sta_scan_done_t wifi_scan_done; wifi_event_sta_authmode_change_t wifi_sta_authmode_change; wifi_event_sta_connected_t wifi_sta_connected; @@ -104,6 +105,8 @@ typedef union { wifi_event_ap_staconnected_t wifi_ap_staconnected; wifi_event_ap_stadisconnected_t wifi_ap_stadisconnected; wifi_event_ftm_report_t wifi_ftm_report; +#endif +#if SOC_WIFI_SUPPORTED wifi_sta_config_t prov_cred_recv; network_prov_wifi_sta_fail_reason_t prov_fail_reason; smartconfig_event_got_ssid_pswd_t sc_got_ssid_pswd; @@ -147,7 +150,7 @@ class NetworkEvents { friend class ESP_NetworkInterface; friend class ETHClass; friend class PPPClass; -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED friend class STAClass; friend class APClass; friend class WiFiGenericClass; diff --git a/libraries/Network/src/NetworkManager.cpp b/libraries/Network/src/NetworkManager.cpp index 88059a60562..b429c482825 100644 --- a/libraries/Network/src/NetworkManager.cpp +++ b/libraries/Network/src/NetworkManager.cpp @@ -10,6 +10,10 @@ #include "esp_mac.h" #include "netdb.h" +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +extern "C" esp_err_t esp_hosted_init(void *); +#endif + NetworkManager::NetworkManager() {} NetworkInterface *getNetifByID(Network_Interface_ID id); @@ -18,6 +22,9 @@ bool NetworkManager::begin() { static bool initialized = false; if (!initialized) { initialized = true; +#if CONFIG_ESP_WIFI_REMOTE_ENABLED + esp_hosted_init(NULL); +#endif #if CONFIG_IDF_TARGET_ESP32 uint8_t mac[8]; if (esp_efuse_mac_get_default(mac) == ESP_OK) { diff --git a/libraries/WiFi/src/AP.cpp b/libraries/WiFi/src/AP.cpp index a61be662495..9cba6e90f10 100644 --- a/libraries/WiFi/src/AP.cpp +++ b/libraries/WiFi/src/AP.cpp @@ -7,7 +7,7 @@ #include "WiFi.h" #include "WiFiGeneric.h" #include "WiFiAP.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include #include #include diff --git a/libraries/WiFi/src/STA.cpp b/libraries/WiFi/src/STA.cpp index 443d2621957..004ce161058 100644 --- a/libraries/WiFi/src/STA.cpp +++ b/libraries/WiFi/src/STA.cpp @@ -6,7 +6,7 @@ #include "WiFi.h" #include "WiFiGeneric.h" #include "WiFiSTA.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include #include #include diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index a854cb0ceb7..7fb0ed16459 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -22,7 +22,7 @@ */ #include "WiFi.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED extern "C" { #include diff --git a/libraries/WiFi/src/WiFi.h b/libraries/WiFi/src/WiFi.h index a823dabd864..ea2efd97697 100644 --- a/libraries/WiFi/src/WiFi.h +++ b/libraries/WiFi/src/WiFi.h @@ -22,7 +22,8 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#include "sdkconfig.h" +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include diff --git a/libraries/WiFi/src/WiFiAP.cpp b/libraries/WiFi/src/WiFiAP.cpp index fac84dc8512..7282daac995 100644 --- a/libraries/WiFi/src/WiFiAP.cpp +++ b/libraries/WiFi/src/WiFiAP.cpp @@ -25,7 +25,7 @@ #include "WiFi.h" #include "WiFiGeneric.h" #include "WiFiAP.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include #include diff --git a/libraries/WiFi/src/WiFiAP.h b/libraries/WiFi/src/WiFiAP.h index 9acd124c27e..4573e92ecf0 100644 --- a/libraries/WiFi/src/WiFiAP.h +++ b/libraries/WiFi/src/WiFiAP.h @@ -23,7 +23,7 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "esp_wifi_types.h" #include "WiFiType.h" diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index ccc9518132b..d096c2e3d6e 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -24,7 +24,7 @@ #include "WiFi.h" #include "WiFiGeneric.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED extern "C" { #include @@ -39,7 +39,9 @@ extern "C" { #include #include #include +#if SOC_WIFI_SUPPORTED #include +#endif #include "lwip/ip_addr.h" #include "lwip/opt.h" #include "lwip/err.h" @@ -103,6 +105,7 @@ static void _arduino_event_cb(void *arg, esp_event_base_t event_base, int32_t ev arduino_event.event_id = ARDUINO_EVENT_WIFI_FTM_REPORT; memcpy(&arduino_event.event_info.wifi_ftm_report, event_data, sizeof(wifi_event_ftm_report_t)); +#if !CONFIG_ESP_WIFI_REMOTE_ENABLED /* * SMART CONFIG * */ @@ -157,6 +160,7 @@ static void _arduino_event_cb(void *arg, esp_event_base_t event_base, int32_t ev } else if (event_base == NETWORK_PROV_EVENT && event_id == NETWORK_PROV_WIFI_CRED_SUCCESS) { log_v("Provisioning Success!"); arduino_event.event_id = ARDUINO_EVENT_PROV_CRED_SUCCESS; +#endif } if (arduino_event.event_id < ARDUINO_EVENT_MAX) { @@ -170,6 +174,7 @@ static bool initWiFiEvents() { return false; } +#if !CONFIG_ESP_WIFI_REMOTE_ENABLED if (esp_event_handler_instance_register(SC_EVENT, ESP_EVENT_ANY_ID, &_arduino_event_cb, NULL, NULL)) { log_e("event_handler_instance_register for SC_EVENT Failed!"); return false; @@ -179,6 +184,7 @@ static bool initWiFiEvents() { log_e("event_handler_instance_register for NETWORK_PROV_EVENT Failed!"); return false; } +#endif return true; } @@ -189,6 +195,7 @@ static bool deinitWiFiEvents() { return false; } +#if !CONFIG_ESP_WIFI_REMOTE_ENABLED if (esp_event_handler_unregister(SC_EVENT, ESP_EVENT_ANY_ID, &_arduino_event_cb)) { log_e("esp_event_handler_unregister for SC_EVENT Failed!"); return false; @@ -198,6 +205,7 @@ static bool deinitWiFiEvents() { log_e("esp_event_handler_unregister for NETWORK_PROV_EVENT Failed!"); return false; } +#endif return true; } @@ -370,6 +378,7 @@ void WiFiGenericClass::_eventCallback(arduino_event_t *event) { // log_d("Arduino Event: %d - %s", event->event_id, WiFi.eventName(event->event_id)); if (event->event_id == ARDUINO_EVENT_WIFI_SCAN_DONE) { WiFiScanClass::_scanDone(); +#if !CONFIG_ESP_WIFI_REMOTE_ENABLED } else if (event->event_id == ARDUINO_EVENT_SC_GOT_SSID_PSWD) { WiFi.begin( (const char *)event->event_info.sc_got_ssid_pswd.ssid, (const char *)event->event_info.sc_got_ssid_pswd.password, 0, @@ -378,6 +387,7 @@ void WiFiGenericClass::_eventCallback(arduino_event_t *event) { } else if (event->event_id == ARDUINO_EVENT_SC_SEND_ACK_DONE) { esp_smartconfig_stop(); WiFiSTAClass::_smartConfigDone = true; +#endif } } @@ -693,6 +703,7 @@ bool WiFiGenericClass::initiateFTM(uint8_t frm_count, uint16_t burst_period, uin * @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) { +#if !CONFIG_ESP_WIFI_REMOTE_ENABLED esp_phy_ant_gpio_config_t wifi_ant_io; @@ -759,7 +770,7 @@ bool WiFiGenericClass::setDualAntennaConfig(uint8_t gpio_ant1, uint8_t gpio_ant2 log_e("Failed to set antenna configuration"); return false; } - +#endif return true; } diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index 2a5ca812999..fe929236a4b 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -23,7 +23,7 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "esp_err.h" #include "esp_event.h" diff --git a/libraries/WiFi/src/WiFiMulti.cpp b/libraries/WiFi/src/WiFiMulti.cpp index a438919f792..f99ce185252 100644 --- a/libraries/WiFi/src/WiFiMulti.cpp +++ b/libraries/WiFi/src/WiFiMulti.cpp @@ -24,7 +24,7 @@ */ #include "WiFiMulti.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include #include #include diff --git a/libraries/WiFi/src/WiFiMulti.h b/libraries/WiFi/src/WiFiMulti.h index 1e11ff13f51..bda053b32d2 100644 --- a/libraries/WiFi/src/WiFiMulti.h +++ b/libraries/WiFi/src/WiFiMulti.h @@ -26,7 +26,7 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "WiFi.h" #include diff --git a/libraries/WiFi/src/WiFiSTA.cpp b/libraries/WiFi/src/WiFiSTA.cpp index 1c1ce42c12f..18c8b7207a4 100644 --- a/libraries/WiFi/src/WiFiSTA.cpp +++ b/libraries/WiFi/src/WiFiSTA.cpp @@ -25,7 +25,7 @@ #include "WiFi.h" #include "WiFiGeneric.h" #include "WiFiSTA.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include #include diff --git a/libraries/WiFi/src/WiFiSTA.h b/libraries/WiFi/src/WiFiSTA.h index 2c046c4c4b9..b3176ed17ca 100644 --- a/libraries/WiFi/src/WiFiSTA.h +++ b/libraries/WiFi/src/WiFiSTA.h @@ -23,7 +23,7 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "WiFiType.h" #include "WiFiGeneric.h" diff --git a/libraries/WiFi/src/WiFiScan.cpp b/libraries/WiFi/src/WiFiScan.cpp index ffacc57f093..27d9edcc70c 100644 --- a/libraries/WiFi/src/WiFiScan.cpp +++ b/libraries/WiFi/src/WiFiScan.cpp @@ -25,7 +25,7 @@ #include "WiFi.h" #include "WiFiGeneric.h" #include "WiFiScan.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED extern "C" { #include diff --git a/libraries/WiFi/src/WiFiScan.h b/libraries/WiFi/src/WiFiScan.h index 0648885292f..5e1097f3ae2 100644 --- a/libraries/WiFi/src/WiFiScan.h +++ b/libraries/WiFi/src/WiFiScan.h @@ -23,7 +23,7 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "WiFiType.h" #include "WiFiGeneric.h" diff --git a/libraries/WiFi/src/WiFiType.h b/libraries/WiFi/src/WiFiType.h index 1d721d33963..83eed72f4cb 100644 --- a/libraries/WiFi/src/WiFiType.h +++ b/libraries/WiFi/src/WiFiType.h @@ -22,7 +22,7 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "esp_wifi_types.h" From f8e03cfaac337731ffaad0a7af0d45e91adab1a4 Mon Sep 17 00:00:00 2001 From: Mahesh Tupe Date: Tue, 15 Oct 2024 20:36:20 +0530 Subject: [PATCH 044/409] Update esp-insights version (#10456) --- idf_component.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idf_component.yml b/idf_component.yml index 9c06ef0fb72..abacb442ef2 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -72,7 +72,7 @@ dependencies: rules: - if: "target != esp32c2" espressif/esp_insights: - version: "^1.0.1" + version: "^1.2.1" rules: - if: "target != esp32c2" espressif/qrcode: From c6bf1b48160935c789b84b64f71bd1da4b8c2ee3 Mon Sep 17 00:00:00 2001 From: Mahesh Tupe Date: Tue, 15 Oct 2024 20:36:20 +0530 Subject: [PATCH 045/409] Update esp-insights version (#10456) --- idf_component.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idf_component.yml b/idf_component.yml index 5570f5d47a5..d1772d0ddb9 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -74,7 +74,7 @@ dependencies: rules: - if: "target not in [esp32c2, esp32p4]" espressif/esp_insights: - version: "^1.0.1" + version: "^1.2.1" rules: - if: "target not in [esp32c2, esp32p4]" espressif/qrcode: From a3f2568a198cac05a0c784856ba6b99e202ce2a9 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Tue, 15 Oct 2024 20:20:04 +0300 Subject: [PATCH 046/409] IDF release/v5.3 (#10465) * fix(usb): Update tinyusb init call * Update esp-insights version (#10456) * Add support for WiFi to ESP32-P4 (#10463) * feat(p4): Add support for WiFi to ESP32-P4 Implements support for external MCU connected through SDIO * fix(p4): Init SDIO host properly on Network boot esp-hosted has one function marked as "constructor" that did not run in the boot phase of the chip. This calls the function when network is started * Fix RainMaker dependent versions because Matter requires Insights 1.0.1 * IDF release/v5.3 707d097b * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: Mahesh Tupe Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- cores/esp32/esp32-hal-tinyusb.c | 19 +++++++------- idf_component.yml | 27 ++++++++++++++----- package/package_esp32_index.template.json | 32 +++++++++++------------ 3 files changed, 46 insertions(+), 32 deletions(-) diff --git a/cores/esp32/esp32-hal-tinyusb.c b/cores/esp32/esp32-hal-tinyusb.c index c69fca08fc7..eca7e5d176c 100644 --- a/cores/esp32/esp32-hal-tinyusb.c +++ b/cores/esp32/esp32-hal-tinyusb.c @@ -174,9 +174,9 @@ void deinit_usb_hal() { esp_err_t tinyusb_driver_install(const tinyusb_config_t *config) { init_usb_hal(config->external_phy); #if CONFIG_IDF_TARGET_ESP32P4 - if (!tud_init(1)) { + if (!tusb_init(1, TUSB_ROLE_DEVICE)) { #else - if (!tud_init(0)) { + if (!tusb_init(0, TUSB_ROLE_DEVICE)) { #endif log_e("Can't initialize the TinyUSB stack."); return ESP_FAIL; @@ -287,15 +287,14 @@ enum { VENDOR_REQUEST_MICROSOFT = 2 }; -static uint8_t const tinyusb_bos_descriptor[] = { - // total length, number of device caps - TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 2), +static uint8_t const tinyusb_bos_descriptor[] = {// total length, number of device caps + TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 2), - // Vendor Code, iLandingPage - TUD_BOS_WEBUSB_DESCRIPTOR(VENDOR_REQUEST_WEBUSB, 1), + // Vendor Code, iLandingPage + TUD_BOS_WEBUSB_DESCRIPTOR(VENDOR_REQUEST_WEBUSB, 1), - // Microsoft OS 2.0 descriptor - TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, VENDOR_REQUEST_MICROSOFT) + // Microsoft OS 2.0 descriptor + TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, VENDOR_REQUEST_MICROSOFT) }; /* @@ -831,7 +830,7 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) { periph_ll_enable_clk_clear_rst(PERIPH_USB_MODULE); } #endif - + tinyusb_config_t tusb_cfg = { .external_phy = false // In the most cases you need to use a `false` value }; diff --git a/idf_component.yml b/idf_component.yml index d1772d0ddb9..12bfe66e739 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -51,8 +51,6 @@ dependencies: require: public espressif/esp_modem: version: "^1.1.0" - espressif/network_provisioning: - version: "~1.0.0" espressif/esp-zboss-lib: version: "^1.0.1" rules: @@ -65,22 +63,39 @@ dependencies: version: "^1.3.4" rules: - if: "target != esp32c2" + # RainMaker Start (Fixed versions, because Matter supports only Insights 1.0.1) + espressif/network_provisioning: + version: "1.0.2" espressif/esp_rainmaker: - version: "^1.0.0" + version: "1.5.0" rules: - if: "target not in [esp32c2, esp32p4]" espressif/rmaker_common: - version: "^1.4.6" + version: "1.4.6" rules: - if: "target not in [esp32c2, esp32p4]" espressif/esp_insights: - version: "^1.2.1" + version: "1.0.1" + rules: + - if: "target not in [esp32c2, esp32p4]" + # New version breaks esp_insights 1.0.1 + espressif/esp_diag_data_store: + version: "1.0.1" + rules: + - if: "target not in [esp32c2, esp32p4]" + espressif/esp_diagnostics: + version: "1.0.2" + rules: + - if: "target not in [esp32c2, esp32p4]" + espressif/cbor: + version: "0.6.0~1" rules: - if: "target not in [esp32c2, esp32p4]" espressif/qrcode: - version: "^0.1.0~1" + version: "0.1.0~2" rules: - if: "target not in [esp32c2, esp32p4]" + # RainMaker End espressif/esp-sr: version: "^1.4.2" rules: diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 413419a9b1c..9227a89034d 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -101,57 +101,57 @@ "host": "i686-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", - "size": "351074410" + "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", + "size": "350992761" }, { "host": "x86_64-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", - "size": "351074410" + "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", + "size": "350992761" }, { "host": "arm64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", - "size": "351074410" + "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", + "size": "350992761" }, { "host": "x86_64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", - "size": "351074410" + "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", + "size": "350992761" }, { "host": "x86_64-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", - "size": "351074410" + "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", + "size": "350992761" }, { "host": "i686-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", - "size": "351074410" + "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", + "size": "350992761" }, { "host": "aarch64-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", - "size": "351074410" + "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", + "size": "350992761" }, { "host": "arm-linux-gnueabihf", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:b4d431c8e6e9eb26c78cb187b9082055544956a4dac8e224ff884f770e5f0e5a", - "size": "351074410" + "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", + "size": "350992761" } ] }, From f706c276711dd1d19fcb3390a6c1df92657be1bf Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 15 Oct 2024 20:42:26 +0300 Subject: [PATCH 047/409] Update TinyUSB init method --- cores/esp32/esp32-hal-tinyusb.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cores/esp32/esp32-hal-tinyusb.c b/cores/esp32/esp32-hal-tinyusb.c index eca7e5d176c..f83e8b61bd2 100644 --- a/cores/esp32/esp32-hal-tinyusb.c +++ b/cores/esp32/esp32-hal-tinyusb.c @@ -173,10 +173,15 @@ void deinit_usb_hal() { esp_err_t tinyusb_driver_install(const tinyusb_config_t *config) { init_usb_hal(config->external_phy); + tusb_rhport_init_t tinit; + memset(&tinit, 0, sizeof(tusb_rhport_init_t)); + tinit.role = TUSB_ROLE_DEVICE; #if CONFIG_IDF_TARGET_ESP32P4 - if (!tusb_init(1, TUSB_ROLE_DEVICE)) { + tinit.speed = TUSB_SPEED_HIGH; + if (!tusb_init(1, &tinit)) { #else - if (!tusb_init(0, TUSB_ROLE_DEVICE)) { + tinit.speed = TUSB_SPEED_FULL; + if (!tusb_init(0, &tinit)) { #endif log_e("Can't initialize the TinyUSB stack."); return ESP_FAIL; From c676ce7dc0860056459e87eeb5a8bac8d730866d Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 15 Oct 2024 21:06:31 +0300 Subject: [PATCH 048/409] fix(p4): Move ESP-HOSTED init to WiFiGeneric @P-R-O-C-H-Y will add the configured pins to periman, so that they can not be assigned to anything else --- libraries/Network/src/NetworkManager.cpp | 7 ------ libraries/WiFi/src/WiFiGeneric.cpp | 32 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/libraries/Network/src/NetworkManager.cpp b/libraries/Network/src/NetworkManager.cpp index b429c482825..88059a60562 100644 --- a/libraries/Network/src/NetworkManager.cpp +++ b/libraries/Network/src/NetworkManager.cpp @@ -10,10 +10,6 @@ #include "esp_mac.h" #include "netdb.h" -#if CONFIG_ESP_WIFI_REMOTE_ENABLED -extern "C" esp_err_t esp_hosted_init(void *); -#endif - NetworkManager::NetworkManager() {} NetworkInterface *getNetifByID(Network_Interface_ID id); @@ -22,9 +18,6 @@ bool NetworkManager::begin() { static bool initialized = false; if (!initialized) { initialized = true; -#if CONFIG_ESP_WIFI_REMOTE_ENABLED - esp_hosted_init(NULL); -#endif #if CONFIG_IDF_TARGET_ESP32 uint8_t mac[8]; if (esp_efuse_mac_get_default(mac) == ESP_OK) { diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index d096c2e3d6e..f3b27365cb6 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -233,9 +233,41 @@ void WiFiGenericClass::useStaticBuffers(bool bufferMode) { extern "C" void phy_bbpll_en_usb(bool en); #endif +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +extern "C" esp_err_t esp_hosted_init(void *); + +static bool wifiHostedInit() { + static bool initialized = false; + if (!initialized) { + initialized = true; + if (esp_hosted_init(NULL) != ESP_OK) { + log_e("esp_hosted_init failed!"); + return false; + } + } + // Attach pins to periman here + // Slave chip model is CONFIG_IDF_SLAVE_TARGET + // CONFIG_ESP_SDIO_PIN_CMD + // CONFIG_ESP_SDIO_PIN_CLK + // CONFIG_ESP_SDIO_PIN_D0 + // CONFIG_ESP_SDIO_PIN_D1 + // CONFIG_ESP_SDIO_PIN_D2 + // CONFIG_ESP_SDIO_PIN_D3 + // CONFIG_ESP_SDIO_GPIO_RESET_SLAVE + + return true; +} +#endif + bool wifiLowLevelInit(bool persistent) { if (!lowLevelInitDone) { lowLevelInitDone = true; +#if CONFIG_ESP_WIFI_REMOTE_ENABLED + if (!wifiHostedInit()) { + lowLevelInitDone = false; + return lowLevelInitDone; + } +#endif if (!Network.begin()) { lowLevelInitDone = false; return lowLevelInitDone; From 9dea05b17f27551c26f455a9517da25b9c10ca7f Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Thu, 17 Oct 2024 02:38:25 +0300 Subject: [PATCH 049/409] IDF release/v5.3 707d097b (#10473) --- package/package_esp32_index.template.json | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 9227a89034d..89ec0cebf8e 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -101,57 +101,57 @@ "host": "i686-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", - "size": "350992761" + "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", + "size": "343593768" }, { "host": "x86_64-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", - "size": "350992761" + "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", + "size": "343593768" }, { "host": "arm64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", - "size": "350992761" + "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", + "size": "343593768" }, { "host": "x86_64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", - "size": "350992761" + "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", + "size": "343593768" }, { "host": "x86_64-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", - "size": "350992761" + "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", + "size": "343593768" }, { "host": "i686-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", - "size": "350992761" + "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", + "size": "343593768" }, { "host": "aarch64-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", - "size": "350992761" + "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", + "size": "343593768" }, { "host": "arm-linux-gnueabihf", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:8a3f8ba621b187a53635deef36e335aa72f18d15c89170a32ce401bedee946be", - "size": "350992761" + "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", + "size": "343593768" } ] }, From bda8fcb457189c82a195565c44ef3bedf60c5979 Mon Sep 17 00:00:00 2001 From: ws-hsw <81347510+H-sw123@users.noreply.github.com> Date: Thu, 17 Oct 2024 07:39:23 +0800 Subject: [PATCH 050/409] addition(3rd_party_board): Add Waveshare-S3-touch-lcd (#10434) * add waveshare_touch_lcd * waveshare_touch_lcd * waveshare_touch_lcd * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- boards.txt | 1204 +++++++++++++++++ .../pins_arduino.h | 73 + .../pins_arduino.h | 116 ++ .../pins_arduino.h | 116 ++ .../pins_arduino.h | 116 ++ .../pins_arduino.h | 116 ++ .../pins_arduino.h | 116 ++ 7 files changed, 1857 insertions(+) create mode 100644 variants/waveshare_esp32_s3_touch_lcd_4/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_touch_lcd_43/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_touch_lcd_43b/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_touch_lcd_5/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_touch_lcd_5b/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_touch_lcd_7/pins_arduino.h diff --git a/boards.txt b/boards.txt index 42070a41a1c..b267f20cb1b 100644 --- a/boards.txt +++ b/boards.txt @@ -42395,3 +42395,1207 @@ waveshare_esp32_s3_touch_amoled_241.menu.EraseFlash.all=Enabled waveshare_esp32_s3_touch_amoled_241.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## + +waveshare_esp32_s3_touch_lcd_43.name=Waveshare ESP32-S3-Touch-LCD-4.3 +waveshare_esp32_s3_touch_lcd_43.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_43.pid.0=0x822E +waveshare_esp32_s3_touch_lcd_43.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_43.upload_port.0.pid=0x822E + +waveshare_esp32_s3_touch_lcd_43.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_43.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_43.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_43.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_43.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_43.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_43.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_43.upload.flags= +waveshare_esp32_s3_touch_lcd_43.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_43.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_43.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_43.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_43.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_43.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_43.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_43.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_43.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_43.build.core=esp32 +waveshare_esp32_s3_touch_lcd_43.build.variant=waveshare_esp32_s3_touch_lcd_43 +waveshare_esp32_s3_touch_lcd_43.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_43 + +waveshare_esp32_s3_touch_lcd_43.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_43.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_43.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_43.build.flash_size=8MB +waveshare_esp32_s3_touch_lcd_43.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_43.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_43.build.boot=qio +waveshare_esp32_s3_touch_lcd_43.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_43.build.partitions=default +waveshare_esp32_s3_touch_lcd_43.build.defines= +waveshare_esp32_s3_touch_lcd_43.build.loop_core= +waveshare_esp32_s3_touch_lcd_43.build.event_core= +waveshare_esp32_s3_touch_lcd_43.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_43.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_43.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_43.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_43.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_43.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_43.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_43.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_43.menu.FlashSize.8M=8MB (64Mb) +waveshare_esp32_s3_touch_lcd_43.menu.FlashSize.8M.build.flash_size=8MB +waveshare_esp32_s3_touch_lcd_43.menu.FlashSize.16M=16MB (128Mb) +waveshare_esp32_s3_touch_lcd_43.menu.FlashSize.16M.build.flash_size=16MB + +waveshare_esp32_s3_touch_lcd_43.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_43.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_43.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_43.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_43.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_43.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_43.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_43.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_43.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_43.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_43.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_43.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_43.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_43.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_43.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_43.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_43.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_43.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_43.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_43.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_43.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_43.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_43.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_43.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_43.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_43.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_43B.name=Waveshare ESP32-S3-Touch-LCD-4.3B +waveshare_esp32_s3_touch_lcd_43B.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_43B.pid.0=0x8231 +waveshare_esp32_s3_touch_lcd_43B.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_43B.upload_port.0.pid=0x8231 + +waveshare_esp32_s3_touch_lcd_43B.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_43B.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_43B.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_43B.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_43B.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_43B.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_43B.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_43B.upload.flags= +waveshare_esp32_s3_touch_lcd_43B.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_43B.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_43B.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_43B.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_43B.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_43B.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_43B.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_43B.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_43B.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_43B.build.core=esp32 +waveshare_esp32_s3_touch_lcd_43B.build.variant=waveshare_esp32_s3_touch_lcd_43b +waveshare_esp32_s3_touch_lcd_43B.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_43B + +waveshare_esp32_s3_touch_lcd_43B.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_43B.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43B.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43B.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_43B.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_43B.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_43B.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_43B.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_43B.build.boot=qio +waveshare_esp32_s3_touch_lcd_43B.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_43B.build.partitions=default +waveshare_esp32_s3_touch_lcd_43B.build.defines= +waveshare_esp32_s3_touch_lcd_43B.build.loop_core= +waveshare_esp32_s3_touch_lcd_43B.build.event_core= +waveshare_esp32_s3_touch_lcd_43B.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_43B.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_43B.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_43B.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_43B.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_43B.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_43B.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_43B.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_43B.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_43B.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_43B.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_43B.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_43B.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_43B.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_43B.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_43B.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_43B.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_43B.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_43B.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_43B.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_43B.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_43B.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43B.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_43B.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_43B.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_43B.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43B.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_43B.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_43B.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_43B.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_43B.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_43B.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_43B.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_43B.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_43B.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_43B.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_7.name=Waveshare ESP32-S3-Touch-LCD-7 +waveshare_esp32_s3_touch_lcd_7.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_7.pid.0=0x8234 +waveshare_esp32_s3_touch_lcd_7.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_7.upload_port.0.pid=0x8234 + +waveshare_esp32_s3_touch_lcd_7.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_7.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_7.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_7.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_7.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_7.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_7.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_7.upload.flags= +waveshare_esp32_s3_touch_lcd_7.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_7.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_7.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_7.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_7.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_7.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_7.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_7.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_7.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_7.build.core=esp32 +waveshare_esp32_s3_touch_lcd_7.build.variant=waveshare_esp32_s3_touch_lcd_7 +waveshare_esp32_s3_touch_lcd_7.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_7 + +waveshare_esp32_s3_touch_lcd_7.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_7.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_7.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_7.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_7.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_7.build.flash_size=8MB +waveshare_esp32_s3_touch_lcd_7.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_7.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_7.build.boot=qio +waveshare_esp32_s3_touch_lcd_7.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_7.build.partitions=default +waveshare_esp32_s3_touch_lcd_7.build.defines= +waveshare_esp32_s3_touch_lcd_7.build.loop_core= +waveshare_esp32_s3_touch_lcd_7.build.event_core= +waveshare_esp32_s3_touch_lcd_7.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_7.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_7.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_7.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_7.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_7.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_7.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_7.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_7.menu.FlashSize.8M=8MB (64Mb) +waveshare_esp32_s3_touch_lcd_7.menu.FlashSize.8M.build.flash_size=8MB +waveshare_esp32_s3_touch_lcd_7.menu.FlashSize.16M=16MB (128Mb) +waveshare_esp32_s3_touch_lcd_7.menu.FlashSize.16M.build.flash_size=16MB + +waveshare_esp32_s3_touch_lcd_7.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_7.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_7.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_7.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_7.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_7.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_7.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_7.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_7.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_7.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_7.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_7.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_7.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_7.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_7.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_7.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_7.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_7.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_7.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_7.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_7.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_7.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_7.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_7.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_7.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_7.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_7.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_7.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_5.name=Waveshare ESP32-S3-Touch-LCD-5 +waveshare_esp32_s3_touch_lcd_5.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_5.pid.0=0x8237 +waveshare_esp32_s3_touch_lcd_5.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_5.upload_port.0.pid=0x8237 + +waveshare_esp32_s3_touch_lcd_5.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_5.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_5.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_5.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_5.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_5.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_5.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_5.upload.flags= +waveshare_esp32_s3_touch_lcd_5.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_5.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_5.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_5.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_5.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_5.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_5.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_5.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_5.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_5.build.core=esp32 +waveshare_esp32_s3_touch_lcd_5.build.variant=waveshare_esp32_s3_touch_lcd_5 +waveshare_esp32_s3_touch_lcd_5.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_5 + +waveshare_esp32_s3_touch_lcd_5.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_5.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_5.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_5.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_5.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_5.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_5.build.boot=qio +waveshare_esp32_s3_touch_lcd_5.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_5.build.partitions=default +waveshare_esp32_s3_touch_lcd_5.build.defines= +waveshare_esp32_s3_touch_lcd_5.build.loop_core= +waveshare_esp32_s3_touch_lcd_5.build.event_core= +waveshare_esp32_s3_touch_lcd_5.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_5.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_5.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_5.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_5.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_5.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_5.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_5.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_5.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_5.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_5.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_5.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_5.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_5.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_5.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_5.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_5.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_5.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_5.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_5.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_5.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_5.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_5.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_5.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_5.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_5.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_5.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_5.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_5.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_5.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_5.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_5.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_5.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_5.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_5B.name=Waveshare ESP32-S3-Touch-LCD-5B +waveshare_esp32_s3_touch_lcd_5B.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_5B.pid.0=0x823A +waveshare_esp32_s3_touch_lcd_5B.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_5B.upload_port.0.pid=0x823A + +waveshare_esp32_s3_touch_lcd_5B.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_5B.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_5B.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_5B.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_5B.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_5B.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_5B.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_5B.upload.flags= +waveshare_esp32_s3_touch_lcd_5B.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_5B.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_5B.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_5B.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_5B.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_5B.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_5B.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_5B.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_5B.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_5B.build.core=esp32 +waveshare_esp32_s3_touch_lcd_5B.build.variant=waveshare_esp32_s3_touch_lcd_5b +waveshare_esp32_s3_touch_lcd_5B.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_5B + +waveshare_esp32_s3_touch_lcd_5B.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_5B.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5B.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5B.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_5B.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_5B.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_5B.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_5B.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_5B.build.boot=qio +waveshare_esp32_s3_touch_lcd_5B.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_5B.build.partitions=default +waveshare_esp32_s3_touch_lcd_5B.build.defines= +waveshare_esp32_s3_touch_lcd_5B.build.loop_core= +waveshare_esp32_s3_touch_lcd_5B.build.event_core= +waveshare_esp32_s3_touch_lcd_5B.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_5B.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_5B.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_5B.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_5B.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_5B.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_5B.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_5B.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_5B.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_5B.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_5B.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_5B.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_5B.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_5B.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_5B.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_5B.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_5B.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_5B.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_5B.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_5B.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_5B.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_5B.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5B.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_5B.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_5B.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_5B.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5B.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_5B.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_5B.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_5B.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_5B.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_5B.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_5B.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_5B.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_5B.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_5B.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_4.name=Waveshare ESP32-S3-Touch-LCD-4 +waveshare_esp32_s3_touch_lcd_4.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_4.pid.0=0x823D +waveshare_esp32_s3_touch_lcd_4.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_4.upload_port.0.pid=0x823D + +waveshare_esp32_s3_touch_lcd_4.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_4.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_4.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_4.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_4.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_4.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_4.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_4.upload.flags= +waveshare_esp32_s3_touch_lcd_4.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_4.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_4.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_4.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_4.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_4.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_4.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_4.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_4.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_4.build.core=esp32 +waveshare_esp32_s3_touch_lcd_4.build.variant=waveshare_esp32_s3_touch_lcd_4 +waveshare_esp32_s3_touch_lcd_4.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_4 + +waveshare_esp32_s3_touch_lcd_4.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_4.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_4.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_4.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_4.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_4.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_4.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_4.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_4.build.boot=qio +waveshare_esp32_s3_touch_lcd_4.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_4.build.partitions=default +waveshare_esp32_s3_touch_lcd_4.build.defines= +waveshare_esp32_s3_touch_lcd_4.build.loop_core= +waveshare_esp32_s3_touch_lcd_4.build.event_core= +waveshare_esp32_s3_touch_lcd_4.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_4.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_4.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_4.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_4.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_4.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_4.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_4.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_4.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_4.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_4.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_4.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_4.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_4.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_4.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_4.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_4.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_4.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_4.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_4.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_4.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_4.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_4.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_4.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_4.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_4.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_4.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_4.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_4.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_4.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_4.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_4.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_4.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_4.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_4.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_4.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## diff --git a/variants/waveshare_esp32_s3_touch_lcd_4/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_4/pins_arduino.h new file mode 100644 index 00000000000..f4a08ea7945 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_4/pins_arduino.h @@ -0,0 +1,73 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x823D + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-4" +#define USB_SERIAL "" + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = -1; +static const uint8_t SCL = -1; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_43/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_43/pins_arduino.h new file mode 100644 index 00000000000..9b60b50e0c1 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_43/pins_arduino.h @@ -0,0 +1,116 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x822E + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-4.3" +#define USB_SERIAL "" + +// display for ST7262 +#define WS_LCD_B3 14 +#define WS_LCD_B4 38 +#define WS_LCD_B5 18 +#define WS_LCD_B6 17 +#define WS_LCD_B7 10 + +#define WS_LCD_G2 39 +#define WS_LCD_G3 0 +#define WS_LCD_G4 45 +#define WS_LCD_G5 48 +#define WS_LCD_G6 47 +#define WS_LCD_G7 21 + +#define WS_LCD_R3 1 +#define WS_LCD_R4 2 +#define WS_LCD_R5 42 +#define WS_LCD_R6 41 +#define WS_LCD_R7 40 + +#define WS_LCD_VSYNC 3 +#define WS_LCD_HSYNC 46 +#define WS_LCD_PCLK 7 +#define WS_LCD_DE 5 + +// Touch for gt911 +#define WS_TP_SDA 8 +#define WS_TP_SCL 9 +#define WS_TP_RST -1 +#define WS_TP_INT 4 + +//RS485 +#define WS_RS485_RXD 16 +#define WS_RS485_TXD 15 + +//CAN +#define WS_CAN_RXD 19 +#define WS_CAN_TXD 20 + +//Onboard CH422G IO expander +#define WS_CH422G_SDA 8 +#define WS_CH422G_SCL 9 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 10; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_43b/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_43b/pins_arduino.h new file mode 100644 index 00000000000..f3bcb406d4c --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_43b/pins_arduino.h @@ -0,0 +1,116 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8231 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-4.3B" +#define USB_SERIAL "" + +// display for ST7262 +#define WS_LCD_B3 14 +#define WS_LCD_B4 38 +#define WS_LCD_B5 18 +#define WS_LCD_B6 17 +#define WS_LCD_B7 10 + +#define WS_LCD_G2 39 +#define WS_LCD_G3 0 +#define WS_LCD_G4 45 +#define WS_LCD_G5 48 +#define WS_LCD_G6 47 +#define WS_LCD_G7 21 + +#define WS_LCD_R3 1 +#define WS_LCD_R4 2 +#define WS_LCD_R5 42 +#define WS_LCD_R6 41 +#define WS_LCD_R7 40 + +#define WS_LCD_VSYNC 3 +#define WS_LCD_HSYNC 46 +#define WS_LCD_PCLK 7 +#define WS_LCD_DE 5 + +// Touch for gt911 +#define WS_TP_SDA 8 +#define WS_TP_SCL 9 +#define WS_TP_RST -1 +#define WS_TP_INT 4 + +//RS485 +#define WS_RS485_RXD 43 +#define WS_RS485_TXD 44 + +//CAN +#define WS_CAN_RXD 15 +#define WS_CAN_TXD 16 + +//Onboard CH422G IO expander +#define WS_CH422G_SDA 8 +#define WS_CH422G_SCL 9 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 10; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_5/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_5/pins_arduino.h new file mode 100644 index 00000000000..135dc0d0895 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_5/pins_arduino.h @@ -0,0 +1,116 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8237 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-5" +#define USB_SERIAL "" + +// display for ST7262 +#define WS_LCD_B3 14 +#define WS_LCD_B4 38 +#define WS_LCD_B5 18 +#define WS_LCD_B6 17 +#define WS_LCD_B7 10 + +#define WS_LCD_G2 39 +#define WS_LCD_G3 0 +#define WS_LCD_G4 45 +#define WS_LCD_G5 48 +#define WS_LCD_G6 47 +#define WS_LCD_G7 21 + +#define WS_LCD_R3 1 +#define WS_LCD_R4 2 +#define WS_LCD_R5 42 +#define WS_LCD_R6 41 +#define WS_LCD_R7 40 + +#define WS_LCD_VSYNC 3 +#define WS_LCD_HSYNC 46 +#define WS_LCD_PCLK 7 +#define WS_LCD_DE 5 + +// Touch for gt911 +#define WS_TP_SDA 8 +#define WS_TP_SCL 9 +#define WS_TP_RST -1 +#define WS_TP_INT 4 + +//RS485 +#define WS_RS485_RXD 43 +#define WS_RS485_TXD 44 + +//CAN +#define WS_CAN_RXD 15 +#define WS_CAN_TXD 16 + +//Onboard CH422G IO expander +#define WS_CH422G_SDA 8 +#define WS_CH422G_SCL 9 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 10; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_5b/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_5b/pins_arduino.h new file mode 100644 index 00000000000..e8829608a26 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_5b/pins_arduino.h @@ -0,0 +1,116 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x823A + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-5B" +#define USB_SERIAL "" + +// display for ST7262 +#define WS_LCD_B3 14 +#define WS_LCD_B4 38 +#define WS_LCD_B5 18 +#define WS_LCD_B6 17 +#define WS_LCD_B7 10 + +#define WS_LCD_G2 39 +#define WS_LCD_G3 0 +#define WS_LCD_G4 45 +#define WS_LCD_G5 48 +#define WS_LCD_G6 47 +#define WS_LCD_G7 21 + +#define WS_LCD_R3 1 +#define WS_LCD_R4 2 +#define WS_LCD_R5 42 +#define WS_LCD_R6 41 +#define WS_LCD_R7 40 + +#define WS_LCD_VSYNC 3 +#define WS_LCD_HSYNC 46 +#define WS_LCD_PCLK 7 +#define WS_LCD_DE 5 + +// Touch for gt911 +#define WS_TP_SDA 8 +#define WS_TP_SCL 9 +#define WS_TP_RST -1 +#define WS_TP_INT 4 + +//RS485 +#define WS_RS485_RXD 43 +#define WS_RS485_TXD 44 + +//CAN +#define WS_CAN_RXD 15 +#define WS_CAN_TXD 16 + +//Onboard CH422G IO expander +#define WS_CH422G_SDA 8 +#define WS_CH422G_SCL 9 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 10; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_7/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_7/pins_arduino.h new file mode 100644 index 00000000000..357edf78c34 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_7/pins_arduino.h @@ -0,0 +1,116 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8234 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-7" +#define USB_SERIAL "" + +// display for ST7262 +#define WS_LCD_B3 14 +#define WS_LCD_B4 38 +#define WS_LCD_B5 18 +#define WS_LCD_B6 17 +#define WS_LCD_B7 10 + +#define WS_LCD_G2 39 +#define WS_LCD_G3 0 +#define WS_LCD_G4 45 +#define WS_LCD_G5 48 +#define WS_LCD_G6 47 +#define WS_LCD_G7 21 + +#define WS_LCD_R3 1 +#define WS_LCD_R4 2 +#define WS_LCD_R5 42 +#define WS_LCD_R6 41 +#define WS_LCD_R7 40 + +#define WS_LCD_VSYNC 3 +#define WS_LCD_HSYNC 46 +#define WS_LCD_PCLK 7 +#define WS_LCD_DE 5 + +// Touch for gt911 +#define WS_TP_SDA 8 +#define WS_TP_SCL 9 +#define WS_TP_RST -1 +#define WS_TP_INT 4 + +//RS485 +#define WS_RS485_RXD 16 +#define WS_RS485_TXD 15 + +//CAN +#define WS_CAN_RXD 19 +#define WS_CAN_TXD 20 + +//Onboard CH422G IO expander +#define WS_CH422G_SDA 8 +#define WS_CH422G_SCL 9 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 10; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ From 7849a7943535bc2e093a5bbb9a70cae3b5f84597 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 17 Oct 2024 06:44:47 +0700 Subject: [PATCH 051/409] Add IOXESP32-C6 and ATD3.5-S3 board (#10471) Co-authored-by: Max <7087907+maxpromer@users.noreply.github.com> --- boards.txt | 358 +++++++++++++++++++++++++++++ variants/atd35s3/pins_arduino.h | 78 +++++++ variants/ioxesp32c6/pins_arduino.h | 35 +++ 3 files changed, 471 insertions(+) create mode 100644 variants/atd35s3/pins_arduino.h create mode 100644 variants/ioxesp32c6/pins_arduino.h diff --git a/boards.txt b/boards.txt index b267f20cb1b..4e82ba796d6 100644 --- a/boards.txt +++ b/boards.txt @@ -38494,6 +38494,8 @@ namino_bianco.menu.EraseFlash.all=Enabled namino_bianco.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +# IOXESP32, IOXESP32U + ioxesp32.name=IOXESP32 ioxesp32.bootloader.tool=esptool_py @@ -38604,6 +38606,7 @@ ioxesp32.menu.EraseFlash.all=Enabled ioxesp32.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +# IOXESP32PS ioxesp32ps.name=IOXESP32PS @@ -38715,6 +38718,178 @@ ioxesp32ps.menu.EraseFlash.all=Enabled ioxesp32ps.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +# IOXESP32-C6 + +ioxesp32c6.name=IOXESP32-C6 + +ioxesp32c6.bootloader.tool=esptool_py +ioxesp32c6.bootloader.tool.default=esptool_py + +ioxesp32c6.upload.tool=esptool_py +ioxesp32c6.upload.tool.default=esptool_py +ioxesp32c6.upload.tool.network=esp_ota + +ioxesp32c6.upload.maximum_size=1310720 +ioxesp32c6.upload.maximum_data_size=327680 +ioxesp32c6.upload.flags= +ioxesp32c6.upload.extra_flags= +ioxesp32c6.upload.use_1200bps_touch=false +ioxesp32c6.upload.wait_for_upload_port=false + +ioxesp32c6.serial.disableDTR=false +ioxesp32c6.serial.disableRTS=false + +ioxesp32c6.build.tarch=riscv32 +ioxesp32c6.build.target=esp +ioxesp32c6.build.mcu=esp32c6 +ioxesp32c6.build.core=esp32 +ioxesp32c6.build.variant=ioxesp32c6 +ioxesp32c6.build.board=ESP32C6_DEV +ioxesp32c6.build.bootloader_addr=0x0 + +ioxesp32c6.build.cdc_on_boot=0 +ioxesp32c6.build.f_cpu=160000000L +ioxesp32c6.build.flash_size=4MB +ioxesp32c6.build.flash_freq=80m +ioxesp32c6.build.flash_mode=qio +ioxesp32c6.build.boot=qio +ioxesp32c6.build.partitions=default +ioxesp32c6.build.defines= + +## IDE 2.0 Seems to not update the value +ioxesp32c6.menu.JTAGAdapter.default=Disabled +ioxesp32c6.menu.JTAGAdapter.default.build.copy_jtag_files=0 +ioxesp32c6.menu.JTAGAdapter.builtin=Integrated USB JTAG +ioxesp32c6.menu.JTAGAdapter.builtin.build.openocdscript=esp32c6-builtin.cfg +ioxesp32c6.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +ioxesp32c6.menu.JTAGAdapter.external=FTDI Adapter +ioxesp32c6.menu.JTAGAdapter.external.build.openocdscript=esp32c6-ftdi.cfg +ioxesp32c6.menu.JTAGAdapter.external.build.copy_jtag_files=1 +ioxesp32c6.menu.JTAGAdapter.bridge=ESP USB Bridge +ioxesp32c6.menu.JTAGAdapter.bridge.build.openocdscript=esp32c6-bridge.cfg +ioxesp32c6.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +ioxesp32c6.menu.CDCOnBoot.default=Disabled +ioxesp32c6.menu.CDCOnBoot.default.build.cdc_on_boot=0 +ioxesp32c6.menu.CDCOnBoot.cdc=Enabled +ioxesp32c6.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +ioxesp32c6.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +ioxesp32c6.menu.PartitionScheme.default.build.partitions=default +ioxesp32c6.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +ioxesp32c6.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +ioxesp32c6.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +ioxesp32c6.menu.PartitionScheme.minimal.build.partitions=minimal +ioxesp32c6.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +ioxesp32c6.menu.PartitionScheme.no_fs.build.partitions=no_fs +ioxesp32c6.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +ioxesp32c6.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +ioxesp32c6.menu.PartitionScheme.no_ota.build.partitions=no_ota +ioxesp32c6.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +ioxesp32c6.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +ioxesp32c6.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +ioxesp32c6.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +ioxesp32c6.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +ioxesp32c6.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +ioxesp32c6.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +ioxesp32c6.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +ioxesp32c6.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +ioxesp32c6.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +ioxesp32c6.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +ioxesp32c6.menu.PartitionScheme.huge_app.build.partitions=huge_app +ioxesp32c6.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +ioxesp32c6.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +ioxesp32c6.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +ioxesp32c6.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +ioxesp32c6.menu.PartitionScheme.rainmaker=RainMaker 4MB +ioxesp32c6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +ioxesp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +ioxesp32c6.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +ioxesp32c6.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +ioxesp32c6.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +ioxesp32c6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs +ioxesp32c6.menu.PartitionScheme.zigbee.build.partitions=zigbee +ioxesp32c6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 +ioxesp32c6.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +ioxesp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +ioxesp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +ioxesp32c6.menu.PartitionScheme.custom=Custom +ioxesp32c6.menu.PartitionScheme.custom.build.partitions= +ioxesp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +ioxesp32c6.menu.CPUFreq.160=160MHz (WiFi) +ioxesp32c6.menu.CPUFreq.160.build.f_cpu=160000000L +ioxesp32c6.menu.CPUFreq.120=120MHz (WiFi) +ioxesp32c6.menu.CPUFreq.120.build.f_cpu=120000000L +ioxesp32c6.menu.CPUFreq.80=80MHz (WiFi) +ioxesp32c6.menu.CPUFreq.80.build.f_cpu=80000000L +ioxesp32c6.menu.CPUFreq.40=40MHz +ioxesp32c6.menu.CPUFreq.40.build.f_cpu=40000000L +ioxesp32c6.menu.CPUFreq.20=20MHz +ioxesp32c6.menu.CPUFreq.20.build.f_cpu=20000000L +ioxesp32c6.menu.CPUFreq.10=10MHz +ioxesp32c6.menu.CPUFreq.10.build.f_cpu=10000000L + +ioxesp32c6.menu.FlashMode.qio=QIO +ioxesp32c6.menu.FlashMode.qio.build.flash_mode=dio +ioxesp32c6.menu.FlashMode.qio.build.boot=qio +ioxesp32c6.menu.FlashMode.dio=DIO +ioxesp32c6.menu.FlashMode.dio.build.flash_mode=dio +ioxesp32c6.menu.FlashMode.dio.build.boot=dio + +ioxesp32c6.menu.FlashFreq.80=80MHz +ioxesp32c6.menu.FlashFreq.80.build.flash_freq=80m +ioxesp32c6.menu.FlashFreq.40=40MHz +ioxesp32c6.menu.FlashFreq.40.build.flash_freq=40m + +ioxesp32c6.menu.UploadSpeed.921600=921600 +ioxesp32c6.menu.UploadSpeed.921600.upload.speed=921600 +ioxesp32c6.menu.UploadSpeed.115200=115200 +ioxesp32c6.menu.UploadSpeed.115200.upload.speed=115200 +ioxesp32c6.menu.UploadSpeed.256000.windows=256000 +ioxesp32c6.menu.UploadSpeed.256000.upload.speed=256000 +ioxesp32c6.menu.UploadSpeed.230400.windows.upload.speed=256000 +ioxesp32c6.menu.UploadSpeed.230400=230400 +ioxesp32c6.menu.UploadSpeed.230400.upload.speed=230400 +ioxesp32c6.menu.UploadSpeed.460800.linux=460800 +ioxesp32c6.menu.UploadSpeed.460800.macosx=460800 +ioxesp32c6.menu.UploadSpeed.460800.upload.speed=460800 +ioxesp32c6.menu.UploadSpeed.512000.windows=512000 +ioxesp32c6.menu.UploadSpeed.512000.upload.speed=512000 + +ioxesp32c6.menu.DebugLevel.none=None +ioxesp32c6.menu.DebugLevel.none.build.code_debug=0 +ioxesp32c6.menu.DebugLevel.error=Error +ioxesp32c6.menu.DebugLevel.error.build.code_debug=1 +ioxesp32c6.menu.DebugLevel.warn=Warn +ioxesp32c6.menu.DebugLevel.warn.build.code_debug=2 +ioxesp32c6.menu.DebugLevel.info=Info +ioxesp32c6.menu.DebugLevel.info.build.code_debug=3 +ioxesp32c6.menu.DebugLevel.debug=Debug +ioxesp32c6.menu.DebugLevel.debug.build.code_debug=4 +ioxesp32c6.menu.DebugLevel.verbose=Verbose +ioxesp32c6.menu.DebugLevel.verbose.build.code_debug=5 + +ioxesp32c6.menu.EraseFlash.none=Disabled +ioxesp32c6.menu.EraseFlash.none.upload.erase_cmd= +ioxesp32c6.menu.EraseFlash.all=Enabled +ioxesp32c6.menu.EraseFlash.all.upload.erase_cmd=-e + +ioxesp32c6.menu.ZigbeeMode.default=Disabled +ioxesp32c6.menu.ZigbeeMode.default.build.zigbee_mode= +ioxesp32c6.menu.ZigbeeMode.default.build.zigbee_libs= +ioxesp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) +ioxesp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED +ioxesp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port +ioxesp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +ioxesp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +ioxesp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +ioxesp32c6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) +ioxesp32c6.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP +ioxesp32c6.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port + +############################################################## +# ATD1.47-S3 atd147_s3.name=ATD1.47-S3 @@ -38896,6 +39071,189 @@ atd147_s3.menu.EraseFlash.none.upload.erase_cmd= atd147_s3.menu.EraseFlash.all=Enabled atd147_s3.menu.EraseFlash.all.upload.erase_cmd=-e +############################################################## +# ATD3.5-S3 + +atd35s3.name=ATD3.5-S3 + +atd35s3.bootloader.tool=esptool_py +atd35s3.bootloader.tool.default=esptool_py + +atd35s3.upload.tool=esptool_py +atd35s3.upload.tool.default=esptool_py +atd35s3.upload.tool.network=esp_ota + +atd35s3.upload.maximum_size=1310720 +atd35s3.upload.maximum_data_size=327680 +atd35s3.upload.flags= +atd35s3.upload.extra_flags= +atd35s3.upload.use_1200bps_touch=false +atd35s3.upload.wait_for_upload_port=false + +atd35s3.serial.disableDTR=false +atd35s3.serial.disableRTS=false + +atd35s3.build.tarch=xtensa +atd35s3.build.bootloader_addr=0x0 +atd35s3.build.target=esp32s3 +atd35s3.build.mcu=esp32s3 +atd35s3.build.core=esp32 +atd35s3.build.variant=atd35s3 +atd35s3.build.board=ATD143_S3 + +atd35s3.build.usb_mode=1 +atd35s3.build.cdc_on_boot=0 +atd35s3.build.msc_on_boot=0 +atd35s3.build.dfu_on_boot=0 +atd35s3.build.f_cpu=240000000L +atd35s3.build.flash_size=8MB +atd35s3.build.flash_freq=80m +atd35s3.build.flash_mode=dio +atd35s3.build.boot=qio +atd35s3.build.boot_freq=80m +atd35s3.build.partitions=default_8MB +atd35s3.build.defines= +atd35s3.build.loop_core= +atd35s3.build.event_core= +atd35s3.build.psram_type=opi +atd35s3.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +atd35s3.menu.JTAGAdapter.default=Disabled +atd35s3.menu.JTAGAdapter.default.build.copy_jtag_files=0 +atd35s3.menu.JTAGAdapter.builtin=Integrated USB JTAG +atd35s3.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +atd35s3.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +atd35s3.menu.JTAGAdapter.external=FTDI Adapter +atd35s3.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +atd35s3.menu.JTAGAdapter.external.build.copy_jtag_files=1 +atd35s3.menu.JTAGAdapter.bridge=ESP USB Bridge +atd35s3.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +atd35s3.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +atd35s3.menu.PSRAM.disabled=Disabled +atd35s3.menu.PSRAM.disabled.build.defines= +atd35s3.menu.PSRAM.disabled.build.psram_type=opi +atd35s3.menu.PSRAM.enabled=Enable +atd35s3.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +atd35s3.menu.PSRAM.enabled.build.psram_type=opi + +atd35s3.menu.LoopCore.1=Core 1 +atd35s3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +atd35s3.menu.LoopCore.0=Core 0 +atd35s3.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +atd35s3.menu.EventsCore.1=Core 1 +atd35s3.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +atd35s3.menu.EventsCore.0=Core 0 +atd35s3.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +atd35s3.menu.USBMode.hwcdc=Hardware CDC and JTAG +atd35s3.menu.USBMode.hwcdc.build.usb_mode=1 +atd35s3.menu.USBMode.default=USB-OTG (TinyUSB) +atd35s3.menu.USBMode.default.build.usb_mode=0 + +atd35s3.menu.CDCOnBoot.default=Disabled +atd35s3.menu.CDCOnBoot.default.build.cdc_on_boot=0 +atd35s3.menu.CDCOnBoot.cdc=Enabled +atd35s3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +atd35s3.menu.MSCOnBoot.default=Disabled +atd35s3.menu.MSCOnBoot.default.build.msc_on_boot=0 +atd35s3.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +atd35s3.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +atd35s3.menu.DFUOnBoot.default=Disabled +atd35s3.menu.DFUOnBoot.default.build.dfu_on_boot=0 +atd35s3.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +atd35s3.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +atd35s3.menu.UploadMode.default=UART0 / Hardware CDC +atd35s3.menu.UploadMode.default.upload.use_1200bps_touch=false +atd35s3.menu.UploadMode.default.upload.wait_for_upload_port=false +atd35s3.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +atd35s3.menu.UploadMode.cdc.upload.use_1200bps_touch=true +atd35s3.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +atd35s3.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +atd35s3.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +atd35s3.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +atd35s3.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +atd35s3.menu.PartitionScheme.minimal.build.partitions=minimal +atd35s3.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +atd35s3.menu.PartitionScheme.no_ota.build.partitions=no_ota +atd35s3.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +atd35s3.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +atd35s3.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +atd35s3.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +atd35s3.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +atd35s3.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +atd35s3.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +atd35s3.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +atd35s3.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +atd35s3.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +atd35s3.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +atd35s3.menu.PartitionScheme.huge_app.build.partitions=huge_app +atd35s3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +atd35s3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +atd35s3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +atd35s3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +atd35s3.menu.PartitionScheme.rainmaker=RainMaker 4MB +atd35s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +atd35s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +atd35s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +atd35s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +atd35s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +atd35s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +atd35s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +atd35s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 + +atd35s3.menu.CPUFreq.240=240MHz (WiFi) +atd35s3.menu.CPUFreq.240.build.f_cpu=240000000L +atd35s3.menu.CPUFreq.160=160MHz (WiFi) +atd35s3.menu.CPUFreq.160.build.f_cpu=160000000L +atd35s3.menu.CPUFreq.80=80MHz (WiFi) +atd35s3.menu.CPUFreq.80.build.f_cpu=80000000L +atd35s3.menu.CPUFreq.40=40MHz +atd35s3.menu.CPUFreq.40.build.f_cpu=40000000L +atd35s3.menu.CPUFreq.20=20MHz +atd35s3.menu.CPUFreq.20.build.f_cpu=20000000L +atd35s3.menu.CPUFreq.10=10MHz +atd35s3.menu.CPUFreq.10.build.f_cpu=10000000L + +atd35s3.menu.UploadSpeed.921600=921600 +atd35s3.menu.UploadSpeed.921600.upload.speed=921600 +atd35s3.menu.UploadSpeed.115200=115200 +atd35s3.menu.UploadSpeed.115200.upload.speed=115200 +atd35s3.menu.UploadSpeed.256000.windows=256000 +atd35s3.menu.UploadSpeed.256000.upload.speed=256000 +atd35s3.menu.UploadSpeed.230400.windows.upload.speed=256000 +atd35s3.menu.UploadSpeed.230400=230400 +atd35s3.menu.UploadSpeed.230400.upload.speed=230400 +atd35s3.menu.UploadSpeed.460800.linux=460800 +atd35s3.menu.UploadSpeed.460800.macosx=460800 +atd35s3.menu.UploadSpeed.460800.upload.speed=460800 +atd35s3.menu.UploadSpeed.512000.windows=512000 +atd35s3.menu.UploadSpeed.512000.upload.speed=512000 + +atd35s3.menu.DebugLevel.none=None +atd35s3.menu.DebugLevel.none.build.code_debug=0 +atd35s3.menu.DebugLevel.error=Error +atd35s3.menu.DebugLevel.error.build.code_debug=1 +atd35s3.menu.DebugLevel.warn=Warn +atd35s3.menu.DebugLevel.warn.build.code_debug=2 +atd35s3.menu.DebugLevel.info=Info +atd35s3.menu.DebugLevel.info.build.code_debug=3 +atd35s3.menu.DebugLevel.debug=Debug +atd35s3.menu.DebugLevel.debug.build.code_debug=4 +atd35s3.menu.DebugLevel.verbose=Verbose +atd35s3.menu.DebugLevel.verbose.build.code_debug=5 + +atd35s3.menu.EraseFlash.none=Disabled +atd35s3.menu.EraseFlash.none.upload.erase_cmd= +atd35s3.menu.EraseFlash.all=Enabled +atd35s3.menu.EraseFlash.all.upload.erase_cmd=-e + ############################################################## # ESP32-S3 PowerFeather diff --git a/variants/atd35s3/pins_arduino.h b/variants/atd35s3/pins_arduino.h new file mode 100644 index 00000000000..c973693b71c --- /dev/null +++ b/variants/atd35s3/pins_arduino.h @@ -0,0 +1,78 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +// LCD pin +#define LCD_CS SS +#define LCD_SCK SCK +#define LCD_SDA MOSI +static const uint8_t LCD_DC = 21; +static const uint8_t LCD_RES = 14; +static const uint8_t LCD_BL = 3; + +// MicroSD Card pin +static const uint8_t SD_CS = 18; +static const uint8_t SD_CD = 17; + +static const uint8_t BTN_A = 4; +#define KEY_BUILTIN BTN_A + +static const uint8_t LED_BUILTIN = 5; + +// DAC pin +static const uint8_t DAC_DIN = 47; +static const uint8_t DAC_BCLK = 48; +static const uint8_t DAC_WS = 45; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/ioxesp32c6/pins_arduino.h b/variants/ioxesp32c6/pins_arduino.h new file mode 100644 index 00000000000..bcd20119514 --- /dev/null +++ b/variants/ioxesp32c6/pins_arduino.h @@ -0,0 +1,35 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define PIN_RGB_LED 8 +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() +#define RGB_BUILTIN LED_BUILTIN +#define RGB_BRIGHTNESS 64 + +static const uint8_t TX = 16; +static const uint8_t RX = 17; + +static const uint8_t SDA = 21; +static const uint8_t SCL = 22; + +static const uint8_t SS = 18; +static const uint8_t MOSI = 23; +static const uint8_t MISO = 20; +static const uint8_t SCK = 19; + +static const uint8_t A0 = 0; +static const uint8_t A1 = 1; +static const uint8_t A2 = 2; +static const uint8_t A3 = 3; +static const uint8_t A4 = 4; +static const uint8_t A5 = 5; +static const uint8_t A6 = 6; + +#endif /* Pins_Arduino_h */ From 51b2fb356da3a8c30b7a4809dff0db3d31362da8 Mon Sep 17 00:00:00 2001 From: Dogus Cendek Date: Thu, 17 Oct 2024 10:43:21 +0300 Subject: [PATCH 052/409] Add our new board "cezerio dev ESP32C6" (#10462) * Add cezerio dev ESP32-C6 * Modify pin number of cezerio dev ESP32C6 Modify pin number of cezerio dev ESP32C6 * Update boards.txt * Update USB_PID Update USB_PID * Update boards.txt Deleted flash and partition options related in flash size bigger than 4MB * Update pins_arduino.h * Merge manually to solve conflicts * Resolve Conflicts * Add cezerio dev ESP32-C6 * Modify pin number of cezerio dev ESP32C6 Modify pin number of cezerio dev ESP32C6 * Update boards.txt * Update USB_PID Update USB_PID * Update pins_arduino.h * Add cezerio dev ESP32C6 * Update pins_arduino.h * Update pins_arduino.h * Update pins_arduino.h --- boards.txt | 173 ++++++++++++++++++++ variants/cezerio_dev_esp32c6/pins_arduino.h | 52 ++++++ 2 files changed, 225 insertions(+) create mode 100644 variants/cezerio_dev_esp32c6/pins_arduino.h diff --git a/boards.txt b/boards.txt index 4e82ba796d6..d1813a7d22a 100644 --- a/boards.txt +++ b/boards.txt @@ -43957,3 +43957,176 @@ waveshare_esp32_s3_touch_lcd_4.menu.EraseFlash.all=Enabled waveshare_esp32_s3_touch_lcd_4.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## + +cezerio_dev_esp32c6.name=cezerio dev ESP32C6 + +cezerio_dev_esp32c6.bootloader.tool=esptool_py +cezerio_dev_esp32c6.bootloader.tool.default=esptool_py + +cezerio_dev_esp32c6.upload.tool=esptool_py +cezerio_dev_esp32c6.upload.tool.default=esptool_py +cezerio_dev_esp32c6.upload.tool.network=esp_ota + +cezerio_dev_esp32c6.upload.maximum_size=1310720 +cezerio_dev_esp32c6.upload.maximum_data_size=327680 +cezerio_dev_esp32c6.upload.flags= +cezerio_dev_esp32c6.upload.extra_flags= +cezerio_dev_esp32c6.upload.use_1200bps_touch=false +cezerio_dev_esp32c6.upload.wait_for_upload_port=false + +cezerio_dev_esp32c6.serial.disableDTR=false +cezerio_dev_esp32c6.serial.disableRTS=false + +cezerio_dev_esp32c6.build.tarch=riscv32 +cezerio_dev_esp32c6.build.target=esp +cezerio_dev_esp32c6.build.mcu=esp32c6 +cezerio_dev_esp32c6.build.core=esp32 +cezerio_dev_esp32c6.build.variant=cezerio_dev_esp32c6 +cezerio_dev_esp32c6.build.board=CEZERIO_DEV_ESP32C6 +cezerio_dev_esp32c6.build.bootloader_addr=0x0 + +cezerio_dev_esp32c6.build.cdc_on_boot=0 +cezerio_dev_esp32c6.build.f_cpu=160000000L +cezerio_dev_esp32c6.build.flash_size=4MB +cezerio_dev_esp32c6.build.flash_freq=80m +cezerio_dev_esp32c6.build.flash_mode=qio +cezerio_dev_esp32c6.build.boot=qio +cezerio_dev_esp32c6.build.partitions=default +cezerio_dev_esp32c6.build.defines= + +## IDE 2.0 Seems to not update the value +cezerio_dev_esp32c6.menu.JTAGAdapter.default=Disabled +cezerio_dev_esp32c6.menu.JTAGAdapter.default.build.copy_jtag_files=0 +cezerio_dev_esp32c6.menu.JTAGAdapter.builtin=Integrated USB JTAG +cezerio_dev_esp32c6.menu.JTAGAdapter.builtin.build.openocdscript=esp32c6-builtin.cfg +cezerio_dev_esp32c6.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +cezerio_dev_esp32c6.menu.JTAGAdapter.external=FTDI Adapter +cezerio_dev_esp32c6.menu.JTAGAdapter.external.build.openocdscript=esp32c6-ftdi.cfg +cezerio_dev_esp32c6.menu.JTAGAdapter.external.build.copy_jtag_files=1 +cezerio_dev_esp32c6.menu.JTAGAdapter.bridge=ESP USB Bridge +cezerio_dev_esp32c6.menu.JTAGAdapter.bridge.build.openocdscript=esp32c6-bridge.cfg +cezerio_dev_esp32c6.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +cezerio_dev_esp32c6.menu.CDCOnBoot.default=Enabled +cezerio_dev_esp32c6.menu.CDCOnBoot.default.build.cdc_on_boot=1 +cezerio_dev_esp32c6.menu.CDCOnBoot.cdc=Disabled +cezerio_dev_esp32c6.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +cezerio_dev_esp32c6.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +cezerio_dev_esp32c6.menu.PartitionScheme.default.build.partitions=default +cezerio_dev_esp32c6.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +cezerio_dev_esp32c6.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +cezerio_dev_esp32c6.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +cezerio_dev_esp32c6.menu.PartitionScheme.minimal.build.partitions=minimal +cezerio_dev_esp32c6.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +cezerio_dev_esp32c6.menu.PartitionScheme.no_fs.build.partitions=no_fs +cezerio_dev_esp32c6.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +cezerio_dev_esp32c6.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +cezerio_dev_esp32c6.menu.PartitionScheme.no_ota.build.partitions=no_ota +cezerio_dev_esp32c6.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +cezerio_dev_esp32c6.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +cezerio_dev_esp32c6.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +cezerio_dev_esp32c6.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +cezerio_dev_esp32c6.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +cezerio_dev_esp32c6.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +cezerio_dev_esp32c6.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +cezerio_dev_esp32c6.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +cezerio_dev_esp32c6.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +cezerio_dev_esp32c6.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +cezerio_dev_esp32c6.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +cezerio_dev_esp32c6.menu.PartitionScheme.huge_app.build.partitions=huge_app +cezerio_dev_esp32c6.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +cezerio_dev_esp32c6.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +cezerio_dev_esp32c6.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +cezerio_dev_esp32c6.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +cezerio_dev_esp32c6.menu.PartitionScheme.rainmaker=RainMaker 4MB +cezerio_dev_esp32c6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +cezerio_dev_esp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +cezerio_dev_esp32c6.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +cezerio_dev_esp32c6.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +cezerio_dev_esp32c6.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +cezerio_dev_esp32c6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs +cezerio_dev_esp32c6.menu.PartitionScheme.zigbee.build.partitions=zigbee +cezerio_dev_esp32c6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 +cezerio_dev_esp32c6.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +cezerio_dev_esp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +cezerio_dev_esp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +cezerio_dev_esp32c6.menu.PartitionScheme.custom=Custom +cezerio_dev_esp32c6.menu.PartitionScheme.custom.build.partitions= +cezerio_dev_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +cezerio_dev_esp32c6.menu.CPUFreq.160=160MHz (WiFi) +cezerio_dev_esp32c6.menu.CPUFreq.160.build.f_cpu=160000000L +cezerio_dev_esp32c6.menu.CPUFreq.120=120MHz (WiFi) +cezerio_dev_esp32c6.menu.CPUFreq.120.build.f_cpu=120000000L +cezerio_dev_esp32c6.menu.CPUFreq.80=80MHz (WiFi) +cezerio_dev_esp32c6.menu.CPUFreq.80.build.f_cpu=80000000L +cezerio_dev_esp32c6.menu.CPUFreq.40=40MHz +cezerio_dev_esp32c6.menu.CPUFreq.40.build.f_cpu=40000000L +cezerio_dev_esp32c6.menu.CPUFreq.20=20MHz +cezerio_dev_esp32c6.menu.CPUFreq.20.build.f_cpu=20000000L +cezerio_dev_esp32c6.menu.CPUFreq.10=10MHz +cezerio_dev_esp32c6.menu.CPUFreq.10.build.f_cpu=10000000L + +cezerio_dev_esp32c6.menu.FlashMode.qio=QIO +cezerio_dev_esp32c6.menu.FlashMode.qio.build.flash_mode=dio +cezerio_dev_esp32c6.menu.FlashMode.qio.build.boot=qio +cezerio_dev_esp32c6.menu.FlashMode.dio=DIO +cezerio_dev_esp32c6.menu.FlashMode.dio.build.flash_mode=dio +cezerio_dev_esp32c6.menu.FlashMode.dio.build.boot=dio + +cezerio_dev_esp32c6.menu.FlashFreq.80=80MHz +cezerio_dev_esp32c6.menu.FlashFreq.80.build.flash_freq=80m +cezerio_dev_esp32c6.menu.FlashFreq.40=40MHz +cezerio_dev_esp32c6.menu.FlashFreq.40.build.flash_freq=40m + +cezerio_dev_esp32c6.menu.FlashSize.4M=4MB (32Mb) +cezerio_dev_esp32c6.menu.FlashSize.4M.build.flash_size=4MB + +cezerio_dev_esp32c6.menu.UploadSpeed.921600=921600 +cezerio_dev_esp32c6.menu.UploadSpeed.921600.upload.speed=921600 +cezerio_dev_esp32c6.menu.UploadSpeed.115200=115200 +cezerio_dev_esp32c6.menu.UploadSpeed.115200.upload.speed=115200 +cezerio_dev_esp32c6.menu.UploadSpeed.256000.windows=256000 +cezerio_dev_esp32c6.menu.UploadSpeed.256000.upload.speed=256000 +cezerio_dev_esp32c6.menu.UploadSpeed.230400.windows.upload.speed=256000 +cezerio_dev_esp32c6.menu.UploadSpeed.230400=230400 +cezerio_dev_esp32c6.menu.UploadSpeed.230400.upload.speed=230400 +cezerio_dev_esp32c6.menu.UploadSpeed.460800.linux=460800 +cezerio_dev_esp32c6.menu.UploadSpeed.460800.macosx=460800 +cezerio_dev_esp32c6.menu.UploadSpeed.460800.upload.speed=460800 +cezerio_dev_esp32c6.menu.UploadSpeed.512000.windows=512000 +cezerio_dev_esp32c6.menu.UploadSpeed.512000.upload.speed=512000 + +cezerio_dev_esp32c6.menu.DebugLevel.none=None +cezerio_dev_esp32c6.menu.DebugLevel.none.build.code_debug=0 +cezerio_dev_esp32c6.menu.DebugLevel.error=Error +cezerio_dev_esp32c6.menu.DebugLevel.error.build.code_debug=1 +cezerio_dev_esp32c6.menu.DebugLevel.warn=Warn +cezerio_dev_esp32c6.menu.DebugLevel.warn.build.code_debug=2 +cezerio_dev_esp32c6.menu.DebugLevel.info=Info +cezerio_dev_esp32c6.menu.DebugLevel.info.build.code_debug=3 +cezerio_dev_esp32c6.menu.DebugLevel.debug=Debug +cezerio_dev_esp32c6.menu.DebugLevel.debug.build.code_debug=4 +cezerio_dev_esp32c6.menu.DebugLevel.verbose=Verbose +cezerio_dev_esp32c6.menu.DebugLevel.verbose.build.code_debug=5 + +cezerio_dev_esp32c6.menu.EraseFlash.none=Disabled +cezerio_dev_esp32c6.menu.EraseFlash.none.upload.erase_cmd= +cezerio_dev_esp32c6.menu.EraseFlash.all=Enabled +cezerio_dev_esp32c6.menu.EraseFlash.all.upload.erase_cmd=-e + +cezerio_dev_esp32c6.menu.ZigbeeMode.default=Disabled +cezerio_dev_esp32c6.menu.ZigbeeMode.default.build.zigbee_mode= +cezerio_dev_esp32c6.menu.ZigbeeMode.default.build.zigbee_libs= +cezerio_dev_esp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) +cezerio_dev_esp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED +cezerio_dev_esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port +cezerio_dev_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +cezerio_dev_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +cezerio_dev_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +cezerio_dev_esp32c6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) +cezerio_dev_esp32c6.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP +cezerio_dev_esp32c6.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port + +############################################################## diff --git a/variants/cezerio_dev_esp32c6/pins_arduino.h b/variants/cezerio_dev_esp32c6/pins_arduino.h new file mode 100644 index 00000000000..3ffc59aee6f --- /dev/null +++ b/variants/cezerio_dev_esp32c6/pins_arduino.h @@ -0,0 +1,52 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define USB_VID 0x303A +#define USB_PID 0x1001 +#define USB_MANUFACTURER "RFtek Electronics" +#define USB_PRODUCT "cezerio dev ESP32C6" +#define USB_SERIAL "" + +#define PIN_RGB_LED 3 +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() +#define RGB_BUILTIN LED_BUILTIN +#define RGBLED LED_BUILTIN +#define RGB_BRIGHTNESS 64 + +static const uint8_t BUT_BUILTIN = 9; +#define BUILTIN_BUT BUT_BUILTIN // backward compatibility +#define BUT_BUILTIN BUT_BUILTIN // allow testing #ifdef BUT_BUILTIN +#define BOOT BUT_BUILTIN + +static const uint8_t TX = 16; +static const uint8_t RX = 17; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 7; + +static const uint8_t SS = 14; +static const uint8_t MOSI = 22; +static const uint8_t MISO = 23; +static const uint8_t SCK = 21; + +static const uint8_t A0 = 0; +static const uint8_t A1 = 1; +static const uint8_t A2 = 2; +static const uint8_t A3 = 3; +static const uint8_t A4 = 4; +static const uint8_t A5 = 5; +static const uint8_t A6 = 6; + +static const uint8_t MATRIX = 18; + +static const uint8_t IMUSD = 8; +static const uint8_t IMUSC = 7; + +#endif /* Pins_Arduino_h */ From 955b277497b4529b685fb0193ba4f7dcc61d11c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Thu, 17 Oct 2024 09:43:47 +0200 Subject: [PATCH 053/409] fix(example): print correct fade direction (#10450) * fix(example): print correct fade direction * fix(example): Change to fade in out * fix(example): Codespell fix --- .../ESP32/examples/AnalogOut/LEDCFade/LEDCFade.ino | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/ESP32/examples/AnalogOut/LEDCFade/LEDCFade.ino b/libraries/ESP32/examples/AnalogOut/LEDCFade/LEDCFade.ino index dc152a63ea4..7155d2791cb 100644 --- a/libraries/ESP32/examples/AnalogOut/LEDCFade/LEDCFade.ino +++ b/libraries/ESP32/examples/AnalogOut/LEDCFade/LEDCFade.ino @@ -21,7 +21,7 @@ #define LEDC_FADE_TIME (3000) bool fade_ended = false; // status of LED fade -bool fade_on = true; +bool fade_in = true; void ARDUINO_ISR_ATTR LED_FADE_ISR() { fade_ended = true; @@ -55,15 +55,15 @@ void loop() { Serial.println("LED fade ended"); fade_ended = false; - // Check if last fade was fade on - if (fade_on) { + // Check what fade should be started next + if (fade_in) { ledcFadeWithInterrupt(LED_PIN, LEDC_START_DUTY, LEDC_TARGET_DUTY, LEDC_FADE_TIME, LED_FADE_ISR); - Serial.println("LED Fade off started."); - fade_on = false; + Serial.println("LED Fade in started."); + fade_in = false; } else { ledcFadeWithInterrupt(LED_PIN, LEDC_TARGET_DUTY, LEDC_START_DUTY, LEDC_FADE_TIME, LED_FADE_ISR); - Serial.println("LED Fade on started."); - fade_on = true; + Serial.println("LED Fade out started."); + fade_in = true; } } } From 612fc4c4bbc48d6f52725ac7d14798976650123f Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 17 Oct 2024 12:12:44 +0300 Subject: [PATCH 054/409] fix(pins): Adjust P4 SPI pins to ones that are available --- variants/esp32p4/pins_arduino.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/variants/esp32p4/pins_arduino.h b/variants/esp32p4/pins_arduino.h index caba8995222..f227de428ef 100644 --- a/variants/esp32p4/pins_arduino.h +++ b/variants/esp32p4/pins_arduino.h @@ -22,10 +22,10 @@ static const uint8_t RX = 38; static const uint8_t SDA = 7; static const uint8_t SCL = 8; -static const uint8_t SS = 10; -static const uint8_t MOSI = 11; -static const uint8_t MISO = 12; -static const uint8_t SCK = 13; +static const uint8_t SS = 27; +static const uint8_t MOSI = 46; +static const uint8_t MISO = 47; +static const uint8_t SCK = 48; static const uint8_t A0 = 16; static const uint8_t A1 = 17; From ee1bc6ba0a7a4bb59d3b1e45760acffaa9603e43 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Thu, 17 Oct 2024 14:30:48 +0300 Subject: [PATCH 055/409] Add RMII Ethernet support for ESP32-P4 (#10479) * fix(eth): Add ETH support for ESP32-P4 Also adds configuration to pins_arduino.h * fix(eth): Enable TLK110 Example on P4 * fix(eth): Fix Ethernet examples * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- boards.txt | 7 +++-- .../examples/ETH_LAN8720/ETH_LAN8720.ino | 12 ++++++-- .../examples/ETH_TLK110/ETH_TLK110.ino | 12 ++++++-- .../Ethernet/examples/ETH_TLK110/ci.json | 5 +--- .../ETH_W5500_Arduino_SPI.ino | 4 +-- .../ETH_W5500_IDF_SPI/ETH_W5500_IDF_SPI.ino | 4 +-- libraries/Ethernet/src/ETH.cpp | 28 +++++++++++++++++-- libraries/Ethernet/src/ETH.h | 26 +++++++++++++++++ variants/esp32p4/pins_arduino.h | 14 ++++++++++ 9 files changed, 96 insertions(+), 16 deletions(-) diff --git a/boards.txt b/boards.txt index fd71c2e80c2..62d66fdc828 100644 --- a/boards.txt +++ b/boards.txt @@ -188,7 +188,10 @@ esp32p4.build.variant=esp32p4 esp32p4.build.board=ESP32P4_DEV esp32p4.build.bootloader_addr=0x2000 +esp32p4.build.usb_mode=0 esp32p4.build.cdc_on_boot=0 +esp32p4.build.msc_on_boot=0 +esp32p4.build.dfu_on_boot=0 esp32p4.build.f_cpu=360000000L esp32p4.build.flash_size=4MB esp32p4.build.flash_freq=80m @@ -216,10 +219,10 @@ esp32p4.menu.PSRAM.disabled.build.defines= esp32p4.menu.PSRAM.enabled=Enabled esp32p4.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM -esp32p4.menu.USBMode.hwcdc=Hardware CDC and JTAG -esp32p4.menu.USBMode.hwcdc.build.usb_mode=1 esp32p4.menu.USBMode.default=USB-OTG (TinyUSB) esp32p4.menu.USBMode.default.build.usb_mode=0 +esp32p4.menu.USBMode.hwcdc=Hardware CDC and JTAG +esp32p4.menu.USBMode.hwcdc.build.usb_mode=1 esp32p4.menu.CDCOnBoot.default=Disabled esp32p4.menu.CDCOnBoot.default.build.cdc_on_boot=0 diff --git a/libraries/Ethernet/examples/ETH_LAN8720/ETH_LAN8720.ino b/libraries/Ethernet/examples/ETH_LAN8720/ETH_LAN8720.ino index 1453df63434..59a32750bf6 100644 --- a/libraries/Ethernet/examples/ETH_LAN8720/ETH_LAN8720.ino +++ b/libraries/Ethernet/examples/ETH_LAN8720/ETH_LAN8720.ino @@ -5,13 +5,21 @@ // Important to be defined BEFORE including ETH.h for ETH.begin() to work. // Example RMII LAN8720 (Olimex, etc.) -#ifndef ETH_PHY_TYPE -#define ETH_PHY_TYPE ETH_PHY_LAN8720 +#ifndef ETH_PHY_MDC +#define ETH_PHY_TYPE ETH_PHY_LAN8720 +#if CONFIG_IDF_TARGET_ESP32 #define ETH_PHY_ADDR 0 #define ETH_PHY_MDC 23 #define ETH_PHY_MDIO 18 #define ETH_PHY_POWER -1 #define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN +#elif CONFIG_IDF_TARGET_ESP32P4 +#define ETH_PHY_ADDR 0 +#define ETH_PHY_MDC 31 +#define ETH_PHY_MDIO 52 +#define ETH_PHY_POWER 51 +#define ETH_CLK_MODE EMAC_CLK_EXT_IN +#endif #endif #include diff --git a/libraries/Ethernet/examples/ETH_TLK110/ETH_TLK110.ino b/libraries/Ethernet/examples/ETH_TLK110/ETH_TLK110.ino index 3252cd120f4..242281c3997 100644 --- a/libraries/Ethernet/examples/ETH_TLK110/ETH_TLK110.ino +++ b/libraries/Ethernet/examples/ETH_TLK110/ETH_TLK110.ino @@ -5,13 +5,21 @@ #include -#ifndef ETH_PHY_TYPE -#define ETH_PHY_TYPE ETH_PHY_TLK110 +#ifndef ETH_PHY_MDC +#define ETH_PHY_TYPE ETH_PHY_TLK110 +#if CONFIG_IDF_TARGET_ESP32 #define ETH_PHY_ADDR 31 #define ETH_PHY_MDC 23 #define ETH_PHY_MDIO 18 #define ETH_PHY_POWER 17 #define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN +#elif CONFIG_IDF_TARGET_ESP32P4 +#define ETH_PHY_ADDR 1 +#define ETH_PHY_MDC 31 +#define ETH_PHY_MDIO 52 +#define ETH_PHY_POWER 51 +#define ETH_CLK_MODE EMAC_CLK_EXT_IN +#endif #endif static bool eth_connected = false; diff --git a/libraries/Ethernet/examples/ETH_TLK110/ci.json b/libraries/Ethernet/examples/ETH_TLK110/ci.json index 0eab13b8841..dcdfd06db51 100644 --- a/libraries/Ethernet/examples/ETH_TLK110/ci.json +++ b/libraries/Ethernet/examples/ETH_TLK110/ci.json @@ -1,8 +1,5 @@ { "requires": [ "CONFIG_ETH_USE_ESP32_EMAC=y" - ], - "targets": { - "esp32p4": false - } + ] } diff --git a/libraries/Ethernet/examples/ETH_W5500_Arduino_SPI/ETH_W5500_Arduino_SPI.ino b/libraries/Ethernet/examples/ETH_W5500_Arduino_SPI/ETH_W5500_Arduino_SPI.ino index d4bc78a1c07..d5d57333a55 100644 --- a/libraries/Ethernet/examples/ETH_W5500_Arduino_SPI/ETH_W5500_Arduino_SPI.ino +++ b/libraries/Ethernet/examples/ETH_W5500_Arduino_SPI/ETH_W5500_Arduino_SPI.ino @@ -9,7 +9,7 @@ // Set this to 1 to enable dual Ethernet support #define USE_TWO_ETH_PORTS 0 -#ifndef ETH_PHY_TYPE +#ifndef ETH_PHY_CS #define ETH_PHY_TYPE ETH_PHY_W5500 #define ETH_PHY_ADDR 1 #define ETH_PHY_CS 15 @@ -24,7 +24,7 @@ #if USE_TWO_ETH_PORTS // Second port on shared SPI bus -#ifndef ETH1_PHY_TYPE +#ifndef ETH1_PHY_CS #define ETH1_PHY_TYPE ETH_PHY_W5500 #define ETH1_PHY_ADDR 1 #define ETH1_PHY_CS 32 diff --git a/libraries/Ethernet/examples/ETH_W5500_IDF_SPI/ETH_W5500_IDF_SPI.ino b/libraries/Ethernet/examples/ETH_W5500_IDF_SPI/ETH_W5500_IDF_SPI.ino index 512bb78ff5e..dad54a745b7 100644 --- a/libraries/Ethernet/examples/ETH_W5500_IDF_SPI/ETH_W5500_IDF_SPI.ino +++ b/libraries/Ethernet/examples/ETH_W5500_IDF_SPI/ETH_W5500_IDF_SPI.ino @@ -8,7 +8,7 @@ // Set this to 1 to enable dual Ethernet support #define USE_TWO_ETH_PORTS 0 -#ifndef ETH_PHY_TYPE +#ifndef ETH_PHY_CS #define ETH_PHY_TYPE ETH_PHY_W5500 #define ETH_PHY_ADDR 1 #define ETH_PHY_CS 15 @@ -22,7 +22,7 @@ #if USE_TWO_ETH_PORTS // Second port on shared SPI bus -#ifndef ETH1_PHY_TYPE +#ifndef ETH1_PHY_CS #define ETH1_PHY_TYPE ETH_PHY_W5500 #define ETH1_PHY_ADDR 1 #define ETH1_PHY_CS 32 diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 13f9c11f7fe..4ef184ac97a 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -148,7 +148,27 @@ void ETHClass::setTaskStackSize(size_t size) { _task_stack_size = size; } -#if (CONFIG_ETH_USE_ESP32_EMAC && !defined(CONFIG_IDF_TARGET_ESP32P4)) +#if CONFIG_ETH_USE_ESP32_EMAC +#if CONFIG_IDF_TARGET_ESP32 +#define ETH_EMAC_DEFAULT_CONFIG() ETH_ESP32_EMAC_DEFAULT_CONFIG() +#elif CONFIG_IDF_TARGET_ESP32P4 +#define ETH_EMAC_DEFAULT_CONFIG() \ + { \ + .smi_gpio = {.mdc_num = 31, .mdio_num = 52}, .interface = EMAC_DATA_INTERFACE_RMII, \ + .clock_config = {.rmii = {.clock_mode = EMAC_CLK_EXT_IN, .clock_gpio = (emac_rmii_clock_gpio_t)ETH_RMII_CLK}}, .dma_burst_len = ETH_DMA_BURST_LEN_32, \ + .intr_priority = 0, \ + .emac_dataif_gpio = \ + {.rmii = \ + {.tx_en_num = ETH_RMII_TX_EN, \ + .txd0_num = ETH_RMII_TX0, \ + .txd1_num = ETH_RMII_TX1, \ + .crs_dv_num = ETH_RMII_CRS_DV, \ + .rxd0_num = ETH_RMII_RX0, \ + .rxd1_num = ETH_RMII_RX1_EN}}, \ + .clock_config_out_in = {.rmii = {.clock_mode = EMAC_CLK_EXT_IN, .clock_gpio = (emac_rmii_clock_gpio_t) - 1}}, \ + } +#endif + bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, int power, eth_clock_mode_t clock_mode) { esp_err_t ret = ESP_OK; if (_eth_index > 2) { @@ -177,12 +197,16 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i #define DEFAULT_RMII_CLK_GPIO (emac_rmii_clock_gpio_t)(CONFIG_ETH_RMII_CLK_IN_GPIO) #endif - eth_esp32_emac_config_t mac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); + eth_esp32_emac_config_t mac_config = ETH_EMAC_DEFAULT_CONFIG(); +#if CONFIG_IDF_TARGET_ESP32 mac_config.clock_config.rmii.clock_mode = (clock_mode) ? EMAC_CLK_OUT : EMAC_CLK_EXT_IN; mac_config.clock_config.rmii.clock_gpio = (1 == clock_mode) ? EMAC_APPL_CLK_OUT_GPIO : (2 == clock_mode) ? EMAC_CLK_OUT_GPIO : (3 == clock_mode) ? EMAC_CLK_OUT_180_GPIO : EMAC_CLK_IN_GPIO; +#elif CONFIG_IDF_TARGET_ESP32P4 + mac_config.clock_config.rmii.clock_mode = (emac_rmii_clock_mode_t)clock_mode; +#endif mac_config.smi_gpio.mdc_num = digitalPinToGPIONumber(mdc); mac_config.smi_gpio.mdio_num = digitalPinToGPIONumber(mdio); diff --git a/libraries/Ethernet/src/ETH.h b/libraries/Ethernet/src/ETH.h index 14d2d042614..10d6b504c2a 100644 --- a/libraries/Ethernet/src/ETH.h +++ b/libraries/Ethernet/src/ETH.h @@ -75,6 +75,7 @@ #if CONFIG_ETH_USE_ESP32_EMAC #define ETH_PHY_IP101 ETH_PHY_TLK110 +#if CONFIG_IDF_TARGET_ESP32 typedef enum { ETH_CLOCK_GPIO0_IN, ETH_CLOCK_GPIO0_OUT, @@ -88,6 +89,31 @@ typedef enum { #define ETH_RMII_RX0 25 #define ETH_RMII_RX1_EN 26 #define ETH_RMII_CRS_DV 27 +#elif CONFIG_IDF_TARGET_ESP32P4 +typedef emac_rmii_clock_mode_t eth_clock_mode_t; +#include "pins_arduino.h" +#ifndef ETH_RMII_TX_EN +#define ETH_RMII_TX_EN 49 +#endif +#ifndef ETH_RMII_TX0 +#define ETH_RMII_TX0 34 +#endif +#ifndef ETH_RMII_TX1 +#define ETH_RMII_TX1 35 +#endif +#ifndef ETH_RMII_RX0 +#define ETH_RMII_RX0 29 +#endif +#ifndef ETH_RMII_RX1_EN +#define ETH_RMII_RX1_EN 30 +#endif +#ifndef ETH_RMII_CRS_DV +#define ETH_RMII_CRS_DV 28 +#endif +#ifndef ETH_RMII_CLK +#define ETH_RMII_CLK 50 +#endif +#endif #endif /* CONFIG_ETH_USE_ESP32_EMAC */ #ifndef ETH_PHY_SPI_FREQ_MHZ diff --git a/variants/esp32p4/pins_arduino.h b/variants/esp32p4/pins_arduino.h index f227de428ef..980e7bdb527 100644 --- a/variants/esp32p4/pins_arduino.h +++ b/variants/esp32p4/pins_arduino.h @@ -57,4 +57,18 @@ static const uint8_t T11 = 13; static const uint8_t T12 = 14; static const uint8_t T13 = 15; +#define ETH_PHY_TYPE ETH_PHY_TLK110 +#define ETH_PHY_ADDR 1 +#define ETH_PHY_MDC 31 +#define ETH_PHY_MDIO 52 +#define ETH_PHY_POWER 51 +#define ETH_RMII_TX_EN 49 +#define ETH_RMII_TX0 34 +#define ETH_RMII_TX1 35 +#define ETH_RMII_RX0 29 +#define ETH_RMII_RX1_EN 30 +#define ETH_RMII_CRS_DV 28 +#define ETH_RMII_CLK 50 +#define ETH_CLK_MODE EMAC_CLK_EXT_IN + #endif /* Pins_Arduino_h */ From ee8931d151665ffc6bb52e3edb9509a6d8e5c401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E4=B9=9D?= <153150268+Sail-211010@users.noreply.github.com> Date: Thu, 17 Oct 2024 19:31:46 +0800 Subject: [PATCH 056/409] Add the Waveshare ESP32-S3-Touch-LCD-1.85 board (#10477) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Delete boards.txt Delete old files * Add files via upload Add the Waveshare ESP32-S3-Touch-LCD-1.85 board * Add files via upload Add the Waveshare ESP32-S3-Touch-LCD-1.85 board * Update pins_arduino.h Modify the pin definition * Add files via upload Add the Waveshare ESP32-S3-Touch-LCD-1.85 board * Update pins_arduino.h Modify the pin definition * feat(board): Add waweshare s3 rouch lcd 185 * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: Jan Procházka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- boards.txt | 237 ++++++++++++++++++ .../pins_arduino.h | 64 +++++ 2 files changed, 301 insertions(+) create mode 100644 variants/waveshare_esp32_s3_touch_lcd_185/pins_arduino.h diff --git a/boards.txt b/boards.txt index d1813a7d22a..74d709ec1e1 100644 --- a/boards.txt +++ b/boards.txt @@ -43958,6 +43958,243 @@ waveshare_esp32_s3_touch_lcd_4.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +waveshare_esp32_s3_touch_lcd_185.name=Waveshare ESP32-S3-Touch-LCD-1.85 +waveshare_esp32_s3_touch_lcd_185.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_185.pid.0=0x8290 +waveshare_esp32_s3_touch_lcd_185.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_185.upload_port.0.pid=0x8290 + +waveshare_esp32_s3_touch_lcd_185.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_185.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_185.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_185.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_185.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_185.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_185.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_185.upload.flags= +waveshare_esp32_s3_touch_lcd_185.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_185.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_185.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_185.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_185.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_185.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_185.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_185.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_185.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_185.build.core=esp32 +waveshare_esp32_s3_touch_lcd_185.build.variant=waveshare_esp32_s3_touch_lcd_185 +waveshare_esp32_s3_touch_lcd_185.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_185 + +waveshare_esp32_s3_touch_lcd_185.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_185.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_185.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_185.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_185.build.flash_freq=120m +waveshare_esp32_s3_touch_lcd_185.build.flash_mode=qio +waveshare_esp32_s3_touch_lcd_185.build.boot=qio +waveshare_esp32_s3_touch_lcd_185.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185.build.partitions=default +waveshare_esp32_s3_touch_lcd_185.build.defines= +waveshare_esp32_s3_touch_lcd_185.build.loop_core= +waveshare_esp32_s3_touch_lcd_185.build.event_core= +waveshare_esp32_s3_touch_lcd_185.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_185.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_touch_lcd_185.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_185.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_185.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_185.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_185.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_185.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_185.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_185.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_185.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_185.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_185.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 +waveshare_esp32_s3_touch_lcd_185.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_185.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +waveshare_esp32_s3_touch_lcd_185.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_185.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_185.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_185.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_185.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_185.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_185.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_185.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_185.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_185.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_185.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_185.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_185.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_185.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_185.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_185.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_185.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_185.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_185.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_185.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_touch_lcd_185.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_touch_lcd_185.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_touch_lcd_185.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_touch_lcd_185.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_touch_lcd_185.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port + +############################################################## + cezerio_dev_esp32c6.name=cezerio dev ESP32C6 cezerio_dev_esp32c6.bootloader.tool=esptool_py diff --git a/variants/waveshare_esp32_s3_touch_lcd_185/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_185/pins_arduino.h new file mode 100644 index 00000000000..863590e321a --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_185/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8290 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-1.85" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 10; +static const uint8_t SDA = 11; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ From 9e48d9f2388a82d0b198f31c214b8becd0ecb204 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 17 Oct 2024 16:13:59 +0300 Subject: [PATCH 057/409] fix(spi): Fix P4 SPI Pin definitions Use GPIOs 36 or lower to avoid LDO power issues --- cores/esp32/esp32-hal-spi.c | 2 +- variants/esp32p4/pins_arduino.h | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cores/esp32/esp32-hal-spi.c b/cores/esp32/esp32-hal-spi.c index af3fd7b5f06..80928309670 100644 --- a/cores/esp32/esp32-hal-spi.c +++ b/cores/esp32/esp32-hal-spi.c @@ -65,7 +65,7 @@ #endif struct spi_struct_t { - spi_dev_t *dev; + volatile spi_dev_t *dev; #if !CONFIG_DISABLE_HAL_LOCKS SemaphoreHandle_t lock; #endif diff --git a/variants/esp32p4/pins_arduino.h b/variants/esp32p4/pins_arduino.h index 980e7bdb527..792146f5ca2 100644 --- a/variants/esp32p4/pins_arduino.h +++ b/variants/esp32p4/pins_arduino.h @@ -22,10 +22,11 @@ static const uint8_t RX = 38; static const uint8_t SDA = 7; static const uint8_t SCL = 8; -static const uint8_t SS = 27; -static const uint8_t MOSI = 46; -static const uint8_t MISO = 47; -static const uint8_t SCK = 48; +// Use GPIOs 36 or lower on the P4 DevKit to avoid LDO power issues with high numbered GPIOs. +static const uint8_t SS = 26; +static const uint8_t MOSI = 32; +static const uint8_t MISO = 33; +static const uint8_t SCK = 36; static const uint8_t A0 = 16; static const uint8_t A1 = 17; From 8570b3d270470c6ff6582aca75a1d9df95364828 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:21:08 -0300 Subject: [PATCH 058/409] Fix formatting in ETH and USB --- libraries/Ethernet/src/ETH.cpp | 44 +++++++++++++++++++++++----------- libraries/USB/src/USBHID.cpp | 4 +++- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 4ef184ac97a..e04174fd490 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -152,22 +152,38 @@ void ETHClass::setTaskStackSize(size_t size) { #if CONFIG_IDF_TARGET_ESP32 #define ETH_EMAC_DEFAULT_CONFIG() ETH_ESP32_EMAC_DEFAULT_CONFIG() #elif CONFIG_IDF_TARGET_ESP32P4 -#define ETH_EMAC_DEFAULT_CONFIG() \ - { \ - .smi_gpio = {.mdc_num = 31, .mdio_num = 52}, .interface = EMAC_DATA_INTERFACE_RMII, \ - .clock_config = {.rmii = {.clock_mode = EMAC_CLK_EXT_IN, .clock_gpio = (emac_rmii_clock_gpio_t)ETH_RMII_CLK}}, .dma_burst_len = ETH_DMA_BURST_LEN_32, \ - .intr_priority = 0, \ - .emac_dataif_gpio = \ - {.rmii = \ - {.tx_en_num = ETH_RMII_TX_EN, \ - .txd0_num = ETH_RMII_TX0, \ - .txd1_num = ETH_RMII_TX1, \ - .crs_dv_num = ETH_RMII_CRS_DV, \ - .rxd0_num = ETH_RMII_RX0, \ - .rxd1_num = ETH_RMII_RX1_EN}}, \ - .clock_config_out_in = {.rmii = {.clock_mode = EMAC_CLK_EXT_IN, .clock_gpio = (emac_rmii_clock_gpio_t) - 1}}, \ +// clang-format off +#define ETH_EMAC_DEFAULT_CONFIG() \ + { \ + .smi_gpio = {.mdc_num = 31, .mdio_num = 52}, \ + .interface = EMAC_DATA_INTERFACE_RMII, \ + .clock_config = { \ + .rmii = { \ + .clock_mode = EMAC_CLK_EXT_IN, \ + .clock_gpio = (emac_rmii_clock_gpio_t)ETH_RMII_CLK \ + } \ + }, \ + .dma_burst_len = ETH_DMA_BURST_LEN_32, \ + .intr_priority = 0, \ + .emac_dataif_gpio = { \ + .rmii = { \ + .tx_en_num = ETH_RMII_TX_EN, \ + .txd0_num = ETH_RMII_TX0, \ + .txd1_num = ETH_RMII_TX1, \ + .crs_dv_num = ETH_RMII_CRS_DV, \ + .rxd0_num = ETH_RMII_RX0, \ + .rxd1_num = ETH_RMII_RX1_EN \ + } \ + }, \ + .clock_config_out_in = { \ + .rmii = { \ + .clock_mode = EMAC_CLK_EXT_IN, \ + .clock_gpio = (emac_rmii_clock_gpio_t) - 1 \ + } \ + }, \ } #endif +// clang-format on bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, int power, eth_clock_mode_t clock_mode) { esp_err_t ret = ESP_OK; diff --git a/libraries/USB/src/USBHID.cpp b/libraries/USB/src/USBHID.cpp index 4bc555b8e30..1d5d86fb3a3 100644 --- a/libraries/USB/src/USBHID.cpp +++ b/libraries/USB/src/USBHID.cpp @@ -206,7 +206,9 @@ extern "C" uint16_t tusb_hid_load_descriptor(uint8_t *dst, uint8_t *itf) { uint8_t descriptor[TUD_HID_INOUT_DESC_LEN] = { // HID Input & Output descriptor // Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval - TUD_HID_INOUT_DESCRIPTOR(*itf, str_index, tinyusb_interface_protocol, tinyusb_hid_device_descriptor_len, ep_out, (uint8_t)(0x80 | ep_in), CFG_TUD_ENDOINT_SIZE, 1) + TUD_HID_INOUT_DESCRIPTOR( + *itf, str_index, tinyusb_interface_protocol, tinyusb_hid_device_descriptor_len, ep_out, (uint8_t)(0x80 | ep_in), CFG_TUD_ENDOINT_SIZE, 1 + ) }; *itf += 1; memcpy(dst, descriptor, TUD_HID_INOUT_DESC_LEN); From edb4ee13d24688d50d2dd6b3979dac6d981f0d53 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Thu, 17 Oct 2024 19:46:14 +0300 Subject: [PATCH 059/409] IDF release/v5.3 707d097b (#10480) --- package/package_esp32_index.template.json | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 89ec0cebf8e..dc32ddae953 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -101,57 +101,57 @@ "host": "i686-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", - "size": "343593768" + "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", + "size": "343601720" }, { "host": "x86_64-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", - "size": "343593768" + "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", + "size": "343601720" }, { "host": "arm64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", - "size": "343593768" + "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", + "size": "343601720" }, { "host": "x86_64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", - "size": "343593768" + "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", + "size": "343601720" }, { "host": "x86_64-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", - "size": "343593768" + "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", + "size": "343601720" }, { "host": "i686-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", - "size": "343593768" + "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", + "size": "343601720" }, { "host": "aarch64-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", - "size": "343593768" + "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", + "size": "343601720" }, { "host": "arm-linux-gnueabihf", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:c75625cbb80f0f9ea437840c7ee00d937e4443af6903b6903bfe98928e36618e", - "size": "343593768" + "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", + "size": "343601720" } ] }, From 064d1c4d972f82c936ce05db22b69ecfc928fcab Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Fri, 18 Oct 2024 14:29:14 -0300 Subject: [PATCH 060/409] fix(build): Fix sdkconfig copy for Arduino CLI (#10484) --- platform.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.txt b/platform.txt index a1574e2f776..d1c3fb3a3dd 100644 --- a/platform.txt +++ b/platform.txt @@ -144,8 +144,8 @@ recipe.hooks.core.prebuild.1.pattern.windows=cmd /c echo "-DARDUINO_CORE_BUILD" recipe.hooks.core.postbuild.1.pattern.windows=cmd /c type nul > "{file_opts.path}" # Copy sdkconfig to build folder -recipe.hooks.prebuild.8.pattern=/usr/bin/env bash -c "cp -f "{runtime.platform.path}"/tools/esp32-arduino-libs/{build.mcu}/sdkconfig "{build.path}"/sdkconfig" -recipe.hooks.prebuild.8.pattern.windows=cmd /c COPY /y "{runtime.platform.path}\tools\esp32-arduino-libs\{build.mcu}\sdkconfig" "{build.path}\sdkconfig" +recipe.hooks.prebuild.8.pattern=/usr/bin/env bash -c "cp -f "{compiler.sdk.path}"/sdkconfig "{build.path}"/sdkconfig" +recipe.hooks.prebuild.8.pattern.windows=cmd /c COPY /y "{compiler.sdk.path}\sdkconfig" "{build.path}\sdkconfig" ## Compile c files recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.extra_flags} {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" -DARDUINO_VARIANT="{build.variant}" -DARDUINO_PARTITION_{build.partitions} {build.extra_flags} {compiler.cpreprocessor.flags} {includes} "@{build.opt.path}" "@{file_opts.path}" "{source_file}" -o "{object_file}" From 4ca635a3b6234a5dca5dfc3f44647235666b431d Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Sat, 19 Oct 2024 06:00:48 -0300 Subject: [PATCH 061/409] ci(json): Add requires_any field and use QIO by default to match IDE (#10472) * ci(FQBN): Use QIO as default as DIO can be used on demand now * fix(indentation): Fix default indentation for bash files * fix(compilation): Make errors appear on CI fail * ci(json): Add requires_any field to JSON and fix comparison --- .editorconfig | 2 +- .github/scripts/install-platformio-esp32.sh | 42 +++++++++-- .github/scripts/sketch_utils.sh | 79 ++++++++++++++++----- .github/scripts/tests_run.sh | 23 +++++- docs/en/contributing.rst | 16 +++-- 5 files changed, 130 insertions(+), 32 deletions(-) diff --git a/.editorconfig b/.editorconfig index eda8544321b..e22936cb1fe 100644 --- a/.editorconfig +++ b/.editorconfig @@ -18,7 +18,7 @@ indent_size = 2 indent_style = space [*.{bash,sh}] -indent_size = 2 +indent_size = 4 indent_style = space [*.{c,cc,cp,cpp,cxx,h,hh,hpp,hxx,ii,inl,ino,ixx,pde,tpl,tpp,txx}] diff --git a/.github/scripts/install-platformio-esp32.sh b/.github/scripts/install-platformio-esp32.sh index a9aab496e19..5091ea69353 100755 --- a/.github/scripts/install-platformio-esp32.sh +++ b/.github/scripts/install-platformio-esp32.sh @@ -96,9 +96,9 @@ function count_sketches(){ # count_sketches continue fi - # Check if the sketch requires any configuration options + # Check if the sketch requires any configuration options (AND) requirements=$(jq -r '.requires[]? // empty' $sketchdir/ci.json) - if [[ "$requirements" != "null" ]] || [[ "$requirements" != "" ]]; then + if [[ "$requirements" != "null" && "$requirements" != "" ]]; then for requirement in $requirements; do requirement=$(echo $requirement | xargs) found_line=$(grep -E "^$requirement" "$SDKCONFIG_DIR/esp32/sdkconfig") @@ -107,6 +107,23 @@ function count_sketches(){ # count_sketches fi done fi + + # Check if the sketch requires any configuration options (OR) + requirements_or=$(jq -r '.requires_any[]? // empty' $sketchdir/ci.json) + if [[ "$requirements_or" != "null" && "$requirements_or" != "" ]]; then + found=false + for requirement in $requirements_or; do + requirement=$(echo $requirement | xargs) + found_line=$(grep -E "^$requirement" "$SDKCONFIG_DIR/esp32/sdkconfig") + if [[ "$found_line" != "" ]]; then + found=true + break + fi + done + if [[ "$found" == "false" ]]; then + continue + fi + fi fi echo $sketch >> sketches.txt @@ -187,9 +204,9 @@ function build_pio_sketches(){ # build_pio_sketches [ex # Default FQBN options if none were passed in the command line. - esp32_opts="PSRAM=enabled,FlashMode=dio${fqbn_append:+,$fqbn_append}" - esp32s2_opts="PSRAM=enabled,FlashMode=dio${fqbn_append:+,$fqbn_append}" - esp32s3_opts="PSRAM=opi,USBMode=default,FlashMode=dio${fqbn_append:+,$fqbn_append}" - esp32c3_opts="FlashMode=dio${fqbn_append:+,$fqbn_append}" - esp32c6_opts="FlashMode=dio${fqbn_append:+,$fqbn_append}" - esp32h2_opts="FlashMode=dio${fqbn_append:+,$fqbn_append}" + esp32_opts="PSRAM=enabled${fqbn_append:+,$fqbn_append}" + esp32s2_opts="PSRAM=enabled${fqbn_append:+,$fqbn_append}" + esp32s3_opts="PSRAM=opi,USBMode=default${fqbn_append:+,$fqbn_append}" + esp32c3_opts="$fqbn_append" + esp32c6_opts="$fqbn_append" + esp32h2_opts="$fqbn_append" # Select the common part of the FQBN based on the target. The rest will be # appended depending on the passed options. + opt="" + case "$target" in "esp32") - fqbn="espressif:esp32:esp32:${options:-$esp32_opts}" + [ -n "${options:-$esp32_opts}" ] && opt=":${options:-$esp32_opts}" + fqbn="espressif:esp32:esp32$opt" ;; "esp32s2") - fqbn="espressif:esp32:esp32s2:${options:-$esp32s2_opts}" + [ -n "${options:-$esp32s2_opts}" ] && opt=":${options:-$esp32s2_opts}" + fqbn="espressif:esp32:esp32s2$opt" ;; "esp32c3") - fqbn="espressif:esp32:esp32c3:${options:-$esp32c3_opts}" + [ -n "${options:-$esp32c3_opts}" ] && opt=":${options:-$esp32c3_opts}" + fqbn="espressif:esp32:esp32c3$opt" ;; "esp32s3") - fqbn="espressif:esp32:esp32s3:${options:-$esp32s3_opts}" + [ -n "${options:-$esp32s3_opts}" ] && opt=":${options:-$esp32s3_opts}" + fqbn="espressif:esp32:esp32s3$opt" ;; "esp32c6") - fqbn="espressif:esp32:esp32c6:${options:-$esp32c6_opts}" + [ -n "${options:-$esp32c6_opts}" ] && opt=":${options:-$esp32c6_opts}" + fqbn="espressif:esp32:esp32c6$opt" ;; "esp32h2") - fqbn="espressif:esp32:esp32h2:${options:-$esp32h2_opts}" + [ -n "${options:-$esp32h2_opts}" ] && opt=":${options:-$esp32h2_opts}" + fqbn="espressif:esp32:esp32h2$opt" ;; esac @@ -163,9 +171,9 @@ function build_sketch(){ # build_sketch [ex exit 0 fi - # Check if the sketch requires any configuration options + # Check if the sketch requires any configuration options (AND) requirements=$(jq -r '.requires[]? // empty' $sketchdir/ci.json) - if [[ "$requirements" != "null" ]] || [[ "$requirements" != "" ]]; then + if [[ "$requirements" != "null" && "$requirements" != "" ]]; then for requirement in $requirements; do requirement=$(echo $requirement | xargs) found_line=$(grep -E "^$requirement" "$SDKCONFIG_DIR/$target/sdkconfig") @@ -175,6 +183,24 @@ function build_sketch(){ # build_sketch [ex fi done fi + + # Check if the sketch excludes any configuration options (OR) + requirements_or=$(jq -r '.requires_any[]? // empty' $sketchdir/ci.json) + if [[ "$requirements_or" != "null" && "$requirements_or" != "" ]]; then + found=false + for requirement in $requirements_or; do + requirement=$(echo $requirement | xargs) + found_line=$(grep -E "^$requirement" "$SDKCONFIG_DIR/$target/sdkconfig") + if [[ "$found_line" != "" ]]; then + found=true + break + fi + done + if [[ "$found" == "false" ]]; then + echo "Target $target meets none of the requirements in requires_any for $sketchname. Skipping." + exit 0 + fi + fi fi ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp" @@ -213,9 +239,9 @@ function build_sketch(){ # build_sketch [ex --build-cache-path "$ARDUINO_CACHE_DIR" \ --build-path "$build_dir" \ $xtra_opts "${sketchdir}" \ - > $output_file + 2>&1 | tee $output_file - exit_status=$? + exit_status=${PIPESTATUS[0]} if [ $exit_status -ne 0 ]; then echo "ERROR: Compilation failed with error code $exit_status" exit $exit_status @@ -322,9 +348,9 @@ function count_sketches(){ # count_sketches [target] [file] [ignore-requi fi if [ "$ignore_requirements" != "1" ]; then - # Check if the sketch requires any configuration options + # Check if the sketch requires any configuration options (AND) requirements=$(jq -r '.requires[]? // empty' $sketchdir/ci.json) - if [[ "$requirements" != "null" ]] || [[ "$requirements" != "" ]]; then + if [[ "$requirements" != "null" && "$requirements" != "" ]]; then for requirement in $requirements; do requirement=$(echo $requirement | xargs) found_line=$(grep -E "^$requirement" $SDKCONFIG_DIR/$target/sdkconfig) @@ -333,6 +359,23 @@ function count_sketches(){ # count_sketches [target] [file] [ignore-requi fi done fi + + # Check if the sketch excludes any configuration options (OR) + requirements_or=$(jq -r '.requires_any[]? // empty' $sketchdir/ci.json) + if [[ "$requirements_or" != "null" && "$requirements_or" != "" ]]; then + found=false + for requirement in $requirements_or; do + requirement=$(echo $requirement | xargs) + found_line=$(grep -E "^$requirement" $SDKCONFIG_DIR/$target/sdkconfig) + if [[ "$found_line" != "" ]]; then + found=true + break + fi + done + if [[ "$found" == "false" ]]; then + continue 2 + fi + fi fi fi echo $sketch >> sketches.txt diff --git a/.github/scripts/tests_run.sh b/.github/scripts/tests_run.sh index 63ab2ca6dad..f4a9b9d6dd4 100755 --- a/.github/scripts/tests_run.sh +++ b/.github/scripts/tests_run.sh @@ -36,9 +36,9 @@ function run_test() { return 0 fi - # Check if the sketch requires any configuration options + # Check if the sketch requires any configuration options (AND) requirements=$(jq -r '.requires[]? // empty' $sketchdir/ci.json) - if [[ "$requirements" != "null" ]] || [[ "$requirements" != "" ]]; then + if [[ "$requirements" != "null" && "$requirements" != "" ]]; then for requirement in $requirements; do requirement=$(echo $requirement | xargs) found_line=$(grep -E "^$requirement" "$SDKCONFIG_PATH") @@ -49,6 +49,25 @@ function run_test() { fi done fi + + # Check if the sketch requires any configuration options (OR) + requirements_or=$(jq -r '.requires_any[]? // empty' $sketchdir/ci.json) + if [[ "$requirements_or" != "null" && "$requirements_or" != "" ]]; then + found=false + for requirement in $requirements_or; do + requirement=$(echo $requirement | xargs) + found_line=$(grep -E "^$requirement" "$SDKCONFIG_PATH") + if [[ "$found_line" != "" ]]; then + found=true + break + fi + done + if [[ "$found" == "false" ]]; then + printf "\033[93mTarget $target meets none of the requirements in requires_any for $sketchname. Skipping.\033[0m\n" + printf "\n\n\n" + return 0 + fi + fi fi if [ $len -eq 1 ]; then diff --git a/docs/en/contributing.rst b/docs/en/contributing.rst index f4ed6c34761..bc3e2e89674 100644 --- a/docs/en/contributing.rst +++ b/docs/en/contributing.rst @@ -172,12 +172,12 @@ And in the ``README.md`` file: By default, the CI system will use the FQBNs specified in the ``.github/scripts/sketch_utils.sh`` file to compile the sketches. Currently, the default FQBNs are: -* ``espressif:esp32:esp32:PSRAM=enabled,FlashMode=dio`` -* ``espressif:esp32:esp32s2:PSRAM=enabled,FlashMode=dio`` -* ``espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,FlashMode=dio`` -* ``espressif:esp32:esp32c3:FlashMode=dio`` -* ``espressif:esp32:esp32c6:FlashMode=dio`` -* ``espressif:esp32:esp32h2:FlashMode=dio`` +* ``espressif:esp32:esp32:PSRAM=enabled`` +* ``espressif:esp32:esp32s2:PSRAM=enabled`` +* ``espressif:esp32:esp32s3:PSRAM=opi,USBMode=default`` +* ``espressif:esp32:esp32c3`` +* ``espressif:esp32:esp32c6`` +* ``espressif:esp32:esp32h2`` There are two ways to alter the FQBNs used to compile the sketches: by using the ``fqbn`` or ``fqbn_append`` fields in the ``ci.json`` file. @@ -408,7 +408,9 @@ CI JSON File The ``ci.json`` file is used to specify how the test suite and sketches will handled by the CI system. It can contain the following fields: * ``requires``: A list of configurations in ``sdkconfig`` that are required to run the test suite. The test suite will only run on the targets - that have the required configurations. By default, no configurations are required. + that have **ALL** the required configurations. By default, no configurations are required. +* ``requires_any``: A list of configurations in ``sdkconfig`` that are required to run the test suite. The test suite will only run on the targets + that have **ANY** of the required configurations. By default, no configurations are required. * ``targets``: A dictionary that specifies the targets for which the tests will be run. The key is the target name and the value is a boolean that specifies if the test should be run for that target. By default, all targets are enabled as long as they have the required configurations specified in the ``requires`` field. This field is also valid for examples. From a7d9b670a8655778c08d745c061e6a6f9f223061 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Mon, 21 Oct 2024 11:56:01 +0300 Subject: [PATCH 062/409] Add missing versions to ISSUE_REPORT Versions 3.0.5 and 3.0.6 were added --- .github/ISSUE_TEMPLATE/Issue-report.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/Issue-report.yml b/.github/ISSUE_TEMPLATE/Issue-report.yml index 17a3f7f2612..d5b756085c7 100644 --- a/.github/ISSUE_TEMPLATE/Issue-report.yml +++ b/.github/ISSUE_TEMPLATE/Issue-report.yml @@ -41,6 +41,8 @@ body: options: - latest master (checkout manually) - latest development Release Candidate (RC-X) + - v3.0.6 + - v3.0.5 - v3.0.4 - v3.0.3 - v3.0.2 From 7cfe470d8d36e2ca45783f0e9b5a80bd3268e5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Mon, 21 Oct 2024 12:29:01 +0200 Subject: [PATCH 063/409] feat(touch): Support NG touch driver for P4 (#10448) * feat(touch): Support NG touch driver for P4 * fix(ci): Touch test + IDF compilation fixes * fix(ci): remove debug prints from touch test * fix(ci): Fix touch test for esp32 * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- CMakeLists.txt | 5 + cores/esp32/esp32-hal-touch-ng.c | 453 ++++++++++++++++++ cores/esp32/esp32-hal-touch-ng.h | 91 ++++ cores/esp32/esp32-hal-touch.c | 27 +- cores/esp32/esp32-hal-touch.h | 4 +- cores/esp32/esp32-hal.h | 1 + cores/esp32/io_pin_remap.h | 2 +- .../DeepSleep/TouchWakeUp/TouchWakeUp.ino | 8 +- .../examples/DeepSleep/TouchWakeUp/ci.json | 3 +- .../Touch/TouchInterrupt/TouchInterrupt.ino | 5 + .../examples/Touch/TouchInterrupt/ci.json | 5 +- .../ESP32/examples/Touch/TouchRead/ci.json | 5 +- tests/validation/touch/ci.json | 5 +- tests/validation/touch/touch.ino | 75 ++- 14 files changed, 643 insertions(+), 46 deletions(-) create mode 100644 cores/esp32/esp32-hal-touch-ng.c create mode 100644 cores/esp32/esp32-hal-touch-ng.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a06f815c9d8..6688a97803d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ set(CORE_SRCS cores/esp32/esp32-hal-timer.c cores/esp32/esp32-hal-tinyusb.c cores/esp32/esp32-hal-touch.c + cores/esp32/esp32-hal-touch-ng.c cores/esp32/esp32-hal-uart.c cores/esp32/esp32-hal-rmt.c cores/esp32/Esp.cpp @@ -317,6 +318,10 @@ if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_OpenThre endif() endif() +if(IDF_TARGET STREQUAL "esp32p4") + list(APPEND requires esp_driver_touch_sens) +endif() + idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires}) if(NOT CONFIG_FREERTOS_HZ EQUAL 1000 AND NOT "$ENV{ARDUINO_SKIP_TICK_CHECK}") diff --git a/cores/esp32/esp32-hal-touch-ng.c b/cores/esp32/esp32-hal-touch-ng.c new file mode 100644 index 00000000000..888a299ec0c --- /dev/null +++ b/cores/esp32/esp32-hal-touch-ng.c @@ -0,0 +1,453 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "soc/soc_caps.h" + +#if SOC_TOUCH_SENSOR_SUPPORTED +#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 for now + +#include "driver/touch_sens.h" +#include "esp32-hal-touch-ng.h" +#include "esp32-hal-periman.h" + +/* + Internal Private Touch Data Structure and Functions +*/ + +typedef void (*voidFuncPtr)(void); +typedef void (*voidArgFuncPtr)(void *); + +typedef struct { + voidFuncPtr fn; + bool callWithArgs; + void *arg; + bool lastStatusIsPressed; +} TouchInterruptHandle_t; + +static TouchInterruptHandle_t __touchInterruptHandlers[SOC_TOUCH_SENSOR_NUM] = { + 0, +}; + +static uint8_t _sample_num = 1; +static uint32_t _div_num = 1; +static uint8_t _coarse_freq_tune = 1; +static uint8_t _fine_freq_tune = 1; +static uint8_t used_pads = 0; + +static uint32_t __touchSleepTime = 256; +static float __touchMeasureTime = 32.0f; + +static touch_sensor_config_t sensor_config; + +static bool initialized = false; +static bool enabled = false; +static bool running = false; +static bool channels_initialized[SOC_TOUCH_SENSOR_NUM] = {false}; + +static touch_sensor_handle_t touch_sensor_handle = NULL; +static touch_channel_handle_t touch_channel_handle[SOC_TOUCH_SENSOR_NUM] = {}; + +// Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio)) +static float s_thresh2bm_ratio = 0.015f; // 1.5% for all channels + +static bool ARDUINO_ISR_ATTR __touchOnActiveISR(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx) { + uint8_t pad_num = (uint8_t)event->chan_id; + __touchInterruptHandlers[pad_num].lastStatusIsPressed = true; + if (__touchInterruptHandlers[pad_num].fn) { + // keeping backward compatibility with "void cb(void)" and with new "void cb(void *)" + if (__touchInterruptHandlers[pad_num].callWithArgs) { + ((voidArgFuncPtr)__touchInterruptHandlers[pad_num].fn)(__touchInterruptHandlers[pad_num].arg); + } else { + __touchInterruptHandlers[pad_num].fn(); + } + } + return false; +} + +static bool ARDUINO_ISR_ATTR __touchOnInactiveISR(touch_sensor_handle_t sens_handle, const touch_inactive_event_data_t *event, void *user_ctx) { + uint8_t pad_num = (uint8_t)event->chan_id; + __touchInterruptHandlers[pad_num].lastStatusIsPressed = false; + if (__touchInterruptHandlers[pad_num].fn) { + // keeping backward compatibility with "void cb(void)" and with new "void cb(void *)" + if (__touchInterruptHandlers[pad_num].callWithArgs) { + ((voidArgFuncPtr)__touchInterruptHandlers[pad_num].fn)(__touchInterruptHandlers[pad_num].arg); + } else { + __touchInterruptHandlers[pad_num].fn(); + } + } + return false; +} + +bool touchStop() { + if (!running) { // Already stopped + return true; + } + if (touch_sensor_stop_continuous_scanning(touch_sensor_handle) != ESP_OK) { + log_e("Touch sensor stop scanning failed!"); + return false; + } + running = false; + return true; +} + +bool touchDisable() { + if (!enabled) { // Already disabled + return true; + } + if (!running && (touch_sensor_disable(touch_sensor_handle) != ESP_OK)) { + log_e("Touch sensor still running or disable failed!"); + return false; + } + enabled = false; + return true; +} + +bool touchStart() { + if (running) { // Already running + return true; + } + if (enabled && (touch_sensor_start_continuous_scanning(touch_sensor_handle) != ESP_OK)) { + log_e("Touch sensor not enabled or failed to start continuous scanning failed!"); + return false; + } + running = true; + return true; +} + +bool touchEnable() { + if (enabled) { // Already enabled + return true; + } + if (touch_sensor_enable(touch_sensor_handle) != ESP_OK) { + log_e("Touch sensor enable failed!"); + return false; + } + enabled = true; + return true; +} + +bool touchBenchmarkThreshold(uint8_t pad) { + if (!touchEnable()) { + return false; + } + + /* Scan the enabled touch channels for several times, to make sure the initial channel data is stable */ + for (int i = 0; i < 3; i++) { + if (touch_sensor_trigger_oneshot_scanning(touch_sensor_handle, 2000) != ESP_OK) { + log_e("Touch sensor trigger oneshot scanning failed!"); + return false; + } + } + + /* Disable the touch channel to rollback the state */ + if (!touchDisable()) { + return false; + } + + // Reconfigure passed pad with new threshold + uint32_t benchmark[_sample_num] = {}; + 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; + } + /* Calculate the proper active thresholds regarding the initial benchmark */ + touch_channel_config_t chan_cfg = {}; + for (int i = 0; i < _sample_num; i++) { + 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]); + } + /* Update the channel configuration */ + if (touch_sensor_reconfig_channel(touch_channel_handle[pad], &chan_cfg) != ESP_OK) { + log_e("Touch sensor threshold reconfig channel failed!"); + return false; + } + return true; +} + +static bool touchDetachBus(void *pin) { + int8_t pad = digitalPinToTouchChannel((int)(pin - 1)); + channels_initialized[pad] = false; + //disable touch pad and delete the channel + 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; + } + return true; +} + +static void __touchInit() { + if (initialized) { + return; + } + // Support only one sample configuration for now + touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG(_div_num, _coarse_freq_tune, _fine_freq_tune); + 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 = { + .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, + }; + + // 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; + } + + sensor_config = sens_cfg; + /* Configure the touch sensor filter */ + touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG(); + if (touch_sensor_config_filter(touch_sensor_handle, &filter_cfg) != ESP_OK) { + goto err; + } + + /* 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, + }; + if (touch_sensor_register_callbacks(touch_sensor_handle, &callbacks, NULL) != ESP_OK) { + goto err; + } + + initialized = true; + return; +err: + log_e(" Touch sensor initialization error."); + initialized = false; + return; +} + +static void __touchChannelInit(int pad) { + if (channels_initialized[pad]) { + return; + } + + // 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 + }; + + if (!touchStop() || !touchDisable()) { + log_e("Touch sensor stop and disable failed!"); + return; + } + + if (touch_sensor_new_channel(touch_sensor_handle, pad, &chan_cfg, &touch_channel_handle[pad]) != ESP_OK) { + log_e("Touch sensor new channel failed!"); + return; + } + + // Benchmark active threshold and reconfigure pad + if (!touchBenchmarkThreshold(pad)) { + log_e("Touch sensor benchmark threshold failed!"); + return; + } + + channels_initialized[pad] = true; + used_pads++; + + if (!touchEnable() || !touchStart()) { + log_e("Touch sensor enable and start failed!"); + } +} + +static touch_value_t __touchRead(uint8_t pin) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + log_e(" No touch pad on selected pin!"); + return 0; + } + + if (perimanGetPinBus(pin, ESP32_BUS_TYPE_TOUCH) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_TOUCH, touchDetachBus); + if (!perimanClearPinBus(pin)) { + return 0; + } + __touchInit(); + __touchChannelInit(pad); + + if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_TOUCH, (void *)(pin + 1), -1, pad)) { + touchDetachBus((void *)(pin + 1)); + return 0; + } + } + + uint32_t touch_read[_sample_num] = {}; + touch_channel_read_data(touch_channel_handle[pad], TOUCH_CHAN_DATA_TYPE_SMOOTH, touch_read); + touch_value_t touch_value = touch_read[0]; // only one sample configuration for now + + return touch_value; +} + +static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Args, bool callWithArgs, touch_value_t threshold) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + log_e(" No touch pad on selected pin!"); + return; + } + + if (userFunc == NULL) { + // detach ISR User Call + __touchInterruptHandlers[pad].fn = NULL; + __touchInterruptHandlers[pad].callWithArgs = false; + __touchInterruptHandlers[pad].arg = NULL; + } else { + // attach ISR User Call + __touchInit(); + __touchChannelInit(pad); + __touchInterruptHandlers[pad].fn = userFunc; + __touchInterruptHandlers[pad].callWithArgs = callWithArgs; + __touchInterruptHandlers[pad].arg = Args; + } + + if (threshold != 0) { + if (!touchStop() || !touchDisable()) { + log_e("Touch sensor stop and disable failed!"); + return; + } + + touch_channel_config_t chan_cfg = {}; + for (int i = 0; i < _sample_num; i++) { + chan_cfg.active_thresh[i] = threshold; + } + + if (touch_sensor_reconfig_channel(touch_channel_handle[pad], &chan_cfg) != ESP_OK) { + log_e("Touch sensor threshold reconfig channel failed!"); + } + + if (!touchEnable() || !touchStart()) { + log_e("Touch sensor enable and start failed!"); + } + } +} + +// it keeps backwards compatibility +static void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), touch_value_t threshold) { + __touchConfigInterrupt(pin, userFunc, NULL, threshold, false); +} + +// 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); +} + +// new additional API to detach touch ISR +static void __touchDettachInterrupt(uint8_t pin) { + __touchConfigInterrupt(pin, NULL, NULL, 0, false); // userFunc as NULL acts as detaching +} + +// /* +// External Public Touch API Functions +// */ + +bool touchInterruptGetLastStatus(uint8_t pin) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + return false; + } + + return __touchInterruptHandlers[pad].lastStatusIsPressed; +} + +void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + log_e(" No touch pad on selected pin!"); + return; + } + + if (perimanGetPinBus(pin, ESP32_BUS_TYPE_TOUCH) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_TOUCH, touchDetachBus); + __touchInit(); + __touchChannelInit(pad); + if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_TOUCH, (void *)(pin + 1), -1, pad)) { + log_e("Failed to set bus to Peripheral manager"); + touchDetachBus((void *)(pin + 1)); + return; + } + } + + log_v("Touch sensor deep sleep wake-up configuration for pad %d with threshold %d", pad, threshold); + if (!touchStop() || !touchDisable()) { + log_e("Touch sensor stop and disable failed!"); + return; + } + + touch_sleep_config_t deep_slp_cfg = { + .slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP, + .deep_slp_chan = touch_channel_handle[pad], + .deep_slp_thresh = {threshold}, + .deep_slp_sens_cfg = NULL, // Use the original touch sensor configuration + }; + + // Register the deep sleep wake-up + if (touch_sensor_config_sleep_wakeup(touch_sensor_handle, &deep_slp_cfg) != ESP_OK) { + log_e("Touch sensor deep sleep wake-up failed!"); + return; + } + + if (!touchEnable() || !touchStart()) { + log_e("Touch sensor enable and start failed!"); + } +} + +void touchSetDefaultThreshold(float percentage) { + s_thresh2bm_ratio = (float)percentage / 100.0f; +} + +void touchSetTiming(float measure, uint32_t sleep) { + if (initialized) { + log_e("Touch sensor already initialized. Cannot set cycles."); + return; + } + __touchSleepTime = sleep; + __touchMeasureTime = measure; +} + +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."); + return; + } + _div_num = div_num; + _coarse_freq_tune = coarse_freq_tune; + _fine_freq_tune = fine_freq_tune; +} + +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 /* SOC_TOUCH_SENSOR_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-touch-ng.h b/cores/esp32/esp32-hal-touch-ng.h new file mode 100644 index 00000000000..0d4eb79ac58 --- /dev/null +++ b/cores/esp32/esp32-hal-touch-ng.h @@ -0,0 +1,91 @@ +/* + Arduino.h - Main include file for the Arduino SDK + Copyright (c) 2005-2013 Arduino Team. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAIN_ESP32_HAL_TOUCH_NEW_H_ +#define MAIN_ESP32_HAL_TOUCH_NEW_H_ + +#include "soc/soc_caps.h" +#if SOC_TOUCH_SENSOR_SUPPORTED +#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp32-hal.h" + +typedef uint32_t touch_value_t; + +/* + * Set time in us that measurement operation takes + * The result from touchRead, threshold and detection + * accuracy depend on these values. + * Note: must be called before setting up touch pads + **/ +void touchSetTiming(float measure, uint32_t sleep); + +/* + * 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); + +/* + * Read touch pad value. + * You can use this method to chose a good threshold value + * to use as value for touchAttachInterrupt. + * */ +touch_value_t touchRead(uint8_t pin); + +/* + * Set function to be called if touch pad value rises by given increment (threshold). + * Use touchRead to determine a proper threshold between touched and untouched state. + * */ +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); + +/* + * 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. + **/ +bool touchInterruptGetLastStatus(uint8_t pin); + +/* + * Set the default threshold for touch pads. + * The threshold is a percentage of the benchmark value. + * The default value is 1.5%. + **/ +void touchSetDefaultThreshold(float percentage); + +/* + * Setup touch pad wake up from deep sleep /light sleep with given threshold. + * When light sleep is used, all used touch pads will be able to wake up the chip. + **/ +void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold); + +#ifdef __cplusplus +} +#endif + +#endif /* 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 93e0cb1c4ac..701bf6d16c9 100644 --- a/cores/esp32/esp32-hal-touch.c +++ b/cores/esp32/esp32-hal-touch.c @@ -14,10 +14,8 @@ #include "soc/soc_caps.h" #if SOC_TOUCH_SENSOR_SUPPORTED -#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 -// ToDo: Implement touch sensor for ESP32P4 -#warning "Touch sensor not implemented for ESP32P4 yet" -#else +#if SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3 + #include "driver/touch_sensor.h" #include "esp32-hal-touch.h" #include "esp32-hal-periman.h" @@ -26,10 +24,10 @@ Internal Private Touch Data Structure and Functions */ -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 static uint16_t __touchSleepCycles = 0x1000; static uint16_t __touchMeasureCycles = 0x1000; -#elif SOC_TOUCH_SENSOR_VERSION >= 2 // ESP32S2, ESP32S3, ESP32P4 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 static uint16_t __touchSleepCycles = TOUCH_PAD_SLEEP_CYCLE_DEFAULT; static uint16_t __touchMeasureCycles = TOUCH_PAD_MEASURE_CYCLE_DEFAULT; #endif @@ -55,7 +53,7 @@ static bool initialized = false; static bool channels_initialized[SOC_TOUCH_SENSOR_NUM] = {false}; static void ARDUINO_ISR_ATTR __touchISR(void *arg) { -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 uint32_t pad_intr = touch_pad_get_status(); //clear interrupt touch_pad_clear_status(); @@ -97,7 +95,7 @@ static void ARDUINO_ISR_ATTR __touchISR(void *arg) { static void __touchSetCycles(uint16_t measure, uint16_t sleep) { __touchSleepCycles = sleep; __touchMeasureCycles = measure; -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 touch_pad_set_measurement_clock_cycles(measure); #elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 touch_pad_set_charge_discharge_times(measure); @@ -127,7 +125,7 @@ static void __touchInit() { esp_err_t err = ESP_OK; -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 err = touch_pad_init(); if (err != ESP_OK) { goto err; @@ -147,7 +145,7 @@ static void __touchInit() { if (err != ESP_OK) { goto err; } - touch_pad_intr_enable(); // returns ESP_OK + touch_pad_intr_enable(); // returns ESP_OK #elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 err = touch_pad_init(); if (err != ESP_OK) { @@ -169,7 +167,6 @@ static void __touchInit() { touch_pad_fsm_start(); // returns ESP_OK //ISR setup moved to __touchChannelInit #endif - initialized = true; return; err: @@ -183,11 +180,11 @@ static void __touchChannelInit(int pad) { return; } -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 // Initial no Threshold and setup __touchInterruptHandlers[pad].fn = NULL; touch_pad_config(pad, TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK -#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 // Initial no Threshold and setup __touchInterruptHandlers[pad].fn = NULL; touch_pad_config(pad); // returns ESP_OK @@ -274,7 +271,7 @@ static void __touchDettachInterrupt(uint8_t pin) { External Public Touch API Functions */ -#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC +#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC void touchInterruptSetThresholdDirection(bool mustbeLower) { if (mustbeLower) { touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW); @@ -328,5 +325,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 == 3 */ +#endif /* 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 cc140d81bb0..4b06c7db766 100644 --- a/cores/esp32/esp32-hal-touch.h +++ b/cores/esp32/esp32-hal-touch.h @@ -22,6 +22,7 @@ #include "soc/soc_caps.h" #if SOC_TOUCH_SENSOR_SUPPORTED +#if SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32 ESP32S2 ESP32S3 #ifdef __cplusplus extern "C" { @@ -37,8 +38,6 @@ extern "C" { typedef uint16_t touch_value_t; #elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2 ESP32S3 typedef uint32_t touch_value_t; -#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 -typedef uint32_t touch_value_t; #endif /* @@ -99,5 +98,6 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold); } #endif +#endif /* SOC_TOUCH_SENSOR_VERSION <= 2 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ #endif /* MAIN_ESP32_HAL_TOUCH_H_ */ diff --git a/cores/esp32/esp32-hal.h b/cores/esp32/esp32-hal.h index 60350ae960b..d80bf2f15de 100644 --- a/cores/esp32/esp32-hal.h +++ b/cores/esp32/esp32-hal.h @@ -74,6 +74,7 @@ void yield(void); #include "esp32-hal-uart.h" #include "esp32-hal-gpio.h" #include "esp32-hal-touch.h" +#include "esp32-hal-touch-ng.h" #include "esp32-hal-dac.h" #include "esp32-hal-adc.h" #include "esp32-hal-spi.h" diff --git a/cores/esp32/io_pin_remap.h b/cores/esp32/io_pin_remap.h index 73789a585e3..10f11a5bf4c 100644 --- a/cores/esp32/io_pin_remap.h +++ b/cores/esp32/io_pin_remap.h @@ -106,7 +106,7 @@ int8_t gpioNumberToDigitalPin(int8_t gpioNumber); #define spiAttachMOSI(spi, mosi) spiAttachMOSI(spi, digitalPinToGPIONumber(mosi)) #define spiAttachSS(spi, cs_num, ss) spiAttachSS(spi, cs_num, digitalPinToGPIONumber(ss)) -// cores/esp32/esp32-hal-touch.h +// cores/esp32/esp32-hal-touch.h && cores/esp32/esp32-hal-touch-ng.h #define touchInterruptGetLastStatus(pin) touchInterruptGetLastStatus(digitalPinToGPIONumber(pin)) #define touchRead(pin) touchRead(digitalPinToGPIONumber(pin)) #define touchAttachInterruptArg(pin, userFunc, arg, threshold) touchAttachInterruptArg(digitalPinToGPIONumber(pin), userFunc, arg, threshold) diff --git a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino index 5aacf1baaf0..9d2b248ba44 100644 --- a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino +++ b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino @@ -15,9 +15,11 @@ Pranav Cherukupalli */ #if CONFIG_IDF_TARGET_ESP32 -#define THRESHOLD 40 /* Greater the value, more the sensitivity */ -#else //ESP32-S2 and ESP32-S3 + default for other chips (to be adjusted) */ +#define THRESHOLD 40 /* Greater the value, more the sensitivity */ +#elif (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3) #define THRESHOLD 5000 /* Lower the value, more the sensitivity */ +#else // ESP32-P4 + default for other chips (to be adjusted) */ +#define THRESHOLD 500 /* Lower the value, more the sensitivity */ #endif RTC_DATA_ATTR int bootCount = 0; @@ -88,7 +90,7 @@ void setup() { touchSleepWakeUpEnable(T3, THRESHOLD); touchSleepWakeUpEnable(T7, THRESHOLD); -#else //ESP32-S2 + ESP32-S3 +#else //ESP32-S2 + ESP32-S3 + ESP32-P4 //Setup sleep wakeup on Touch Pad 3 (GPIO3) touchSleepWakeUpEnable(T3, THRESHOLD); diff --git a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json index cd679adefad..25c42144223 100644 --- a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json +++ b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json @@ -2,7 +2,6 @@ "targets": { "esp32c3": false, "esp32c6": false, - "esp32h2": false, - "esp32p4": false + "esp32h2": false } } diff --git a/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino b/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino index 0f0880902fb..3b4e5f0b9e9 100644 --- a/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino +++ b/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino @@ -3,7 +3,12 @@ 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 + bool touch1detected = false; bool touch2detected = false; diff --git a/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json b/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json index 4363987f4d6..c0ecf9fc0a5 100644 --- a/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json +++ b/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json @@ -1,8 +1,5 @@ { "requires": [ "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" - ], - "targets": { - "esp32p4": false - } + ] } diff --git a/libraries/ESP32/examples/Touch/TouchRead/ci.json b/libraries/ESP32/examples/Touch/TouchRead/ci.json index 4363987f4d6..c0ecf9fc0a5 100644 --- a/libraries/ESP32/examples/Touch/TouchRead/ci.json +++ b/libraries/ESP32/examples/Touch/TouchRead/ci.json @@ -1,8 +1,5 @@ { "requires": [ "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" - ], - "targets": { - "esp32p4": false - } + ] } diff --git a/tests/validation/touch/ci.json b/tests/validation/touch/ci.json index 1abbabeae0c..855e9bd964d 100644 --- a/tests/validation/touch/ci.json +++ b/tests/validation/touch/ci.json @@ -5,8 +5,5 @@ }, "requires": [ "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" - ], - "targets": { - "esp32p4": false - } + ] } diff --git a/tests/validation/touch/touch.ino b/tests/validation/touch/touch.ino index 60f6e7f7966..97aac8a65e6 100644 --- a/tests/validation/touch/touch.ino +++ b/tests/validation/touch/touch.ino @@ -2,6 +2,10 @@ #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) @@ -15,11 +19,7 @@ uint8_t TOUCH_GPIOS[] = {4, 2, 15, 13, 12, 14, 27, 33, 32}; #define NO_TOUCH_GPIO 25 -#define RELEASED_VALUE 75 //75+ read value to pass test -#define PRESSED_VALUE 20 //20- read value to pass test -#define INTERRUPT_THRESHOLD 40 - -#else //ESP32S2 and ESP32S3 +#elif (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3) #define TEST_TOUCH_CHANNEL (12) //14 static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { @@ -33,7 +33,25 @@ uint8_t TOUCH_GPIOS[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 /*,13,14*/}; #define NO_TOUCH_GPIO 17 -#if CONFIG_IDF_TARGET_ESP32S2 +#else //ESP32P4 + +#define TEST_TOUCH_CHANNEL (5) //14 +static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { + TOUCH_PAD_NUM0, 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*/ +}; + +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 @@ -41,12 +59,13 @@ uint8_t TOUCH_GPIOS[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 /*,13,14*/}; #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 #else #error Test not currently supported on this chip. Please adjust and try again! #endif -#endif - bool touch1detected = false; bool touch2detected = false; @@ -59,17 +78,25 @@ void gotTouch2() { } /* - * Change the slope to get larger value from touch sensor. + * Change the slope to get larger value from touch sensor. (Capacitor for ESP32P4) */ 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); +#else + touch_ll_set_internal_capacitor(0x7f); +#endif } /* - * Change the slope to get smaller value from touch sensor. + * Change the slope to get smaller value from touch sensor. (Capacitor for ESP32P4) */ 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); +#else + touch_ll_set_internal_capacitor(0); +#endif } /* These functions are intended to be called before and after each test. */ @@ -87,6 +114,7 @@ void tearDown(void) { */ 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 @@ -109,6 +137,29 @@ void test_touch_read(void) { 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++) { + touch_unpressed[i] = touchRead(TOUCH_GPIOS[i]); + } + + // TEST PRESS STATE + for (int j = 0; j < TEST_TOUCH_CHANNEL; j++) { + test_press_fake(touch_list[j]); + } + delay(100); + + touch_value_t touch_pressed[sizeof(TOUCH_GPIOS)]; + for (int k = 0; k < sizeof(TOUCH_GPIOS); k++) { + touch_pressed[k] = touchRead(TOUCH_GPIOS[k]); + } + + // 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]); + } +#endif } void test_touch_interrtupt(void) { @@ -146,4 +197,6 @@ void setup() { UNITY_END(); } -void loop() {} +void loop() { + delay(10); +} From 83d35683c3736178de595a0ad0424ea3e8f5a4fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Mon, 21 Oct 2024 14:03:44 +0200 Subject: [PATCH 064/409] feat(sdmmc): Add SDMMC support for P4 + remove BUILTIN LED (#10460) * feat(sdmmc): Add support for P4 * fix(board): Remove builtin led * Update libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino Add missing note about power pin for P4 Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> * ci(pre-commit): Apply automatic fixes * feat(sdmmc): Option to set power channel * feat(sdmmc): Update pins_arduino.h * feat(sdmmc): remove sdmmc power from periman * fix(sdmmc): use corrent variable * fix(sdmmc): Remove periman * feat(sdmmc): Toggle power pin if defined * feat(sdmmc): setPowerChannel available only when supported * feat(sdmmc): Toggle sd power pin for 200ms * fix(example): Remove p4 pins as they are listed already * feat(sdmmc): Check if power channel is specified * ci(pre-commit): Apply automatic fixes * fix(ci): codespell fix --------- Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino | 20 ++-- .../SD_MMC/examples/SDMMC_time/SDMMC_time.ino | 1 + libraries/SD_MMC/src/SD_MMC.cpp | 106 ++++++++++++++++-- libraries/SD_MMC/src/SD_MMC.h | 6 + variants/esp32p4/pins_arduino.h | 28 +++-- 5 files changed, 138 insertions(+), 23 deletions(-) diff --git a/libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino b/libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino index 030caae759c..e03f5ceb25e 100644 --- a/libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino +++ b/libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino @@ -14,6 +14,7 @@ * Connections for ║ ║ ╔═══╩═║═║═══╗ ║ ║ ║ * full-sized ║ ║ ║ ╔═╝ ║ ║ ║ ║ ║ * SD card ║ ║ ║ ║ ║ ║ ║ ║ ║ + * ESP32-P4 Func EV | 40 39 GND 43 3V3 GND 44 43 42 | SLOT 0 (IO_MUX) * ESP32-S3 DevKit | 21 47 GND 39 3V3 GND 40 41 42 | * ESP32-S3-USB-OTG | 38 37 GND 36 3V3 GND 35 34 33 | * ESP32 | 4 2 GND 14 3V3 GND 15 13 12 | @@ -42,6 +43,7 @@ #include "FS.h" #include "SD_MMC.h" +#ifdef CONFIG_IDF_TARGET_ESP32S3 // Default pins for ESP-S3 // Warning: ESP32-S3-WROOM-2 is using most of the default GPIOs (33-37) to interface with on-board OPI flash. // If the SD_MMC is initialized with default pins it will result in rebooting loop - please @@ -54,6 +56,7 @@ int d0 = 37; int d1 = 38; int d2 = 33; int d3 = 39; // GPIO 34 is not broken-out on ESP32-S3-DevKitC-1 v1.1 +#endif void listDir(fs::FS &fs, const char *dirname, uint8_t levels) { Serial.printf("Listing directory: %s\n", dirname); @@ -211,15 +214,16 @@ void testFileIO(fs::FS &fs, const char *path) { void setup() { Serial.begin(115200); /* - // If you want to change the pin assignment on ESP32-S3 uncomment this block and the appropriate + // If you want to change the pin assignment or you get an error that some pins + // are not assigned on ESP32-S3/ESP32-P4 uncomment this block and the appropriate // line depending if you want to use 1-bit or 4-bit line. - // Please note that ESP32 does not allow pin change and will always fail. + // Please note that ESP32 does not allow pin change and setPins() will always fail. //if(! SD_MMC.setPins(clk, cmd, d0)){ //if(! SD_MMC.setPins(clk, cmd, d0, d1, d2, d3)){ - Serial.println("Pin change failed!"); - return; - } - */ + // Serial.println("Pin change failed!"); + // return; + //} + */ if (!SD_MMC.begin()) { Serial.println("Card Mount Failed"); @@ -262,4 +266,6 @@ void setup() { Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024)); } -void loop() {} +void loop() { + delay(10); +} diff --git a/libraries/SD_MMC/examples/SDMMC_time/SDMMC_time.ino b/libraries/SD_MMC/examples/SDMMC_time/SDMMC_time.ino index bd9f150f3e8..d1e933e4f4b 100644 --- a/libraries/SD_MMC/examples/SDMMC_time/SDMMC_time.ino +++ b/libraries/SD_MMC/examples/SDMMC_time/SDMMC_time.ino @@ -14,6 +14,7 @@ * Connections for ║ ║ ╔═══╩═║═║═══╗ ║ ║ ║ * full-sized ║ ║ ║ ╔═╝ ║ ║ ║ ║ ║ * SD card ║ ║ ║ ║ ║ ║ ║ ║ ║ + * ESP32-P4 Func EV | 40 39 GND 43 3V3 GND 44 43 42 | SLOT 0 (IO_MUX) * ESP32-S3 DevKit | 21 47 GND 39 3V3 GND 40 41 42 | * ESP32-S3-USB-OTG | 38 37 GND 36 3V3 GND 35 34 33 | * ESP32 | 4 2 GND 14 3V3 GND 15 13 12 | diff --git a/libraries/SD_MMC/src/SD_MMC.cpp b/libraries/SD_MMC/src/SD_MMC.cpp index 80cb150baa2..4a0962ff7e4 100644 --- a/libraries/SD_MMC/src/SD_MMC.cpp +++ b/libraries/SD_MMC/src/SD_MMC.cpp @@ -32,11 +32,14 @@ #include "ff.h" #include "esp32-hal-periman.h" +#if SOC_SDMMC_IO_POWER_EXTERNAL +#include "sd_pwr_ctrl_by_on_chip_ldo.h" +#endif + using namespace fs; SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) { -#if !defined(CONFIG_IDF_TARGET_ESP32P4) -#if defined(SOC_SDMMC_USE_GPIO_MATRIX) && defined(BOARD_HAS_SDMMC) +#if defined(SOC_SDMMC_USE_GPIO_MATRIX) && defined(BOARD_HAS_SDMMC) && !defined(CONFIG_IDF_TARGET_ESP32P4) _pin_clk = SDMMC_CLK; _pin_cmd = SDMMC_CMD; _pin_d0 = SDMMC_D0; @@ -45,9 +48,8 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) { _pin_d2 = SDMMC_D2; _pin_d3 = SDMMC_D3; #endif // BOARD_HAS_1BIT_SDMMC -#endif // !defined(CONFIG_IDF_TARGET_ESP32P4) -#elif SOC_SDMMC_USE_IOMUX && defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32) +#elif defined(SOC_SDMMC_USE_IOMUX) && defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32) _pin_clk = SDMMC_SLOT1_IOMUX_PIN_NUM_CLK; _pin_cmd = SDMMC_SLOT1_IOMUX_PIN_NUM_CMD; _pin_d0 = SDMMC_SLOT1_IOMUX_PIN_NUM_D0; @@ -57,7 +59,9 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) { _pin_d3 = SDMMC_SLOT1_IOMUX_PIN_NUM_D3; #endif // BOARD_HAS_1BIT_SDMMC -#elif SOC_SDMMC_USE_IOMUX && defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32P4) +// ESP32-P4 can use either IOMUX or GPIO matrix +#elif defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32P4) +#if defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0) _pin_clk = SDMMC_SLOT0_IOMUX_PIN_NUM_CLK; _pin_cmd = SDMMC_SLOT0_IOMUX_PIN_NUM_CMD; _pin_d0 = SDMMC_SLOT0_IOMUX_PIN_NUM_D0; @@ -66,6 +70,19 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) { _pin_d2 = SDMMC_SLOT0_IOMUX_PIN_NUM_D2; _pin_d3 = SDMMC_SLOT0_IOMUX_PIN_NUM_D3; #endif // BOARD_HAS_1BIT_SDMMC +#else + _pin_clk = SDMMC_CLK; + _pin_cmd = SDMMC_CMD; + _pin_d0 = SDMMC_D0; +#ifndef BOARD_HAS_1BIT_SDMMC + _pin_d1 = SDMMC_D1; + _pin_d2 = SDMMC_D2; + _pin_d3 = SDMMC_D3; +#endif // BOARD_HAS_1BIT_SDMMC +#endif // BOARD_SDMMC_SLOT_NO +#endif +#if defined(SOC_SDMMC_IO_POWER_EXTERNAL) && defined(BOARD_SDMMC_POWER_CHANNEL) + _power_channel = BOARD_SDMMC_POWER_CHANNEL; #endif } @@ -95,7 +112,7 @@ bool SDMMCFS::setPins(int clk, int cmd, int d0, int d1, int d2, int d3) { d2 = digitalPinToGPIONumber(d2); d3 = digitalPinToGPIONumber(d3); -#ifdef SOC_SDMMC_USE_GPIO_MATRIX +#if defined(SOC_SDMMC_USE_GPIO_MATRIX) && !defined(CONFIG_IDF_TARGET_ESP32P4) // SoC supports SDMMC pin configuration via GPIO matrix. Save the pins for later use in SDMMCFS::begin. _pin_clk = (int8_t)clk; _pin_cmd = (int8_t)cmd; @@ -116,11 +133,42 @@ bool SDMMCFS::setPins(int clk, int cmd, int d0, int d1, int d2, int d3) { return false; } return true; +#elif defined(CONFIG_IDF_TARGET_ESP32P4) +#if defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0) + // ESP32-P4 can use either IOMUX or GPIO matrix + bool pins_ok = + (clk == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_CLK) && (cmd == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_CMD) && (d0 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D0) + && (((d1 == -1) && (d2 == -1) && (d3 == -1)) || ((d1 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D1) && (d2 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D2) && (d3 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D3))); + if (!pins_ok) { + log_e("SDMMCFS: specified pins are not supported when using IOMUX (SDMMC SLOT 0)."); + return false; + } + return true; +#else + _pin_clk = (int8_t)clk; + _pin_cmd = (int8_t)cmd; + _pin_d0 = (int8_t)d0; + _pin_d1 = (int8_t)d1; + _pin_d2 = (int8_t)d2; + _pin_d3 = (int8_t)d3; + return true; +#endif #else #error SoC not supported #endif } +#ifdef SOC_SDMMC_IO_POWER_EXTERNAL +bool SDMMCFS::setPowerChannel(int power_channel) { + if (_card != nullptr) { + log_e("SD_MMC.setPowerChannel must be called before SD_MMC.begin"); + return false; + } + _power_channel = power_channel; + return true; +} +#endif + bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_failed, int sdmmc_frequency, uint8_t maxOpenFiles) { if (_card) { return true; @@ -135,7 +183,9 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_ } //mount sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); -#ifdef SOC_SDMMC_USE_GPIO_MATRIX +#if (defined(SOC_SDMMC_USE_GPIO_MATRIX) && !defined(CONFIG_IDF_TARGET_ESP32P4)) \ + || (defined(CONFIG_IDF_TARGET_ESP32P4) && ((defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 1)) || !defined(BOARD_HAS_SDMMC))) + log_d("pin_cmd: %d, pin_clk: %d, pin_d0: %d, pin_d1: %d, pin_d2: %d, pin_d3: %d", _pin_cmd, _pin_clk, _pin_d0, _pin_d1, _pin_d2, _pin_d3); // SoC supports SDMMC pin configuration via GPIO matrix. // Check that the pins have been set either in the constructor or setPins function. if (_pin_cmd == -1 || _pin_clk == -1 || _pin_d0 == -1 || (!mode1bit && (_pin_d1 == -1 || _pin_d2 == -1 || _pin_d3 == -1))) { @@ -175,7 +225,18 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_ sdmmc_host_t host = SDMMC_HOST_DEFAULT(); host.flags = SDMMC_HOST_FLAG_4BIT; +#if defined(CONFIG_IDF_TARGET_ESP32P4) && defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0) + host.slot = SDMMC_HOST_SLOT_0; + // reconfigure slot_config to remove all pins in order to use IO_MUX + slot_config = { + .cd = SDMMC_SLOT_NO_CD, + .wp = SDMMC_SLOT_NO_WP, + .width = 4, + .flags = 0, + }; +#else host.slot = SDMMC_HOST_SLOT_1; +#endif host.max_freq_khz = sdmmc_frequency; #ifdef BOARD_HAS_1BIT_SDMMC mode1bit = true; @@ -186,6 +247,34 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_ } _mode1bit = mode1bit; +#ifdef SOC_SDMMC_IO_POWER_EXTERNAL + if (_power_channel == -1) { + log_i("On-chip power channel specified, use external power for SDMMC"); + } else { + sd_pwr_ctrl_ldo_config_t ldo_config = { + .ldo_chan_id = _power_channel, + }; + sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL; + + if (sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle) != ESP_OK) { + log_e("Failed to create a new on-chip LDO power control driver"); + return false; + } + host.pwr_ctrl_handle = pwr_ctrl_handle; + } +#endif + +#if defined(BOARD_SDMMC_POWER_PIN) +#ifndef BOARD_SDMMC_POWER_ON_LEVEL +#error "BOARD_SDMMC_POWER_ON_LEVEL not defined, please define it in pins_arduino.h" +#endif + pinMode(BOARD_SDMMC_POWER_PIN, OUTPUT); + digitalWrite(BOARD_SDMMC_POWER_PIN, !BOARD_SDMMC_POWER_ON_LEVEL); + delay(200); + digitalWrite(BOARD_SDMMC_POWER_PIN, BOARD_SDMMC_POWER_ON_LEVEL); + perimanSetPinBusExtraType(BOARD_SDMMC_POWER_PIN, "SDMMC_POWER"); +#endif + esp_vfs_fat_sdmmc_mount_config_t mount_config = { .format_if_mount_failed = format_if_mount_failed, .max_files = maxOpenFiles, @@ -252,6 +341,9 @@ void SDMMCFS::end() { perimanClearPinBus(_pin_d2); perimanClearPinBus(_pin_d3); } +#if defined(BOARD_SDMMC_POWER_PIN) + perimanClearPinBus(BOARD_SDMMC_POWER_PIN); +#endif } } diff --git a/libraries/SD_MMC/src/SD_MMC.h b/libraries/SD_MMC/src/SD_MMC.h index a2bc12aed64..b6fe13a0d24 100644 --- a/libraries/SD_MMC/src/SD_MMC.h +++ b/libraries/SD_MMC/src/SD_MMC.h @@ -44,6 +44,9 @@ class SDMMCFS : public FS { int8_t _pin_d1 = -1; int8_t _pin_d2 = -1; int8_t _pin_d3 = -1; +#ifdef SOC_SDMMC_IO_POWER_EXTERNAL + int8_t _power_channel = -1; +#endif uint8_t _pdrv = 0xFF; bool _mode1bit = false; @@ -51,6 +54,9 @@ class SDMMCFS : public FS { SDMMCFS(FSImplPtr impl); bool setPins(int clk, int cmd, int d0); bool setPins(int clk, int cmd, int d0, int d1, int d2, int d3); +#ifdef SOC_SDMMC_IO_POWER_EXTERNAL + bool setPowerChannel(int power_channel); +#endif bool begin( const char *mountpoint = "/sdcard", bool mode1bit = false, bool format_if_mount_failed = false, int sdmmc_frequency = BOARD_MAX_SDMMC_FREQ, uint8_t maxOpenFiles = 5 diff --git a/variants/esp32p4/pins_arduino.h b/variants/esp32p4/pins_arduino.h index 792146f5ca2..cbb1e871ae5 100644 --- a/variants/esp32p4/pins_arduino.h +++ b/variants/esp32p4/pins_arduino.h @@ -4,15 +4,6 @@ #include #include "soc/soc_caps.h" -#define PIN_NEOPIXEL 44 -// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; -#define BUILTIN_LED LED_BUILTIN // backward compatibility -#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() -#define RGB_BUILTIN LED_BUILTIN -#define RGB_BRIGHTNESS 64 - // BOOT_MODE 35 // BOOT_MODE2 36 pullup @@ -58,6 +49,8 @@ static const uint8_t T11 = 13; static const uint8_t T12 = 14; static const uint8_t T13 = 15; +/* ESP32-P4 EV Function board specific definitions */ +//ETH #define ETH_PHY_TYPE ETH_PHY_TLK110 #define ETH_PHY_ADDR 1 #define ETH_PHY_MDC 31 @@ -72,4 +65,21 @@ static const uint8_t T13 = 15; #define ETH_RMII_CLK 50 #define ETH_CLK_MODE EMAC_CLK_EXT_IN +//SDMMC +#define BOARD_HAS_SDMMC +#define BOARD_SDMMC_SLOT 0 +#define BOARD_SDMMC_POWER_CHANNEL 4 +#define BOARD_SDMMC_POWER_PIN 45 +#define BOARD_SDMMC_POWER_ON_LEVEL LOW + +//WIFI - ESP32C6 +#define BOARD_HAS_SDIO_ESP_HOSTED +#define BOARD_SDIO_ESP_HOSTED_CLK 18 +#define BOARD_SDIO_ESP_HOSTED_CMD 19 +#define BOARD_SDIO_ESP_HOSTED_D0 14 +#define BOARD_SDIO_ESP_HOSTED_D1 15 +#define BOARD_SDIO_ESP_HOSTED_D2 16 +#define BOARD_SDIO_ESP_HOSTED_D3 17 +#define BOARD_SDIO_ESP_HOSTED_RESET 54 + #endif /* Pins_Arduino_h */ From 9e643c08a700a62415a5c3f311788e1b1edd64fe Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Mon, 21 Oct 2024 09:45:59 -0300 Subject: [PATCH 065/409] fix(testing): Checkout proper branch for Wokwi tests and small QoL improvements (#10435) * fix(tests): Add missing newlines to output * fix(tests): Improve fibonacci test * fix(tests): Remove redundant targets from json * fix(wokwi): Checkout proper base branch for wokwi tests * feat(logging): Add logging to some tests to improve debugging * fix(ci): Make CI more permissive and improve messages * fix(tests): Bump pytest-embedded version to support P4 --- .github/scripts/tests_matrix.sh | 26 +++++++++++++ .github/workflows/dangerjs.yml | 4 +- .github/workflows/tests.yml | 38 +++++++++---------- .github/workflows/tests_results.yml | 1 + .github/workflows/tests_wokwi.yml | 36 ++++++++++++++++-- tests/performance/coremark/coremark.ino | 2 +- tests/performance/fibonacci/fibonacci.ino | 2 +- tests/performance/fibonacci/test_fibonacci.py | 33 ++++++++-------- tests/performance/psramspeed/ci.json | 8 ++-- tests/performance/psramspeed/psramspeed.ino | 2 +- tests/performance/ramspeed/ramspeed.ino | 2 +- tests/performance/superpi/superpi.ino | 2 +- tests/requirements.txt | 8 ++-- tests/validation/gpio/test_gpio.py | 10 +++++ tests/validation/nvs/test_nvs.py | 9 +++++ tests/validation/periman/test_periman.py | 8 +++- tests/validation/psram/ci.json | 7 +--- tests/validation/wifi/test_wifi.py | 9 +++++ 18 files changed, 143 insertions(+), 64 deletions(-) create mode 100644 .github/scripts/tests_matrix.sh diff --git a/.github/scripts/tests_matrix.sh b/.github/scripts/tests_matrix.sh new file mode 100644 index 00000000000..ca0b6eb8684 --- /dev/null +++ b/.github/scripts/tests_matrix.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +build_types="'validation'" +hw_types="'validation'" +wokwi_types="'validation'" +qemu_types="'validation'" + +if [[ $IS_PR != 'true' ]] || [[ $PERFORMANCE_ENABLED == 'true' ]]; then + build_types+=",'performance'" + hw_types+=",'performance'" + #wokwi_types+=",'performance'" + #qemu_types+=",'performance'" +fi + +targets="'esp32','esp32s2','esp32s3','esp32c3','esp32c6','esp32h2'" + +mkdir -p info + +echo "[$wokwi_types]" > info/wokwi_types.txt +echo "[$targets]" > info/targets.txt + +echo "build-types=[$build_types]" >> $GITHUB_OUTPUT +echo "hw-types=[$hw_types]" >> $GITHUB_OUTPUT +echo "wokwi-types=[$wokwi_types]" >> $GITHUB_OUTPUT +echo "qemu-types=[$qemu_types]" >> $GITHUB_OUTPUT +echo "targets=[$targets]" >> $GITHUB_OUTPUT diff --git a/.github/workflows/dangerjs.yml b/.github/workflows/dangerjs.yml index 9f7360bc34f..75c046731f3 100644 --- a/.github/workflows/dangerjs.yml +++ b/.github/workflows/dangerjs.yml @@ -19,4 +19,6 @@ jobs: - name: DangerJS pull request linter uses: espressif/shared-github-dangerjs@v1 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + rule-max-commits: 'false' + commit-messages-min-summary-length: '10' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 26de19d8f10..ab8baa6d14c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -57,29 +57,25 @@ jobs: hw-types: ${{ steps.set-matrix.outputs.hw-types }} wokwi-types: ${{ steps.set-matrix.outputs.wokwi-types }} qemu-types: ${{ steps.set-matrix.outputs.qemu-types }} + targets: ${{ steps.set-matrix.outputs.targets }} + env: + IS_PR: ${{ github.event.pull_request.number != null }} + PERFORMANCE_ENABLED: ${{ contains(github.event.pull_request.labels.*.name, 'perf_test') }} steps: + - name: Checkout + uses: actions/checkout@v4 + with: + sparse-checkout: .github/scripts/tests_matrix.sh + - name: Set matrix id: set-matrix - run: | - build_types='["validation"' - hw_types='["validation"' - wokwi_types='["validation"' - qemu_types='["validation"' - - is_pr=${{ github.event.pull_request.number != null }} - is_performance_enabled=${{ contains(github.event.pull_request.labels.*.name, 'perf_test') }} - - if [[ $is_pr != 'true' ]] || [[ $is_performance_enabled == 'true' ]]; then - build_types+=',"performance"' - hw_types+=',"performance"' - #wokwi_types+=',"performance"' - #qemu_types+=',"performance"' - fi + run: bash .github/scripts/tests_matrix.sh - echo "build-types=$build_types]" >> $GITHUB_OUTPUT - echo "hw-types=$hw_types]" >> $GITHUB_OUTPUT - echo "wokwi-types=$wokwi_types]" >> $GITHUB_OUTPUT - echo "qemu-types=$qemu_types]" >> $GITHUB_OUTPUT + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: matrix_info + path: info/* call-build-tests: name: Build @@ -88,7 +84,7 @@ jobs: strategy: matrix: type: ${{ fromJson(needs.gen-matrix.outputs.build-types) }} - chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'] + chip: ${{ fromJson(needs.gen-matrix.outputs.targets) }} with: type: ${{ matrix.type }} chip: ${{ matrix.chip }} @@ -105,7 +101,7 @@ jobs: fail-fast: false matrix: type: ${{ fromJson(needs.gen-matrix.outputs.hw-types) }} - chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'] + chip: ${{ fromJson(needs.gen-matrix.outputs.targets) }} with: type: ${{ matrix.type }} chip: ${{ matrix.chip }} diff --git a/.github/workflows/tests_results.yml b/.github/workflows/tests_results.yml index a255016c413..f9c572bf546 100644 --- a/.github/workflows/tests_results.yml +++ b/.github/workflows/tests_results.yml @@ -79,6 +79,7 @@ jobs: event_name: ${{ env.original_event }} files: ./artifacts/**/*.xml action_fail: true + compare_to_earlier_commit: false - name: Fail if tests failed if: ${{ env.original_conclusion == 'failure' || env.original_conclusion == 'timed_out' || github.event.workflow_run.conclusion == 'failure' || github.event.workflow_run.conclusion == 'timed_out' }} diff --git a/.github/workflows/tests_wokwi.yml b/.github/workflows/tests_wokwi.yml index f016cad25e0..a891ca89dfd 100644 --- a/.github/workflows/tests_wokwi.yml +++ b/.github/workflows/tests_wokwi.yml @@ -22,6 +22,9 @@ jobs: outputs: pr_num: ${{ steps.set-ref.outputs.pr_num }} ref: ${{ steps.set-ref.outputs.ref }} + base: ${{ steps.set-ref.outputs.base }} + targets: ${{ steps.set-ref.outputs.targets }} + types: ${{ steps.set-ref.outputs.types }} steps: - name: Report pending uses: actions/github-script@v7 @@ -51,10 +54,18 @@ jobs: name: event_file path: artifacts/event_file + - name: Download and extract matrix info + uses: actions/download-artifact@v4 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + name: matrix_info + path: artifacts/matrix_info + - name: Try to read PR number id: set-ref run: | - pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json) + pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json | tr -cd "[:digit:]") if [ -z "$pr_num" ] || [ "$pr_num" == "null" ]; then pr_num="" fi @@ -64,11 +75,22 @@ jobs: ref=${{ github.ref }} fi - action=$(jq -r '.action' artifacts/event_file/event.json) + action=$(jq -r '.action' artifacts/event_file/event.json | tr -cd "[:alpha:]_") if [ "$action" == "null" ]; then action="" fi + base=$(jq -r '.pull_request.base.ref' artifacts/event_file/event.json | tr -cd "[:alnum:]/_.-") + if [ -z "$base" ] || [ "$base" == "null" ]; then + base=${{ github.ref }} + fi + + types=$(cat artifacts/matrix_info/wokwi_types.txt | tr -cd "[:alpha:],[]'") + targets=$(cat artifacts/matrix_info/targets.txt | tr -cd "[:alnum:],[]'") + + echo "base = $base" + echo "targets = $targets" + echo "types = $types" echo "pr_num = $pr_num" printf "$ref" >> artifacts/ref.txt @@ -98,6 +120,9 @@ jobs: cat artifacts/conclusion.txt echo "pr_num=$pr_num" >> $GITHUB_OUTPUT + echo "base=$base" >> $GITHUB_OUTPUT + echo "targets=$targets" >> $GITHUB_OUTPUT + echo "types=$types" >> $GITHUB_OUTPUT echo "ref=$ref" >> $GITHUB_OUTPUT - name: Download and extract parent hardware results @@ -164,8 +189,8 @@ jobs: strategy: fail-fast: false matrix: - type: ['validation'] - chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'] + type: ${{ fromJson(needs.get-artifacts.outputs.types) }} + chip: ${{ fromJson(needs.get-artifacts.outputs.targets) }} steps: - name: Report pending uses: actions/github-script@v7 @@ -211,9 +236,12 @@ jobs: echo "enabled=$enabled" >> $GITHUB_OUTPUT # Note that changes to the workflows and tests will only be picked up after the PR is merged + # DO NOT CHECKOUT THE USER'S REPOSITORY IN THIS WORKFLOW. IT HAS HIGH SECURITY RISKS. - name: Checkout repository if: ${{ steps.check-tests.outputs.enabled == 'true' }} uses: actions/checkout@v4 + with: + ref: ${{ needs.get-artifacts.outputs.base || github.ref }} - uses: actions/setup-python@v5 if: ${{ steps.check-tests.outputs.enabled == 'true' }} diff --git a/tests/performance/coremark/coremark.ino b/tests/performance/coremark/coremark.ino index 776db7874db..872b53050f0 100644 --- a/tests/performance/coremark/coremark.ino +++ b/tests/performance/coremark/coremark.ino @@ -40,7 +40,7 @@ void setup() { Serial.printf("Cores: %d\n", CONFIG_SOC_CPU_CORES_NUM); Serial.flush(); for (int i = 0; i < N_RUNS; i++) { - Serial.printf("Run %d", i); + Serial.printf("Run %d\n", i); coremark_main(); Serial.flush(); } diff --git a/tests/performance/fibonacci/fibonacci.ino b/tests/performance/fibonacci/fibonacci.ino index 01fd6f7bee2..c82fd6b70d8 100644 --- a/tests/performance/fibonacci/fibonacci.ino +++ b/tests/performance/fibonacci/fibonacci.ino @@ -31,7 +31,7 @@ void setup() { Serial.printf("N: %d\n", FIB_N); Serial.flush(); for (int i = 0; i < N_RUNS; i++) { - Serial.printf("Run %d", i); + Serial.printf("Run %d\n", i); unsigned long start = millis(); fibonacci = fib(FIB_N); unsigned long elapsed = millis() - start; diff --git a/tests/performance/fibonacci/test_fibonacci.py b/tests/performance/fibonacci/test_fibonacci.py index 622ea77ee4b..ced9368184e 100644 --- a/tests/performance/fibonacci/test_fibonacci.py +++ b/tests/performance/fibonacci/test_fibonacci.py @@ -2,24 +2,21 @@ import logging import os +fib_results = {} + +def fib(n): + if n < 2: + return n + elif str(n) in fib_results: + return fib_results[str(n)] + else: + fib_results[str(n)] = fib(n - 1) + fib(n - 2) + return fib_results[str(n)] + def test_fibonacci(dut, request): LOGGER = logging.getLogger(__name__) - # Fibonacci results starting from fib(35) to fib(45) - fib_results = [ - 9227465, - 14930352, - 24157817, - 39088169, - 63245986, - 102334155, - 165580141, - 267914296, - 433494437, - 701408733, - ] - # Match "Runs: %d" res = dut.expect(r"Runs: (\d+)", timeout=60) runs = int(res.group(0).decode("utf-8").split(" ")[1]) @@ -30,7 +27,11 @@ def test_fibonacci(dut, request): res = dut.expect(r"N: (\d+)", timeout=300) fib_n = int(res.group(0).decode("utf-8").split(" ")[1]) LOGGER.info("Calculating Fibonacci({})".format(fib_n)) - assert fib_n > 30 and fib_n < 50, "Invalid Fibonacci number" + assert fib_n > 0, "Invalid Fibonacci number" + + # Calculate Fibonacci results + expected_result = fib(fib_n) + LOGGER.info("Expected Fibonacci result: {}".format(expected_result)) list_time = [] @@ -48,7 +49,7 @@ def test_fibonacci(dut, request): assert fib_result > 0, "Invalid Fibonacci result" # Check if the result is correct - assert fib_result == fib_results[fib_n - 35] + assert fib_result == expected_result # Match "Time: %lu.%03lu s" res = dut.expect(r"Time: (\d+)\.(\d+) s", timeout=300) diff --git a/tests/performance/psramspeed/ci.json b/tests/performance/psramspeed/ci.json index 8d58dbf5250..341df103671 100644 --- a/tests/performance/psramspeed/ci.json +++ b/tests/performance/psramspeed/ci.json @@ -3,9 +3,7 @@ "qemu": false, "wokwi": false }, - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SPIRAM=y" + ] } diff --git a/tests/performance/psramspeed/psramspeed.ino b/tests/performance/psramspeed/psramspeed.ino index 81175e6b3a5..be91733abfc 100644 --- a/tests/performance/psramspeed/psramspeed.ino +++ b/tests/performance/psramspeed/psramspeed.ino @@ -252,7 +252,7 @@ void setup() { Serial.printf("Max test size: %d\n", MAX_TEST_SIZE); Serial.flush(); for (int i = 0; i < N_RUNS; i++) { - Serial.printf("Run %d", i); + Serial.printf("Run %d\n", i); memcpy_speed_test(dest, src, MAX_TEST_SIZE, N_COPIES); Serial.flush(); memset_speed_test(dest, FILL_VALUE, MAX_TEST_SIZE, N_COPIES); diff --git a/tests/performance/ramspeed/ramspeed.ino b/tests/performance/ramspeed/ramspeed.ino index e0ab0db4c5f..776f6540679 100644 --- a/tests/performance/ramspeed/ramspeed.ino +++ b/tests/performance/ramspeed/ramspeed.ino @@ -248,7 +248,7 @@ void setup() { Serial.printf("Max test size: %d\n", MAX_TEST_SIZE); Serial.flush(); for (int i = 0; i < N_RUNS; i++) { - Serial.printf("Run %d", i); + Serial.printf("Run %d\n", i); memcpy_speed_test(dest, src, MAX_TEST_SIZE, N_COPIES); Serial.flush(); memset_speed_test(dest, FILL_VALUE, MAX_TEST_SIZE, N_COPIES); diff --git a/tests/performance/superpi/superpi.ino b/tests/performance/superpi/superpi.ino index ffa6c932b35..7ac4b2f13d7 100644 --- a/tests/performance/superpi/superpi.ino +++ b/tests/performance/superpi/superpi.ino @@ -25,7 +25,7 @@ void setup() { Serial.printf("Digits: %d\n", DIGITS); Serial.flush(); for (int i = 0; i < N_RUNS; i++) { - Serial.printf("Run %d", i); + Serial.printf("Run %d\n", i); unsigned long start = millis(); pi_calc(DIGITS); unsigned long elapsed = millis() - start; diff --git a/tests/requirements.txt b/tests/requirements.txt index 1b43a6104f2..63d204a96b0 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,7 +1,7 @@ cryptography==43.0.1 --only-binary cryptography pytest-cov==5.0.0 -pytest-embedded-serial-esp==1.11.5 -pytest-embedded-arduino==1.11.5 -pytest-embedded-wokwi==1.11.5 -pytest-embedded-qemu==1.11.5 +pytest-embedded-serial-esp==1.11.6 +pytest-embedded-arduino==1.11.6 +pytest-embedded-wokwi==1.11.6 +pytest-embedded-qemu==1.11.6 diff --git a/tests/validation/gpio/test_gpio.py b/tests/validation/gpio/test_gpio.py index e36282561b5..f11b9fd99cc 100644 --- a/tests/validation/gpio/test_gpio.py +++ b/tests/validation/gpio/test_gpio.py @@ -1,5 +1,15 @@ +import logging + def test_gpio(dut): + LOGGER = logging.getLogger(__name__) + dut.expect_exact("Button test") + + LOGGER.info("Expecting button press 1") dut.expect_exact("Button pressed 1 times") + + LOGGER.info("Expecting button press 2") dut.expect_exact("Button pressed 2 times") + + LOGGER.info("Expecting button press 3") dut.expect_exact("Button pressed 3 times") diff --git a/tests/validation/nvs/test_nvs.py b/tests/validation/nvs/test_nvs.py index 364df56de1c..a2b4842fa91 100644 --- a/tests/validation/nvs/test_nvs.py +++ b/tests/validation/nvs/test_nvs.py @@ -1,4 +1,13 @@ +import logging + def test_nvs(dut): + LOGGER = logging.getLogger(__name__) + + LOGGER.info("Expecting counter value 0") dut.expect_exact("Current counter value: 0") + + LOGGER.info("Expecting counter value 1") dut.expect_exact("Current counter value: 1") + + LOGGER.info("Expecting counter value 2") dut.expect_exact("Current counter value: 2") diff --git a/tests/validation/periman/test_periman.py b/tests/validation/periman/test_periman.py index d8dc4b8eeb5..a2d25f5ba09 100644 --- a/tests/validation/periman/test_periman.py +++ b/tests/validation/periman/test_periman.py @@ -1,4 +1,7 @@ +import logging + def test_periman(dut): + LOGGER = logging.getLogger(__name__) peripherals = [ "GPIO", "SigmaDelta", @@ -29,9 +32,10 @@ def test_periman(dut): if peripheral in peripherals: if "not" in console_output: - assert False, f"Peripheral {peripheral} printed when it should not" + assert False, f"Output printed when it should not after peripheral {peripheral}" + LOGGER.info(f"Correct output after peripheral: {peripheral}") peripherals.remove(peripheral) else: assert False, f"Unknown peripheral: {peripheral}" - assert peripherals == [], f"Missing peripherals output: {peripherals}" + assert peripherals == [], f"Missing output after peripherals: {peripherals}" diff --git a/tests/validation/psram/ci.json b/tests/validation/psram/ci.json index fc34574cf37..341df103671 100644 --- a/tests/validation/psram/ci.json +++ b/tests/validation/psram/ci.json @@ -5,10 +5,5 @@ }, "requires": [ "CONFIG_SPIRAM=y" - ], - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + ] } diff --git a/tests/validation/wifi/test_wifi.py b/tests/validation/wifi/test_wifi.py index 49dd22797d2..769283b06bd 100644 --- a/tests/validation/wifi/test_wifi.py +++ b/tests/validation/wifi/test_wifi.py @@ -1,6 +1,15 @@ +import logging + def test_wifi(dut): + LOGGER = logging.getLogger(__name__) + + LOGGER.info("Starting WiFi Scan") dut.expect_exact("Scan start") dut.expect_exact("Scan done") dut.expect_exact("Wokwi-GUEST") + LOGGER.info("WiFi Scan done") + + LOGGER.info("Connecting to WiFi") dut.expect_exact("WiFi connected") dut.expect_exact("IP address:") + LOGGER.info("WiFi connected") From f668557b547ddd25e464977bfbdc3d41afbdc319 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:22:02 -0300 Subject: [PATCH 066/409] Enable tests for ESP32P4 --- .github/scripts/tests_matrix.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/tests_matrix.sh b/.github/scripts/tests_matrix.sh index ca0b6eb8684..74fece91f8e 100644 --- a/.github/scripts/tests_matrix.sh +++ b/.github/scripts/tests_matrix.sh @@ -12,7 +12,7 @@ if [[ $IS_PR != 'true' ]] || [[ $PERFORMANCE_ENABLED == 'true' ]]; then #qemu_types+=",'performance'" fi -targets="'esp32','esp32s2','esp32s3','esp32c3','esp32c6','esp32h2'" +targets="'esp32','esp32s2','esp32s3','esp32c3','esp32c6','esp32h2','esp32p4'" mkdir -p info From c40444ab338e6c33c5160ee12dfe36246c482025 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 21 Oct 2024 10:42:43 -0300 Subject: [PATCH 067/409] feat(matter): initial commit with arduino matter lib (#10467) * feat(matter): initial commit with arduino matter lib * feat(matter): add matter library to cmakelists.txt * fix(matter): add correct guard for ci * fix(matter): using correct ci requirements in ci.json * fix(matter): using correct ci requirements in header files * fix(matter): using correct ci requirements header and examples * fix(typo): typo and commentaries * fix(typo): typo and commentaries * fix(typo): typo and commentaries * fix(commentary): longer explanation * feat(matter): api simplification with begin * feat(matter): testing flashmode=qio in CI * feat(matter): testing flashmode=qio in CI * fix(matter): changes CI FQBN * fix(matte): include all fqbn in ci.json using qio * fix(matter): revert ci and guard changes * fix(matter): typo and commentaties * feat(matter): adds a light toggle switch button * feat(matter): improved the button control * feat(matter): using switch instead of if() for attibute change * fix(matter): switch/case scope * fix(matter): problems found after pressing reset * feat(matter): improve example using preferences * fix(pre-commit): Fix and apply pre-commit hooks --------- Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> --- .pre-commit-config.yaml | 1 + CMakeLists.txt | 5 + .../MatterCommissionTest.ino | 65 +++++++ .../examples/MatterCommissionTest/ci.json | 7 + .../MatterComposedLights.ino | 94 ++++++++++ .../examples/MatterComposedLights/ci.json | 7 + .../MatterOnOffLight/MatterOnOffLight.ino | 138 +++++++++++++++ .../Matter/examples/MatterOnOffLight/ci.json | 7 + libraries/Matter/keywords.txt | 35 ++++ libraries/Matter/library.properties | 9 + libraries/Matter/src/Matter.cpp | 163 ++++++++++++++++++ libraries/Matter/src/Matter.h | 40 +++++ libraries/Matter/src/MatterEndPoint.h | 23 +++ libraries/Matter/src/MatterOnOffLight.cpp | 107 ++++++++++++ libraries/Matter/src/MatterOnOffLight.h | 34 ++++ 15 files changed, 735 insertions(+) create mode 100644 libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino create mode 100644 libraries/Matter/examples/MatterCommissionTest/ci.json create mode 100644 libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino create mode 100644 libraries/Matter/examples/MatterComposedLights/ci.json create mode 100644 libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino create mode 100644 libraries/Matter/examples/MatterOnOffLight/ci.json create mode 100644 libraries/Matter/keywords.txt create mode 100644 libraries/Matter/library.properties create mode 100644 libraries/Matter/src/Matter.cpp create mode 100644 libraries/Matter/src/Matter.h create mode 100644 libraries/Matter/src/MatterEndPoint.h create mode 100644 libraries/Matter/src/MatterOnOffLight.cpp create mode 100644 libraries/Matter/src/MatterOnOffLight.h diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0aff5b6f07b..6a949631bd9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,6 +26,7 @@ repos: - id: trailing-whitespace args: [--markdown-linebreak-ext=md] - id: pretty-format-json + stages: [manual] args: [--autofix] types_or: [json] exclude: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 6688a97803d..e552299b8aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,6 +94,7 @@ set(ARDUINO_ALL_LIBRARIES HTTPUpdate Insights LittleFS + Matter NetBIOS Network OpenThread @@ -165,6 +166,10 @@ set(ARDUINO_LIBRARY_OpenThread_SRCS libraries/OpenThread/src/OThreadCLI.cpp libraries/OpenThread/src/OThreadCLI_Util.cpp) +set(ARDUINO_LIBRARY_Matter_SRCS + libraries/Matter/src/MatterOnOffLight.cpp + libraries/Matter/src/Matter.cpp) + set(ARDUINO_LIBRARY_PPP_SRCS libraries/PPP/src/PPP.cpp libraries/PPP/src/ppp.c) diff --git a/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino b/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino new file mode 100644 index 00000000000..a9afb0c4484 --- /dev/null +++ b/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino @@ -0,0 +1,65 @@ +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// On/Off Light Endpoint +#include +MatterOnOffLight OnOffLight; + +// WiFi is manually set and started + +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + +void setup() { + Serial.begin(115200); + while (!Serial) { + delay(100); + } + + // We start by connecting to a WiFi network + Serial.print("Connecting to "); + Serial.println(ssid); + // enable IPv6 + WiFi.enableIPv6(true); + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println("\r\nWiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + delay(500); + + // Initialize at least one Matter EndPoint + OnOffLight.begin(); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); +} + +void loop() { + // Check Matter Commissioning state + if (!Matter.isDeviceCommissioned()) { + Serial.println(""); + Serial.println("Matter Node is not commissioned yet."); + Serial.println("Initiate the device discovery in your Matter environment."); + Serial.println("Commission it to your Matter hub with the manual pairing code or QR code"); + Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str()); + Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str()); + // waits for Matter Light Commissioning. + while (!Matter.isDeviceCommissioned()) { + delay(5000); + Serial.println("Matter Fabric not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi."); + Serial.println("====> Decommissioning in 30 seconds. <===="); + delay(30000); + Matter.decommission(); + Serial.println("Matter Node is decommissioned. Commsssioning widget shall start over."); +} diff --git a/libraries/Matter/examples/MatterCommissionTest/ci.json b/libraries/Matter/examples/MatterCommissionTest/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterCommissionTest/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino b/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino new file mode 100644 index 00000000000..63f154d4492 --- /dev/null +++ b/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino @@ -0,0 +1,94 @@ +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// There will be 3 On/Off Light Endpoints in the same Node +#include +MatterOnOffLight OnOffLight1; +MatterOnOffLight OnOffLight2; +MatterOnOffLight OnOffLight3; + +// Matter Protocol Endpoint Callback for each Light Accessory +bool setLightOnOff1(bool state) { + Serial.printf("CB-Light1 changed state to: %s\r\n", state ? "ON" : "OFF"); + return true; +} + +bool setLightOnOff2(bool state) { + Serial.printf("CB-Light2 changed state to: %s\r\n", state ? "ON" : "OFF"); + return true; +} + +bool setLightOnOff3(bool state) { + Serial.printf("CB-Light3 changed state to: %s\r\n", state ? "ON" : "OFF"); + return true; +} + +// WiFi is manually set and started + +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + +void setup() { + Serial.begin(115200); + while (!Serial) { + delay(100); + } + + // We start by connecting to a WiFi network + Serial.print("Connecting to "); + Serial.println(ssid); + // enable IPv6 + WiFi.enableIPv6(true); + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println("\r\nWiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + delay(500); + + // Initialize all 3 Matter EndPoints + OnOffLight1.begin(); + OnOffLight2.begin(); + OnOffLight3.begin(); + OnOffLight1.onChangeOnOff(setLightOnOff1); + OnOffLight2.onChangeOnOff(setLightOnOff2); + OnOffLight3.onChangeOnOff(setLightOnOff3); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); +} + +void loop() { + // Check Matter Light Commissioning state + if (!Matter.isDeviceCommissioned()) { + Serial.println(""); + Serial.println("Matter Node is not commissioned yet."); + Serial.println("Initiate the device discovery in your Matter environment."); + Serial.println("Commission it to your Matter hub with the manual pairing code or QR code"); + Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str()); + Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str()); + // waits for Matter Light Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } + + //displays the Light state every 3 seconds + Serial.println("======================"); + Serial.printf("Matter Light #1 is %s\r\n", OnOffLight1.getOnOff() ? "ON" : "OFF"); + Serial.printf("Matter Light #2 is %s\r\n", OnOffLight2.getOnOff() ? "ON" : "OFF"); + Serial.printf("Matter Light #3 is %s\r\n", OnOffLight3.getOnOff() ? "ON" : "OFF"); + delay(3000); +} diff --git a/libraries/Matter/examples/MatterComposedLights/ci.json b/libraries/Matter/examples/MatterComposedLights/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterComposedLights/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino b/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino new file mode 100644 index 00000000000..64981b23a66 --- /dev/null +++ b/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino @@ -0,0 +1,138 @@ +// Matter Manager +#include +#include +#include + +// List of Matter Endpoints for this Node +// On/Off Light Endpoint +#include +MatterOnOffLight OnOffLight; + +// it will keep last OnOff state stored, using Preferences +Preferences lastStatePref; + +// set your board LED pin here +#ifdef LED_BUILTIN +const uint8_t ledPin = LED_BUILTIN; +#else +const uint8_t ledPin = 2; // Set your pin here if your board has not defined LED_BUILTIN +#warning "Do not forget to set the LED pin" +#endif + +// set your board USER BUTTON pin here +const uint8_t buttonPin = 0; // Set your pin here. Using BOOT Button. C6/C3 use GPIO9. + +// Matter Protocol Endpoint Callback +bool setLightOnOff(bool state) { + Serial.printf("User Callback :: New Light State = %s\r\n", state ? "ON" : "OFF"); + if (state) { + digitalWrite(ledPin, HIGH); + } else { + digitalWrite(ledPin, LOW); + } + // store last OnOff state for when the Light is restarted / power goes off + lastStatePref.putBool("lastOnOffState", state); + // This callback must return the success state to Matter core + return true; +} + +// WiFi is manually set and started + +const char *ssid = "Apartment B15"; // Change this to your WiFi SSID +const char *password = "flat-pony-body"; // Change this to your WiFi password + +void setup() { + // Initialize the USER BUTTON (Boot button) GPIO that will act as a toggle switch + pinMode(buttonPin, INPUT_PULLUP); + // Initialize the LED (light) GPIO and Matter End Point + pinMode(ledPin, OUTPUT); + + Serial.begin(115200); + while (!Serial) { + delay(100); + } + + // We start by connecting to a WiFi network + Serial.print("Connecting to "); + Serial.println(ssid); + // enable IPv6 + WiFi.enableIPv6(true); + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println("\r\nWiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + delay(500); + + // Initialize Matter EndPoint + lastStatePref.begin("matterLight", false); + bool lastOnOffState = lastStatePref.getBool("lastOnOffState", true); + OnOffLight.begin(lastOnOffState); + OnOffLight.onChangeOnOff(setLightOnOff); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + // This may be a restart of a already commissioned Matter accessory + if (Matter.isDeviceCommissioned()) { + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + Serial.printf("Initial state: %s\r\n", OnOffLight.getOnOff() ? "ON" : "OFF"); + setLightOnOff(OnOffLight.getOnOff()); // configure the Light based on initial state + } +} +// Button control +uint32_t button_time_stamp = 0; // debouncing control +bool button_state = false; // false = released | true = pressed +const uint32_t debouceTime = 250; // button debouncing time (ms) +const uint32_t decommissioningTimeout = 10000; // keep the button pressed for 10s to decommission the light + +void loop() { + // Check Matter Light Commissioning state, which may change during execution of loop() + if (!Matter.isDeviceCommissioned()) { + Serial.println(""); + Serial.println("Matter Node is not commissioned yet."); + Serial.println("Initiate the device discovery in your Matter environment."); + Serial.println("Commission it to your Matter hub with the manual pairing code or QR code"); + Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str()); + Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str()); + // waits for Matter Light Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.printf("Initial state: %s\r\n", OnOffLight.getOnOff() ? "ON" : "OFF"); + setLightOnOff(OnOffLight.getOnOff()); // configure the Light based on initial state + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } + + // A button is also used to control the light + // Check if the button has been pressed + if (digitalRead(buttonPin) == LOW && !button_state) { + // deals with button debouncing + button_time_stamp = millis(); // record the time while the button is pressed. + button_state = true; // pressed. + } + + // Onboard User Button is used as a Light toggle switch or to decommission it + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > debouceTime && digitalRead(buttonPin) == HIGH) { + button_state = false; // released + // Toggle button is released - toggle the light + Serial.println("User button released. Toggling Light!"); + OnOffLight.toggle(); // Matter Controller also can see the change + + // Factory reset is triggered if the button is pressed longer than 10 seconds + if (time_diff > decommissioningTimeout) { + Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again."); + OnOffLight.setOnOff(false); // turn the light off + Matter.decommission(); + } + } +} diff --git a/libraries/Matter/examples/MatterOnOffLight/ci.json b/libraries/Matter/examples/MatterOnOffLight/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterOnOffLight/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/keywords.txt b/libraries/Matter/keywords.txt new file mode 100644 index 00000000000..7ff3e90f3b4 --- /dev/null +++ b/libraries/Matter/keywords.txt @@ -0,0 +1,35 @@ +####################################### +# Syntax Coloring Map For OpenThread +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Matter KEYWORD1 +MatterOnOffLight KEYWORD1 +MatterEndPoint KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +end KEYWORD2 +start KEYWORD2 +getManualPairingCode KEYWORD2 +getOnboardingQRCodeUrl KEYWORD2 +isDeviceCommissioned KEYWORD2 +isWiFiConnected KEYWORD2 +isThreadConnected KEYWORD2 +isDeviceConnected KEYWORD2 +decommission KEYWORD2 +attributeChangeCB KEYWORD2 +setOnOff KEYWORD2 +getOnOff KEYWORD2 +toggle KEYWORD2 +onChangeOnOff KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/Matter/library.properties b/libraries/Matter/library.properties new file mode 100644 index 00000000000..e08c750fb59 --- /dev/null +++ b/libraries/Matter/library.properties @@ -0,0 +1,9 @@ +name=Matter +version=3.1.0 +author=Rodrigo Garcia | GitHub @SuGlider +maintainer=Rodrigo Garcia +sentence=Library for supporting Matter environment on ESP32. +paragraph=This library implements Matter accessories using WiFi network. +category=Communication +url=https://github.com/espressif/arduino-esp32/ +architectures=esp32 diff --git a/libraries/Matter/src/Matter.cpp b/libraries/Matter/src/Matter.cpp new file mode 100644 index 00000000000..49504babac0 --- /dev/null +++ b/libraries/Matter/src/Matter.cpp @@ -0,0 +1,163 @@ +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include "MatterEndPoint.h" + +using namespace esp_matter; +using namespace esp_matter::attribute; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +constexpr auto k_timeout_seconds = 300; + +static bool _matter_has_started = false; +static node::config_t node_config; +static node_t *deviceNode = NULL; + +typedef void *app_driver_handle_t; +esp_err_t matter_light_attribute_update( + app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val +); + +// This callback is called for every attribute update. The callback implementation shall +// handle the desired attributes and return an appropriate error code. If the attribute +// is not of your interest, please do not return an error code and strictly return ESP_OK. +static esp_err_t app_attribute_update_cb( + attribute::callback_type_t type, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val, void *priv_data +) { + esp_err_t err = ESP_OK; + MatterEndPoint *ep = (MatterEndPoint *)priv_data; // endpoint pointer to base class + switch (type) { + case PRE_UPDATE: // Callback before updating the value in the database + log_i("Attribute update callback: PRE_UPDATE"); + if (ep != NULL) { + err = ep->attributeChangeCB(endpoint_id, cluster_id, attribute_id, val) ? ESP_OK : ESP_FAIL; + } + break; + case POST_UPDATE: // Callback after updating the value in the database + log_i("Attribute update callback: POST_UPDATE"); + break; + case READ: // Callback for reading the attribute value. This is used when the `ATTRIBUTE_FLAG_OVERRIDE` is set. + log_i("Attribute update callback: READ"); + break; + case WRITE: // Callback for writing the attribute value. This is used when the `ATTRIBUTE_FLAG_OVERRIDE` is set. + log_i("Attribute update callback: WRITE"); + break; + default: log_i("Attribute update callback: Unknown type %d", type); + } + return err; +} + +// This callback is invoked when clients interact with the Identify Cluster. +// In the callback implementation, an endpoint can identify itself. (e.g., by flashing an LED or light). +static esp_err_t app_identification_cb(identification::callback_type_t type, uint16_t endpoint_id, uint8_t effect_id, uint8_t effect_variant, void *priv_data) { + log_i("Identification callback: type: %u, effect: %u, variant: %u", type, effect_id, effect_variant); + return ESP_OK; +} + +// This callback is invoked for all Matter events. The application can handle the events as required. +static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) { + switch (event->Type) { + case chip::DeviceLayer::DeviceEventType::kInterfaceIpAddressChanged: + log_i( + "Interface %s Address changed", event->InterfaceIpAddressChanged.Type == chip::DeviceLayer::InterfaceIpChangeType::kIpV4_Assigned ? "IPv4" : "IPV6" + ); + break; + case chip::DeviceLayer::DeviceEventType::kCommissioningComplete: log_i("Commissioning complete"); break; + case chip::DeviceLayer::DeviceEventType::kFailSafeTimerExpired: log_i("Commissioning failed, fail safe timer expired"); break; + case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStarted: log_i("Commissioning session started"); break; + case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStopped: log_i("Commissioning session stopped"); break; + case chip::DeviceLayer::DeviceEventType::kCommissioningWindowOpened: log_i("Commissioning window opened"); break; + case chip::DeviceLayer::DeviceEventType::kCommissioningWindowClosed: log_i("Commissioning window closed"); break; + case chip::DeviceLayer::DeviceEventType::kFabricRemoved: + { + log_i("Fabric removed successfully"); + if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0) { + log_i("No fabric left, opening commissioning window"); + chip::CommissioningWindowManager &commissionMgr = chip::Server::GetInstance().GetCommissioningWindowManager(); + constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds16(k_timeout_seconds); + if (!commissionMgr.IsCommissioningWindowOpen()) { + // After removing last fabric, it does not remove the Wi-Fi credentials and still has IP connectivity so, only advertising on DNS-SD. + CHIP_ERROR err = commissionMgr.OpenBasicCommissioningWindow(kTimeoutSeconds, chip::CommissioningWindowAdvertisement::kDnssdOnly); + if (err != CHIP_NO_ERROR) { + log_e("Failed to open commissioning window, err:%" CHIP_ERROR_FORMAT, err.Format()); + } + } + } + break; + } + case chip::DeviceLayer::DeviceEventType::kFabricWillBeRemoved: log_i("Fabric will be removed"); break; + case chip::DeviceLayer::DeviceEventType::kFabricUpdated: log_i("Fabric is updated"); break; + case chip::DeviceLayer::DeviceEventType::kFabricCommitted: log_i("Fabric is committed"); break; + case chip::DeviceLayer::DeviceEventType::kBLEDeinitialized: log_i("BLE deinitialized and memory reclaimed"); break; + default: break; + } +} + +void ArduinoMatter::_init() { + if (_matter_has_started) { + return; + } + + // Create a Matter node and add the mandatory Root Node device type on endpoint 0 + // node handle can be used to add/modify other endpoints. + deviceNode = node::create(&node_config, app_attribute_update_cb, app_identification_cb); + if (deviceNode == nullptr) { + log_e("Failed to create Matter node"); + return; + } + + _matter_has_started = true; +} + +void ArduinoMatter::begin() { + if (!_matter_has_started) { + log_w("No Matter endpoint has been created. Please create an endpoint first."); + return; + } + + /* Matter start */ + esp_err_t err = esp_matter::start(app_event_cb); + if (err != ESP_OK) { + log_e("Failed to start Matter, err:%d", err); + _matter_has_started = false; + } +} + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +bool ArduinoMatter::isThreadConnected() { + return false; // Thread Network TBD +} +#endif + +bool ArduinoMatter::isDeviceCommissioned() { + return chip::Server::GetInstance().GetFabricTable().FabricCount() > 0; +} + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION +bool ArduinoMatter::isWiFiConnected() { + return chip::DeviceLayer::ConnectivityMgr().IsWiFiStationConnected(); +} +#endif + +bool ArduinoMatter::isDeviceConnected() { + bool retCode = false; +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + retCode |= ArduinoMatter::isThreadConnected(); +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION + retCode |= ArduinoMatter::isWiFiConnected(); +#endif + return retCode; +} + +void ArduinoMatter::decommission() { + esp_matter::factory_reset(); +} + +// Global Matter Object +ArduinoMatter Matter; + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/Matter.h b/libraries/Matter/src/Matter.h new file mode 100644 index 00000000000..a1ce0f2f644 --- /dev/null +++ b/libraries/Matter/src/Matter.h @@ -0,0 +1,40 @@ +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +using namespace esp_matter; + +class ArduinoMatter { +public: + static inline String getManualPairingCode() { + // return the pairing code for manual pairing + return String("34970112332"); + } + static inline String getOnboardingQRCodeUrl() { + // return the URL for the QR code for onboarding + return String("https://project-chip.github.io/connectedhomeip/qrcode.html?data=MT:Y.K9042C00KA0648G00"); + } + static void begin(); + static bool isDeviceCommissioned(); +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION + static bool isWiFiConnected(); +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + static bool isThreadConnected(); +#endif + static bool isDeviceConnected(); + static void decommission(); + + // list of Matter EndPoints Friend Classes + friend class MatterOnOffLight; + +protected: + static void _init(); +}; + +extern ArduinoMatter Matter; + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndPoint.h b/libraries/Matter/src/MatterEndPoint.h new file mode 100644 index 00000000000..2be5bf5bb5d --- /dev/null +++ b/libraries/Matter/src/MatterEndPoint.h @@ -0,0 +1,23 @@ +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +// Matter Endpoint Base Class. Controls the endpoint ID and allows the child class to overwrite attribute change call +class MatterEndPoint { +public: + uint16_t getEndPointId() { + return endpoint_id; + } + void setEndPointId(uint16_t ep) { + endpoint_id = ep; + } + + virtual bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) = 0; + +protected: + uint16_t endpoint_id = 0; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterOnOffLight.cpp b/libraries/Matter/src/MatterOnOffLight.cpp new file mode 100644 index 00000000000..7e8926ffdef --- /dev/null +++ b/libraries/Matter/src/MatterOnOffLight.cpp @@ -0,0 +1,107 @@ +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +bool MatterOnOffLight::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_w("Matter On-Off Light device has not begun."); + return false; + } + + if (endpoint_id == getEndPointId()) { + if (cluster_id == OnOff::Id) { + if (attribute_id == OnOff::Attributes::OnOff::Id) { + if (_onChangeCB != NULL) { + ret = _onChangeCB(val->val.b); + log_d("OnOffLight state changed to %d", val->val.b); + if (ret == true) { + state = val->val.b; + } + } + } + } + } + return ret; +} + +MatterOnOffLight::MatterOnOffLight() {} + +MatterOnOffLight::~MatterOnOffLight() { + end(); +} + +bool MatterOnOffLight::begin(bool initialState) { + ArduinoMatter::_init(); + on_off_light::config_t light_config; + light_config.on_off.on_off = initialState; + state = initialState; + light_config.on_off.lighting.start_up_on_off = nullptr; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = on_off_light::create(node::get(), &light_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create on-off light endpoint"); + return false; + } + + setEndPointId(endpoint::get_id(endpoint)); + log_i("On-Off Light created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterOnOffLight::end() { + started = false; +} + +bool MatterOnOffLight::setOnOff(bool newState) { + if (!started) { + log_w("Matter On-Off Light device has not begun."); + return false; + } + + // avoid processing the a "no-change" + if (state == newState) { + return true; + } + + state = newState; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, OnOff::Id); + attribute_t *attribute = attribute::get(cluster, OnOff::Attributes::OnOff::Id); + + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + + if (val.val.b != state) { + val.val.b = state; + attribute::update(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, &val); + } + return true; +} + +bool MatterOnOffLight::getOnOff() { + return state; +} + +bool MatterOnOffLight::toggle() { + return setOnOff(!state); +} + +MatterOnOffLight::operator bool() { + return getOnOff(); +} + +void MatterOnOffLight::operator=(bool newState) { + setOnOff(newState); +} +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterOnOffLight.h b/libraries/Matter/src/MatterOnOffLight.h new file mode 100644 index 00000000000..39220652e21 --- /dev/null +++ b/libraries/Matter/src/MatterOnOffLight.h @@ -0,0 +1,34 @@ +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterOnOffLight : public MatterEndPoint { +public: + MatterOnOffLight(); + ~MatterOnOffLight(); + virtual bool begin(bool initialState = false); // default initial state is off + void end(); // this will just stop processing Light Matter events + + bool setOnOff(bool newState); // returns true if successful + bool getOnOff(); // returns current light state + bool toggle(); // returns true if successful + + operator bool(); // returns current light state + void operator=(bool state); // turns light on or off + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + // User Callback for whenever the Light state is changed by the Matter Controller + using EndPointCB = std::function; + void onChangeOnOff(EndPointCB onChangeCB) { + _onChangeCB = onChangeCB; + } + +protected: + bool started = false; + bool state = false; // default initial state is off, but it can be changed by begin(bool) + EndPointCB _onChangeCB = NULL; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ From 01789a7a894bee8c75e25a6c99b5059174c9b8a5 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Mon, 21 Oct 2024 12:29:05 -0300 Subject: [PATCH 068/409] fix(formatting): Fix formatting and disable JSON hook (#10492) --- .pre-commit-config.yaml | 1 + tests/performance/fibonacci/test_fibonacci.py | 1 + tests/validation/gpio/test_gpio.py | 1 + tests/validation/nvs/test_nvs.py | 1 + tests/validation/periman/test_periman.py | 1 + tests/validation/wifi/test_wifi.py | 1 + 6 files changed, 6 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0aff5b6f07b..6a949631bd9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,6 +26,7 @@ repos: - id: trailing-whitespace args: [--markdown-linebreak-ext=md] - id: pretty-format-json + stages: [manual] args: [--autofix] types_or: [json] exclude: | diff --git a/tests/performance/fibonacci/test_fibonacci.py b/tests/performance/fibonacci/test_fibonacci.py index ced9368184e..cf560d9691c 100644 --- a/tests/performance/fibonacci/test_fibonacci.py +++ b/tests/performance/fibonacci/test_fibonacci.py @@ -4,6 +4,7 @@ fib_results = {} + def fib(n): if n < 2: return n diff --git a/tests/validation/gpio/test_gpio.py b/tests/validation/gpio/test_gpio.py index f11b9fd99cc..8aa3a42dcc6 100644 --- a/tests/validation/gpio/test_gpio.py +++ b/tests/validation/gpio/test_gpio.py @@ -1,5 +1,6 @@ import logging + def test_gpio(dut): LOGGER = logging.getLogger(__name__) diff --git a/tests/validation/nvs/test_nvs.py b/tests/validation/nvs/test_nvs.py index a2b4842fa91..424095a49ba 100644 --- a/tests/validation/nvs/test_nvs.py +++ b/tests/validation/nvs/test_nvs.py @@ -1,5 +1,6 @@ import logging + def test_nvs(dut): LOGGER = logging.getLogger(__name__) diff --git a/tests/validation/periman/test_periman.py b/tests/validation/periman/test_periman.py index a2d25f5ba09..2728abcef80 100644 --- a/tests/validation/periman/test_periman.py +++ b/tests/validation/periman/test_periman.py @@ -1,5 +1,6 @@ import logging + def test_periman(dut): LOGGER = logging.getLogger(__name__) peripherals = [ diff --git a/tests/validation/wifi/test_wifi.py b/tests/validation/wifi/test_wifi.py index 769283b06bd..5049aae7b85 100644 --- a/tests/validation/wifi/test_wifi.py +++ b/tests/validation/wifi/test_wifi.py @@ -1,5 +1,6 @@ import logging + def test_wifi(dut): LOGGER = logging.getLogger(__name__) From f1f0e4d4f302f10c663beac581bda7bdb8039270 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 21 Oct 2024 14:43:54 -0300 Subject: [PATCH 069/409] Update MatterOnOffLight.ino --- .../Matter/examples/MatterOnOffLight/MatterOnOffLight.ino | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino b/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino index 64981b23a66..736e033e3d2 100644 --- a/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino +++ b/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino @@ -37,9 +37,8 @@ bool setLightOnOff(bool state) { } // WiFi is manually set and started - -const char *ssid = "Apartment B15"; // Change this to your WiFi SSID -const char *password = "flat-pony-body"; // Change this to your WiFi password +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password void setup() { // Initialize the USER BUTTON (Boot button) GPIO that will act as a toggle switch From e509d33d27a6933223679d5813245e10481ab5a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:56:18 +0200 Subject: [PATCH 070/409] fix(ci): Chnage approach in listing the changed boards (#10495) --- .github/scripts/find_new_boards.sh | 54 +++++++++--------------------- 1 file changed, 16 insertions(+), 38 deletions(-) diff --git a/.github/scripts/find_new_boards.sh b/.github/scripts/find_new_boards.sh index 77c98877d2a..083f1448e83 100755 --- a/.github/scripts/find_new_boards.sh +++ b/.github/scripts/find_new_boards.sh @@ -8,53 +8,32 @@ url="https://api.github.com/repos/$owner_repository/pulls/$pr_number/files" echo $url # Get changes in boards.txt file from PR -Patch=$(curl $url | jq -r '.[] | select(.filename == "boards.txt") | .patch ') +Boards_modified_url=$(curl -s $url | jq -r '.[] | select(.filename == "boards.txt") | .raw_url') -# Extract only changed lines number and count -substring_patch=$(echo "$Patch" | grep -o '@@[^@]*@@') +# Echo the modified boards.txt file URL +echo "Modified boards.txt file URL:" +echo $Boards_modified_url -params_array=() +# Download the modified boards.txt file +curl -L -o boards_pr.txt $Boards_modified_url -IFS=$'\n' read -d '' -ra params <<< $(echo "$substring_patch" | grep -oE '[-+][0-9]+,[0-9]+') +# Compare boards.txt file in the repo with the modified file +diff=$(diff -u boards.txt boards_pr.txt) -for param in "${params[@]}" -do - echo "The parameter is $param" - params_array+=("$param") -done +# Extract added or modified lines (lines starting with '+' or '-') +modified_lines=$(echo "$diff" | grep -E '^[+-][^+-]') boards_array=() previous_board="" file="boards.txt" -# Loop through boards.txt file and extract all boards that were added -for (( c=0; c<${#params_array[@]}; c+=2 )) +# Extract board names from the modified lines, and add them to the boards_array +while read -r line do - deletion_count=$( echo "${params_array[c]}" | cut -d',' -f2 | cut -d' ' -f1 ) - addition_line=$( echo "${params_array[c+1]}" | cut -d'+' -f2 | cut -d',' -f1 ) - addition_count=$( echo "${params_array[c+1]}" | cut -d'+' -f2 | cut -d',' -f2 | cut -d' ' -f1 ) - addition_end=$(($addition_line+$addition_count)) - - addition_line=$(($addition_line + 3)) - addition_end=$(($addition_end - $deletion_count)) - - echo $addition_line - echo $addition_end - - i=0 - - while read -r line - do - i=$((i+1)) - if [ $i -lt $addition_line ] - then - continue - elif [ $i -gt $addition_end ] - then - break - fi board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1) - if [ "$board_name" != "" ] && [ "$board_name" != "esp32_family" ] + # remove + or - from the board name at the beginning + board_name=$(echo "$board_name" | sed 's/^[+-]//') + if [ "$board_name" != "" ] && [ "$board_name" != "+" ] && [ "$board_name" != "-" ] && [ "$board_name" != "esp32_family" ] then if [ "$board_name" != "$previous_board" ] then @@ -63,8 +42,7 @@ do echo "Added 'espressif:esp32:$board_name' to array" fi fi - done < "$file" -done +done <<< "$modified_lines" # Create JSON like string with all boards found and pass it to env variable board_count=${#boards_array[@]} From 0045cfa658a4cbcbb800462b9e986966c32ed198 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 21 Oct 2024 19:23:28 -0300 Subject: [PATCH 071/409] fix(matter): change place of wifi credentials in code --- .../Matter/examples/MatterOnOffLight/MatterOnOffLight.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino b/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino index 736e033e3d2..751bcb3d99e 100644 --- a/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino +++ b/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino @@ -22,6 +22,10 @@ const uint8_t ledPin = 2; // Set your pin here if your board has not defined LE // set your board USER BUTTON pin here const uint8_t buttonPin = 0; // Set your pin here. Using BOOT Button. C6/C3 use GPIO9. +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + // Matter Protocol Endpoint Callback bool setLightOnOff(bool state) { Serial.printf("User Callback :: New Light State = %s\r\n", state ? "ON" : "OFF"); @@ -36,10 +40,6 @@ bool setLightOnOff(bool state) { return true; } -// WiFi is manually set and started -const char *ssid = "your-ssid"; // Change this to your WiFi SSID -const char *password = "your-password"; // Change this to your WiFi password - void setup() { // Initialize the USER BUTTON (Boot button) GPIO that will act as a toggle switch pinMode(buttonPin, INPUT_PULLUP); From 7a33a9eeffd9ff69aaad72aead4d79d532cc1235 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 21 Oct 2024 19:25:20 -0300 Subject: [PATCH 072/409] fix(matter): change the place of wifi credentials in the code --- .../MatterComposedLights/MatterComposedLights.ino | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino b/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino index 63f154d4492..5d4acb557f5 100644 --- a/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino +++ b/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino @@ -9,6 +9,10 @@ MatterOnOffLight OnOffLight1; MatterOnOffLight OnOffLight2; MatterOnOffLight OnOffLight3; +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + // Matter Protocol Endpoint Callback for each Light Accessory bool setLightOnOff1(bool state) { Serial.printf("CB-Light1 changed state to: %s\r\n", state ? "ON" : "OFF"); @@ -25,11 +29,6 @@ bool setLightOnOff3(bool state) { return true; } -// WiFi is manually set and started - -const char *ssid = "your-ssid"; // Change this to your WiFi SSID -const char *password = "your-password"; // Change this to your WiFi password - void setup() { Serial.begin(115200); while (!Serial) { From 8ac076c44c45a80b9f02ed197340241d6894fd41 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 21 Oct 2024 19:26:34 -0300 Subject: [PATCH 073/409] fix(matter): empty line removing - style --- .../examples/MatterCommissionTest/MatterCommissionTest.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino b/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino index a9afb0c4484..48ec0355092 100644 --- a/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino +++ b/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino @@ -8,7 +8,6 @@ MatterOnOffLight OnOffLight; // WiFi is manually set and started - const char *ssid = "your-ssid"; // Change this to your WiFi SSID const char *password = "your-password"; // Change this to your WiFi password From 20a28b58bc3fd5ff613e2860d65e0953446f264b Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 22 Oct 2024 12:13:04 +0300 Subject: [PATCH 074/409] fix(net): Do not use netif_index_to_name Causes error on recent IDF builds --- cores/esp32/IPAddress.cpp | 14 +++++++------- libraries/Network/src/NetworkInterface.cpp | 8 ++------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/cores/esp32/IPAddress.cpp b/cores/esp32/IPAddress.cpp index b4fc4c3f7e0..74fabaf0f9c 100644 --- a/cores/esp32/IPAddress.cpp +++ b/cores/esp32/IPAddress.cpp @@ -344,13 +344,13 @@ size_t IPAddress::printTo(Print &p, bool includeZone) const { n += p.print(':'); } } - // add a zone if zone-id is non-zero - if (_zone > 0 && includeZone) { - n += p.print('%'); - char if_name[NETIF_NAMESIZE]; - netif_index_to_name(_zone, if_name); - n += p.print(if_name); - } + // add a zone if zone-id is non-zero (causes exception on recent IDF builds) + // if (_zone > 0 && includeZone) { + // n += p.print('%'); + // char if_name[NETIF_NAMESIZE]; + // netif_index_to_name(_zone, if_name); + // n += p.print(if_name); + // } return n; } diff --git a/libraries/Network/src/NetworkInterface.cpp b/libraries/Network/src/NetworkInterface.cpp index f4bb1d48392..e699d609ca1 100644 --- a/libraries/Network/src/NetworkInterface.cpp +++ b/libraries/Network/src/NetworkInterface.cpp @@ -115,14 +115,10 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void *event_data) { setStatusBits(ESP_NETIF_HAS_LOCAL_IP6_BIT); } #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE - char if_name[NETIF_NAMESIZE] = { - 0, - }; - netif_index_to_name(event->ip6_info.ip.zone, if_name); static const char *addr_types[] = {"UNKNOWN", "GLOBAL", "LINK_LOCAL", "SITE_LOCAL", "UNIQUE_LOCAL", "IPV4_MAPPED_IPV6"}; log_v( - "IF %s Got IPv6: Interface: %d, IP Index: %d, Type: %s, Zone: %d (%s), Address: " IPV6STR, desc(), _interface_id, event->ip_index, addr_types[addr_type], - event->ip6_info.ip.zone, if_name, IPV62STR(event->ip6_info.ip) + "IF %s Got IPv6: Interface: %d, IP Index: %d, Type: %s, Zone: %d, Address: " IPV6STR, desc(), _interface_id, event->ip_index, addr_types[addr_type], + event->ip6_info.ip.zone, IPV62STR(event->ip6_info.ip) ); #endif memcpy(&arduino_event.event_info.got_ip6, event_data, sizeof(ip_event_got_ip6_t)); From 774201ade36955bad468d616170006c8dbdf747f Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 22 Oct 2024 15:19:24 +0300 Subject: [PATCH 075/409] fix(build): Require main component to include all components --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e552299b8aa..5a8955248ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -312,7 +312,7 @@ endforeach() set(includedirs variants/${CONFIG_ARDUINO_VARIANT}/ cores/esp32/ ${ARDUINO_LIBRARIES_INCLUDEDIRS}) set(srcs ${CORE_SRCS} ${ARDUINO_LIBRARIES_SRCS}) set(priv_includes cores/esp32/libb64) -set(requires spi_flash esp_partition mbedtls wpa_supplicant esp_adc esp_eth http_parser esp_ringbuf esp_driver_gptimer esp_driver_usb_serial_jtag driver espressif__network_provisioning) +set(requires main spi_flash esp_partition mbedtls wpa_supplicant esp_adc esp_eth http_parser esp_ringbuf esp_driver_gptimer esp_driver_usb_serial_jtag driver espressif__network_provisioning) set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support bt esp_hid usb esp_psram ${ARDUINO_LIBRARIES_REQUIRES}) if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_OpenThread) From 16314664269019a57665d221a39e655190224e06 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 22 Oct 2024 15:55:37 +0300 Subject: [PATCH 076/409] fix(build): Update required components and menu --- CMakeLists.txt | 8 +++++++- Kconfig.projbuild | 30 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a8955248ad..57220990c1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -312,7 +312,7 @@ endforeach() set(includedirs variants/${CONFIG_ARDUINO_VARIANT}/ cores/esp32/ ${ARDUINO_LIBRARIES_INCLUDEDIRS}) set(srcs ${CORE_SRCS} ${ARDUINO_LIBRARIES_SRCS}) set(priv_includes cores/esp32/libb64) -set(requires main spi_flash esp_partition mbedtls wpa_supplicant esp_adc esp_eth http_parser esp_ringbuf esp_driver_gptimer esp_driver_usb_serial_jtag driver espressif__network_provisioning) +set(requires spi_flash esp_partition mbedtls wpa_supplicant esp_adc esp_eth http_parser esp_ringbuf esp_driver_gptimer esp_driver_usb_serial_jtag driver espressif__network_provisioning) set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support bt esp_hid usb esp_psram ${ARDUINO_LIBRARIES_REQUIRES}) if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_OpenThread) @@ -372,3 +372,9 @@ endif() if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ArduinoOTA) maybe_add_component(esp_https_ota) endif() +if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ESP_SR) + maybe_add_component(espressif__esp_sr) +endif() +if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_Matter) + maybe_add_component(espressif__esp_matter) +endif() diff --git a/Kconfig.projbuild b/Kconfig.projbuild index 2085a11ea7d..9966463f8c1 100644 --- a/Kconfig.projbuild +++ b/Kconfig.projbuild @@ -266,6 +266,11 @@ config ARDUINO_SELECTIVE_Wire depends on ARDUINO_SELECTIVE_COMPILATION default y +config ARDUINO_SELECTIVE_ESP_SR + bool "Enable ESP-SR" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + config ARDUINO_SELECTIVE_EEPROM bool "Enable EEPROM" depends on ARDUINO_SELECTIVE_COMPILATION @@ -286,6 +291,11 @@ config ARDUINO_SELECTIVE_Update depends on ARDUINO_SELECTIVE_COMPILATION default y +config ARDUINO_SELECTIVE_Zigbee + bool "Enable Zigbee" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + config ARDUINO_SELECTIVE_FS bool "Enable FS" depends on ARDUINO_SELECTIVE_COMPILATION @@ -358,6 +368,11 @@ config ARDUINO_SELECTIVE_HTTPClient select ARDUINO_SELECTIVE_NetworkClientSecure default y +config ARDUINO_SELECTIVE_Matter + bool "Enable Matter" + depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network + default y + config ARDUINO_SELECTIVE_NetBIOS bool "Enable NetBIOS" depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network @@ -399,4 +414,19 @@ config ARDUINO_SELECTIVE_SimpleBLE depends on ARDUINO_SELECTIVE_COMPILATION default y +config ARDUINO_SELECTIVE_RainMaker + bool "Enable RainMaker" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + +config ARDUINO_SELECTIVE_OpenThread + bool "Enable OpenThread" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + +config ARDUINO_SELECTIVE_Insights + bool "Enable Insights" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + endmenu From aefe8a55d35469a8d8e7022971c89627dc6a1015 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Tue, 22 Oct 2024 17:40:11 +0300 Subject: [PATCH 077/409] IDF release/v5.3 59550599 (#10498) --- package/package_esp32_index.template.json | 68 +++++++++++------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index dc32ddae953..b1c7e23734c 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -42,7 +42,7 @@ { "packager": "esp32", "name": "esp32-arduino-libs", - "version": "idf-release_v5.3-707d097b" + "version": "idf-release_v5.3-59550599" }, { "packager": "esp32", @@ -95,63 +95,63 @@ "tools": [ { "name": "esp32-arduino-libs", - "version": "idf-release_v5.3-707d097b", + "version": "idf-release_v5.3-59550599", "systems": [ { "host": "i686-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", - "size": "343601720" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", + "size": "343729890" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", - "size": "343601720" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", + "size": "343729890" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", - "size": "343601720" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", + "size": "343729890" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", - "size": "343601720" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", + "size": "343729890" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", - "size": "343601720" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", + "size": "343729890" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", - "size": "343601720" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", + "size": "343729890" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", - "size": "343601720" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", + "size": "343729890" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-707d097b.zip", - "checksum": "SHA-256:e09d25302eeb1d0e40001280c8fb17e87974496046b929536bb56a50007aa0eb", - "size": "343601720" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", + "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", + "size": "343729890" } ] }, From 0eee5c4a13c6808faef0c9476073d422ed326db4 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Tue, 22 Oct 2024 20:17:40 +0300 Subject: [PATCH 078/409] fix(arduino): Move extra_flags to flags (#10493) This will help external library developers --- platform.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/platform.txt b/platform.txt index c97c374e75d..00052ec807e 100644 --- a/platform.txt +++ b/platform.txt @@ -50,10 +50,10 @@ compiler.common_werror_flags=-Werror=return-type # Compile Flags compiler.cpreprocessor.flags="@{compiler.sdk.path}/flags/defines" "-I{build.source.path}" -iprefix "{compiler.sdk.path}/include/" "@{compiler.sdk.path}/flags/includes" "-I{compiler.sdk.path}/{build.memory_type}/include" -compiler.c.flags="@{compiler.sdk.path}/flags/c_flags" {compiler.warning_flags} {compiler.optimization_flags} {compiler.common_werror_flags} -compiler.cpp.flags="@{compiler.sdk.path}/flags/cpp_flags" {compiler.warning_flags} {compiler.optimization_flags} {compiler.common_werror_flags} -compiler.S.flags="@{compiler.sdk.path}/flags/S_flags" {compiler.warning_flags} {compiler.optimization_flags} -compiler.c.elf.flags="@{compiler.sdk.path}/flags/ld_flags" "@{compiler.sdk.path}/flags/ld_scripts" +compiler.c.flags=-MMD -c "@{compiler.sdk.path}/flags/c_flags" {compiler.warning_flags} {compiler.optimization_flags} {compiler.common_werror_flags} +compiler.cpp.flags=-MMD -c "@{compiler.sdk.path}/flags/cpp_flags" {compiler.warning_flags} {compiler.optimization_flags} {compiler.common_werror_flags} +compiler.S.flags=-MMD -c -x assembler-with-cpp "@{compiler.sdk.path}/flags/S_flags" {compiler.warning_flags} {compiler.optimization_flags} +compiler.c.elf.flags="-Wl,--Map={build.path}/{build.project_name}.map" "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.sdk.path}/{build.memory_type}" "-Wl,--wrap=esp_panic_handler" "@{compiler.sdk.path}/flags/ld_flags" "@{compiler.sdk.path}/flags/ld_scripts" compiler.c.elf.libs="@{compiler.sdk.path}/flags/ld_libs" compiler.ar.flags=cr @@ -67,10 +67,10 @@ compiler.ar.cmd={compiler.prefix}gcc-ar compiler.size.cmd={compiler.prefix}size # These can be overridden in platform.local.txt -compiler.c.extra_flags=-MMD -c -compiler.cpp.extra_flags=-MMD -c -compiler.S.extra_flags=-MMD -c -x assembler-with-cpp -compiler.c.elf.extra_flags="-Wl,--Map={build.path}/{build.project_name}.map" "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.sdk.path}/{build.memory_type}" "-Wl,--wrap=esp_panic_handler" +compiler.c.extra_flags= +compiler.cpp.extra_flags= +compiler.S.extra_flags= +compiler.c.elf.extra_flags= compiler.ar.extra_flags= compiler.objcopy.eep.extra_flags= compiler.elf2hex.extra_flags= From 4944dd0df3dcf452b86a72e652ef3bc08eb7da83 Mon Sep 17 00:00:00 2001 From: clashman Date: Tue, 22 Oct 2024 19:22:15 +0200 Subject: [PATCH 079/409] fix(littlefs): Add missing dependency (#10496) --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a858ee79cd..16639e689c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,6 +157,7 @@ set(ARDUINO_LIBRARY_HTTPUpdate_SRCS libraries/HTTPUpdate/src/HTTPUpdate.cpp) set(ARDUINO_LIBRARY_Insights_SRCS libraries/Insights/src/Insights.cpp) set(ARDUINO_LIBRARY_LittleFS_SRCS libraries/LittleFS/src/LittleFS.cpp) +set(ARDUINO_LIBRARY_LittleFS_REQUIRES esp_littlefs) set(ARDUINO_LIBRARY_NetBIOS_SRCS libraries/NetBIOS/src/NetBIOS.cpp) From 4285912a46d6b5283a55d2342a7ca5ed1b926e15 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Tue, 22 Oct 2024 20:40:15 +0300 Subject: [PATCH 080/409] fix(cmake): Use proper name for LittleFS component --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 16639e689c7..d7e5ae83b35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,7 +157,7 @@ set(ARDUINO_LIBRARY_HTTPUpdate_SRCS libraries/HTTPUpdate/src/HTTPUpdate.cpp) set(ARDUINO_LIBRARY_Insights_SRCS libraries/Insights/src/Insights.cpp) set(ARDUINO_LIBRARY_LittleFS_SRCS libraries/LittleFS/src/LittleFS.cpp) -set(ARDUINO_LIBRARY_LittleFS_REQUIRES esp_littlefs) +set(ARDUINO_LIBRARY_LittleFS_REQUIRES joltwallet__littlefs) set(ARDUINO_LIBRARY_NetBIOS_SRCS libraries/NetBIOS/src/NetBIOS.cpp) From dc1a49e6f0c51eeae0179e909cc9cc3afa82d802 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Wed, 23 Oct 2024 02:04:03 +0300 Subject: [PATCH 081/409] IDF release/v5.3 (#10503) * fix(psram): Do not disable PSRAM when used as component Information: https://github.com/espressif/arduino-esp32/issues/10500 * IDF release/v5.3 59550599 --- cores/esp32/esp32-hal-psram.h | 3 ++- package/package_esp32_index.template.json | 32 +++++++++++------------ 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/cores/esp32/esp32-hal-psram.h b/cores/esp32/esp32-hal-psram.h index e82af1342c2..69c1c625157 100644 --- a/cores/esp32/esp32-hal-psram.h +++ b/cores/esp32/esp32-hal-psram.h @@ -21,7 +21,8 @@ extern "C" { #include "sdkconfig.h" -#ifndef BOARD_HAS_PSRAM +// Clear flags in Arduino IDE when PSRAM is disabled +#if defined(ESP32_ARDUINO_LIB_BUILDER) && !defined(BOARD_HAS_PSRAM) #ifdef CONFIG_SPIRAM_SUPPORT #undef CONFIG_SPIRAM_SUPPORT #endif diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index b1c7e23734c..ad941e841f6 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -101,57 +101,57 @@ "host": "i686-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", - "size": "343729890" + "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", + "size": "343730097" }, { "host": "x86_64-mingw32", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", - "size": "343729890" + "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", + "size": "343730097" }, { "host": "arm64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", - "size": "343729890" + "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", + "size": "343730097" }, { "host": "x86_64-apple-darwin", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", - "size": "343729890" + "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", + "size": "343730097" }, { "host": "x86_64-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", - "size": "343729890" + "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", + "size": "343730097" }, { "host": "i686-pc-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", - "size": "343729890" + "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", + "size": "343730097" }, { "host": "aarch64-linux-gnu", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", - "size": "343729890" + "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", + "size": "343730097" }, { "host": "arm-linux-gnueabihf", "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d8edd2fcf990c5af4627c9446efd8c5badb34cfcccfcc3b63bb117d1da77bfae", - "size": "343729890" + "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", + "size": "343730097" } ] }, From 0f5219df0e3222d9188334187b6bd0f11b7e2316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Wed, 23 Oct 2024 09:24:36 +0200 Subject: [PATCH 082/409] fix(ci): Get correct file for the diff (#10507) --- .github/scripts/find_new_boards.sh | 31 +++++++++++++++--------------- .github/workflows/boards.yml | 2 +- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/.github/scripts/find_new_boards.sh b/.github/scripts/find_new_boards.sh index 083f1448e83..706676b4a4c 100755 --- a/.github/scripts/find_new_boards.sh +++ b/.github/scripts/find_new_boards.sh @@ -2,30 +2,31 @@ # Get inputs from command owner_repository=$1 -pr_number=$2 +base_ref=$2 -url="https://api.github.com/repos/$owner_repository/pulls/$pr_number/files" -echo $url +# Download the boards.txt file from the base branch +curl -L -o boards_base.txt https://raw.githubusercontent.com/$owner_repository/$base_ref/boards.txt -# Get changes in boards.txt file from PR -Boards_modified_url=$(curl -s $url | jq -r '.[] | select(.filename == "boards.txt") | .raw_url') +# Compare boards.txt file in the repo with the modified file from PR +diff=$(diff -u boards_base.txt boards.txt) -# Echo the modified boards.txt file URL -echo "Modified boards.txt file URL:" -echo $Boards_modified_url - -# Download the modified boards.txt file -curl -L -o boards_pr.txt $Boards_modified_url - -# Compare boards.txt file in the repo with the modified file -diff=$(diff -u boards.txt boards_pr.txt) +# Check if the diff is empty +if [ -z "$diff" ] +then + echo "No changes in boards.txt file" + echo "FQBNS=" + exit 0 +fi # Extract added or modified lines (lines starting with '+' or '-') modified_lines=$(echo "$diff" | grep -E '^[+-][^+-]') +# Print the modified lines for debugging +echo "Modified lines:" +echo "$modified_lines" + boards_array=() previous_board="" -file="boards.txt" # Extract board names from the modified lines, and add them to the boards_array while read -r line diff --git a/.github/workflows/boards.yml b/.github/workflows/boards.yml index 8d5868b083b..a14f57508c6 100644 --- a/.github/workflows/boards.yml +++ b/.github/workflows/boards.yml @@ -29,7 +29,7 @@ jobs: - name: Get board name run: - bash .github/scripts/find_new_boards.sh ${{ github.repository }} ${{github.event.number}} + bash .github/scripts/find_new_boards.sh ${{ github.repository }} ${{github.base_ref}} test-boards: needs: find-boards From a0139bc37d63efe28fabb2ef57d1e369b4ad38c7 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Wed, 23 Oct 2024 05:45:30 -0300 Subject: [PATCH 083/409] fix(tests): Add missing files to compilation tests (#10501) * fix(tests): Add CMakeLists file to compilation tests * fix(tests): Add variant files that are used in compilation * fix(c2): Move C2 as it is only tested as component --------- Co-authored-by: Me No Dev --- .github/workflows/push.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 0f76fe81fb8..19e53b844f2 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -21,12 +21,20 @@ on: - 'idf_component.yml' - 'Kconfig.projbuild' - 'package.json' + - 'CMakeLists.txt' - '.github/workflows/push.yml' - '.github/scripts/**' - '!.github/scripts/find_*' - '!.github/scripts/on-release.sh' - '!.github/scripts/tests_*' - '!.github/scripts/upload_*' + - "variants/esp32/**/*" + - "variants/esp32s2/**/*" + - "variants/esp32s3/**/*" + - "variants/esp32c2/**/*" + - "variants/esp32c3/**/*" + - "variants/esp32c6/**/*" + - "variants/esp32h2/**/*" concurrency: group: build-${{github.event.pull_request.number || github.ref}} @@ -74,6 +82,12 @@ jobs: - '!tools/platformio-build.py' - 'platform.txt' - 'programmers.txt' + - "variants/esp32/**/*" + - "variants/esp32s2/**/*" + - "variants/esp32s3/**/*" + - "variants/esp32c3/**/*" + - "variants/esp32c6/**/*" + - "variants/esp32h2/**/*" libraries: - 'libraries/**/examples/**' - 'libraries/**/src/**' @@ -92,6 +106,8 @@ jobs: idf: - 'idf_component.yml' - 'Kconfig.projbuild' + - 'CMakeLists.txt' + - "variants/esp32c2/**/*" platformio: - 'package.json' - '.github/scripts/install-platformio-esp32.sh' From 1756bd567cca0c25cc155999bcc15387099ceb29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Wed, 23 Oct 2024 10:46:04 +0200 Subject: [PATCH 084/409] fix(zigbee): Enable internal pull-up resistor (#10491) Enable the internal pull-up resistor for BUTTON_PIN --- .../Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino | 2 +- .../Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino | 2 +- .../Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino | 2 +- .../Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino | 2 +- .../Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino index 1ce9ff56816..01e8c24900f 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino @@ -65,7 +65,7 @@ void setup() { rgbLedWrite(LED_PIN, 0, 0, 0); // Init button for factory reset - pinMode(BUTTON_PIN, INPUT); + pinMode(BUTTON_PIN, INPUT_PULLUP); // Set callback function for light change zbColorLight.onLightChange(setRGBLight); diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino index a494623e436..0514464e8e9 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino @@ -54,7 +54,7 @@ void setup() { } //Init button switch - pinMode(SWITCH_PIN, INPUT); + pinMode(SWITCH_PIN, INPUT_PULLUP); //Optional: set Zigbee device name and model zbSwitch.setManufacturerAndModel("Espressif", "ZigbeeSwitch"); diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino index 2f13357a156..e0bc3747eb3 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino @@ -51,7 +51,7 @@ void setup() { digitalWrite(LED_PIN, LOW); // Init button for factory reset - pinMode(BUTTON_PIN, INPUT); + pinMode(BUTTON_PIN, INPUT_PULLUP); //Optional: set Zigbee device name and model zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb"); diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino index 92249e980ab..b614b136bef 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino @@ -59,7 +59,7 @@ void setup() { } // Init button switch - pinMode(BUTTON_PIN, INPUT); + pinMode(BUTTON_PIN, INPUT_PULLUP); // Optional: set Zigbee device name and model zbTempSensor.setManufacturerAndModel("Espressif", "ZigbeeTempSensor"); diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino index 8f4ea0b543d..ac7b023d6d9 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino @@ -65,7 +65,7 @@ void setup() { } // Init button switch - pinMode(BUTTON_PIN, INPUT); + pinMode(BUTTON_PIN, INPUT_PULLUP); // Set callback functions for temperature and configuration receive zbThermostat.onTempRecieve(recieveSensorTemp); From bcc357c0cac2710d41820961167e8383ecb1aadc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Wed, 23 Oct 2024 10:47:50 +0200 Subject: [PATCH 085/409] fix(ci): Boards test set fail-fast to false (#10508) --- .github/workflows/boards.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/boards.yml b/.github/workflows/boards.yml index a14f57508c6..a309e4ed2ce 100644 --- a/.github/workflows/boards.yml +++ b/.github/workflows/boards.yml @@ -42,6 +42,7 @@ jobs: name: "espressif:esp32" strategy: + fail-fast: false matrix: ${{ fromJson(needs.find-boards.outputs.fqbns) }} steps: From 3502b9c7a9c9fcecc51c1f40ea0180a8563f44cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E4=B9=9D?= <153150268+Sail-211010@users.noreply.github.com> Date: Wed, 23 Oct 2024 20:16:12 +0800 Subject: [PATCH 086/409] Add multiple boards of the Waveshare ESP32-S3-Touch-LCD-1.46 type (#10482) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Delete boards.txt Delete old files * Add files via upload Add new board * Add files via upload Add new board * Delete boards.txt Delete old files, modify the definition of the case error * Add files via upload Modify the definition of the case error * ci(pre-commit): Apply automatic fixes * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: Jan Procházka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Co-authored-by: Me No Dev Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> --- boards.txt | 1899 +++++++++++++++++ .../waveshare_esp32_s3_lcd_146/pins_arduino.h | 64 + .../waveshare_esp32_s3_lcd_147/pins_arduino.h | 64 + .../waveshare_esp32_s3_lcd_185/pins_arduino.h | 64 + .../pins_arduino.h | 64 + .../pins_arduino.h | 64 + .../pins_arduino.h | 64 + .../pins_arduino.h | 64 + .../pins_arduino.h | 64 + 9 files changed, 2411 insertions(+) create mode 100644 variants/waveshare_esp32_s3_lcd_146/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_lcd_147/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_lcd_185/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_relay_6ch/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_touch_lcd_146/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_touch_lcd_185_box/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_touch_lcd_21/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_touch_lcd_28/pins_arduino.h diff --git a/boards.txt b/boards.txt index 74d709ec1e1..8d4cc529ed7 100644 --- a/boards.txt +++ b/boards.txt @@ -44367,3 +44367,1902 @@ cezerio_dev_esp32c6.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP cezerio_dev_esp32c6.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port ############################################################## + +waveshare_esp32_s3_lcd_185.name=Waveshare ESP32-S3-LCD-1.85 +waveshare_esp32_s3_lcd_185.vid.0=0x303a +waveshare_esp32_s3_lcd_185.pid.0=0x8242 +waveshare_esp32_s3_lcd_185.upload_port.0.vid=0x303a +waveshare_esp32_s3_lcd_185.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_lcd_185.bootloader.tool=esptool_py +waveshare_esp32_s3_lcd_185.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_lcd_185.upload.tool=esptool_py +waveshare_esp32_s3_lcd_185.upload.tool.default=esptool_py +waveshare_esp32_s3_lcd_185.upload.tool.network=esp_ota + +waveshare_esp32_s3_lcd_185.upload.maximum_size=1310720 +waveshare_esp32_s3_lcd_185.upload.maximum_data_size=327680 +waveshare_esp32_s3_lcd_185.upload.flags= +waveshare_esp32_s3_lcd_185.upload.extra_flags= +waveshare_esp32_s3_lcd_185.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_185.upload.wait_for_upload_port=false + +waveshare_esp32_s3_lcd_185.serial.disableDTR=false +waveshare_esp32_s3_lcd_185.serial.disableRTS=false + +waveshare_esp32_s3_lcd_185.build.tarch=xtensa +waveshare_esp32_s3_lcd_185.build.bootloader_addr=0x0 +waveshare_esp32_s3_lcd_185.build.target=esp32s3 +waveshare_esp32_s3_lcd_185.build.mcu=esp32s3 +waveshare_esp32_s3_lcd_185.build.core=esp32 +waveshare_esp32_s3_lcd_185.build.variant=waveshare_esp32_s3_lcd_185 +waveshare_esp32_s3_lcd_185.build.board=WAVESHARE_ESP32_S3_LCD_185 + +waveshare_esp32_s3_lcd_185.build.usb_mode=1 +waveshare_esp32_s3_lcd_185.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_185.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_185.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_185.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_185.build.flash_size=16MB +waveshare_esp32_s3_lcd_185.build.flash_freq=120m +waveshare_esp32_s3_lcd_185.build.flash_mode=qio +waveshare_esp32_s3_lcd_185.build.boot=qio +waveshare_esp32_s3_lcd_185.build.boot_freq=80m +waveshare_esp32_s3_lcd_185.build.partitions=default +waveshare_esp32_s3_lcd_185.build.defines= +waveshare_esp32_s3_lcd_185.build.loop_core= +waveshare_esp32_s3_lcd_185.build.event_core= +waveshare_esp32_s3_lcd_185.build.psram_type=opi +waveshare_esp32_s3_lcd_185.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_lcd_185.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_lcd_185.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_lcd_185.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_lcd_185.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_lcd_185.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_lcd_185.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_lcd_185.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_lcd_185.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_lcd_185.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_lcd_185.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_lcd_185.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_lcd_185.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_lcd_185.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_lcd_185.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_lcd_185.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_lcd_185.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_lcd_185.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_lcd_185.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_lcd_185.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_lcd_185.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_lcd_185.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_lcd_185.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 +waveshare_esp32_s3_lcd_185.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_lcd_185.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +waveshare_esp32_s3_lcd_185.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_lcd_185.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_lcd_185.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_lcd_185.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_lcd_185.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_185.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_185.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_lcd_185.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_lcd_185.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_185.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_185.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_185.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_lcd_185.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_lcd_185.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_185.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_185.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_lcd_185.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_lcd_185.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_185.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_lcd_185.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_lcd_185.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_lcd_185.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_lcd_185.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_lcd_185.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_185.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_lcd_185.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_lcd_185.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_lcd_185.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_lcd_185.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_lcd_185.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_lcd_185.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_lcd_185.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_lcd_185.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_lcd_185.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_lcd_185.menu.DebugLevel.none=None +waveshare_esp32_s3_lcd_185.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_lcd_185.menu.DebugLevel.error=Error +waveshare_esp32_s3_lcd_185.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_lcd_185.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_lcd_185.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_lcd_185.menu.DebugLevel.info=Info +waveshare_esp32_s3_lcd_185.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_lcd_185.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_lcd_185.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_lcd_185.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_lcd_185.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_lcd_185.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_lcd_185.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_lcd_185.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_lcd_185.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_lcd_185.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_lcd_185.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_lcd_185.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_lcd_185.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_lcd_185.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_lcd_185.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port + +############################################################## + +waveshare_esp32_s3_touch_lcd_146.name=Waveshare ESP32-S3-Touch-LCD-1.46 +waveshare_esp32_s3_touch_lcd_146.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_146.pid.0=0x8242 +waveshare_esp32_s3_touch_lcd_146.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_146.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_touch_lcd_146.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_146.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_146.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_146.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_146.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_146.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_146.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_146.upload.flags= +waveshare_esp32_s3_touch_lcd_146.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_146.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_146.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_146.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_146.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_146.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_146.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_146.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_146.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_146.build.core=esp32 +waveshare_esp32_s3_touch_lcd_146.build.variant=waveshare_esp32_s3_touch_lcd_146 +waveshare_esp32_s3_touch_lcd_146.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_146 + +waveshare_esp32_s3_touch_lcd_146.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_146.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_146.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_146.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_146.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_146.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_146.build.flash_freq=120m +waveshare_esp32_s3_touch_lcd_146.build.flash_mode=qio +waveshare_esp32_s3_touch_lcd_146.build.boot=qio +waveshare_esp32_s3_touch_lcd_146.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_146.build.partitions=default +waveshare_esp32_s3_touch_lcd_146.build.defines= +waveshare_esp32_s3_touch_lcd_146.build.loop_core= +waveshare_esp32_s3_touch_lcd_146.build.event_core= +waveshare_esp32_s3_touch_lcd_146.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_146.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_touch_lcd_146.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_146.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_146.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_146.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_146.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_146.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_146.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_146.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_146.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_146.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_146.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 +waveshare_esp32_s3_touch_lcd_146.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_146.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +waveshare_esp32_s3_touch_lcd_146.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_146.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_146.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_146.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_146.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_146.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_146.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_146.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_146.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_146.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_146.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_146.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_146.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_146.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_146.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_146.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_146.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_146.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_146.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_146.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_146.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_146.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_touch_lcd_146.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_touch_lcd_146.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_touch_lcd_146.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_touch_lcd_146.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_touch_lcd_146.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port + +############################################################## + +waveshare_esp32_s3_lcd_146.name=Waveshare ESP32-S3-LCD-1.46 +waveshare_esp32_s3_lcd_146.vid.0=0x303a +waveshare_esp32_s3_lcd_146.pid.0=0x8242 +waveshare_esp32_s3_lcd_146.upload_port.0.vid=0x303a +waveshare_esp32_s3_lcd_146.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_lcd_146.bootloader.tool=esptool_py +waveshare_esp32_s3_lcd_146.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_lcd_146.upload.tool=esptool_py +waveshare_esp32_s3_lcd_146.upload.tool.default=esptool_py +waveshare_esp32_s3_lcd_146.upload.tool.network=esp_ota + +waveshare_esp32_s3_lcd_146.upload.maximum_size=1310720 +waveshare_esp32_s3_lcd_146.upload.maximum_data_size=327680 +waveshare_esp32_s3_lcd_146.upload.flags= +waveshare_esp32_s3_lcd_146.upload.extra_flags= +waveshare_esp32_s3_lcd_146.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_146.upload.wait_for_upload_port=false + +waveshare_esp32_s3_lcd_146.serial.disableDTR=false +waveshare_esp32_s3_lcd_146.serial.disableRTS=false + +waveshare_esp32_s3_lcd_146.build.tarch=xtensa +waveshare_esp32_s3_lcd_146.build.bootloader_addr=0x0 +waveshare_esp32_s3_lcd_146.build.target=esp32s3 +waveshare_esp32_s3_lcd_146.build.mcu=esp32s3 +waveshare_esp32_s3_lcd_146.build.core=esp32 +waveshare_esp32_s3_lcd_146.build.variant=waveshare_esp32_s3_lcd_146 +waveshare_esp32_s3_lcd_146.build.board=WAVESHARE_ESP32_S3_LCD_146 + +waveshare_esp32_s3_lcd_146.build.usb_mode=1 +waveshare_esp32_s3_lcd_146.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_146.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_146.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_146.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_146.build.flash_size=16MB +waveshare_esp32_s3_lcd_146.build.flash_freq=120m +waveshare_esp32_s3_lcd_146.build.flash_mode=qio +waveshare_esp32_s3_lcd_146.build.boot=qio +waveshare_esp32_s3_lcd_146.build.boot_freq=80m +waveshare_esp32_s3_lcd_146.build.partitions=default +waveshare_esp32_s3_lcd_146.build.defines= +waveshare_esp32_s3_lcd_146.build.loop_core= +waveshare_esp32_s3_lcd_146.build.event_core= +waveshare_esp32_s3_lcd_146.build.psram_type=opi +waveshare_esp32_s3_lcd_146.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_lcd_146.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_lcd_146.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_lcd_146.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_lcd_146.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_lcd_146.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_lcd_146.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_lcd_146.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_lcd_146.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_lcd_146.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_lcd_146.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_lcd_146.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_lcd_146.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_lcd_146.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_lcd_146.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_lcd_146.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_lcd_146.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_lcd_146.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_lcd_146.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_lcd_146.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_lcd_146.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_lcd_146.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_lcd_146.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 +waveshare_esp32_s3_lcd_146.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_lcd_146.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +waveshare_esp32_s3_lcd_146.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_lcd_146.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_lcd_146.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_lcd_146.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_lcd_146.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_146.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_146.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_lcd_146.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_lcd_146.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_146.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_146.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_146.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_lcd_146.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_lcd_146.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_146.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_146.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_lcd_146.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_lcd_146.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_146.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_lcd_146.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_lcd_146.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_lcd_146.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_lcd_146.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_lcd_146.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_146.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_lcd_146.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_lcd_146.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_lcd_146.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_lcd_146.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_lcd_146.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_lcd_146.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_lcd_146.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_lcd_146.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_lcd_146.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_lcd_146.menu.DebugLevel.none=None +waveshare_esp32_s3_lcd_146.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_lcd_146.menu.DebugLevel.error=Error +waveshare_esp32_s3_lcd_146.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_lcd_146.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_lcd_146.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_lcd_146.menu.DebugLevel.info=Info +waveshare_esp32_s3_lcd_146.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_lcd_146.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_lcd_146.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_lcd_146.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_lcd_146.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_lcd_146.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_lcd_146.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_lcd_146.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_lcd_146.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_lcd_146.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_lcd_146.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_lcd_146.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_lcd_146.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_lcd_146.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_lcd_146.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port + +############################################################## + +waveshare_esp32_s3_touch_lcd_185_box.name=Waveshare ESP32-S3-Touch-LCD-1.85-BOX +waveshare_esp32_s3_touch_lcd_185_box.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_185_box.pid.0=0x8242 +waveshare_esp32_s3_touch_lcd_185_box.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_185_box.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_touch_lcd_185_box.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_185_box.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_185_box.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_185_box.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_185_box.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_185_box.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_185_box.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_185_box.upload.flags= +waveshare_esp32_s3_touch_lcd_185_box.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_185_box.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_185_box.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_185_box.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_185_box.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_185_box.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_185_box.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_185_box.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_185_box.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_185_box.build.core=esp32 +waveshare_esp32_s3_touch_lcd_185_box.build.variant=waveshare_esp32_s3_touch_lcd_185_box +waveshare_esp32_s3_touch_lcd_185_box.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_185_BOX + +waveshare_esp32_s3_touch_lcd_185_box.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_185_box.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185_box.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185_box.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_185_box.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_185_box.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_185_box.build.flash_freq=120m +waveshare_esp32_s3_touch_lcd_185_box.build.flash_mode=qio +waveshare_esp32_s3_touch_lcd_185_box.build.boot=qio +waveshare_esp32_s3_touch_lcd_185_box.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.build.partitions=default +waveshare_esp32_s3_touch_lcd_185_box.build.defines= +waveshare_esp32_s3_touch_lcd_185_box.build.loop_core= +waveshare_esp32_s3_touch_lcd_185_box.build.event_core= +waveshare_esp32_s3_touch_lcd_185_box.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_185_box.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_touch_lcd_185_box.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_185_box.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_185_box.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_185_box.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_185_box.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_185_box.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_185_box.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_185_box.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_185_box.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_185_box.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_185_box.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 +waveshare_esp32_s3_touch_lcd_185_box.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_185_box.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +waveshare_esp32_s3_touch_lcd_185_box.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_185_box.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_185_box.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_185_box.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_185_box.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185_box.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_185_box.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_185_box.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185_box.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_185_box.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_185_box.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_185_box.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_185_box.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_185_box.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_185_box.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_185_box.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_touch_lcd_185_box.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_touch_lcd_185_box.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_touch_lcd_185_box.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_touch_lcd_185_box.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_touch_lcd_185_box.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port + +############################################################## + +waveshare_esp32_s3_lcd_147.name=Waveshare ESP32-S3-LCD-1.47 +waveshare_esp32_s3_lcd_147.vid.0=0x303a +waveshare_esp32_s3_lcd_147.pid.0=0x8242 +waveshare_esp32_s3_lcd_147.upload_port.0.vid=0x303a +waveshare_esp32_s3_lcd_147.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_lcd_147.bootloader.tool=esptool_py +waveshare_esp32_s3_lcd_147.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_lcd_147.upload.tool=esptool_py +waveshare_esp32_s3_lcd_147.upload.tool.default=esptool_py +waveshare_esp32_s3_lcd_147.upload.tool.network=esp_ota + +waveshare_esp32_s3_lcd_147.upload.maximum_size=1310720 +waveshare_esp32_s3_lcd_147.upload.maximum_data_size=327680 +waveshare_esp32_s3_lcd_147.upload.flags= +waveshare_esp32_s3_lcd_147.upload.extra_flags= +waveshare_esp32_s3_lcd_147.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_147.upload.wait_for_upload_port=false + +waveshare_esp32_s3_lcd_147.serial.disableDTR=false +waveshare_esp32_s3_lcd_147.serial.disableRTS=false + +waveshare_esp32_s3_lcd_147.build.tarch=xtensa +waveshare_esp32_s3_lcd_147.build.bootloader_addr=0x0 +waveshare_esp32_s3_lcd_147.build.target=esp32s3 +waveshare_esp32_s3_lcd_147.build.mcu=esp32s3 +waveshare_esp32_s3_lcd_147.build.core=esp32 +waveshare_esp32_s3_lcd_147.build.variant=waveshare_esp32_s3_lcd_147 +waveshare_esp32_s3_lcd_147.build.board=WAVESHARE_ESP32_S3_LCD_147 + +waveshare_esp32_s3_lcd_147.build.usb_mode=1 +waveshare_esp32_s3_lcd_147.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_147.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_147.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_147.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_147.build.flash_size=16MB +waveshare_esp32_s3_lcd_147.build.flash_freq=80m +waveshare_esp32_s3_lcd_147.build.flash_mode=qio +waveshare_esp32_s3_lcd_147.build.boot=qio +waveshare_esp32_s3_lcd_147.build.boot_freq=80m +waveshare_esp32_s3_lcd_147.build.partitions=default +waveshare_esp32_s3_lcd_147.build.defines= +waveshare_esp32_s3_lcd_147.build.loop_core= +waveshare_esp32_s3_lcd_147.build.event_core= +waveshare_esp32_s3_lcd_147.build.psram_type=opi +waveshare_esp32_s3_lcd_147.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_lcd_147.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_lcd_147.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_lcd_147.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_lcd_147.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_lcd_147.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_lcd_147.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_lcd_147.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_lcd_147.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_lcd_147.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_lcd_147.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_lcd_147.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_lcd_147.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_lcd_147.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_lcd_147.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_lcd_147.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_lcd_147.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_lcd_147.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_lcd_147.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_lcd_147.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_lcd_147.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_lcd_147.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_lcd_147.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_lcd_147.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_lcd_147.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_lcd_147.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_lcd_147.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_lcd_147.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_lcd_147.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_lcd_147.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_147.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_147.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_lcd_147.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_lcd_147.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_147.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_147.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_147.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_lcd_147.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_lcd_147.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_147.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_147.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_lcd_147.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_lcd_147.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_147.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_lcd_147.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_lcd_147.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_lcd_147.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_lcd_147.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_lcd_147.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_147.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_lcd_147.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_lcd_147.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_lcd_147.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_lcd_147.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_lcd_147.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_lcd_147.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_lcd_147.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_lcd_147.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_lcd_147.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_lcd_147.menu.DebugLevel.none=None +waveshare_esp32_s3_lcd_147.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_lcd_147.menu.DebugLevel.error=Error +waveshare_esp32_s3_lcd_147.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_lcd_147.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_lcd_147.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_lcd_147.menu.DebugLevel.info=Info +waveshare_esp32_s3_lcd_147.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_lcd_147.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_lcd_147.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_lcd_147.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_lcd_147.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_lcd_147.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_lcd_147.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_lcd_147.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_lcd_147.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_lcd_147.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_lcd_147.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_lcd_147.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_lcd_147.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_lcd_147.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_lcd_147.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port + +############################################################## + +waveshare_esp32_s3_touch_lcd_21.name=Waveshare ESP32-S3-Touch-LCD-2.1 +waveshare_esp32_s3_touch_lcd_21.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_21.pid.0=0x8242 +waveshare_esp32_s3_touch_lcd_21.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_21.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_touch_lcd_21.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_21.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_21.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_21.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_21.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_21.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_21.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_21.upload.flags= +waveshare_esp32_s3_touch_lcd_21.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_21.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_21.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_21.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_21.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_21.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_21.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_21.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_21.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_21.build.core=esp32 +waveshare_esp32_s3_touch_lcd_21.build.variant=waveshare_esp32_s3_touch_lcd_21 +waveshare_esp32_s3_touch_lcd_21.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_21 + +waveshare_esp32_s3_touch_lcd_21.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_21.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_21.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_21.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_21.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_21.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_21.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_21.build.flash_mode=qio +waveshare_esp32_s3_touch_lcd_21.build.boot=qio +waveshare_esp32_s3_touch_lcd_21.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_21.build.partitions=default +waveshare_esp32_s3_touch_lcd_21.build.defines= +waveshare_esp32_s3_touch_lcd_21.build.loop_core= +waveshare_esp32_s3_touch_lcd_21.build.event_core= +waveshare_esp32_s3_touch_lcd_21.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_21.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_touch_lcd_21.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_21.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_21.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_21.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_21.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_21.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_21.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_21.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_21.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_21.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_21.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_21.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_21.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_21.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_21.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_21.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_21.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_21.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_21.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_21.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_21.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_21.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_21.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_21.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_21.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_21.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_21.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_21.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_21.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_21.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_21.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_21.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_21.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_21.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_21.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_touch_lcd_21.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_touch_lcd_21.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_touch_lcd_21.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_touch_lcd_21.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_touch_lcd_21.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port + +############################################################## + +waveshare_esp32_s3_touch_lcd_28.name=Waveshare ESP32-S3-Touch-LCD-2.8 +waveshare_esp32_s3_touch_lcd_28.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_28.pid.0=0x8242 +waveshare_esp32_s3_touch_lcd_28.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_28.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_touch_lcd_28.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_28.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_28.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_28.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_28.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_28.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_28.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_28.upload.flags= +waveshare_esp32_s3_touch_lcd_28.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_28.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_28.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_28.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_28.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_28.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_28.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_28.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_28.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_28.build.core=esp32 +waveshare_esp32_s3_touch_lcd_28.build.variant=waveshare_esp32_s3_touch_lcd_28 +waveshare_esp32_s3_touch_lcd_28.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_28 + +waveshare_esp32_s3_touch_lcd_28.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_28.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_28.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_28.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_28.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_28.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_28.build.flash_freq=120m +waveshare_esp32_s3_touch_lcd_28.build.flash_mode=qio +waveshare_esp32_s3_touch_lcd_28.build.boot=qio +waveshare_esp32_s3_touch_lcd_28.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_28.build.partitions=default +waveshare_esp32_s3_touch_lcd_28.build.defines= +waveshare_esp32_s3_touch_lcd_28.build.loop_core= +waveshare_esp32_s3_touch_lcd_28.build.event_core= +waveshare_esp32_s3_touch_lcd_28.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_28.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_touch_lcd_28.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_28.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_28.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_28.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_28.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_28.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_28.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_28.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_28.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_28.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_28.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 +waveshare_esp32_s3_touch_lcd_28.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_28.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +waveshare_esp32_s3_touch_lcd_28.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_28.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_28.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_28.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_28.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_28.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_28.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_28.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_28.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_28.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_28.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_28.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_28.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_28.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_28.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_28.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_28.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_28.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_28.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_28.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_28.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_28.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_touch_lcd_28.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_touch_lcd_28.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_touch_lcd_28.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_touch_lcd_28.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_touch_lcd_28.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port + +############################################################## + +waveshare_esp32_s3_relay_6ch.name=Waveshare ESP32-S3-Relay-6CH +waveshare_esp32_s3_relay_6ch.vid.0=0x303a +waveshare_esp32_s3_relay_6ch.pid.0=0x8242 +waveshare_esp32_s3_relay_6ch.upload_port.0.vid=0x303a +waveshare_esp32_s3_relay_6ch.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_relay_6ch.bootloader.tool=esptool_py +waveshare_esp32_s3_relay_6ch.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_relay_6ch.upload.tool=esptool_py +waveshare_esp32_s3_relay_6ch.upload.tool.default=esptool_py +waveshare_esp32_s3_relay_6ch.upload.tool.network=esp_ota + +waveshare_esp32_s3_relay_6ch.upload.maximum_size=1310720 +waveshare_esp32_s3_relay_6ch.upload.maximum_data_size=327680 +waveshare_esp32_s3_relay_6ch.upload.flags= +waveshare_esp32_s3_relay_6ch.upload.extra_flags= +waveshare_esp32_s3_relay_6ch.upload.use_1200bps_touch=false +waveshare_esp32_s3_relay_6ch.upload.wait_for_upload_port=false + +waveshare_esp32_s3_relay_6ch.serial.disableDTR=false +waveshare_esp32_s3_relay_6ch.serial.disableRTS=false + +waveshare_esp32_s3_relay_6ch.build.tarch=xtensa +waveshare_esp32_s3_relay_6ch.build.bootloader_addr=0x0 +waveshare_esp32_s3_relay_6ch.build.target=esp32s3 +waveshare_esp32_s3_relay_6ch.build.mcu=esp32s3 +waveshare_esp32_s3_relay_6ch.build.core=esp32 +waveshare_esp32_s3_relay_6ch.build.variant=waveshare_esp32_s3_relay_6ch +waveshare_esp32_s3_relay_6ch.build.board=WAVESHARE_ESP32_S3_RELAY_6CH + +waveshare_esp32_s3_relay_6ch.build.usb_mode=1 +waveshare_esp32_s3_relay_6ch.build.cdc_on_boot=0 +waveshare_esp32_s3_relay_6ch.build.msc_on_boot=0 +waveshare_esp32_s3_relay_6ch.build.dfu_on_boot=0 +waveshare_esp32_s3_relay_6ch.build.f_cpu=240000000L +waveshare_esp32_s3_relay_6ch.build.flash_size=8MB +waveshare_esp32_s3_relay_6ch.build.flash_freq=80m +waveshare_esp32_s3_relay_6ch.build.flash_mode=qio +waveshare_esp32_s3_relay_6ch.build.boot=qio +waveshare_esp32_s3_relay_6ch.build.boot_freq=80m +waveshare_esp32_s3_relay_6ch.build.partitions=default +waveshare_esp32_s3_relay_6ch.build.defines= +waveshare_esp32_s3_relay_6ch.build.loop_core= +waveshare_esp32_s3_relay_6ch.build.event_core= +waveshare_esp32_s3_relay_6ch.build.psram_type= +waveshare_esp32_s3_relay_6ch.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_relay_6ch.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_relay_6ch.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_relay_6ch.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_relay_6ch.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_relay_6ch.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_relay_6ch.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_relay_6ch.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_relay_6ch.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_relay_6ch.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_relay_6ch.menu.FlashSize.8M=8MB (64Mb) +waveshare_esp32_s3_relay_6ch.menu.FlashSize.8M.build.flash_size=8MB +waveshare_esp32_s3_relay_6ch.menu.FlashSize.8M.build.partitions=default_8MB +waveshare_esp32_s3_relay_6ch.menu.FlashSize.16M=16MB (128Mb) +waveshare_esp32_s3_relay_6ch.menu.FlashSize.16M.build.flash_size=16MB + +waveshare_esp32_s3_relay_6ch.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_relay_6ch.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_relay_6ch.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_relay_6ch.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_relay_6ch.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_relay_6ch.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_relay_6ch.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_relay_6ch.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_relay_6ch.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_relay_6ch.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_relay_6ch.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_relay_6ch.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_relay_6ch.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_relay_6ch.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_relay_6ch.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_relay_6ch.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_relay_6ch.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_relay_6ch.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_relay_6ch.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_relay_6ch.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_relay_6ch.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_relay_6ch.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_relay_6ch.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_relay_6ch.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_relay_6ch.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_relay_6ch.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_relay_6ch.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_relay_6ch.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_relay_6ch.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_relay_6ch.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.none=None +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.error=Error +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.info=Info +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_relay_6ch.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_relay_6ch.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_relay_6ch.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_relay_6ch.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port + +############################################################## diff --git a/variants/waveshare_esp32_s3_lcd_146/pins_arduino.h b/variants/waveshare_esp32_s3_lcd_146/pins_arduino.h new file mode 100644 index 00000000000..2539f207bd0 --- /dev/null +++ b/variants/waveshare_esp32_s3_lcd_146/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8258 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-1.46" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 10; +static const uint8_t SDA = 11; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_lcd_147/pins_arduino.h b/variants/waveshare_esp32_s3_lcd_147/pins_arduino.h new file mode 100644 index 00000000000..b79a970c1ef --- /dev/null +++ b/variants/waveshare_esp32_s3_lcd_147/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x828A + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-LCD-1.47" +#define USB_SERIAL "" + +#define PIN_RGB_LED 38 + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_lcd_185/pins_arduino.h b/variants/waveshare_esp32_s3_lcd_185/pins_arduino.h new file mode 100644 index 00000000000..f8542f014e7 --- /dev/null +++ b/variants/waveshare_esp32_s3_lcd_185/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8290 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-LCD-1.85" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 10; +static const uint8_t SDA = 11; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_relay_6ch/pins_arduino.h b/variants/waveshare_esp32_s3_relay_6ch/pins_arduino.h new file mode 100644 index 00000000000..f389f5e1358 --- /dev/null +++ b/variants/waveshare_esp32_s3_relay_6ch/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8273 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Relay-6CH" +#define USB_SERIAL "" + +#define PIN_RGB_LED 38 + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_146/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_146/pins_arduino.h new file mode 100644 index 00000000000..1c14bfe6714 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_146/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8287 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-1.85-Box" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 10; +static const uint8_t SDA = 11; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_185_box/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_185_box/pins_arduino.h new file mode 100644 index 00000000000..438da04025a --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_185_box/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x825B + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-2.1" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 7; +static const uint8_t SDA = 15; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_21/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_21/pins_arduino.h new file mode 100644 index 00000000000..a6c76a7ff34 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_21/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x825E + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-2.8" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 10; +static const uint8_t SDA = 11; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_28/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_28/pins_arduino.h new file mode 100644 index 00000000000..a6c76a7ff34 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_28/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x825E + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-2.8" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 10; +static const uint8_t SDA = 11; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ From 6e88445ba90e2eb8bdfb14f128b1d1773c0bdabb Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Wed, 23 Oct 2024 15:30:30 +0300 Subject: [PATCH 087/409] fix(i2s): Use separate variables when reading and writing (#10509) --- libraries/ESP_I2S/src/ESP_I2S.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/libraries/ESP_I2S/src/ESP_I2S.cpp b/libraries/ESP_I2S/src/ESP_I2S.cpp index 395c7b587ed..f4bd92b52d5 100644 --- a/libraries/ESP_I2S/src/ESP_I2S.cpp +++ b/libraries/ESP_I2S/src/ESP_I2S.cpp @@ -806,17 +806,19 @@ bool I2SClass::configureRX(uint32_t rate, i2s_data_bit_width_t bits_cfg, i2s_slo size_t I2SClass::readBytes(char *buffer, size_t size) { size_t bytes_read = 0; + size_t bytes_to_read = 0; size_t total_size = 0; last_error = ESP_FAIL; if (rx_chan == NULL) { return total_size; } while (total_size < size) { - bytes_read = size - total_size; - if (rx_transform_buf != NULL && bytes_read > I2S_READ_CHUNK_SIZE) { - bytes_read = I2S_READ_CHUNK_SIZE; + bytes_read = 0; + bytes_to_read = size - total_size; + if (rx_transform_buf != NULL && bytes_to_read > I2S_READ_CHUNK_SIZE) { + bytes_to_read = I2S_READ_CHUNK_SIZE; } - I2S_ERROR_CHECK_RETURN(rx_fn(rx_chan, rx_transform_buf, (char *)(buffer + total_size), bytes_read, &bytes_read, _timeout), 0); + I2S_ERROR_CHECK_RETURN(rx_fn(rx_chan, rx_transform_buf, (char *)(buffer + total_size), bytes_to_read, &bytes_read, _timeout), 0); total_size += bytes_read; } return total_size; @@ -825,13 +827,15 @@ size_t I2SClass::readBytes(char *buffer, size_t size) { size_t I2SClass::write(const uint8_t *buffer, size_t size) { size_t written = 0; size_t bytes_sent = 0; + size_t bytes_to_send = 0; last_error = ESP_FAIL; if (tx_chan == NULL) { return written; } while (written < size) { - bytes_sent = size - written; - esp_err_t err = i2s_channel_write(tx_chan, (char *)(buffer + written), bytes_sent, &bytes_sent, _timeout); + bytes_sent = 0; + bytes_to_send = size - written; + esp_err_t err = i2s_channel_write(tx_chan, (char *)(buffer + written), bytes_to_send, &bytes_sent, _timeout); setWriteError(err); I2S_ERROR_CHECK_RETURN(err, written); written += bytes_sent; From cb83cda06a621b095e52029edbfa4049a9a84bb9 Mon Sep 17 00:00:00 2001 From: Thomas Weller Date: Wed, 23 Oct 2024 19:39:12 +0200 Subject: [PATCH 088/409] Fix comments for AD types in advertising (#10512) --- libraries/BLE/src/BLEAdvertising.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/BLE/src/BLEAdvertising.cpp b/libraries/BLE/src/BLEAdvertising.cpp index 1f2e6cd2887..2d71c4d7478 100644 --- a/libraries/BLE/src/BLEAdvertising.cpp +++ b/libraries/BLE/src/BLEAdvertising.cpp @@ -352,7 +352,7 @@ void BLEAdvertisementData::setCompleteServices(BLEUUID uuid) { switch (uuid.bitSize()) { case 16: { - // [Len] [0x02] [LL] [HH] + // [Len] [0x03] [LL] [HH] cdata[0] = 3; cdata[1] = ESP_BLE_AD_TYPE_16SRV_CMPL; // 0x03 addData(String(cdata, 2) + String((char *)&uuid.getNative()->uuid.uuid16, 2)); @@ -361,7 +361,7 @@ void BLEAdvertisementData::setCompleteServices(BLEUUID uuid) { case 32: { - // [Len] [0x04] [LL] [LL] [HH] [HH] + // [Len] [0x05] [LL] [LL] [HH] [HH] cdata[0] = 5; cdata[1] = ESP_BLE_AD_TYPE_32SRV_CMPL; // 0x05 addData(String(cdata, 2) + String((char *)&uuid.getNative()->uuid.uuid32, 4)); @@ -370,7 +370,7 @@ void BLEAdvertisementData::setCompleteServices(BLEUUID uuid) { case 128: { - // [Len] [0x04] [0] [1] ... [15] + // [Len] [0x07] [0] [1] ... [15] cdata[0] = 17; cdata[1] = ESP_BLE_AD_TYPE_128SRV_CMPL; // 0x07 addData(String(cdata, 2) + String((char *)uuid.getNative()->uuid.uuid128, 16)); @@ -453,7 +453,7 @@ void BLEAdvertisementData::setPartialServices(BLEUUID uuid) { case 128: { - // [Len] [0x04] [0] [1] ... [15] + // [Len] [0x06] [0] [1] ... [15] cdata[0] = 17; cdata[1] = ESP_BLE_AD_TYPE_128SRV_PART; // 0x06 addData(String(cdata, 2) + String((char *)&uuid.getNative()->uuid.uuid128, 16)); From 6dfd95898387bf10eb6348a22c2499073efb9f16 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Thu, 24 Oct 2024 00:46:01 +0300 Subject: [PATCH 089/409] fix(eth): Set default clock in pin value to zero (#10513) When Arduino is used as component, `CONFIG_ETH_RMII_CLK_IN_GPIO` might not be defined, so we set it to const `0` to clear the issue. --- libraries/Ethernet/src/ETH.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index e04174fd490..e3f2197221c 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -210,7 +210,7 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i #if CONFIG_IDF_TARGET_ESP32 #undef DEFAULT_RMII_CLK_GPIO -#define DEFAULT_RMII_CLK_GPIO (emac_rmii_clock_gpio_t)(CONFIG_ETH_RMII_CLK_IN_GPIO) +#define DEFAULT_RMII_CLK_GPIO (emac_rmii_clock_gpio_t)(0) #endif eth_esp32_emac_config_t mac_config = ETH_EMAC_DEFAULT_CONFIG(); From 330beb40a501f2006abfbc9241fd81dc306d676b Mon Sep 17 00:00:00 2001 From: zinkett <96108358+zinkett@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:31:54 +0200 Subject: [PATCH 090/409] Update lib - User can choose if calc MD5 from encrypted or decrypted file (#10510) * User can choose if calc MD5 from decrypted file At the present moment, if user want use OTA, the function calculate MD5 of the decrypted file, but if file is encrypted from source, could be more useful to know the MD5 of the encrypted file. * md5 * Update Updater.cpp * Update libraries/Update/src/Update.h Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> * Update libraries/Update/src/Update.h Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> * Update libraries/Update/src/Updater.cpp Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> * Update libraries/Update/src/Updater.cpp Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- libraries/Update/src/Update.h | 4 +++- libraries/Update/src/Updater.cpp | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libraries/Update/src/Update.h b/libraries/Update/src/Update.h index 7ae5e980751..5832846fd28 100644 --- a/libraries/Update/src/Update.h +++ b/libraries/Update/src/Update.h @@ -137,8 +137,9 @@ class UpdateClass { /* sets the expected MD5 for the firmware (hexString) + If calc_post_decryption is true, the update library will calculate the MD5 after the decryption, if false the calculation occurs before the decryption */ - bool setMD5(const char *expected_md5); + bool setMD5(const char *expected_md5, bool calc_post_decryption = true); /* returns the MD5 String of the successfully ended firmware @@ -257,6 +258,7 @@ class UpdateClass { const esp_partition_t *_partition; String _target_md5; + bool _target_md5_decrypted = true; MD5Builder _md5; int _ledPin; diff --git a/libraries/Update/src/Updater.cpp b/libraries/Update/src/Updater.cpp index 78f93602cde..e92f84d4599 100644 --- a/libraries/Update/src/Updater.cpp +++ b/libraries/Update/src/Updater.cpp @@ -348,6 +348,11 @@ bool UpdateClass::_writeBuffer() { log_d("Decrypting OTA Image"); } } + + if (!_target_md5_decrypted) { + _md5.add(_buffer, _bufferLen); + } + //check if data in buffer needs decrypting if (_cryptMode & U_AES_IMAGE_DECRYPTING_BIT) { if (!_decryptBuffer()) { @@ -404,7 +409,9 @@ bool UpdateClass::_writeBuffer() { if (!_progress && _command == U_FLASH) { _buffer[0] = ESP_IMAGE_HEADER_MAGIC; } - _md5.add(_buffer, _bufferLen); + if (_target_md5_decrypted) { + _md5.add(_buffer, _bufferLen); + } _progress += _bufferLen; _bufferLen = 0; if (_progress_callback) { @@ -446,12 +453,13 @@ bool UpdateClass::_verifyEnd() { return false; } -bool UpdateClass::setMD5(const char *expected_md5) { +bool UpdateClass::setMD5(const char *expected_md5, bool calc_post_decryption) { if (strlen(expected_md5) != 32) { return false; } _target_md5 = expected_md5; _target_md5.toLowerCase(); + _target_md5_decrypted = calc_post_decryption; return true; } From 07c510e3adc0dfe4a284d0f47d6ecd07286c712f Mon Sep 17 00:00:00 2001 From: vortigont Date: Thu, 24 Oct 2024 21:15:13 +0900 Subject: [PATCH 091/409] fix (NetworkEvents lib) remove checks for duplicated event handlers (#10376) * lib Network: add cpp syntax to structs * [Network] deprecate NetworkEvents::removeEvent() for std::function callbacks removing event callback via std::function pointer does not work as expected for lambdas (issue #10365) here mark NetworkEvents::removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX) as deprecated in favor of removing by callback's id for NetworkEvents::onEvent remove checking for dublicate event handler, this does not work for lambdas too remove NetworkEvents::find methods as unnecessary move cbEventList container inside the class declare NetworkEventCbList_t as a cpp struct with constructor, allows using std::vector.emplace() when adding new items to container optimize NetworkEvents::remove() calls to use erase-remove idiom for std::vector * [Network] hide event task under private member of NetworkEvents class prevent checkForEvent loop to be callable from outside the task's thread * refactor(NetworkEvents) code polishing and comments - rename NetworkEvents::cbEventList as private member NetworkEvents_cbEventList - NetworkEvents::getStatusBits() add const qualifier - turn statics into constexpr - add indexes to enum::arduino_event_id_t to make events indexing consistent for SOCs with/without WiFi also leave some index gaps to minimize renumbering on adding new events - add doxygen help to NetworkEvents:: methods - declare NetworkEvents::eventName() as static, that could be used without creating class scope - potential mem leak in postEvent * refactor(NetworkEvents) add (optional) mutex lock for container operations provide thread safety for dual core SoCs since std::mutex brings additional componetns of libstdc++ lib it impacts resulting image size significantly (around 50k) Might be enabled on-demand if thread-safety is required * ci(pre-commit): Apply automatic fixes * fix(spelling): Fix spelling mistakes --------- Co-authored-by: Rodrigo Garcia Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> --- libraries/Network/src/NetworkEvents.cpp | 325 ++++++++++-------------- libraries/Network/src/NetworkEvents.h | 180 +++++++++++-- 2 files changed, 289 insertions(+), 216 deletions(-) diff --git a/libraries/Network/src/NetworkEvents.cpp b/libraries/Network/src/NetworkEvents.cpp index bb02282e9b3..5a7e7c49afa 100644 --- a/libraries/Network/src/NetworkEvents.cpp +++ b/libraries/Network/src/NetworkEvents.cpp @@ -8,28 +8,6 @@ #include "esp_task.h" #include "esp32-hal.h" -typedef struct NetworkEventCbList { - static network_event_handle_t current_id; - network_event_handle_t id; - NetworkEventCb cb; - NetworkEventFuncCb fcb; - NetworkEventSysCb scb; - arduino_event_id_t event; - - NetworkEventCbList() : id(current_id++), cb(NULL), fcb(NULL), scb(NULL), event(ARDUINO_EVENT_NONE) {} -} NetworkEventCbList_t; -network_event_handle_t NetworkEventCbList::current_id = 1; - -// arduino dont like std::vectors move static here -static std::vector cbEventList; - -static void _network_event_task(void *arg) { - for (;;) { - ((NetworkEvents *)arg)->checkForEvent(); - } - vTaskDelete(NULL); -} - NetworkEvents::NetworkEvents() : _arduino_event_group(NULL), _arduino_event_queue(NULL), _arduino_event_task_handle(NULL) {} NetworkEvents::~NetworkEvents() { @@ -43,8 +21,9 @@ NetworkEvents::~NetworkEvents() { } if (_arduino_event_queue != NULL) { arduino_event_t *event = NULL; + // consume queue while (xQueueReceive(_arduino_event_queue, &event, 0) == pdTRUE) { - free(event); + delete event; } vQueueDelete(_arduino_event_queue); _arduino_event_queue = NULL; @@ -78,7 +57,14 @@ bool NetworkEvents::initNetworkEvents() { } if (!_arduino_event_task_handle) { - xTaskCreateUniversal(_network_event_task, "arduino_events", 4096, this, ESP_TASKD_EVENT_PRIO - 1, &_arduino_event_task_handle, ARDUINO_EVENT_RUNNING_CORE); + xTaskCreateUniversal( + [](void *self) { + static_cast(self)->_checkForEvent(); + }, + "arduino_events", // label + 4096, // event task's stack size + this, ESP_TASKD_EVENT_PRIO - 1, &_arduino_event_task_handle, ARDUINO_EVENT_RUNNING_CORE + ); if (!_arduino_event_task_handle) { log_e("Network Event Task Start Failed!"); return false; @@ -88,66 +74,76 @@ bool NetworkEvents::initNetworkEvents() { return true; } -bool NetworkEvents::postEvent(arduino_event_t *data) { +bool NetworkEvents::postEvent(const arduino_event_t *data) { if (data == NULL || _arduino_event_queue == NULL) { return false; } - arduino_event_t *event = (arduino_event_t *)malloc(sizeof(arduino_event_t)); + arduino_event_t *event = new arduino_event_t(); if (event == NULL) { log_e("Arduino Event Malloc Failed!"); return false; } + memcpy(event, data, sizeof(arduino_event_t)); if (xQueueSend(_arduino_event_queue, &event, portMAX_DELAY) != pdPASS) { log_e("Arduino Event Send Failed!"); + delete event; // release mem on error return false; } return true; } -void NetworkEvents::checkForEvent() { - arduino_event_t *event = NULL; +void NetworkEvents::_checkForEvent() { + // this task can't run without the queue if (_arduino_event_queue == NULL) { + _arduino_event_task_handle = NULL; + vTaskDelete(NULL); return; } - if (xQueueReceive(_arduino_event_queue, &event, portMAX_DELAY) != pdTRUE) { - return; - } - if (event == NULL) { - return; - } - log_v("Network Event: %d - %s", event->event_id, eventName(event->event_id)); - for (uint32_t i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (entry.cb || entry.fcb || entry.scb) { - if (entry.event == (arduino_event_id_t)event->event_id || entry.event == ARDUINO_EVENT_MAX) { - if (entry.cb) { - entry.cb((arduino_event_id_t)event->event_id); - } else if (entry.fcb) { - entry.fcb((arduino_event_id_t)event->event_id, (arduino_event_info_t)event->event_info); - } else { - entry.scb(event); + + for (;;) { + arduino_event_t *event = NULL; + // wait for an event on a queue + if (xQueueReceive(_arduino_event_queue, &event, portMAX_DELAY) != pdTRUE) { + continue; + } + if (event == NULL) { + continue; + } + log_v("Network Event: %d - %s", event->event_id, eventName(event->event_id)); + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::unique_lock lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + // iterate over registered callbacks + for (auto &i : _cbEventList) { + if (i.cb || i.fcb || i.scb) { + if (i.event == (arduino_event_id_t)event->event_id || i.event == ARDUINO_EVENT_MAX) { + if (i.cb) { + i.cb((arduino_event_id_t)event->event_id); + continue; + } + + if (i.fcb) { + i.fcb((arduino_event_id_t)event->event_id, (arduino_event_info_t)event->event_info); + continue; + } + + i.scb(event); } } } - } - free(event); -} -uint32_t NetworkEvents::findEvent(NetworkEventCb cbEvent, arduino_event_id_t event) { - uint32_t i; +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + lock.unlock(); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - if (!cbEvent) { - return cbEventList.size(); + // release the event object's memory + delete event; } - for (i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (entry.cb == cbEvent && entry.event == event) { - break; - } - } - return i; + vTaskDelete(NULL); } template static size_t getStdFunctionAddress(std::function f) { @@ -159,55 +155,17 @@ template static size_t getStdFunctionAddress(std::fun return (size_t)fnPointer; } -uint32_t NetworkEvents::findEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event) { - uint32_t i; - - if (!cbEvent) { - return cbEventList.size(); - } - - for (i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (getStdFunctionAddress(entry.fcb) == getStdFunctionAddress(cbEvent) && entry.event == event) { - break; - } - } - return i; -} - -uint32_t NetworkEvents::findEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event) { - uint32_t i; - - if (!cbEvent) { - return cbEventList.size(); - } - - for (i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (entry.scb == cbEvent && entry.event == event) { - break; - } - } - return i; -} - network_event_handle_t NetworkEvents::onEvent(NetworkEventCb cbEvent, arduino_event_id_t event) { if (!cbEvent) { return 0; } - if (findEvent(cbEvent, event) < cbEventList.size()) { - log_w("Attempt to add duplicate event handler!"); - return 0; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = cbEvent; - newEventHandler.fcb = NULL; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); - return newEventHandler.id; + _cbEventList.emplace_back(++_current_id, cbEvent, nullptr, nullptr, event); + return _cbEventList.back().id; } network_event_handle_t NetworkEvents::onEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event) { @@ -215,18 +173,12 @@ network_event_handle_t NetworkEvents::onEvent(NetworkEventFuncCb cbEvent, arduin return 0; } - if (findEvent(cbEvent, event) < cbEventList.size()) { - log_w("Attempt to add duplicate event handler!"); - return 0; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = cbEvent; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); - return newEventHandler.id; + _cbEventList.emplace_back(++_current_id, nullptr, cbEvent, nullptr, event); + return _cbEventList.back().id; } network_event_handle_t NetworkEvents::onEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event) { @@ -234,18 +186,12 @@ network_event_handle_t NetworkEvents::onEvent(NetworkEventSysCb cbEvent, arduino return 0; } - if (findEvent(cbEvent, event) < cbEventList.size()) { - log_w("Attempt to add duplicate event handler!"); - return 0; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = NULL; - newEventHandler.scb = cbEvent; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); - return newEventHandler.id; + _cbEventList.emplace_back(++_current_id, nullptr, nullptr, cbEvent, event); + return _cbEventList.back().id; } network_event_handle_t NetworkEvents::onSysEvent(NetworkEventCb cbEvent, arduino_event_id_t event) { @@ -253,18 +199,12 @@ network_event_handle_t NetworkEvents::onSysEvent(NetworkEventCb cbEvent, arduino return 0; } - if (findEvent(cbEvent, event) < cbEventList.size()) { - log_w("Attempt to add duplicate event handler!"); - return 0; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = cbEvent; - newEventHandler.fcb = NULL; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.insert(cbEventList.begin(), newEventHandler); - return newEventHandler.id; + _cbEventList.emplace(_cbEventList.begin(), ++_current_id, cbEvent, nullptr, nullptr, event); + return _cbEventList.front().id; } network_event_handle_t NetworkEvents::onSysEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event) { @@ -272,18 +212,12 @@ network_event_handle_t NetworkEvents::onSysEvent(NetworkEventFuncCb cbEvent, ard return 0; } - if (findEvent(cbEvent, event) < cbEventList.size()) { - log_w("Attempt to add duplicate event handler!"); - return 0; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = cbEvent; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.insert(cbEventList.begin(), newEventHandler); - return newEventHandler.id; + _cbEventList.emplace(_cbEventList.begin(), ++_current_id, nullptr, cbEvent, nullptr, event); + return _cbEventList.front().id; } network_event_handle_t NetworkEvents::onSysEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event) { @@ -291,77 +225,88 @@ network_event_handle_t NetworkEvents::onSysEvent(NetworkEventSysCb cbEvent, ardu return 0; } - if (findEvent(cbEvent, event) < cbEventList.size()) { - log_w("Attempt to add duplicate event handler!"); - return 0; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = NULL; - newEventHandler.scb = cbEvent; - newEventHandler.event = event; - cbEventList.insert(cbEventList.begin(), newEventHandler); - return newEventHandler.id; + _cbEventList.emplace(_cbEventList.begin(), ++_current_id, nullptr, nullptr, cbEvent, event); + return _cbEventList.front().id; } void NetworkEvents::removeEvent(NetworkEventCb cbEvent, arduino_event_id_t event) { - uint32_t i; - if (!cbEvent) { return; } - i = findEvent(cbEvent, event); - if (i >= cbEventList.size()) { - log_w("Event handler not found!"); - return; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - cbEventList.erase(cbEventList.begin() + i); + _cbEventList.erase( + std::remove_if( + _cbEventList.begin(), _cbEventList.end(), + [cbEvent, event](const NetworkEventCbList_t &e) { + return e.cb == cbEvent && e.event == event; + } + ), + _cbEventList.end() + ); } void NetworkEvents::removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event) { - uint32_t i; - if (!cbEvent) { return; } - i = findEvent(cbEvent, event); - if (i >= cbEventList.size()) { - log_w("Event handler not found!"); - return; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - cbEventList.erase(cbEventList.begin() + i); + _cbEventList.erase( + std::remove_if( + _cbEventList.begin(), _cbEventList.end(), + [cbEvent, event](const NetworkEventCbList_t &e) { + return getStdFunctionAddress(e.fcb) == getStdFunctionAddress(cbEvent) && e.event == event; + } + ), + _cbEventList.end() + ); } void NetworkEvents::removeEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event) { - uint32_t i; - if (!cbEvent) { return; } - i = findEvent(cbEvent, event); - if (i >= cbEventList.size()) { - log_w("Event handler not found!"); - return; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - cbEventList.erase(cbEventList.begin() + i); + _cbEventList.erase( + std::remove_if( + _cbEventList.begin(), _cbEventList.end(), + [cbEvent, event](const NetworkEventCbList_t &e) { + return e.scb == cbEvent && e.event == event; + } + ), + _cbEventList.end() + ); } void NetworkEvents::removeEvent(network_event_handle_t id) { - for (uint32_t i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (entry.id == id) { - cbEventList.erase(cbEventList.begin() + i); - return; - } - } - log_w("Event handler not found!"); +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + _cbEventList.erase( + std::remove_if( + _cbEventList.begin(), _cbEventList.end(), + [id](const NetworkEventCbList_t &e) { + return e.id == id; + } + ), + _cbEventList.end() + ); } int NetworkEvents::setStatusBits(int bits) { @@ -380,7 +325,7 @@ int NetworkEvents::clearStatusBits(int bits) { return xEventGroupClearBits(_arduino_event_group, bits); } -int NetworkEvents::getStatusBits() { +int NetworkEvents::getStatusBits() const { if (!_arduino_event_group) { return _initial_bits; } diff --git a/libraries/Network/src/NetworkEvents.h b/libraries/Network/src/NetworkEvents.h index ac324d19841..e134d6816a2 100644 --- a/libraries/Network/src/NetworkEvents.h +++ b/libraries/Network/src/NetworkEvents.h @@ -16,6 +16,9 @@ #include "freertos/queue.h" #include "freertos/semphr.h" #include "freertos/event_groups.h" +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 +#include +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 #if SOC_WIFI_SUPPORTED #include "esp_wifi_types.h" @@ -24,8 +27,8 @@ #endif #if SOC_WIFI_SUPPORTED -static const int WIFI_SCANNING_BIT = BIT0; -static const int WIFI_SCAN_DONE_BIT = BIT1; +constexpr int WIFI_SCANNING_BIT = BIT0; +constexpr int WIFI_SCAN_DONE_BIT = BIT1; #endif #define NET_HAS_IP6_GLOBAL_BIT 0 @@ -33,7 +36,7 @@ static const int WIFI_SCAN_DONE_BIT = BIT1; ESP_EVENT_DECLARE_BASE(ARDUINO_EVENTS); typedef enum { - ARDUINO_EVENT_NONE, + ARDUINO_EVENT_NONE = 0, ARDUINO_EVENT_ETH_START, ARDUINO_EVENT_ETH_STOP, ARDUINO_EVENT_ETH_CONNECTED, @@ -42,10 +45,11 @@ typedef enum { ARDUINO_EVENT_ETH_LOST_IP, ARDUINO_EVENT_ETH_GOT_IP6, #if SOC_WIFI_SUPPORTED - ARDUINO_EVENT_WIFI_OFF, + ARDUINO_EVENT_WIFI_OFF = 100, ARDUINO_EVENT_WIFI_READY, ARDUINO_EVENT_WIFI_SCAN_DONE, - ARDUINO_EVENT_WIFI_STA_START, + ARDUINO_EVENT_WIFI_FTM_REPORT, + ARDUINO_EVENT_WIFI_STA_START = 110, ARDUINO_EVENT_WIFI_STA_STOP, ARDUINO_EVENT_WIFI_STA_CONNECTED, ARDUINO_EVENT_WIFI_STA_DISCONNECTED, @@ -53,24 +57,23 @@ typedef enum { ARDUINO_EVENT_WIFI_STA_GOT_IP, ARDUINO_EVENT_WIFI_STA_GOT_IP6, ARDUINO_EVENT_WIFI_STA_LOST_IP, - ARDUINO_EVENT_WIFI_AP_START, + ARDUINO_EVENT_WIFI_AP_START = 130, ARDUINO_EVENT_WIFI_AP_STOP, ARDUINO_EVENT_WIFI_AP_STACONNECTED, ARDUINO_EVENT_WIFI_AP_STADISCONNECTED, ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED, ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED, ARDUINO_EVENT_WIFI_AP_GOT_IP6, - ARDUINO_EVENT_WIFI_FTM_REPORT, - ARDUINO_EVENT_WPS_ER_SUCCESS, + ARDUINO_EVENT_WPS_ER_SUCCESS = 140, ARDUINO_EVENT_WPS_ER_FAILED, ARDUINO_EVENT_WPS_ER_TIMEOUT, ARDUINO_EVENT_WPS_ER_PIN, ARDUINO_EVENT_WPS_ER_PBC_OVERLAP, - ARDUINO_EVENT_SC_SCAN_DONE, + ARDUINO_EVENT_SC_SCAN_DONE = 150, ARDUINO_EVENT_SC_FOUND_CHANNEL, ARDUINO_EVENT_SC_GOT_SSID_PSWD, ARDUINO_EVENT_SC_SEND_ACK_DONE, - ARDUINO_EVENT_PROV_INIT, + ARDUINO_EVENT_PROV_INIT = 160, ARDUINO_EVENT_PROV_DEINIT, ARDUINO_EVENT_PROV_START, ARDUINO_EVENT_PROV_END, @@ -78,7 +81,7 @@ typedef enum { ARDUINO_EVENT_PROV_CRED_FAIL, ARDUINO_EVENT_PROV_CRED_SUCCESS, #endif - ARDUINO_EVENT_PPP_START, + ARDUINO_EVENT_PPP_START = 200, ARDUINO_EVENT_PPP_STOP, ARDUINO_EVENT_PPP_CONNECTED, ARDUINO_EVENT_PPP_DISCONNECTED, @@ -110,36 +113,123 @@ typedef union { #endif } arduino_event_info_t; -typedef struct { +/** + * @brief struct combines arduino event id and event's data object + * + */ +struct arduino_event_t { arduino_event_id_t event_id; arduino_event_info_t event_info; -} arduino_event_t; - -typedef void (*NetworkEventCb)(arduino_event_id_t event); -typedef std::function NetworkEventFuncCb; -typedef void (*NetworkEventSysCb)(arduino_event_t *event); +}; -typedef size_t network_event_handle_t; +// type aliases +using NetworkEventCb = void (*)(arduino_event_id_t event); +using NetworkEventFuncCb = std::function; +using NetworkEventSysCb = void (*)(arduino_event_t *event); +using network_event_handle_t = size_t; +/** + * @brief Class that provides network events callback handling + * it registers user callback functions for event handling, + * maintains the queue of events and propagates the event among subscribed callbacks + * callback are called in the context of a dedicated task consuming the queue + * + */ class NetworkEvents { public: NetworkEvents(); ~NetworkEvents(); + /** + * @brief register callback function to be executed on arduino event(s) + * @note if same handler is registered twice or more than same handler would be called twice or more times + * + * @param cbEvent static callback function + * @param event event to process, any event by default + * @return network_event_handle_t + */ network_event_handle_t onEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief register functional callback to be executed on arduino event(s) + * also used for lambda callbacks + * @note if same handler is registered twice or more than same handler would be called twice or more times + * + * @param cbEvent static callback function + * @param event event to process, any event by default + * @return network_event_handle_t + */ network_event_handle_t onEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief register static system callback to be executed on arduino event(s) + * callback function would be supplied with a pointer to arduino_event_t structure as an argument + * + * @note if same handler is registered twice or more than same handler would be called twice or more times + * + * @param cbEvent static callback function + * @param event event to process, any event by default + * @return network_event_handle_t + */ network_event_handle_t onEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief unregister static function callback + * @note a better way to unregister callbacks is to save/unregister via network_event_handle_t + * + * @param cbEvent static callback function + * @param event event to process, any event by default + */ void removeEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); - void removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief unregister functional callback + * @note a better way to unregister callbacks is to save/unregister via network_event_handle_t + * @note this does not work for lambda's! Do unregister via network_event_handle_t + * + * @param cbEvent functional callback + * @param event event to process, any event by default + */ + void removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX) + __attribute__((deprecated("removing functional callbacks via pointer is deprecated, use removeEvent(network_event_handle_t) instead"))); + + /** + * @brief unregister static system function callback + * @note a better way to unregister callbacks is to save/unregister via network_event_handle_t + * + * @param cbEvent static callback function + * @param event event to process, any event by default + */ void removeEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief unregister event callback via handler + * + * @param cbEvent static callback function + * @param event event to process, any event by default + */ void removeEvent(network_event_handle_t event_handle); - const char *eventName(arduino_event_id_t id); + /** + * @brief get a human-readable name of an event by it's id + * + * @param id event id code + * @return const char* event name string + */ + static const char *eventName(arduino_event_id_t id); - void checkForEvent(); - bool postEvent(arduino_event_t *event); + /** + * @brief post an event to the queue + * and propagade and event to subscribed handlers + * @note posting an event will trigger context switch from a lower priority task + * + * @param event a pointer to arduino_event_t struct + * @return true if event was queued susccessfuly + * @return false on memrory allocation error or queue is full + */ + bool postEvent(const arduino_event_t *event); - int getStatusBits(); + int getStatusBits() const; int waitStatusBits(int bits, uint32_t timeout_ms); int setStatusBits(int bits); int clearStatusBits(int bits); @@ -155,15 +245,53 @@ class NetworkEvents { protected: bool initNetworkEvents(); - uint32_t findEvent(NetworkEventCb cbEvent, arduino_event_id_t event); - uint32_t findEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event); - uint32_t findEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event); + // same as onEvent() but places newly added handler at the beginning of registered events list network_event_handle_t onSysEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + // same as onEvent() but places newly added handler at the beginning of registered events list network_event_handle_t onSysEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + // same as onEvent() but places newly added handler at the beginning of registered events list network_event_handle_t onSysEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); private: + /** + * @brief an object holds callback's definitions: + * - callback id + * - callback function pointers + * - binded event id + * + */ + struct NetworkEventCbList_t { + network_event_handle_t id; + NetworkEventCb cb; + NetworkEventFuncCb fcb; + NetworkEventSysCb scb; + arduino_event_id_t event; + + explicit NetworkEventCbList_t( + network_event_handle_t id, NetworkEventCb cb = nullptr, NetworkEventFuncCb fcb = nullptr, NetworkEventSysCb scb = nullptr, + arduino_event_id_t event = ARDUINO_EVENT_MAX + ) + : id(id), cb(cb), fcb(fcb), scb(scb), event(event) {} + }; + + // define initial id's value + network_event_handle_t _current_id{0}; + EventGroupHandle_t _arduino_event_group; QueueHandle_t _arduino_event_queue; TaskHandle_t _arduino_event_task_handle; + + // registered events callbacks container + std::vector _cbEventList; + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + // container access mutex + std::mutex _mtx; +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + /** + * @brief task function that picks events from an event queue and calls registered callbacks + * + */ + void _checkForEvent(); }; From a3ee37669eaecbff6ef7180c675bf83cd94c4dc6 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:56:45 -0300 Subject: [PATCH 092/409] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ee43fa0537..5b1b1865efa 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Here are the ESP32 series supported by the Arduino-ESP32 project: | ESP32-S3 | Yes | Yes | [ESP32-S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) | | ESP32-C6 | Yes | Yes | [ESP32-C6](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) | | ESP32-H2 | Yes | Yes | [ESP32-H2](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) | -| ESP32-P4 | No | No | [ESP32-P4](https://www.espressif.com/sites/default/files/documentation/esp32-p4_datasheet_en.pdf) | +| ESP32-P4 | No | Yes | [ESP32-P4](https://www.espressif.com/sites/default/files/documentation/esp32-p4_datasheet_en.pdf) | > [!NOTE] > ESP32-C2 is also supported by Arduino-ESP32 but requires rebuilding the static libraries. This is not trivial and requires a good understanding of the ESP-IDF From 9ac705e5f2889a9cb425e8d24bb90ba4b1e092a2 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Fri, 25 Oct 2024 14:53:35 +0300 Subject: [PATCH 093/409] IDF release/v5.3 a0f798cf (#10522) --- package/package_esp32_index.template.json | 128 +++++++++++----------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index ad941e841f6..aafaa211eba 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -42,7 +42,7 @@ { "packager": "esp32", "name": "esp32-arduino-libs", - "version": "idf-release_v5.3-59550599" + "version": "idf-release_v5.3-a0f798cf" }, { "packager": "esp32", @@ -67,7 +67,7 @@ { "packager": "esp32", "name": "openocd-esp32", - "version": "v0.12.0-esp32-20240821" + "version": "v0.12.0-esp32-20241016" }, { "packager": "esp32", @@ -95,63 +95,63 @@ "tools": [ { "name": "esp32-arduino-libs", - "version": "idf-release_v5.3-59550599", + "version": "idf-release_v5.3-a0f798cf", "systems": [ { "host": "i686-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", - "size": "343730097" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "checksum": "SHA-256:cc0c44739a2ae9b4d17b0026907132592a3888fdf3bb910c2ad730931fc6c9dc", + "size": "344062217" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", - "size": "343730097" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "checksum": "SHA-256:cc0c44739a2ae9b4d17b0026907132592a3888fdf3bb910c2ad730931fc6c9dc", + "size": "344062217" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", - "size": "343730097" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "checksum": "SHA-256:cc0c44739a2ae9b4d17b0026907132592a3888fdf3bb910c2ad730931fc6c9dc", + "size": "344062217" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", - "size": "343730097" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "checksum": "SHA-256:cc0c44739a2ae9b4d17b0026907132592a3888fdf3bb910c2ad730931fc6c9dc", + "size": "344062217" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", - "size": "343730097" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "checksum": "SHA-256:cc0c44739a2ae9b4d17b0026907132592a3888fdf3bb910c2ad730931fc6c9dc", + "size": "344062217" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", - "size": "343730097" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "checksum": "SHA-256:cc0c44739a2ae9b4d17b0026907132592a3888fdf3bb910c2ad730931fc6c9dc", + "size": "344062217" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", - "size": "343730097" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "checksum": "SHA-256:cc0c44739a2ae9b4d17b0026907132592a3888fdf3bb910c2ad730931fc6c9dc", + "size": "344062217" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-59550599.zip", - "checksum": "SHA-256:d2f18131dc7220c2d89ece7f8594fa3866523f8183612af37112ed0177f41af7", - "size": "343730097" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-a0f798cf.zip", + "checksum": "SHA-256:cc0c44739a2ae9b4d17b0026907132592a3888fdf3bb910c2ad730931fc6c9dc", + "size": "344062217" } ] }, @@ -405,56 +405,56 @@ }, { "name": "openocd-esp32", - "version": "v0.12.0-esp32-20240821", + "version": "v0.12.0-esp32-20241016", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-linux-amd64-0.12.0-esp32-20240821.tar.gz", - "archiveFileName": "openocd-esp32-linux-amd64-0.12.0-esp32-20240821.tar.gz", - "checksum": "SHA-256:f8c68541fa38307bc0c0763b7e1e3fe4e943d5d45da07d817a73b492e103b652", - "size": "2373094" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-linux-amd64-0.12.0-esp32-20241016.tar.gz", + "archiveFileName": "openocd-esp32-linux-amd64-0.12.0-esp32-20241016.tar.gz", + "checksum": "SHA-256:e82b0f036dc99244bead5f09a86e91bb2365cbcd1122ac68261e5647942485df", + "size": "2398717" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-linux-arm64-0.12.0-esp32-20240821.tar.gz", - "archiveFileName": "openocd-esp32-linux-arm64-0.12.0-esp32-20240821.tar.gz", - "checksum": "SHA-256:4d6e263d84e447354dc685848557d6c284dda7fe007ee451f729a7edfa7baad7", - "size": "2251272" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-linux-arm64-0.12.0-esp32-20241016.tar.gz", + "archiveFileName": "openocd-esp32-linux-arm64-0.12.0-esp32-20241016.tar.gz", + "checksum": "SHA-256:8f8daf5bd22ec5d2fa9257b0862ec33da18ee677e023fb9a9eb17f74ce208c76", + "size": "2271584" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-linux-armel-0.12.0-esp32-20240821.tar.gz", - "archiveFileName": "openocd-esp32-linux-armel-0.12.0-esp32-20240821.tar.gz", - "checksum": "SHA-256:9d45679f2c4cf450d5e2350047cf57bb76dde2487d30cebce0a72c9173b5c45b", - "size": "2390074" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-linux-armel-0.12.0-esp32-20241016.tar.gz", + "archiveFileName": "openocd-esp32-linux-armel-0.12.0-esp32-20241016.tar.gz", + "checksum": "SHA-256:bc9c020ecf20e2000f76cffa44305fd5bc44d2e688ea78cce423399d33f19767", + "size": "2414206" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-macos-0.12.0-esp32-20240821.tar.gz", - "archiveFileName": "openocd-esp32-macos-0.12.0-esp32-20240821.tar.gz", - "checksum": "SHA-256:565c8fabc5f19a6e7a0864a294d74b307eec30b9291d16d3fc90e273f0330cb4", - "size": "2485320" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-macos-0.12.0-esp32-20241016.tar.gz", + "archiveFileName": "openocd-esp32-macos-0.12.0-esp32-20241016.tar.gz", + "checksum": "SHA-256:02a2dffe801a2d005fa9e614d80ff8173395b2cb0b5d3118d0229d094a9946a7", + "size": "2508089" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-macos-arm64-0.12.0-esp32-20240821.tar.gz", - "archiveFileName": "openocd-esp32-macos-arm64-0.12.0-esp32-20240821.tar.gz", - "checksum": "SHA-256:68c5c7cf3d15b9810939a5edabc6ff2c9f4fc32262de91fc292a180bc5cc0637", - "size": "2530336" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-macos-arm64-0.12.0-esp32-20241016.tar.gz", + "archiveFileName": "openocd-esp32-macos-arm64-0.12.0-esp32-20241016.tar.gz", + "checksum": "SHA-256:c382f9e884d6565cb6089bff5f200f4810994667d885f062c3d3c5625a0fa9d6", + "size": "2552569" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-win32-0.12.0-esp32-20240821.zip", - "archiveFileName": "openocd-esp32-win32-0.12.0-esp32-20240821.zip", - "checksum": "SHA-256:463fc2903ddaf03f86ff50836c5c63cc696550b0446140159eddfd2e85570c5d", - "size": "2916409" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-win32-0.12.0-esp32-20241016.zip", + "archiveFileName": "openocd-esp32-win32-0.12.0-esp32-20241016.zip", + "checksum": "SHA-256:3b5d615e0a72cc771a45dd469031312d5881c01d7b6bc9edb29b8b6bda8c2e90", + "size": "2946244" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240821/openocd-esp32-win64-0.12.0-esp32-20240821.zip", - "archiveFileName": "openocd-esp32-win64-0.12.0-esp32-20240821.zip", - "checksum": "SHA-256:550f57369f1f1f6cc600b5dffa3378fd6164d8ea8db7c567cf41091771f090cb", - "size": "2916408" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-win64-0.12.0-esp32-20241016.zip", + "archiveFileName": "openocd-esp32-win64-0.12.0-esp32-20241016.zip", + "checksum": "SHA-256:5e7b2fd1947d3a8625f6a11db7a2340cf2f41ff4c61284c022c7d7c32b18780a", + "size": "2946244" } ] }, From 38a4c29fedf3c0f681ce8850c107c9d0011a80ec Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Fri, 25 Oct 2024 14:57:21 +0300 Subject: [PATCH 094/409] feature(rtos): Add Tasks status print function (#10515) * feature(rtos): Add Tasks status print function * fix(cmake): Add the new cpp file to CMakeLists * fix(stats): Adjust size of Load column * fix(format): Fix print of runtime formatting * fix(stats): Add license, usage note and C++ guards * fix(stats): Fix formatting and variable names * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- CMakeLists.txt | 1 + cores/esp32/Arduino.h | 1 + cores/esp32/freertos_stats.cpp | 111 +++++++++++++++++++++++++++++++++ cores/esp32/freertos_stats.h | 28 +++++++++ 4 files changed, 141 insertions(+) create mode 100644 cores/esp32/freertos_stats.cpp create mode 100644 cores/esp32/freertos_stats.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9964d85abd0..591b0b31568 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ set(CORE_SRCS cores/esp32/esp32-hal-uart.c cores/esp32/esp32-hal-rmt.c cores/esp32/Esp.cpp + cores/esp32/freertos_stats.cpp cores/esp32/FunctionalInterrupt.cpp cores/esp32/HardwareSerial.cpp cores/esp32/HEXBuilder.cpp diff --git a/cores/esp32/Arduino.h b/cores/esp32/Arduino.h index 2b115505cff..ab7e497dcf6 100644 --- a/cores/esp32/Arduino.h +++ b/cores/esp32/Arduino.h @@ -199,6 +199,7 @@ void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); #include "Udp.h" #include "HardwareSerial.h" #include "Esp.h" +#include "freertos_stats.h" // Use float-compatible stl abs() and round(), we don't use Arduino macros to avoid issues with the C++ libraries using std::abs; diff --git a/cores/esp32/freertos_stats.cpp b/cores/esp32/freertos_stats.cpp new file mode 100644 index 00000000000..50a98bf502b --- /dev/null +++ b/cores/esp32/freertos_stats.cpp @@ -0,0 +1,111 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "freertos_stats.h" +#include "sdkconfig.h" + +#if CONFIG_FREERTOS_USE_TRACE_FACILITY +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/portable.h" +#endif /* CONFIG_FREERTOS_USE_TRACE_FACILITY */ + +void printRunningTasks(Print &printer) { +#if CONFIG_FREERTOS_USE_TRACE_FACILITY +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS +#define FREERTOS_TASK_NUMBER_MAX_NUM 256 // RunTime stats for how many Tasks to be stored + static configRUN_TIME_COUNTER_TYPE ulRunTimeCounters[FREERTOS_TASK_NUMBER_MAX_NUM]; + static configRUN_TIME_COUNTER_TYPE ulLastRunTime = 0; + configRUN_TIME_COUNTER_TYPE ulCurrentRunTime = 0, ulTaskRunTime = 0; +#endif + configRUN_TIME_COUNTER_TYPE ulTotalRunTime = 0; + TaskStatus_t *pxTaskStatusArray = NULL; + volatile UBaseType_t uxArraySize = 0, x = 0; + const char *taskStates[] = {"Running", "Ready", "Blocked", "Suspended", "Deleted", "Invalid"}; + + // Take a snapshot of the number of tasks in case it changes while this function is executing. + uxArraySize = uxTaskGetNumberOfTasks(); + + // Allocate a TaskStatus_t structure for each task. + pxTaskStatusArray = (TaskStatus_t *)pvPortMalloc(uxArraySize * sizeof(TaskStatus_t)); + + if (pxTaskStatusArray != NULL) { + // Generate raw status information about each task. + uxArraySize = uxTaskGetSystemState(pxTaskStatusArray, uxArraySize, &ulTotalRunTime); + +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + ulCurrentRunTime = ulTotalRunTime - ulLastRunTime; + ulLastRunTime = ulTotalRunTime; +#endif + printer.printf( + "Tasks: %u" +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + ", Runtime: %lus, Period: %luus" +#endif + "\n", + uxArraySize +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + , + ulTotalRunTime / 1000000, ulCurrentRunTime +#endif + ); + printer.printf("Num\t Name" +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + "\tLoad" +#endif + "\tPrio\t Free" +#if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID + "\tCore" +#endif + "\tState\r\n"); + for (x = 0; x < uxArraySize; x++) { +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + if (pxTaskStatusArray[x].xTaskNumber < FREERTOS_TASK_NUMBER_MAX_NUM) { + ulTaskRunTime = (pxTaskStatusArray[x].ulRunTimeCounter - ulRunTimeCounters[pxTaskStatusArray[x].xTaskNumber]); + ulRunTimeCounters[pxTaskStatusArray[x].xTaskNumber] = pxTaskStatusArray[x].ulRunTimeCounter; + ulTaskRunTime = (ulTaskRunTime * 100) / ulCurrentRunTime; // in percentage + } else { + ulTaskRunTime = 0; + } +#endif + printer.printf( + "%3u\t%16s" +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + "\t%3lu%%" +#endif + "\t%4u\t%5lu" +#if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID + "\t%4c" +#endif + "\t%s\r\n", + pxTaskStatusArray[x].xTaskNumber, pxTaskStatusArray[x].pcTaskName, +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + ulTaskRunTime, +#endif + pxTaskStatusArray[x].uxCurrentPriority, pxTaskStatusArray[x].usStackHighWaterMark, +#if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID + (pxTaskStatusArray[x].xCoreID == tskNO_AFFINITY) ? '*' : ('0' + pxTaskStatusArray[x].xCoreID), +#endif + taskStates[pxTaskStatusArray[x].eCurrentState] + ); + } + + // The array is no longer needed, free the memory it consumes. + vPortFree(pxTaskStatusArray); + printer.println(); + } +#else + printer.println("FreeRTOS trace facility is not enabled."); +#endif /* CONFIG_FREERTOS_USE_TRACE_FACILITY */ +} diff --git a/cores/esp32/freertos_stats.h b/cores/esp32/freertos_stats.h new file mode 100644 index 00000000000..ea9e1a55a21 --- /dev/null +++ b/cores/esp32/freertos_stats.h @@ -0,0 +1,28 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus + +#include "Print.h" + +/* + * Executing this function will cause interrupts and + * the scheduler to be blocked for some time. + * Please use only for debugging purposes. + */ +void printRunningTasks(Print &printer); + +#endif From 9aeb1ba548636070495c132f7e7e82df78387c34 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 25 Oct 2024 09:07:37 -0300 Subject: [PATCH 095/409] ESP32-P4 UART Pin Definitions (#10521) * feat(uart): allow pins_arduino.h to define esp32-p4 uart pins ESP32-P4 has UART default pins only for UART0 and UART1. This PR allows the board definition from pins_arduino.h to define RX2 ... RX4 and TX2 ... TX4 if necessary. It also solves the issue of begin(baud) with no pins for UART2...4 by just sending a error message and returning. * feat(uart): removes the uart2 pin definitions - not existant * fix(uart): solves the case when uart has already been initialized * ci(pre-commit): Apply automatic fixes * fix(ci): uart definition for esp32-p4 uart2 rx,tx pins --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- cores/esp32/HardwareSerial.cpp | 42 ++++++++++++++++++++++++++++++++++ cores/esp32/HardwareSerial.h | 4 ---- tests/validation/uart/uart.ino | 8 +++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index a6a7573f6e3..fb93dad1c47 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -313,6 +313,11 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in // map logical pins to GPIO numbers rxPin = digitalPinToGPIONumber(rxPin); txPin = digitalPinToGPIONumber(txPin); + int8_t _rxPin = uart_get_RxPin(_uart_nr); + int8_t _txPin = uart_get_TxPin(_uart_nr); + + rxPin = rxPin < 0 ? _rxPin : rxPin; + txPin = txPin < 0 ? _txPin : txPin; HSERIAL_MUTEX_LOCK(); // First Time or after end() --> set default Pins @@ -341,14 +346,51 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in case UART_NUM_2: if (rxPin < 0 && txPin < 0) { // do not change RX2/TX2 if it has already been set before +#ifdef RX2 rxPin = _rxPin < 0 ? (int8_t)RX2 : _rxPin; +#endif +#ifdef TX2 txPin = _txPin < 0 ? (int8_t)TX2 : _txPin; +#endif + } + break; +#endif +#if SOC_UART_HP_NUM > 3 // may save some flash bytes... + case UART_NUM_3: + if (rxPin < 0 && txPin < 0) { + // do not change RX2/TX2 if it has already been set before +#ifdef RX3 + rxPin = _rxPin < 0 ? (int8_t)RX3 : _rxPin; +#endif +#ifdef TX3 + txPin = _txPin < 0 ? (int8_t)TX3 : _txPin; +#endif + } + break; +#endif +#if SOC_UART_HP_NUM > 4 // may save some flash bytes... + case UART_NUM_4: + if (rxPin < 0 && txPin < 0) { + // do not change RX2/TX2 if it has already been set before +#ifdef RX4 + rxPin = _rxPin < 0 ? (int8_t)RX4 : _rxPin; +#endif +#ifdef TX4 + txPin = _txPin < 0 ? (int8_t)TX4 : _txPin; +#endif } break; #endif } } + // if no RX/TX pins are defined, it will not start the UART driver + if (rxPin < 0 && txPin < 0) { + log_e("No RX/TX pins defined. Please set RX/TX pins."); + HSERIAL_MUTEX_UNLOCK(); + return; + } + // IDF UART driver keeps Pin setting on restarting. Negative Pin number will keep it unmodified. // it will detach previous UART attached pins diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index 8eb7f2c91a6..a33d5def34d 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -200,8 +200,6 @@ typedef enum { #define RX2 (gpio_num_t)4 #elif CONFIG_IDF_TARGET_ESP32S3 #define RX2 (gpio_num_t)19 -#elif CONFIG_IDF_TARGET_ESP32P4 -#define RX2 (gpio_num_t)15 #endif #endif @@ -210,8 +208,6 @@ typedef enum { #define TX2 (gpio_num_t)25 #elif CONFIG_IDF_TARGET_ESP32S3 #define TX2 (gpio_num_t)20 -#elif CONFIG_IDF_TARGET_ESP32P4 -#define TX2 (gpio_num_t)14 #endif #endif #endif /* SOC_UART_HP_NUM > 2 */ diff --git a/tests/validation/uart/uart.ino b/tests/validation/uart/uart.ino index e5fa0a8285f..01c449867db 100644 --- a/tests/validation/uart/uart.ino +++ b/tests/validation/uart/uart.ino @@ -52,6 +52,14 @@ #define NEW_TX1 10 #endif +// ESP32-P4 has no UART pin definition for RX2, TX2, RX3, TX3, RX4, TX4 +#ifndef RX2 +#define RX2 RX1 +#endif +#ifndef TX2 +#define TX2 RX1 +#endif + /* Utility global variables */ static String recv_msg = ""; From 74e4a744ce0bae127cd2eeac04e62c2bf45a9c93 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 25 Oct 2024 14:48:35 -0300 Subject: [PATCH 096/409] feat(uart): uart break example improvement (#10525) prints the HEXA and CHAR in order to allow the user to see why there is 1 extra char (0x00) when BREAK is received. --- .../OnReceiveError_BREAK_Demo/OnReceiveError_BREAK_Demo.ino | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/ESP32/examples/Serial/OnReceiveError_BREAK_Demo/OnReceiveError_BREAK_Demo.ino b/libraries/ESP32/examples/Serial/OnReceiveError_BREAK_Demo/OnReceiveError_BREAK_Demo.ino index fb7af04c5f5..209cf8922be 100644 --- a/libraries/ESP32/examples/Serial/OnReceiveError_BREAK_Demo/OnReceiveError_BREAK_Demo.ino +++ b/libraries/ESP32/examples/Serial/OnReceiveError_BREAK_Demo/OnReceiveError_BREAK_Demo.ino @@ -80,7 +80,11 @@ void onReceiveFunction() { received_bytes = received_bytes + available; Serial.printf("onReceive Callback:: There are %d bytes available: {", available); while (available--) { - Serial.print((char)Serial1.read()); + char c = Serial1.read(); + Serial.printf("0x%x='%c'", c, c); + if (available) { + Serial.print(" "); + } } Serial.println("}"); } From a805e0696c6564d356b2a1dc616af08394d082d4 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:49:05 -0300 Subject: [PATCH 097/409] feat(esptool): Update esptool to v4.8.1 (#10524) * feat(esptool): Update esptool to v4.8.1 * fix(archives): Fix checksums --- package/package_esp32_index.template.json | 44 +++++++++++------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index aafaa211eba..9681cf54c98 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -72,7 +72,7 @@ { "packager": "esp32", "name": "esptool_py", - "version": "4.6" + "version": "4.8.1" }, { "packager": "esp32", @@ -460,42 +460,42 @@ }, { "name": "esptool_py", - "version": "4.8.0", + "version": "4.8.1", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/esptool/releases/download/v4.8.0/esptool-v4.8.0-linux-amd64.zip", - "archiveFileName": "esptool-v4.8.0-linux-amd64.zip", - "checksum": "SHA-256:e637adc204b74b980013e89dafce6e056401ec26c94e205b0158075a836c56c6", - "size": "64617780" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC1/esptool-v4.8.1-linux-amd64.tar.gz", + "archiveFileName": "esptool-v4.8.1-linux-amd64.tar.gz", + "checksum": "SHA-256:aaaaa25e1c64442ae93604812376783dbc50f34536221b5897456e12f01e1bfd", + "size": "64635657" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/esptool/releases/download/v4.8.0/esptool-v4.8.0-linux-arm64.zip", - "archiveFileName": "esptool-v4.8.0-linux-arm64.zip", - "checksum": "SHA-256:c3a7749bed8d1929b0ad35743cc5557d60ecb81a10ffac28cb55ed1545e0223a", - "size": "54432155" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC1/esptool-v4.8.1-linux-arm64.tar.gz", + "archiveFileName": "esptool-v4.8.1-linux-arm64.tar.gz", + "checksum": "SHA-256:76170a9282bdc52fddd75e4498fd6bee55fe19088a34ab363b3aeff800d73f60", + "size": "54449306" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/esptool/releases/download/v4.8.0/esptool-v4.8.0-linux-arm32.zip", - "archiveFileName": "esptool-v4.8.0-linux-arm32.zip", - "checksum": "SHA-256:b781a86b53a17d24e02996c0a7958f9b76f6873fc1cc07c64ab6326e19395570", - "size": "45858426" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC1/esptool-v4.8.1-linux-arm32.tar.gz", + "archiveFileName": "esptool-v4.8.1-linux-arm32.tar.gz", + "checksum": "SHA-256:26b842e22a66b3d01e830a4784686a69cfb107d774a4093327ec6bba7bb17794", + "size": "45868720" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/esptool/releases/download/v4.8.0/esptool-v4.8.0-macos.zip", - "archiveFileName": "esptool-v4.8.0-macos.zip", - "checksum": "SHA-256:73bba755d2da15ef18b8b8d8fe37c459d296648efb02d5449a3fc0035930306a", - "size": "29821710" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC1/esptool-v4.8.1-macos.tar.gz", + "archiveFileName": "esptool-v4.8.1-macos.tar.gz", + "checksum": "SHA-256:6e1fc5ea04490e849c925c48d5cee590164fcf9b9bd419a7b014c2fb48a13743", + "size": "29828542" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/esptool/releases/download/v4.8.0/esptool-v4.8.0-win64.zip", - "archiveFileName": "esptool-v4.8.0-win64.zip", - "checksum": "SHA-256:5575beabfe8c1c1ea7c1a0f1bd42ee97ac3f4c4dae5fc74cda58be0e23016da3", - "size": "33608471" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC1/esptool-v4.8.1-win64.zip", + "archiveFileName": "esptool-v4.8.1-win64.zip", + "checksum": "SHA-256:3e97fb990fdd721b923b478eaaa046967c7919dbc9cbd04c445307571177918a", + "size": "33612728" } ] }, From 87ad78d787ebd8cb1638642d6c70d2b335f0be90 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Tue, 29 Oct 2024 13:10:20 +0200 Subject: [PATCH 098/409] fix(bm): Board Manager install will fail on Windows (#10533) * fix(bm): Board Manager install will fail on Windows On some Windows installations, Board Manager will fail to install the RC2 core, because it could not find esptool for the given OS. * fix(package): EspTool for Mac is only ARM64 version cc: @lucasssvaz --- package/package_esp32_index.template.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 9681cf54c98..5f05469a185 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -484,12 +484,19 @@ "size": "45868720" }, { - "host": "x86_64-apple-darwin", + "host": "arm64-apple-darwin", "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC1/esptool-v4.8.1-macos.tar.gz", "archiveFileName": "esptool-v4.8.1-macos.tar.gz", "checksum": "SHA-256:6e1fc5ea04490e849c925c48d5cee590164fcf9b9bd419a7b014c2fb48a13743", "size": "29828542" }, + { + "host": "i686-mingw32", + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC1/esptool-v4.8.1-win64.zip", + "archiveFileName": "esptool-v4.8.1-win64.zip", + "checksum": "SHA-256:3e97fb990fdd721b923b478eaaa046967c7919dbc9cbd04c445307571177918a", + "size": "33612728" + }, { "host": "x86_64-mingw32", "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC1/esptool-v4.8.1-win64.zip", From d47771f2cc649c3cd52a3f6eb3d9b97c82005ffb Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 29 Oct 2024 12:10:40 +0100 Subject: [PATCH 099/409] fix(sntp): Lock / Unlock LWIP if CONFIG_LWIP_TCPIP_CORE_LOCKING is set (#10529) * fix(sntp): Lock / Unlock LWIP if CONFIG_LWIP_TCPIP_CORE_LOCKING is set Fixes: https://github.com/espressif/arduino-esp32/issues/10526 * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- cores/esp32/esp32-hal-time.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/cores/esp32/esp32-hal-time.c b/cores/esp32/esp32-hal-time.c index 23bd3bf9e99..25c060eabdd 100644 --- a/cores/esp32/esp32-hal-time.c +++ b/cores/esp32/esp32-hal-time.c @@ -17,6 +17,10 @@ //#include "tcpip_adapter.h" #include "esp_netif.h" +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING +#include "lwip/priv/tcpip_priv.h" +#endif + static void setTimeZone(long offset, int daylight) { char cst[17] = {0}; char cdt[17] = "DST"; @@ -50,11 +54,25 @@ void configTime(long gmtOffset_sec, int daylightOffset_sec, const char *server1, if (sntp_enabled()) { sntp_stop(); } + +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING + if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { + LOCK_TCPIP_CORE(); + } +#endif + sntp_setoperatingmode(SNTP_OPMODE_POLL); sntp_setservername(0, (char *)server1); sntp_setservername(1, (char *)server2); sntp_setservername(2, (char *)server3); sntp_init(); + +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING + if (sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { + UNLOCK_TCPIP_CORE(); + } +#endif + setTimeZone(-gmtOffset_sec, daylightOffset_sec); } @@ -68,11 +86,25 @@ void configTzTime(const char *tz, const char *server1, const char *server2, cons if (sntp_enabled()) { sntp_stop(); } + +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING + if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { + LOCK_TCPIP_CORE(); + } +#endif + sntp_setoperatingmode(SNTP_OPMODE_POLL); sntp_setservername(0, (char *)server1); sntp_setservername(1, (char *)server2); sntp_setservername(2, (char *)server3); sntp_init(); + +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING + if (sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { + UNLOCK_TCPIP_CORE(); + } +#endif + setenv("TZ", tz, 1); tzset(); } From 05102fe853fea3687ddf9c4f3adf51aa168a5219 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Thu, 31 Oct 2024 08:13:08 -0300 Subject: [PATCH 100/409] docs(lib-builder): Improve UI and Docker image sections (#10535) * docs(lib-builder): Improve UI and Docker image sections * docs(lib-builder): Apply review suggestions --- docs/en/lib_builder.rst | 72 +++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/docs/en/lib_builder.rst b/docs/en/lib_builder.rst index 3d28761ab2d..a05fd45d584 100644 --- a/docs/en/lib_builder.rst +++ b/docs/en/lib_builder.rst @@ -204,6 +204,50 @@ You can then run the UI using the following command: ./tools/config_editor/app.py +Pre-Configuring the UI +********************** + +The UI can be pre-configured using command line arguments. The following arguments are available: + +- ``-t, --target ``: Comma-separated list of targets to be compiled. + Choose from: *all*, *esp32*, *esp32s2*, *esp32s3*, *esp32c2*, *esp32c3*, *esp32c6*, *esp32h2*. Default: all except *esp32c2*; +- ``--copy, --no-copy``: Enable/disable copying the compiled libraries to ``arduino-esp32``. Enabled by default; +- ``-c, --arduino-path ``: Path to ``arduino-esp32`` directory. Default: OS dependent; +- ``-A, --arduino-branch ``: Branch of the ``arduino-esp32`` repository to be used. Default: set by the build script; +- ``-I, --idf-branch ``: Branch of the ``ESP-IDF`` repository to be used. Default: set by the build script; +- ``-i, --idf-commit ``: Commit of the ``ESP-IDF`` repository to be used. Default: set by the build script; +- ``-D, --debug-level ``: Debug level to be set in ``ESP-IDF``. + Choose from: *default*, *none*, *error*, *warning*, *info*, *debug*, *verbose*. Default: *default*. + +Please note that all these options can be changed in the UI itself and are only used for automation purposes. + +Screens +******* + +There are many screens in the UI that are used to configure the libraries to be compiled. +Note that in all screens you can also use the shortcut keys shown in the footer bar to navigate. + +The UI consists of the following screens: + +- **Main Menu**: The main screen shows buttons to navigate to the other screens. +- **Compile Screen**: The compile screen shows the output of the compilation process and any errors that may have occurred. +- **Sdkconfig Editor**: The sdkconfig editor screen is a simple text editor that shows you the sdkconfig files that will be used for compilation. + You can edit the files here to customize the generated libraries. +- **Settings Screen**: The settings screen allows you to change the settings of the compilation process. + Here you can change: + + - The targets that the libraries will be compiled for. To save time, you can compile the libraries only for the target you are using; + - Whether the compiled libraries will be copied to the ``arduino-esp32`` directory after compilation so that they can be used in the Arduino IDE; + - The path to the ``arduino-esp32`` directory. This will be automatically set if the ``arduino-esp32`` repository is in one of the default locations. + If not, you can set it manually here. If using the docker image, it should not be changed as the mount point is fixed; + - The branch of the ``arduino-esp32`` repository to be used. This is useful if you want to compile the libraries for a + specific branch or pull request of the ``arduino-esp32`` repository. Leave empty to use the default branch for this ``ESP-IDF`` version; + - The branch of the ``ESP-IDF`` repository to be used. This is useful if you want to compile the libraries for a specific branch of the ``ESP-IDF`` repository. + Leave empty to use the default branch for this IDF version; + - The commit of the ``ESP-IDF`` repository to be used. This is useful if you want to compile the libraries for a specific commit on the selected branch. + Leave empty to use the latest commit; + - The debug level to be set in ``ESP-IDF``. + Docker Image ------------ @@ -224,8 +268,9 @@ Tags Multiple tags of this image are maintained: -- ``latest``: tracks ``master`` branch of the Lib Builder -- ``release-vX.Y``: tracks ``release/vX.Y`` branch of the Lib Builder +- ``latest``: tracks ``master`` branch of the Lib Builder. Note that the ``latest`` tag is not recommended for use as, depending on the + development stage of the Lib Builder, it might not be stable or might not contain the latest changes; +- ``release-vX.Y``: tracks ``release/vX.Y`` branch of the Lib Builder. .. note:: Versions of Lib Builder released before this feature was introduced do not have corresponding Docker image versions. @@ -234,7 +279,7 @@ Multiple tags of this image are maintained: Usage ***** -Before using the ``espressif/esp32-arduino-lib-builder`` Docker image locally, make sure you have Docker installed. +Before using the ``espressif/esp32-arduino-lib-builder`` Docker image locally, make sure you have Docker installed and running on your machine. Follow the instructions at https://docs.docker.com/install/, if it is not installed yet. If using the image in a CI environment, consult the documentation of your CI service on how to specify the image used for the build process. @@ -248,7 +293,7 @@ To run the Docker image manually, use the following command from the root of the .. code-block:: bash - docker run --rm -it -v $PWD:/arduino-esp32 -e TERM=xterm-256color espressif/esp32-arduino-lib-builder + docker run --rm -it -v $PWD:/arduino-esp32 -e TERM=xterm-256color espressif/esp32-arduino-lib-builder:release-v5.1 This will start the Lib Builder UI for compiling the libraries. The above command explained: @@ -258,7 +303,8 @@ This will start the Lib Builder UI for compiling the libraries. The above comman - ``-t`` Allocate a pseudo-TTY; - ``-e TERM=xterm-256color``: Optional. Sets the terminal type to ``xterm-256color`` to display colors correctly; - ``-v $PWD:/arduino-esp32``: Optional. Mounts the current folder at ``/arduino-esp32`` inside the container. If not provided, the container will not copy the compiled libraries to the host machine; -- ``espressif/esp32-arduino-lib-builder``: uses Docker image ``espressif/esp32-arduino-lib-builder`` with tag ``latest``. The ``latest`` tag is implicitly added by Docker when no tag is specified. +- ``espressif/esp32-arduino-lib-builder:release-v5.1``: uses Docker image ``espressif/esp32-arduino-lib-builder`` with tag ``release-v5.1``. + The ``latest`` tag is implicitly added by Docker when no tag is specified. It is recommended to use a specific version tag to ensure reproducibility of the build process. .. warning:: The ``-v`` option is used to mount a folder from the host machine to the container. Make sure the folder already exists on the host machine before running the command. @@ -278,14 +324,15 @@ For example, to run a terminal inside the container, you can run: .. code-block:: bash - docker run -it espressif/esp32-arduino-lib-builder:latest /bin/bash + docker run -it espressif/esp32-arduino-lib-builder:release-v5.1 /bin/bash Running the Docker image using the provided run script will depend on the host OS. -Use the following command from the root of the ``arduino-esp32`` repository to execute the image in a Linux or macOS environment: +Use the following command from the root of the ``arduino-esp32`` repository to execute the image in a Linux or macOS environment for +the ``release-v5.1`` tag: .. code-block:: bash - curl -LJO https://raw.githubusercontent.com/espressif/esp32-arduino-lib-builder/master/tools/docker/run.sh + curl -LJO https://raw.githubusercontent.com/espressif/esp32-arduino-lib-builder/refs/heads/release/v5.1/tools/docker/run.sh chmod +x run.sh ./run.sh $PWD @@ -293,9 +340,16 @@ For Windows, use the following command in PowerShell from the root of the ``ardu .. code-block:: powershell - Invoke-WebRequest -Uri "https://raw.githubusercontent.com/espressif/esp32-arduino-lib-builder/master/tools/docker/run.ps1" -OutFile "run.ps1" + Invoke-WebRequest -Uri "https://raw.githubusercontent.com/espressif/esp32-arduino-lib-builder/refs/heads/release/v5.1/tools/docker/run.ps1" -OutFile "run.ps1" .\run.ps1 $pwd +As the script is unsigned, you may need to change the execution policy of the current session before running the script. +To do so, run the following command in PowerShell: + +.. code-block:: powershell + + Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass + .. warning:: It is always a good practice to understand what the script does before running it. Make sure to analyze the content of the script to ensure it is safe to run and won't cause any harm to your system. From eeecf844a7cfc4f0e019777c7da8979946993178 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Mon, 4 Nov 2024 18:12:20 -0300 Subject: [PATCH 101/409] ci(workflows): General improvements and fixes (#10544) * ci(triggers): Improve workflow triggering and bump versions * ci(runtime): Improve runtime tests triggers * fix(push): Fix push chunks script indentation and lib detection --- .github/scripts/set_push_chunks.sh | 116 ++++++++++++++--------------- .github/workflows/pre-commit.yml | 14 +++- .github/workflows/push.yml | 6 +- .github/workflows/tests.yml | 7 +- tests/requirements.txt | 8 +- tools/pre-commit/requirements.txt | 2 +- 6 files changed, 81 insertions(+), 72 deletions(-) diff --git a/.github/scripts/set_push_chunks.sh b/.github/scripts/set_push_chunks.sh index 472205f0c38..11a93a7159d 100644 --- a/.github/scripts/set_push_chunks.sh +++ b/.github/scripts/set_push_chunks.sh @@ -4,73 +4,73 @@ build_all=false chunks_count=0 if [[ $CORE_CHANGED == 'true' ]] || [[ $IS_PR != 'true' ]]; then - echo "Core files changed or not a PR. Building all." - build_all=true - chunks_count=$MAX_CHUNKS + echo "Core files changed or not a PR. Building all." + build_all=true + chunks_count=$MAX_CHUNKS elif [[ $LIB_CHANGED == 'true' ]]; then - echo "Libraries changed. Building only affected sketches." - if [[ $NETWORKING_CHANGED == 'true' ]]; then - echo "Networking libraries changed. Building networking related sketches." - networking_sketches="$(find libraries/WiFi -name *.ino) " - networking_sketches+="$(find libraries/Ethernet -name *.ino) " - networking_sketches+="$(find libraries/PPP -name *.ino) " - networking_sketches+="$(find libraries/NetworkClientSecure -name *.ino) " - networking_sketches+="$(find libraries/WebServer -name *.ino) " - fi - if [[ $FS_CHANGED == 'true' ]]; then - echo "FS libraries changed. Building FS related sketches." - fs_sketches="$(find libraries/SD -name *.ino) " - fs_sketches+="$(find libraries/SD_MMC -name *.ino) " - fs_sketches+="$(find libraries/SPIFFS -name *.ino) " - fs_sketches+="$(find libraries/LittleFS -name *.ino) " - fs_sketches+="$(find libraries/FFat -name *.ino) " - fi - sketches="$networking_sketches $fs_sketches" - for file in $LIB_FILES; do - if [[ $file == *.ino ]]; then - # If file ends with .ino, add it to the list of sketches - echo "Sketch found: $file" - sketches+="$file " - elif [[ $(basename $(dirname $file)) == "src" ]]; then - # If file is in a src directory, find all sketches in the parent/examples directory - echo "Library src file found: $file" - lib=$(dirname $(dirname $file)) - if [[ -d $lib/examples ]]; then - lib_sketches=$(find $lib/examples -name *.ino) - sketches+="$lib_sketches " - echo "Library sketches: $lib_sketches" - fi - else - # If file is in a example folder but it is not a sketch, find all sketches in the current directory - echo "File in example folder found: $file" - sketch=$(find $(dirname $file) -name *.ino) - sketches+="$sketch " - echo "Sketch in example folder: $sketch" - fi - echo "" - done + echo "Libraries changed. Building only affected sketches." + if [[ $NETWORKING_CHANGED == 'true' ]]; then + echo "Networking libraries changed. Building networking related sketches." + networking_sketches="$(find libraries/WiFi -name *.ino) " + networking_sketches+="$(find libraries/Ethernet -name *.ino) " + networking_sketches+="$(find libraries/PPP -name *.ino) " + networking_sketches+="$(find libraries/NetworkClientSecure -name *.ino) " + networking_sketches+="$(find libraries/WebServer -name *.ino) " + fi + if [[ $FS_CHANGED == 'true' ]]; then + echo "FS libraries changed. Building FS related sketches." + fs_sketches="$(find libraries/SD -name *.ino) " + fs_sketches+="$(find libraries/SD_MMC -name *.ino) " + fs_sketches+="$(find libraries/SPIFFS -name *.ino) " + fs_sketches+="$(find libraries/LittleFS -name *.ino) " + fs_sketches+="$(find libraries/FFat -name *.ino) " + fi + sketches="$networking_sketches $fs_sketches" + for file in $LIB_FILES; do + lib=$(echo $file | awk -F "/" '{print $1"/"$2}') + if [[ "$file" == *.ino ]]; then + # If file ends with .ino, add it to the list of sketches + echo "Sketch found: $file" + sketches+="$file " + elif [[ "$file" == "$lib/src/"* ]]; then + # If file is inside the src directory, find all sketches in the lib/examples directory + echo "Library src file found: $file" + if [[ -d $lib/examples ]]; then + lib_sketches=$(find $lib/examples -name *.ino) + sketches+="$lib_sketches " + echo "Library sketches: $lib_sketches" + fi + else + # If file is in a example folder but it is not a sketch, find all sketches in the current directory + echo "File in example folder found: $file" + sketch=$(find $(dirname $file) -name *.ino) + sketches+="$sketch " + echo "Sketch in example folder: $sketch" + fi + echo "" + done fi if [[ -n $sketches ]]; then - # Remove duplicates - sketches=$(echo $sketches | tr ' ' '\n' | sort | uniq) - for sketch in $sketches; do - echo $sketch >> sketches_found.txt - chunks_count=$((chunks_count+1)) - done - echo "Number of sketches found: $chunks_count" - echo "Sketches:" - echo "$sketches" + # Remove duplicates + sketches=$(echo $sketches | tr ' ' '\n' | sort | uniq) + for sketch in $sketches; do + echo $sketch >> sketches_found.txt + chunks_count=$((chunks_count+1)) + done + echo "Number of sketches found: $chunks_count" + echo "Sketches:" + echo "$sketches" - if [[ $chunks_count -gt $MAX_CHUNKS ]]; then - echo "More sketches than the allowed number of chunks found. Limiting to $MAX_CHUNKS chunks." - chunks_count=$MAX_CHUNKS - fi + if [[ $chunks_count -gt $MAX_CHUNKS ]]; then + echo "More sketches than the allowed number of chunks found. Limiting to $MAX_CHUNKS chunks." + chunks_count=$MAX_CHUNKS + fi fi chunks='["0"' for i in $(seq 1 $(( $chunks_count - 1 )) ); do - chunks+=",\"$i\"" + chunks+=",\"$i\"" done chunks+="]" diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index c4ae017c229..8257e78c822 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -6,7 +6,7 @@ on: branches: - master pull_request: - types: [opened, reopened, synchronize, labeled, unlabeled] + types: [opened, reopened, synchronize, labeled] concurrency: group: pre-commit-${{github.event.pull_request.number || github.ref}} @@ -15,8 +15,10 @@ concurrency: jobs: lint: if: | + github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'Status: Pending Merge') || - github.event_name != 'pull_request' + contains(github.event.pull_request.labels.*.name, 'Re-trigger Pre-commit Hooks') + name: Check if fixes are needed runs-on: ubuntu-latest steps: @@ -25,6 +27,12 @@ jobs: with: fetch-depth: 2 + - name: Remove Label + if: contains(github.event.pull_request.labels.*.name, 'Re-trigger Pre-commit Hooks') + run: gh pr edit ${{ github.event.number }} --remove-label 'Re-trigger Pre-commit Hooks' + env: + GH_TOKEN: ${{ github.token }} + - name: Set up Python 3 uses: actions/setup-python@v5 with: @@ -65,7 +73,7 @@ jobs: key: ${{ steps.restore-cache.outputs.cache-primary-key }} - name: Push changes using pre-commit-ci-lite - uses: pre-commit-ci/lite-action@v1.0.2 + uses: pre-commit-ci/lite-action@v1.1.0 # Only push changes in PRs if: ${{ always() && github.event_name == 'pull_request' }} with: diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 19e53b844f2..82159e1b8a4 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -5,7 +5,7 @@ on: push: branches: - master - - release/v2.x + - release/* pull_request: paths: - 'cores/**' @@ -47,6 +47,7 @@ jobs: cmake-check: name: Check cmake file runs-on: ubuntu-latest + if: ${{ !(github.event_name == 'pull_request' && startsWith(github.head_ref, 'release/')) }} steps: - uses: actions/checkout@v4 - run: bash ./.github/scripts/check-cmakelists.sh @@ -54,6 +55,7 @@ jobs: gen-chunks: name: Generate chunks runs-on: ubuntu-latest + if: ${{ !(github.event_name == 'pull_request' && startsWith(github.head_ref, 'release/')) }} outputs: build_all: ${{ steps.set-chunks.outputs.build_all }} build_libraries: ${{ steps.set-chunks.outputs.build_libraries }} @@ -307,7 +309,7 @@ jobs: #Upload PR number as artifact upload-pr-number: name: Upload PR number - if: github.event_name == 'pull_request' + if: ${{ github.event_name == 'pull_request' && !startsWith(github.head_ref, 'release/') }} runs-on: ubuntu-latest steps: - name: Save the PR number in an artifact diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ab8baa6d14c..f57a1925c1c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,10 +26,9 @@ on: - '!.github/scripts/upload_py_tools.sh' - 'tests/**' - 'cores/**' - - 'libraries/**' - - '!libraries/**.md' - - '!libraries/**.txt' - - '!libraries/**.properties' + - 'libraries/*/src/**.cpp' + - 'libraries/*/src/**.h' + - 'libraries/*/src/**.c' - 'package/**' schedule: - cron: '0 2 * * *' diff --git a/tests/requirements.txt b/tests/requirements.txt index 63d204a96b0..a7df8928665 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,7 +1,7 @@ cryptography==43.0.1 --only-binary cryptography pytest-cov==5.0.0 -pytest-embedded-serial-esp==1.11.6 -pytest-embedded-arduino==1.11.6 -pytest-embedded-wokwi==1.11.6 -pytest-embedded-qemu==1.11.6 +pytest-embedded-serial-esp==1.11.8 +pytest-embedded-arduino==1.11.8 +pytest-embedded-wokwi==1.11.8 +pytest-embedded-qemu==1.11.8 diff --git a/tools/pre-commit/requirements.txt b/tools/pre-commit/requirements.txt index 7b88387b05b..aca4a61191f 100644 --- a/tools/pre-commit/requirements.txt +++ b/tools/pre-commit/requirements.txt @@ -1,2 +1,2 @@ -pre-commit==3.7.1 +pre-commit==4.0.1 docutils==0.16 From 57d0deef2dfaf916e9ad93bdeaab0442433109db Mon Sep 17 00:00:00 2001 From: wurongmin <55608753+wurongmin@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:42:19 +0800 Subject: [PATCH 102/409] feat(boards): add Waveshare ESP32-S3-Touch-AMOLED boards (#10549) * Add files via upload * Add files via upload * feat(boards): add Waveshare ESP32-S3-Touch-AMOLED boards Added three micro snow development boards to boards * feat(boards): add Waveshare ESP32-S3-Touch-AMOLED variants A trio of micro-snow variants have been added to the variants * Delete variants/waveshare_esp32_s3_touch_amoled_143/pins_arduino.h * Delete variants/waveshare_esp32_s3_touch_amoled_164 directory * Delete variants/waveshare_esp32_s3_touch_amoled_191 directory * feat(boards): Three variants of the development board were added waveshare_esp32_s3_touch_amoled_143 waveshare_esp32_s3_touch_amoled_164 waveshare_esp32_s3_touch_amoled_191 * feat(boards): Add three boards to boards * feat(boards): Add the variants * feat(boards): Fixed the boards file To ensure that each plate type only one * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- boards.txt | 606 ++++++++++++++++++ .../pins_arduino.h | 49 ++ .../pins_arduino.h | 55 ++ .../pins_arduino.h | 57 ++ 4 files changed, 767 insertions(+) create mode 100644 variants/waveshare_esp32_s3_touch_amoled_143/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_touch_amoled_164/pins_arduino.h create mode 100644 variants/waveshare_esp32_s3_touch_amoled_191/pins_arduino.h diff --git a/boards.txt b/boards.txt index 8d4cc529ed7..9bb3f53b7bf 100644 --- a/boards.txt +++ b/boards.txt @@ -46266,3 +46266,609 @@ waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MOD waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port ############################################################## + +waveshare_esp32_s3_touch_amoled_164.name=Waveshare ESP32-S3-Touch-AMOLED-1.64 +waveshare_esp32_s3_touch_amoled_164.vid.0=0x303a +waveshare_esp32_s3_touch_amoled_164.pid.0=0x8249 +waveshare_esp32_s3_touch_amoled_164.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_amoled_164.upload_port.0.pid=0x8249 + +waveshare_esp32_s3_touch_amoled_164.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_amoled_164.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_amoled_164.upload.tool=esptool_py +waveshare_esp32_s3_touch_amoled_164.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_amoled_164.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_amoled_164.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_amoled_164.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_amoled_164.upload.flags= +waveshare_esp32_s3_touch_amoled_164.upload.extra_flags= +waveshare_esp32_s3_touch_amoled_164.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_164.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_amoled_164.serial.disableDTR=false +waveshare_esp32_s3_touch_amoled_164.serial.disableRTS=false + +waveshare_esp32_s3_touch_amoled_164.build.tarch=xtensa +waveshare_esp32_s3_touch_amoled_164.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_amoled_164.build.target=esp32s3 +waveshare_esp32_s3_touch_amoled_164.build.mcu=esp32s3 +waveshare_esp32_s3_touch_amoled_164.build.core=esp32 +waveshare_esp32_s3_touch_amoled_164.build.variant=waveshare_esp32_s3_touch_amoled_164 +waveshare_esp32_s3_touch_amoled_164.build.board=WAVESHARE_ESP32_S3_TOUCH_AMOLED_164 + +waveshare_esp32_s3_touch_amoled_164.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_164.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_164.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_164.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_164.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_164.build.flash_size=16MB + +waveshare_esp32_s3_touch_amoled_164.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_164.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_164.build.boot=qio +waveshare_esp32_s3_touch_amoled_164.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_164.build.partitions=default +waveshare_esp32_s3_touch_amoled_164.build.defines= +waveshare_esp32_s3_touch_amoled_164.build.loop_core= +waveshare_esp32_s3_touch_amoled_164.build.event_core= +waveshare_esp32_s3_touch_amoled_164.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_164.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_amoled_164.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_amoled_164.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_amoled_164.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_164.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_amoled_164.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_amoled_164.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_amoled_164.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_164.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_164.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_164.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_164.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_164.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_164.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_164.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_164.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_amoled_164.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_164.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_amoled_164.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_amoled_164.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_164.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_164.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_amoled_164.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_164.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_164.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_164.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_164.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_164.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_164.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_164.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_164.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) + +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 + +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_amoled_164.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_amoled_164.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_amoled_164.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_amoled_164.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_amoled_143.name=Waveshare ESP32-S3-Touch-AMOLED-1.43 +waveshare_esp32_s3_touch_amoled_143.vid.0=0x303a +waveshare_esp32_s3_touch_amoled_143.pid.0=0x824a +waveshare_esp32_s3_touch_amoled_143.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_amoled_143.upload_port.0.pid=0x824a + +waveshare_esp32_s3_touch_amoled_143.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_amoled_143.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_amoled_143.upload.tool=esptool_py +waveshare_esp32_s3_touch_amoled_143.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_amoled_143.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_amoled_143.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_amoled_143.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_amoled_143.upload.flags= +waveshare_esp32_s3_touch_amoled_143.upload.extra_flags= +waveshare_esp32_s3_touch_amoled_143.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_143.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_amoled_143.serial.disableDTR=false +waveshare_esp32_s3_touch_amoled_143.serial.disableRTS=false + +waveshare_esp32_s3_touch_amoled_143.build.tarch=xtensa +waveshare_esp32_s3_touch_amoled_143.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_amoled_143.build.target=esp32s3 +waveshare_esp32_s3_touch_amoled_143.build.mcu=esp32s3 +waveshare_esp32_s3_touch_amoled_143.build.core=esp32 +waveshare_esp32_s3_touch_amoled_143.build.variant=waveshare_esp32_s3_touch_amoled_143 +waveshare_esp32_s3_touch_amoled_143.build.board=WAVESHARE_ESP32_S3_TOUCH_AMOLED_143 + +waveshare_esp32_s3_touch_amoled_143.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_143.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_143.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_143.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_143.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_143.build.flash_size=16MB + +waveshare_esp32_s3_touch_amoled_143.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_143.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_143.build.boot=qio +waveshare_esp32_s3_touch_amoled_143.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_143.build.partitions=default +waveshare_esp32_s3_touch_amoled_143.build.defines= +waveshare_esp32_s3_touch_amoled_143.build.loop_core= +waveshare_esp32_s3_touch_amoled_143.build.event_core= +waveshare_esp32_s3_touch_amoled_143.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_143.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_amoled_143.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_amoled_143.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_amoled_143.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_143.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_amoled_143.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_amoled_143.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_amoled_143.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_143.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_143.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_143.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_143.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_143.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_143.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_143.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_143.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_amoled_143.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_143.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_amoled_143.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_amoled_143.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_143.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_143.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_amoled_143.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_143.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_143.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_143.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_143.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_143.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_143.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_143.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_143.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) + +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 + +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_amoled_143.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_amoled_143.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_amoled_143.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_amoled_143.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_amoled_191.name=Waveshare ESP32-S3-Touch-AMOLED-1.91 +waveshare_esp32_s3_touch_amoled_191.vid.0=0x303a +waveshare_esp32_s3_touch_amoled_191.pid.0=0x824b +waveshare_esp32_s3_touch_amoled_191.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_amoled_191.upload_port.0.pid=0x824b + +waveshare_esp32_s3_touch_amoled_191.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_amoled_191.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_amoled_191.upload.tool=esptool_py +waveshare_esp32_s3_touch_amoled_191.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_amoled_191.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_amoled_191.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_amoled_191.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_amoled_191.upload.flags= +waveshare_esp32_s3_touch_amoled_191.upload.extra_flags= +waveshare_esp32_s3_touch_amoled_191.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_191.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_amoled_191.serial.disableDTR=false +waveshare_esp32_s3_touch_amoled_191.serial.disableRTS=false + +waveshare_esp32_s3_touch_amoled_191.build.tarch=xtensa +waveshare_esp32_s3_touch_amoled_191.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_amoled_191.build.target=esp32s3 +waveshare_esp32_s3_touch_amoled_191.build.mcu=esp32s3 +waveshare_esp32_s3_touch_amoled_191.build.core=esp32 +waveshare_esp32_s3_touch_amoled_191.build.variant=waveshare_esp32_s3_touch_amoled_191 +waveshare_esp32_s3_touch_amoled_191.build.board=WAVESHARE_ESP32_S3_TOUCH_AMOLED_191 + +waveshare_esp32_s3_touch_amoled_191.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_191.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_191.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_191.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_191.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_191.build.flash_size=16MB + +waveshare_esp32_s3_touch_amoled_191.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_191.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_191.build.boot=qio +waveshare_esp32_s3_touch_amoled_191.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_191.build.partitions=default +waveshare_esp32_s3_touch_amoled_191.build.defines= +waveshare_esp32_s3_touch_amoled_191.build.loop_core= +waveshare_esp32_s3_touch_amoled_191.build.event_core= +waveshare_esp32_s3_touch_amoled_191.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_191.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_amoled_191.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_amoled_191.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_amoled_191.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_191.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_amoled_191.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_amoled_191.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_amoled_191.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_191.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_191.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_191.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_191.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_191.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_191.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_191.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_191.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_amoled_191.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_191.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_amoled_191.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_amoled_191.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_191.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_191.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_amoled_191.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_191.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_191.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_191.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_191.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_191.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_191.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_191.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_191.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) + +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 + +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_amoled_191.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_amoled_191.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_amoled_191.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_amoled_191.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## diff --git a/variants/waveshare_esp32_s3_touch_amoled_143/pins_arduino.h b/variants/waveshare_esp32_s3_touch_amoled_143/pins_arduino.h new file mode 100644 index 00000000000..ed6df1d3a2c --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_amoled_143/pins_arduino.h @@ -0,0 +1,49 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x824A + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-AMOLED-1.43" +#define USB_SERIAL "" + +// display QSPI SPI2 +#define QSPI_CS 9 +#define QSPI_SCK 10 +#define QSPI_D0 11 +#define QSPI_D1 12 +#define QSPI_D2 13 +#define QSPI_D3 14 +#define AMOLED_RESET 21 +#define AMOLED_TE -1 +#define AMOLED_PWR_EN -1 +// Touch I2C +#define TP_SCL 48 +#define TP_SDA 47 +#define TP_RST -1 +#define TP_INT -1 + +// RTC +#define RTC_INT 15 +// Partial voltage measurement method +#define BAT_ADC 4 +// Onboard QMI8658 IMU +#define QMI_INT1 8 + +static const uint8_t SDA = 47; +static const uint8_t SCL = 48; +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +//esp32s3-PSFlash SPI1/SPI0 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_amoled_164/pins_arduino.h b/variants/waveshare_esp32_s3_touch_amoled_164/pins_arduino.h new file mode 100644 index 00000000000..ce17a49972a --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_amoled_164/pins_arduino.h @@ -0,0 +1,55 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8249 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-AMOLED-1.64" +#define USB_SERIAL "" + +// display QSPI SPI2 +#define QSPI_CS 9 +#define QSPI_SCK 10 +#define QSPI_D0 11 +#define QSPI_D1 12 +#define QSPI_D2 13 +#define QSPI_D3 14 +#define AMOLED_RESET 21 +#define AMOLED_TE -1 +#define AMOLED_PWR_EN -1 + +// Touch I2C +#define TP_SCL 48 +#define TP_SDA 47 +#define TP_RST -1 +#define TP_INT -1 + +//key +#define KEY_0 0 +//ADC +#define BAT_ADC 4 + +//SD_CARD +#define SD_CS 38 +#define SD_MOSI 39 +#define SD_MISO 40 +#define SD_SCLK 41 + +static const uint8_t SDA = 47; +static const uint8_t SCL = 48; + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +//esp32s3-PSFlash SPI1/SPI0 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_amoled_191/pins_arduino.h b/variants/waveshare_esp32_s3_touch_amoled_191/pins_arduino.h new file mode 100644 index 00000000000..7e882a7ef46 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_amoled_191/pins_arduino.h @@ -0,0 +1,57 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x824B + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-AMOLED-1.91" +#define USB_SERIAL "" + +// display QSPI SPI2 +#define QSPI_CS 6 +#define QSPI_SCK 47 +#define QSPI_D0 18 +#define QSPI_D1 7 +#define QSPI_D2 48 +#define QSPI_D3 5 +#define AMOLED_RESET 17 +#define AMOLED_TE -1 +#define AMOLED_PWR_EN -1 +// Touch I2C +#define TP_SCL 39 +#define TP_SDA 40 +#define TP_RST -1 +#define TP_INT -1 + +// Partial voltage measurement method +#define BAT_ADC 1 +// Onboard QMI8658 IMU +#define QMI_INT1 45 +#define QMI_INT1 46 + +//SD +#define SD_CS 9 +#define SD_MISO 8 +#define SD_MOSI 42 +#define SD_CLK 47 + +//i2c + +static const uint8_t SDA = 40; +static const uint8_t SCL = 39; + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +//esp32s3-PSFlash SPI1/SPI0 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK +#endif /* Pins_Arduino_h */ From 870468bb25a4a64879ee5e472bbfa2ff65c06735 Mon Sep 17 00:00:00 2001 From: ASDosjani <62965528+ASDosjani@users.noreply.github.com> Date: Mon, 4 Nov 2024 22:43:07 +0100 Subject: [PATCH 103/409] Update BLE5_periodic_advertising.ino (#10538) --- .../BLE5_periodic_advertising/BLE5_periodic_advertising.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/BLE/examples/BLE5_periodic_advertising/BLE5_periodic_advertising.ino b/libraries/BLE/examples/BLE5_periodic_advertising/BLE5_periodic_advertising.ino index 796f63666db..0b9d4f87630 100644 --- a/libraries/BLE/examples/BLE5_periodic_advertising/BLE5_periodic_advertising.ino +++ b/libraries/BLE/examples/BLE5_periodic_advertising/BLE5_periodic_advertising.ino @@ -1,5 +1,5 @@ /* - Simple BLE5 multi advertising example on esp32 C3/S3 + Simple BLE5 periodic advertising example on esp32 C3/S3 only ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED can be used for periodic advertising author: chegewara From 11f3cff53f097b3e3a901c7e5f21e49b9bce828e Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Mon, 4 Nov 2024 18:49:40 -0300 Subject: [PATCH 104/409] fix(get.py): Check if win32 tools also exist when running on win64 (#10565) * fix(get.py): Check if win32 tools also exist when running on win64 * change(tools): Push generated binaries to PR --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- tools/get.exe | Bin 6930008 -> 7493192 bytes tools/get.py | 12 ++++++++++++ 2 files changed, 12 insertions(+) diff --git a/tools/get.exe b/tools/get.exe index 161cb193cae89e3dbc84006a7c7332e2683eb329..671b1507b0be78379e80de0100fce5af0621c75a 100644 GIT binary patch delta 1572460 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

f;$FaMl#;*YQ~0ChojN*33aP& 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%0Aqh7SOUQk=W4oN(;Ql$BTY7v@mom4vohAlkYXRj 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�ho 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≤RC9W8_G332{!1 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