From 8f14c13245c59a2f885e4074e1299f4dad52e3a5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 17 Jul 2024 15:42:38 +0200 Subject: [PATCH 001/117] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 41ab65c..c833e7c 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,13 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with 2. Create PlatformIO project and configure a platform option in [platformio.ini](https://docs.platformio.org/page/projectconf.html) file: ## Stable version -espressif Arduino 3.0.2 and IDF 5.1.4 +espressif Arduino 3.0.3 and IDF 5.1.4 See `platform` [documentation](https://docs.platformio.org/en/latest/projectconf/sections/env/options/platform/platform.html#projectconf-env-platform) for details. ```ini [env:stable] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/2024.07.00/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip board = ... ... ``` @@ -28,11 +28,11 @@ board = ... ```ini [env:development] -platform = https://github.com/pioarduino/platform-espressif32.git#Arduino/IDF51 +platform = https://github.com/pioarduino/platform-espressif32.git#development board = ... ... ``` # Configuration -Please navigate to [documentation](https://docs.platformio.org/page/platforms/espressif32.html). \ No newline at end of file +Please navigate to [documentation](https://docs.platformio.org/page/platforms/espressif32.html). From 2ce731a339a1f1219e5b506fcfeb5076c5fe9327 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 18 Jul 2024 13:11:06 +0200 Subject: [PATCH 002/117] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c833e7c..2ee9220 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +# pioarduino (p)eople (i)nitiated (o)ptimized (arduino) # Fork of Platformio Espressif 32: development platform for [PlatformIO](https://platformio.org) [![Build Status](https://github.com/pioarduino/platform-espressif32/workflows/Examples/badge.svg)](https://github.com/pioarduino/platform-espressif32/actions) From 77b00e457150251035218c89fbee064c902041dc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 30 Jul 2024 19:12:42 +0200 Subject: [PATCH 003/117] Backport from upstream supporting all IDF 5.X --- builder/frameworks/espidf.py | 116 +++++++++++++++++++++++++++-------- 1 file changed, 89 insertions(+), 27 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 08c14bb..b3ccdde 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -58,12 +58,9 @@ board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") idf_variant = mcu.lower() -# Required until Arduino switches to v5 -IDF5 = ( - platform.get_package_version("framework-espidf") - .split(".")[1] - .startswith("5") -) +IDF_version = platform.get_package_version("framework-espidf") +IDF5 = IDF_version.split(".")[1].startswith("5") # bool; Major IDF5 ? +IDF_minor = int(("".join(IDF_version.split(".")[1]))[1:3]) # Minor version as int IDF_ENV_VERSION = "1.0.0" FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( @@ -248,7 +245,7 @@ def populate_idf_env_vars(idf_env): os.path.dirname(get_python_exe()), ] - if mcu not in ("esp32c2", "esp32c3", "esp32c6","esp32h2"): + if mcu not in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"): additional_packages.append( os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), ) @@ -503,7 +500,7 @@ def extract_linker_script_fragments_backup(framework_components_dir, sdk_config) sys.stderr.write("Error: Failed to extract paths to linker script fragments\n") env.Exit(1) - if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2"): + if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"): result.append(os.path.join(framework_components_dir, "riscv", "linker.lf")) # Add extra linker fragments @@ -644,16 +641,30 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): '--objdump "{objdump}"' ).format(**args) + initial_ld_script = os.path.join( + FRAMEWORK_DIR, + "components", + "esp_system", + "ld", + idf_variant, + "sections.ld.in", + ) + + if IDF5 and IDF_minor > 2: + initial_ld_script = preprocess_linker_file( + initial_ld_script, + os.path.join( + BUILD_DIR, + "esp-idf", + "esp_system", + "ld", + "sections.ld.in", + ) + ) + return env.Command( os.path.join("$BUILD_DIR", "sections.ld"), - os.path.join( - FRAMEWORK_DIR, - "components", - "esp_system", - "ld", - idf_variant, - "sections.ld.in", - ), + initial_ld_script, env.VerboseAction(cmd, "Generating project linker script $TARGET"), ) @@ -1103,6 +1114,46 @@ def get_app_partition_offset(pt_table, pt_offset): return app_params.get("offset", "0x10000") +def preprocess_linker_file(src_ld_script, target_ld_script): + return env.Command( + target_ld_script, + src_ld_script, + env.VerboseAction( + " ".join( + [ + os.path.join( + platform.get_package_dir("tool-cmake"), + "bin", + "cmake", + ), + "-DCC=%s" + % os.path.join( + TOOLCHAIN_DIR, + "bin", + "$CC", + ), + "-DSOURCE=$SOURCE", + "-DTARGET=$TARGET", + "-DCONFIG_DIR=%s" % os.path.join(BUILD_DIR, "config"), + "-DLD_DIR=%s" + % os.path.join( + FRAMEWORK_DIR, "components", "esp_system", "ld" + ), + "-P", + os.path.join( + "$BUILD_DIR", + "esp-idf", + "esp_system", + "ld", + "linker_script_generator.cmake", + ), + ] + ), + "Generating LD script $TARGET", + ), + ) + + def generate_mbedtls_bundle(sdk_config): bundle_path = os.path.join("$BUILD_DIR", "x509_crt_bundle") if os.path.isfile(env.subst(bundle_path)): @@ -1349,19 +1400,30 @@ generate_default_component() # if not board.get("build.ldscript", ""): - linker_script = env.Command( - os.path.join("$BUILD_DIR", "memory.ld"), - board.get( - "build.esp-idf.ldscript", + initial_ld_script = board.get("build.esp-idf.ldscript", os.path.join( + FRAMEWORK_DIR, + "components", + "esp_system", + "ld", + idf_variant, + "memory.ld.in", + )) + + if IDF5 and IDF_minor > 2: + initial_ld_script = preprocess_linker_file( + initial_ld_script, os.path.join( - FRAMEWORK_DIR, - "components", + BUILD_DIR, + "esp-idf", "esp_system", "ld", - idf_variant, "memory.ld.in", - ), - ), + ) + ) + + linker_script = env.Command( + os.path.join("$BUILD_DIR", "memory.ld"), + initial_ld_script, env.VerboseAction( '$CC -I"$BUILD_DIR/config" -I"%s" -C -P -x c -E $SOURCE -o $TARGET' % os.path.join(FRAMEWORK_DIR, "components", "esp_system", "ld"), @@ -1601,7 +1663,7 @@ env.Prepend( ( board.get( "upload.bootloader_offset", - "0x0" if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2") else "0x1000", + "0x0" if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2") else ("0x2000" if mcu in ("esp32p4") else "0x1000"), ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), @@ -1712,7 +1774,7 @@ env["BUILDERS"]["ElfToBin"].action = action # ulp_dir = os.path.join(PROJECT_DIR, "ulp") -if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c2", "esp32c3", "esp32h2"): +if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"): env.SConscript("ulp.py", exports="env sdk_config project_config idf_variant") # From fd59eadf6e09de421d35bcf2b28c9e3596defac2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 30 Jul 2024 21:38:32 +0200 Subject: [PATCH 004/117] Fix wrong partition name entry --- boards/adafruit_feather_esp32s3_reversetft.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boards/adafruit_feather_esp32s3_reversetft.json b/boards/adafruit_feather_esp32s3_reversetft.json index c9209de..8de715f 100644 --- a/boards/adafruit_feather_esp32s3_reversetft.json +++ b/boards/adafruit_feather_esp32s3_reversetft.json @@ -1,8 +1,7 @@ { "build": { "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv", + "partitions": "tinyuf2-partitions-4MB.csv", "memory_type": "qio_qspi" }, "core": "esp32", From 18cb216bea0ffb63390d035d76451af9d8c0435d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 30 Jul 2024 22:04:25 +0200 Subject: [PATCH 005/117] Update ulp.py --- builder/frameworks/ulp.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index eccd106..2233764 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -13,6 +13,7 @@ # limitations under the License. import os +import sys from platformio import fs from platformio.util import get_systype @@ -34,11 +35,12 @@ ULP_BUILD_DIR = os.path.join( def prepare_ulp_env_vars(env): ulp_env.PrependENVPath("IDF_PATH", FRAMEWORK_DIR) + toolchain_path = platform.get_package_dir( + "toolchain-xtensa-%s" % idf_variant + ) + additional_packages = [ - os.path.join( - platform.get_package_dir("toolchain-xtensa-%s" % idf_variant), - "bin", - ), + toolchain_path, os.path.join( platform.get_package_dir("toolchain-esp32ulp"), "bin", @@ -57,7 +59,7 @@ def prepare_ulp_env_vars(env): def collect_ulp_sources(): return [ - fs.to_unix_path(os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp", f)) + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp", f) for f in os.listdir(os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp")) if f.endswith((".c", ".S", ".s")) ] @@ -95,7 +97,7 @@ def generate_ulp_config(target_config): "-riscv" if riscv_ulp_enabled else "", ), ), - "-DULP_S_SOURCES=%s" % ";".join([s.get_abspath() for s in source]), + "-DULP_S_SOURCES=%s" % ";".join([fs.to_unix_path(s.get_abspath()) for s in source]), "-DULP_APP_NAME=ulp_main", "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), "-DCOMPONENT_INCLUDES=%s" % ";".join(get_component_includes(target_config)), @@ -110,7 +112,10 @@ def generate_ulp_config(target_config): os.path.join(FRAMEWORK_DIR, "components", "ulp", "cmake"), ) - exec_command(cmd) + result = exec_command(cmd) + if result["returncode"] != 0: + sys.stderr.write(result["err"] + "\n") + env.Exit(1) ulp_sources = collect_ulp_sources() ulp_sources.sort() From f3ec0c3acd2ac1b219a69126635dbe4f239913d9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 1 Aug 2024 13:43:22 +0200 Subject: [PATCH 006/117] Fix board --- boards/airm2m_core_esp32c3.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/boards/airm2m_core_esp32c3.json b/boards/airm2m_core_esp32c3.json index e227fad..d2d5b30 100644 --- a/boards/airm2m_core_esp32c3.json +++ b/boards/airm2m_core_esp32c3.json @@ -1,15 +1,13 @@ { "build": { - "arduino":{ - "ldscript": "esp32c3_out.ld" - }, "core": "esp32", "f_cpu": "160000000L", "f_flash": "80000000L", "flash_mode": "dio", "extra_flags": [ "-DARDUINO_AirM2M_CORE_ESP32C3", - "-DARDUINO_USB_MODE=1" + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "mcu": "esp32c3", "variant": "AirM2M_CORE_ESP32C3" From 8e304b1948e0746cf4ab4a042e344e64ffe1e4f6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:19:59 +0200 Subject: [PATCH 007/117] refactor IDF 5.x minor version check --- builder/frameworks/espidf.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index b3ccdde..d0783b3 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -58,9 +58,11 @@ board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") idf_variant = mcu.lower() -IDF_version = platform.get_package_version("framework-espidf") -IDF5 = IDF_version.split(".")[1].startswith("5") # bool; Major IDF5 ? -IDF_minor = int(("".join(IDF_version.split(".")[1]))[1:3]) # Minor version as int +IDF5 = ( + platform.get_package_version("framework-espidf") + .split(".")[1] + .startswith("5") +) IDF_ENV_VERSION = "1.0.0" FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( @@ -650,7 +652,8 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): "sections.ld.in", ) - if IDF5 and IDF_minor > 2: + framework_version = [int(v) for v in get_framework_version().split(".")] + if framework_version[:2] > [5, 2]: initial_ld_script = preprocess_linker_file( initial_ld_script, os.path.join( @@ -1409,7 +1412,8 @@ if not board.get("build.ldscript", ""): "memory.ld.in", )) - if IDF5 and IDF_minor > 2: + framework_version = [int(v) for v in get_framework_version().split(".")] + if framework_version[:2] > [5, 2]: initial_ld_script = preprocess_linker_file( initial_ld_script, os.path.join( From d3cf7cff3bdb7879a92eeee8aa0993ee5a600d0e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 2 Aug 2024 13:43:59 +0200 Subject: [PATCH 008/117] core 3.0.4 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index ffc9bab..e6ba4ed 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/archive/refs/heads/master.zip" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.4/esp32-3.0.4.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/esp32-arduino-libs/archive/refs/heads/idf-release/v5.1.zip" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.4/esp32-arduino-libs-3.0.4.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "pioarduino", - "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.4.240726/esp-idf-v5.1.4.zip" + "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.4.240801/esp-idf-v5.1.4.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 265459d61f754671ec910ab99d31d259321cfa6d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:13:17 +0200 Subject: [PATCH 009/117] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 92e0043..767f26a 100644 --- a/README.md +++ b/README.md @@ -34,13 +34,13 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with 1. Configure a platform option in [platformio.ini](https://docs.platformio.org/page/projectconf.html) file: ### Stable version -espressif Arduino 3.0.3 and IDF 5.1.4 +espressif Arduino 3.0.4 and IDF 5.1.4 See `platform` [documentation](https://docs.platformio.org/en/latest/projectconf/sections/env/options/platform/platform.html#projectconf-env-platform) for details. ```ini [env:stable] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip board = ... ... ``` From cde7851be2f251851cabba5e662dc0162e02e46b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:18:48 +0200 Subject: [PATCH 010/117] IDF v5.1.4.240801 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index ffc9bab..1321342 100644 --- a/platform.json +++ b/platform.json @@ -45,7 +45,7 @@ "type": "framework", "optional": true, "owner": "pioarduino", - "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.4.240726/esp-idf-v5.1.4.zip" + "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.4.240801/esp-idf-v5.1.4.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From ae6ab1881a52ab5e54bac39b8295c8b1e7b94d79 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 3 Aug 2024 13:57:02 +0200 Subject: [PATCH 011/117] Fix Platform version --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index e6ba4ed..f034560 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "51.03.03+develop", + "version": "51.03.04", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" From 2c00c66ea9b8694a70adc3cbb808d6ea6d81c419 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:01:46 +0200 Subject: [PATCH 012/117] Bump version to: "51.03.04+develop" --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 1321342..ffdf9ce 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "51.03.03+develop", + "version": "51.03.04+develop", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" From 439fd0700e8c5927d1a08828c30c6359c6c2b771 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:40:38 +0200 Subject: [PATCH 013/117] IDF 5.1.4.240805 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index ffdf9ce..53fd4c9 100644 --- a/platform.json +++ b/platform.json @@ -45,7 +45,7 @@ "type": "framework", "optional": true, "owner": "pioarduino", - "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.4.240801/esp-idf-v5.1.4.zip" + "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.4.240805/esp-idf-v5.1.4.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 123326b2a217ce033045aeca83dd877c219bcf56 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 6 Aug 2024 20:46:07 +0200 Subject: [PATCH 014/117] add C2 to example --- examples/espidf-arduino-littlefs/platformio.ini | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/espidf-arduino-littlefs/platformio.ini b/examples/espidf-arduino-littlefs/platformio.ini index d0c7038..88224fb 100644 --- a/examples/espidf-arduino-littlefs/platformio.ini +++ b/examples/espidf-arduino-littlefs/platformio.ini @@ -11,14 +11,17 @@ [env] platform = espressif32 framework = arduino, espidf +board_build.filesystem = littlefs +board_build.partitions = partitions_custom.csv monitor_speed = 115200 + +[env:esp32dev] +board = esp32dev board_build.embed_txtfiles = managed_components/espressif__esp_insights/server_certs/https_server.crt managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt -[env:esp32dev] -board = esp32dev -board_build.filesystem = littlefs -board_build.partitions = partitions_custom.csv +[env:esp32-c2-devkitm-1] +board = boards/esp32-c2-devkitm-1 From b871fd2f73bff6198a36e1a716672d43f0e3ab49 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 6 Aug 2024 20:51:40 +0200 Subject: [PATCH 015/117] Fix board entry --- examples/espidf-arduino-littlefs/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/espidf-arduino-littlefs/platformio.ini b/examples/espidf-arduino-littlefs/platformio.ini index 88224fb..986a2db 100644 --- a/examples/espidf-arduino-littlefs/platformio.ini +++ b/examples/espidf-arduino-littlefs/platformio.ini @@ -24,4 +24,4 @@ board_build.embed_txtfiles = managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt [env:esp32-c2-devkitm-1] -board = boards/esp32-c2-devkitm-1 +board = esp32-c2-devkitm-1 From 61dfe93398bf5ba34b0005d20b084abe57f5b6ae Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 7 Aug 2024 15:21:49 +0200 Subject: [PATCH 016/117] Fix bootloader offset --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index d0783b3..ce17b39 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1667,7 +1667,7 @@ env.Prepend( ( board.get( "upload.bootloader_offset", - "0x0" if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2") else ("0x2000" if mcu in ("esp32p4") else "0x1000"), + "0x0" if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2") else "0x1000", ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), From 187e1cbaed5888158d65c5dc24100c6d3cc65cb2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 7 Aug 2024 15:24:38 +0200 Subject: [PATCH 017/117] Fix bootloader offset --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index d0783b3..ce17b39 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1667,7 +1667,7 @@ env.Prepend( ( board.get( "upload.bootloader_offset", - "0x0" if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2") else ("0x2000" if mcu in ("esp32p4") else "0x1000"), + "0x0" if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2") else "0x1000", ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), From df8ab31a6f30cf694ff62271f554b2e808b3ffae Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 7 Aug 2024 17:20:05 +0200 Subject: [PATCH 018/117] Update bootloader offset code retrieve --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index ce17b39..775d1a4 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1667,7 +1667,7 @@ env.Prepend( ( board.get( "upload.bootloader_offset", - "0x0" if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2") else "0x1000", + "0x0" if mcu in ["esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2"] else ("0x2000" if mcu in ["esp32p4"] else "0x1000"), ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), From 57e4458895363e6ac38ad5f8be8bad735536a714 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 7 Aug 2024 17:21:23 +0200 Subject: [PATCH 019/117] Update bootloader offset code retrieve --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index ce17b39..775d1a4 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1667,7 +1667,7 @@ env.Prepend( ( board.get( "upload.bootloader_offset", - "0x0" if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2") else "0x1000", + "0x0" if mcu in ["esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2"] else ("0x2000" if mcu in ["esp32p4"] else "0x1000"), ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), From 342e640a5a6b7efc4e8d28dee3a191868f045658 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:05:04 +0200 Subject: [PATCH 020/117] add h2zero NimBLE example --- .github/workflows/examples.yml | 1 + .../espidf-arduino-h2zero-BLE_scan/.gitignore | 2 + .../CMakeLists.txt | 4 ++ .../espidf-arduino-h2zero-BLE_scan/README.md | 7 +++ .../include/README | 39 ++++++++++++++ .../espidf-arduino-h2zero-BLE_scan/lib/README | 46 ++++++++++++++++ .../platformio.ini | 22 ++++++++ .../sdkconfig.defaults | 34 ++++++++++++ .../src/CMakeLists.txt | 6 +++ .../src/idf_component.yml | 40 ++++++++++++++ .../src/main.cpp | 54 +++++++++++++++++++ 11 files changed, 255 insertions(+) create mode 100644 examples/espidf-arduino-h2zero-BLE_scan/.gitignore create mode 100644 examples/espidf-arduino-h2zero-BLE_scan/CMakeLists.txt create mode 100644 examples/espidf-arduino-h2zero-BLE_scan/README.md create mode 100644 examples/espidf-arduino-h2zero-BLE_scan/include/README create mode 100644 examples/espidf-arduino-h2zero-BLE_scan/lib/README create mode 100644 examples/espidf-arduino-h2zero-BLE_scan/platformio.ini create mode 100644 examples/espidf-arduino-h2zero-BLE_scan/sdkconfig.defaults create mode 100644 examples/espidf-arduino-h2zero-BLE_scan/src/CMakeLists.txt create mode 100644 examples/espidf-arduino-h2zero-BLE_scan/src/idf_component.yml create mode 100644 examples/espidf-arduino-h2zero-BLE_scan/src/main.cpp diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index a9e0352..8e8a32b 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -18,6 +18,7 @@ jobs: - "examples/arduino-rmt-blink" - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" + - "examples/espidf-arduino-h2zero-BLE_scan" - "examples/espidf-arduino-blink" - "examples/espidf-arduino-littlefs" - "examples/espidf-blink" diff --git a/examples/espidf-arduino-h2zero-BLE_scan/.gitignore b/examples/espidf-arduino-h2zero-BLE_scan/.gitignore new file mode 100644 index 0000000..b9f3806 --- /dev/null +++ b/examples/espidf-arduino-h2zero-BLE_scan/.gitignore @@ -0,0 +1,2 @@ +.pio +.vscode diff --git a/examples/espidf-arduino-h2zero-BLE_scan/CMakeLists.txt b/examples/espidf-arduino-h2zero-BLE_scan/CMakeLists.txt new file mode 100644 index 0000000..b6275f6 --- /dev/null +++ b/examples/espidf-arduino-h2zero-BLE_scan/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.16.0) +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +add_compile_definitions(ARDUINO_ARCH_ESP32=1) +project(Arduino_IDF_BLE_scan) diff --git a/examples/espidf-arduino-h2zero-BLE_scan/README.md b/examples/espidf-arduino-h2zero-BLE_scan/README.md new file mode 100644 index 0000000..5601e54 --- /dev/null +++ b/examples/espidf-arduino-h2zero-BLE_scan/README.md @@ -0,0 +1,7 @@ +# Arduino_IDF_BLE_scan example using 3rd party NimBLE stack + +BLE scan example, using the great h2zero NimBLE implementation. The needed NimBLE lib is loaded via the IDF component manager -> `idf_component.yml`. +Mandantory not to forget to switch Arduino included BLE libs. +Done in `sdkconfig.defaults` + +Thx @h2zero for the great BLE library. diff --git a/examples/espidf-arduino-h2zero-BLE_scan/include/README b/examples/espidf-arduino-h2zero-BLE_scan/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/examples/espidf-arduino-h2zero-BLE_scan/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/espidf-arduino-h2zero-BLE_scan/lib/README b/examples/espidf-arduino-h2zero-BLE_scan/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/examples/espidf-arduino-h2zero-BLE_scan/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/espidf-arduino-h2zero-BLE_scan/platformio.ini b/examples/espidf-arduino-h2zero-BLE_scan/platformio.ini new file mode 100644 index 0000000..ae81cfd --- /dev/null +++ b/examples/espidf-arduino-h2zero-BLE_scan/platformio.ini @@ -0,0 +1,22 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env] +platform = espressif32 +framework = arduino, espidf +monitor_speed = 115200 +board_build.embed_txtfiles = + managed_components/espressif__esp_insights/server_certs/https_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt + +[env:esp32] +board = esp32dev diff --git a/examples/espidf-arduino-h2zero-BLE_scan/sdkconfig.defaults b/examples/espidf-arduino-h2zero-BLE_scan/sdkconfig.defaults new file mode 100644 index 0000000..267ca7f --- /dev/null +++ b/examples/espidf-arduino-h2zero-BLE_scan/sdkconfig.defaults @@ -0,0 +1,34 @@ +# CONFIG_AUTOSTART_ARDUINO is not set +# CONFIG_WS2812_LED_ENABLE is not set +CONFIG_FREERTOS_HZ=1000 +CONFIG_MBEDTLS_PSK_MODES=y +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y + +# Override some defaults so BT stack is enabled +# in this example +# +# BT config +# +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n +CONFIG_BTDM_CTRL_MODE_BTDM=n +CONFIG_BT_BLUEDROID_ENABLED=n +CONFIG_BT_NIMBLE_ENABLED=y + +# +# Arduino Configuration +# +# +# Disable all Arduino included BLE libraries +# +CONFIG_ARDUINO_SELECTIVE_COMPILATION=y +# CONFIG_ARDUINO_SELECTIVE_WiFiProv is not set +# CONFIG_ARDUINO_SELECTIVE_BLE is not set +# CONFIG_ARDUINO_SELECTIVE_BluetoothSerial is not set +# CONFIG_ARDUINO_SELECTIVE_SimpleBLE is not set +# end of Arduino Configuration \ No newline at end of file diff --git a/examples/espidf-arduino-h2zero-BLE_scan/src/CMakeLists.txt b/examples/espidf-arduino-h2zero-BLE_scan/src/CMakeLists.txt new file mode 100644 index 0000000..483bc0c --- /dev/null +++ b/examples/espidf-arduino-h2zero-BLE_scan/src/CMakeLists.txt @@ -0,0 +1,6 @@ +# This file was automatically generated for projects +# without default 'CMakeLists.txt' file. + +FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*) + +idf_component_register(SRCS ${app_sources}) diff --git a/examples/espidf-arduino-h2zero-BLE_scan/src/idf_component.yml b/examples/espidf-arduino-h2zero-BLE_scan/src/idf_component.yml new file mode 100644 index 0000000..98b4cbf --- /dev/null +++ b/examples/espidf-arduino-h2zero-BLE_scan/src/idf_component.yml @@ -0,0 +1,40 @@ +dependencies: + # Required IDF version + idf: ">=4.4" + + esp-nimble-cpp: + git: https://github.com/h2zero/esp-nimble-cpp.git + + + # # Defining a dependency from the registry: + # # https://components.espressif.com/component/example/cmp + # example/cmp: "^3.3.3" # Automatically update minor releases + # + # # Other ways to define dependencies + # + # # For components maintained by Espressif only name can be used. + # # Same as `espressif/cmp` + # component: "~1.0.0" # Automatically update bugfix releases + # + # # Or in a longer form with extra parameters + # component2: + # version: ">=2.0.0" + # + # # For transient dependencies `public` flag can be set. + # # `public` flag doesn't have an effect for the `main` component. + # # All dependencies of `main` are public by default. + # public: true + # + # # For components hosted on non-default registry: + # service_url: "https://componentregistry.company.com" + # + # # For components in git repository: + # test_component: + # path: test_component + # git: ssh://git@gitlab.com/user/components.git + # + # # For test projects during component development + # # components can be used from a local directory + # # with relative or absolute path + # some_local_component: + # path: ../../projects/component diff --git a/examples/espidf-arduino-h2zero-BLE_scan/src/main.cpp b/examples/espidf-arduino-h2zero-BLE_scan/src/main.cpp new file mode 100644 index 0000000..04b6e5f --- /dev/null +++ b/examples/espidf-arduino-h2zero-BLE_scan/src/main.cpp @@ -0,0 +1,54 @@ +/* + Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp + Ported to Arduino ESP32 by Evandro Copercini + Refactored back to IDF by H2zero +*/ + +/** NimBLE differences highlighted in comment blocks **/ + +/*******original******** +#include +#include +#include +#include +***********************/ + +#include + +#include + +extern "C"{void app_main(void);} + +int scanTime = 5 * 1000; // In milliseconds, 0 = scan forever +BLEScan* pBLEScan; + +class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { + void onResult(BLEAdvertisedDevice* advertisedDevice) { + printf("Advertised Device: %s \n", advertisedDevice->toString().c_str()); + } +}; + +void scanTask (void * parameter){ + for(;;) { + // put your main code here, to run repeatedly: + BLEScanResults foundDevices = pBLEScan->getResults(scanTime, false); + printf("Devices found: %d\n", foundDevices.getCount()); + printf("Scan done!\n"); + pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory + vTaskDelay(2000/portTICK_PERIOD_MS); // Delay a second between loops. + } + + vTaskDelete(NULL); +} + +void app_main(void) { + printf("Scanning...\n"); + + BLEDevice::init(""); + pBLEScan = BLEDevice::getScan(); //create new scan + pBLEScan->setScanCallbacks(new MyAdvertisedDeviceCallbacks()); + pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster + pBLEScan->setInterval(100); + pBLEScan->setWindow(99); // less or equal setInterval value + xTaskCreate(scanTask, "scanTask", 5000, NULL, 1, NULL); +} From b6261bc213c633e97d3aa013f325909ba5bcb34d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:19:21 +0200 Subject: [PATCH 021/117] add conflicting libs to `lib_ignore` as safeguard. LDF may add this unwanted libs --- examples/espidf-arduino-h2zero-BLE_scan/platformio.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/espidf-arduino-h2zero-BLE_scan/platformio.ini b/examples/espidf-arduino-h2zero-BLE_scan/platformio.ini index ae81cfd..7b9a517 100644 --- a/examples/espidf-arduino-h2zero-BLE_scan/platformio.ini +++ b/examples/espidf-arduino-h2zero-BLE_scan/platformio.ini @@ -17,6 +17,11 @@ board_build.embed_txtfiles = managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt +lib_ignore = + BLE + BluetoothSerial + SimpleBLE + WiFiProv [env:esp32] board = esp32dev From 54bd4b84f513c005f57aa224cbd3d8376c9e1076 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 12 Aug 2024 17:18:52 +0200 Subject: [PATCH 022/117] remove outdated linker script --- boards/esp32-solo1.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/boards/esp32-solo1.json b/boards/esp32-solo1.json index e87b7e1..7ec0f3a 100644 --- a/boards/esp32-solo1.json +++ b/boards/esp32-solo1.json @@ -1,8 +1,5 @@ { "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, "core": "esp32", "extra_flags": "-DARDUINO_ESP32_DEV -DARDUINO_USB_CDC_ON_BOOT=0 -DCORE32SOLO1", "f_cpu": "80000000L", From 85ae384b4cfc54e210e57f8b6ff9701cd7bafbd2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 12 Aug 2024 18:38:48 +0200 Subject: [PATCH 023/117] fix managed components compile fail --- builder/frameworks/espidf.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 775d1a4..ed2cc0e 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -53,6 +53,9 @@ if os.environ.get("PYTHONPATH"): env = DefaultEnvironment() env.SConscript("_embed_files.py", exports="env") +# Allow changes in folders of managed components +os.environ["IDF_COMPONENT_OVERWRITE_MANAGED_COMPONENTS"] = "1" + platform = env.PioPlatform() board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") From a438ac8da2de92c60a26c49445b0c547bc414a0b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 14 Aug 2024 08:49:50 +0200 Subject: [PATCH 024/117] Delete boards/heltec_wifi_kit_32_v2.json --- boards/heltec_wifi_kit_32_v2.json | 35 ------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 boards/heltec_wifi_kit_32_v2.json diff --git a/boards/heltec_wifi_kit_32_v2.json b/boards/heltec_wifi_kit_32_v2.json deleted file mode 100644 index eb80db6..0000000 --- a/boards/heltec_wifi_kit_32_v2.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_HELTEC_WIFI_KIT_32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "heltec_wifi_kit_32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Heltec WiFi Kit 32 (V2)", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.heltec.cn/project/wifi-kit-32/?lang=en", - "vendor": "Heltec Automation" -} From 2ffeaedbb0ac105f215dd76a8c7d105297c921e4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 14 Aug 2024 08:54:39 +0200 Subject: [PATCH 025/117] Fix uppercase --- boards/heltec_wifi_kit_32_V3.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/heltec_wifi_kit_32_V3.json b/boards/heltec_wifi_kit_32_V3.json index d106319..62d7301 100644 --- a/boards/heltec_wifi_kit_32_V3.json +++ b/boards/heltec_wifi_kit_32_V3.json @@ -21,7 +21,7 @@ ] ], "mcu": "esp32s3", - "variant": "heltec_wifi_kit_32_v3" + "variant": "heltec_wifi_kit_32_V3" }, "connectivity": [ "wifi", From 2b20b1aa8bf41faef7c8b6f7f58c497e39107af2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 14 Aug 2024 13:30:08 +0200 Subject: [PATCH 026/117] Create adafruit_feather_esp32c6.json --- boards/adafruit_feather_esp32c6.json | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 boards/adafruit_feather_esp32c6.json diff --git a/boards/adafruit_feather_esp32c6.json b/boards/adafruit_feather_esp32c6.json new file mode 100644 index 0000000..2eaf8f7 --- /dev/null +++ b/boards/adafruit_feather_esp32c6.json @@ -0,0 +1,38 @@ +{ + "build": { + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32C6", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c6", + "variant": "adafruit_feather_esp32c6" + }, + "connectivity": [ + "wifi", + "bluetooth", + "zigbee", + "thread" + ], + "debug": { + "openocd_target": "esp32c6.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-C6", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5933", + "vendor": "Adafruit" +} From d14a67e4f75c8c4cff3fee905e0a91f0cbab6a40 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:31:12 +0200 Subject: [PATCH 027/117] Update "idf-component-manager" to "~=2.0.1" --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index ed2cc0e..855a800 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1258,7 +1258,7 @@ def install_python_deps(): "future": ">=0.18.3", "pyparsing": ">=3.1.0,<4" if IDF5 else ">=2.0.3,<2.4.0", "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", - "idf-component-manager": "~=1.5.2" if IDF5 else "~=1.0", + "idf-component-manager": "~=2.0.1" if IDF5 else "~=1.0", "esp-idf-kconfig": ">=1.4.2,<2.0.0" } From ed8df6c3c555ceec8d3c19d70a9d58b30902ea37 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 17 Aug 2024 12:57:36 +0200 Subject: [PATCH 028/117] add `bluetooth` to esp32-c6-devkitc-1.json --- boards/esp32-c6-devkitc-1.json | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/esp32-c6-devkitc-1.json b/boards/esp32-c6-devkitc-1.json index b82e07f..a5732a1 100644 --- a/boards/esp32-c6-devkitc-1.json +++ b/boards/esp32-c6-devkitc-1.json @@ -8,6 +8,7 @@ "variant": "esp32c6" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { From 500941f4a2e68a05c28933cca2d298b7e17c4b7b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:14:59 +0200 Subject: [PATCH 029/117] latest develop libs for Arduino 3.0.4 branch master --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 53fd4c9..977c738 100644 --- a/platform.json +++ b/platform.json @@ -39,7 +39,7 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/esp32-arduino-libs/archive/refs/heads/idf-release/v5.1.zip" + "version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.1/esp32-arduino-libs-idf-release_v5.1-d38afc77.zip" }, "framework-espidf": { "type": "framework", From 94fa3a2ba029f5a2e3a6103ef47438fb743f769b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:34:22 +0200 Subject: [PATCH 030/117] fetch Arduino libs dl URL from manifest json --- platform.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform.py b/platform.py index 0debfbd..824e545 100644 --- a/platform.py +++ b/platform.py @@ -37,6 +37,11 @@ class Espressif32Platform(PlatformBase): if "arduino" in frameworks: self.packages["framework-arduinoespressif32"]["optional"] = False self.packages["framework-arduinoespressif32-libs"]["optional"] = False + # use latest espressif Arduino libs + URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/idf-release/v5.1/package/package_esp32_index.template.json" + packjdata = requests.get(URL).json() + dyn_lib_url = packjdata['packages'][0]['tools'][0]['systems'][0]['url'] + self.packages["framework-arduinoespressif32-libs"]["version"] = dyn_lib_url if "buildfs" in targets: filesystem = variables.get("board_build.filesystem", "littlefs") From 2703500777072c92a93606f44b1628001528addc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:36:39 +0200 Subject: [PATCH 031/117] latest Arduino libs dl URL is fetched in platform.py --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 977c738..d50bbaa 100644 --- a/platform.json +++ b/platform.json @@ -39,7 +39,7 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.1/esp32-arduino-libs-idf-release_v5.1-d38afc77.zip" + "version": "" }, "framework-espidf": { "type": "framework", From 56d18fad355ea738651a30fe91bfa0efe2f36e0e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 28 Aug 2024 20:16:27 +0200 Subject: [PATCH 032/117] use Arduino branch master --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index 824e545..53f6afe 100644 --- a/platform.py +++ b/platform.py @@ -38,7 +38,7 @@ class Espressif32Platform(PlatformBase): self.packages["framework-arduinoespressif32"]["optional"] = False self.packages["framework-arduinoespressif32-libs"]["optional"] = False # use latest espressif Arduino libs - URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/idf-release/v5.1/package/package_esp32_index.template.json" + URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/master/package/package_esp32_index.template.json" packjdata = requests.get(URL).json() dyn_lib_url = packjdata['packages'][0]['tools'][0]['systems'][0]['url'] self.packages["framework-arduinoespressif32-libs"]["version"] = dyn_lib_url From 76b271062bd980a81a01d75a6176065df272abed Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 29 Aug 2024 14:03:56 +0200 Subject: [PATCH 033/117] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 767f26a..764b3f6 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with integrated Wi-Fi and Bluetooth. ESP32 integrates an antenna switch, RF balun, power amplifier, low-noise receive amplifier, filters, and power management modules. * [Documentation](https://docs.platformio.org/page/platforms/espressif32.html) (advanced usage, packages, boards, frameworks, etc.) +* Issues with boards (wrong / missing). All issues caused from boards will **not** be fixed from the maintainer(s). A PR needs to be provided to solve. ## IDE Preparation From e79eb2f68391a8551f2db2f710434720849823c1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 29 Aug 2024 14:07:42 +0200 Subject: [PATCH 034/117] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 767f26a..0a71d07 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with integrated Wi-Fi and Bluetooth. ESP32 integrates an antenna switch, RF balun, power amplifier, low-noise receive amplifier, filters, and power management modules. * [Documentation](https://docs.platformio.org/page/platforms/espressif32.html) (advanced usage, packages, boards, frameworks, etc.) +* Issues with boards (wrong / missing). All issues caused from boards will not be fixed from the maintainer(s). A PR needs to be provided to solve. ## IDE Preparation From 52f5a730b2339232090698a76f910bd5b1dd4f85 Mon Sep 17 00:00:00 2001 From: Sylvain Quendez Date: Thu, 29 Aug 2024 15:20:22 +0200 Subject: [PATCH 035/117] Fixed board m5stick-c (#26) * Update m5stick-c.json with the correct variant * Update m5stick-c.json --------- Co-authored-by: Jason2866 <24528715+Jason2866@users.noreply.github.com> --- boards/m5stick-c.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/boards/m5stick-c.json b/boards/m5stick-c.json index 5c96d7e..e27d82a 100644 --- a/boards/m5stick-c.json +++ b/boards/m5stick-c.json @@ -1,15 +1,12 @@ { "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, "core": "esp32", "extra_flags": "-DARDUINO_M5Stick_C", "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", "mcu": "esp32", - "variant": "m5stick_c" + "variant": "m5stack_stickc" }, "connectivity": [ "wifi", From 097e56366eb9e8aecb51b5a53276c458601c4839 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 29 Aug 2024 15:57:14 +0200 Subject: [PATCH 036/117] Create CONTRIBUTING.md --- CONTRIBUTING.md | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..03a725f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,111 @@ +# Contributing + +**Any contribution helps our team and makes pioarduino better for the entire community!** + +Everybody is welcome and invited to contribute to pioarduino Project by: + +* Testing newly released features and reporting issues. +* Providing Pull Requests (Features, Proof of Concepts or Fixes) +* Contributing missing documentation for features in our (not yet existing ;-)) documentation + +This document describes rules that are in effect for this repository, meant for handling issues by contributors in the issue tracker and PRs. + +## Opening New Issues + +**Issue tracker is NOT a general discussion forum!** +1. Opening an issue means that a problem exists in the code and should be addressed by the project contributors. +2. When opening an issue, provide as much as possible infos. The information is important! With insufficient info about the provided issue, the issue may be closed. +3. Questions of type "How do I..." or "Can you please help me with..." WILL NOT be handled here. Such questions should be directed to pioarduino Support Chat. All issues of this type will be closed with a simple reference to this contributing policy. +4. Issues about topics already handled in the documentation will be closed in a similar manner. +5. Issues for unmerged PRs will be closed. If there is an issue with a PR, the explanation should be added to the PR itself. +6. Issues with accompanied investigation that shows the root of the problem should be given priority. +7. Duplicate issues will be closed. + +## Triaging of Issues/PR's + +1. Any contributor to the project can participate in the triaging process, if he/she/them chooses to do so. +2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor. +3. Issues that are accepted should be marked with appropriate labels. +4. Issues that could impact functionality for many users should be considered severe. +5. Issues with feature requests should be discussed for viability/desirability. +6. Feature requests or changes that are meant to address a very specific/limited use case, may be denied, or may be required to be redesigned, generalized, or simplified. +7. Feature requests that are not accompanied by a PR: + * could be closed immediately (denied). + * could be closed after some predetermined period of time (left as candidate for somebody to pick up). +8. In some cases, feedback may be requested from the issue reporter, either as additional info for clarification, additional testing, or other. If no feedback is provided, the issue may be closed by a contributor or after 30 days by the STALE bot. + +## Pull requests + +A Pull Request (PR) is the process where code modifications are managed in GitHub. + +The process is straight-forward. + + - Read [How to get faster PR reviews](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) by Kubernetes (but skip step 0) + - Fork the pioarduino platform-espressif32 Repository [git repository](https://github.com/pioarduino/platform-espressif32). + - Write/Change the code in your Fork for a new feature, bug fix, optimization, etc. + - Ensure tests work. + - Create a Pull Request against the [**develop**](https://github.com/pioarduino/platform-espressif32/tree/develop) branch of pioarduino. + +1. All pull requests must be done against the develop branch. +2. Only relevant files should be touched (Also beware if your editor has auto-formatting feature enabled). +3. Only one feature/fix should be added per PR. A PR for mass changes in boards manifest is allowed. +4. PRs that don't compile (fail in CI Tests) or cause coding errors will not be merged. Please fix the issue. Same goes for PRs that are raised against older commit in develop - you might need to rebase and resolve conflicts. +5. All pull requests should undergo peer review by at least one contributor other than the creator, excepts for the owner. +6. All pull requests should consider updates to the documentation. +7. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority. +8. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged. +9. By submitting a PR, it is needed to use the provided PR template and check all boxes, performing the required tasks and accepting the CLA. +10. Pull requests that don't meet the above will be denied and closed. + +-------------------------------------- + +## Contributor License Agreement (CLA) + +``` +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the GPL-3.0 license; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the GPL-3.0 license; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it) is maintained indefinitely + and may be redistributed consistent with this project or the open + source license(s) involved. +``` + +This Contributor License Agreement (CLA) was adopted on April 1st, 2019. + +The text of this license is available under the [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/). It is based on the Linux [Developer Certificate Of Origin](http://elinux.org/Developer_Certificate_Of_Origin), but is modified to explicitly use the GPL-3.0 license and not mention sign-off (due to GitHub.com keeps an historial, with your user name, of PRs' commits and all editions on PR's comments). + +To accept the CLA it is required to put a x between [ ] on `[ ] I accept the CLA` in the PR template when submitting it. The [ ] is an opt-in box, so you have to manually accept it. + +**Why a CLA ?** + +_"A Contributor License Agreement (CLA) is strongly recommended when accepting third party contributions to an open development project, such as an open source software project. In order to redistribute contributions, it is necessary to ensure that the project has the necessary rights to do so. A Contributor License Agreement is a lightweight agreement, signed by the copyright holder, that grants the necessary rights for the contribution to be redistributed as part of the project."_ [OSS Watch](http://oss-watch.ac.uk/resources/cla) + +A CLA is a legal document in which you state _you are entitled to contribute the code/documentation/translation to the project_ you’re contributing to and that _you are willing to have it used in distributions and derivative works_. This means that should there be any kind of legal issue in the future as to the origins and ownership of any particular piece of code, then that project has the necessary forms on file from the contributor(s) saying they were permitted to make this contribution. + +CLA is a safety because it also ensures that once you have provided a contribution, you cannot try to withdraw permission for its use at a later date. People can therefore use that software, confident that they will not be asked to stop using pieces of the code at a later date. + +A __license__ grants "outbound" rights to the user of project. + +A __CLA__ enables a contributor to grant "inbound" rights to a project. + + + + + + + + From 06e43471830961783b97701dadf59f3f3faea7eb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 29 Aug 2024 15:59:37 +0200 Subject: [PATCH 037/117] Create PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..65cb3bb --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ +## Description: + +**Related issue (if applicable):** fixes # + +## Checklist: + - [ ] The pull request is done against the latest develop branch + - [ ] Only relevant files were touched + - [ ] Only one feature/fix was added per PR, more changes are allowed when changing boards.json + - [ ] I accept the [CLA](https://github.com/pioarduino/platform-espressif32/blob/develop/CONTRIBUTING.md). From c962c91ef183c57ed4c8e7782aff9bce516487dc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 29 Aug 2024 16:00:01 +0200 Subject: [PATCH 038/117] Delete .github/FUNDING.yml --- .github/FUNDING.yml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 6f70f7e..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -custom: https://platformio.org/donate From 56c845bf88730c4440976a3e73069a013443baea Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 29 Aug 2024 16:03:11 +0200 Subject: [PATCH 039/117] Create config.yml --- .github/config.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/config.yml diff --git a/.github/config.yml b/.github/config.yml new file mode 100644 index 0000000..6ef38dd --- /dev/null +++ b/.github/config.yml @@ -0,0 +1,11 @@ +# Configuration for sentiment-bot - https://github.com/behaviorbot/sentiment-bot + +# *Required* toxicity threshold between 0 and .99 with the higher numbers being the most toxic +# Anything higher than this threshold will be marked as toxic and commented on +sentimentBotToxicityThreshold: .7 + +# *Required* Comment to reply with +sentimentBotReplyComment: > + Please be sure to review the code of conduct and be respectful of other users. + +# Note: the bot will only work if your repository has a Code of Conduct From 2b5a2ed7c3a10b7a892e3a2ed5094cae144e8c2b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 29 Aug 2024 16:05:20 +0200 Subject: [PATCH 040/117] Create stale-actions.yml --- .github/workflows/stale-actions.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/stale-actions.yml diff --git a/.github/workflows/stale-actions.yml b/.github/workflows/stale-actions.yml new file mode 100644 index 0000000..e3b6856 --- /dev/null +++ b/.github/workflows/stale-actions.yml @@ -0,0 +1,23 @@ +name: "Mark or close stale issues and PRs" + +on: + schedule: + - cron: "30 * * * *" + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + days-before-stale: 25 + days-before-close: 5 + stale-issue-message: "This issue has been automatically marked as stale because it hasn't any activity in last few weeks. It will be closed if no further activity occurs. Thank you for your contributions." + stale-pr-message: "This PR has been automatically marked as stale because it hasn't any activity in last few weeks. It will be closed if no further activity occurs. Thank you for your contributions." + close-issue-message: "This issue was automatically closed because of being stale. Feel free to open a new one if you still experience this problem." + close-pr-message: "This PR was automatically closed because of being stale." + stale-pr-label: "stale" + stale-issue-label: "stale" + exempt-issue-labels: "bug,enhancement,pinned,security" + exempt-pr-labels: "bug,enhancement,pinned,security" From 2656164f80833b3c171a7d27ad94277fc540841d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 29 Aug 2024 16:11:59 +0200 Subject: [PATCH 041/117] add code of conduct --- code_of_conduct.md | 134 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 code_of_conduct.md diff --git a/code_of_conduct.md b/code_of_conduct.md new file mode 100644 index 0000000..d122043 --- /dev/null +++ b/code_of_conduct.md @@ -0,0 +1,134 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[pioarduino](https://github.com/pioarduino/platform-espressif32/issues/new/choose). +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations + From dbd7731e6253a3af50b47a324b36e38d46861e61 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 4 Sep 2024 19:07:36 +0200 Subject: [PATCH 042/117] Update platform.py --- platform.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform.py b/platform.py index 53f6afe..f1b67fd 100644 --- a/platform.py +++ b/platform.py @@ -23,6 +23,11 @@ from platformio.public import PlatformBase, to_unix_path IS_WINDOWS = sys.platform.startswith("win") +# Set Platformio env var to use windows_amd64 for all windows architectures +# only windows_amd64 native espressif toolchains are available +# needs platformio core >= 6.1.16b2 or pioarduino core 6.1.16+test +if IS_WINDOWS: + os.environ["PLATFORMIO_SYSTEM_TYPE"] = "windows_amd64" class Espressif32Platform(PlatformBase): From 87d27ab20cf28eecca946754db06432170f85a71 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 6 Sep 2024 15:55:55 +0200 Subject: [PATCH 043/117] better handling of complex Macros from cmake model --- builder/frameworks/espidf.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 855a800..db9c324 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -324,8 +324,9 @@ def extract_defines(compile_group): define_string = define_string.strip() if "=" in define_string: define, value = define_string.split("=", maxsplit=1) - if '"' in value and not value.startswith("\\"): - # Escape only raw values + if any(char in value for char in (' ', '<', '>')): + value = f'"{value}"' + elif '"' in value and not value.startswith("\\"): value = value.replace('"', '\\"') return (define, value) return define_string @@ -336,8 +337,11 @@ def extract_defines(compile_group): ] for f in compile_group.get("compileCommandFragments", []): - if f.get("fragment", "").startswith("-D"): - result.append(_normalize_define(f["fragment"][2:])) + fragment = f.get("fragment", "").strip() + if fragment.startswith('"'): + fragment = fragment.strip('"') + if fragment.startswith("-D"): + result.append(_normalize_define(fragment[2:])) return result From 7f9a9c1d2ad97549ab9b46eb6dc33946e84248b9 Mon Sep 17 00:00:00 2001 From: Christian Glombek Date: Sun, 8 Sep 2024 12:37:22 -0500 Subject: [PATCH 044/117] Add Sparkfun ESP32-C6 Thing Plus board definition (#31) --- boards/sparkfun_esp32c6_thing_plus.json | 38 +++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 boards/sparkfun_esp32c6_thing_plus.json diff --git a/boards/sparkfun_esp32c6_thing_plus.json b/boards/sparkfun_esp32c6_thing_plus.json new file mode 100644 index 0000000..f752f66 --- /dev/null +++ b/boards/sparkfun_esp32c6_thing_plus.json @@ -0,0 +1,38 @@ +{ + "build": { + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c6", + "variant": "sparkfun_esp32c6_thing_plus", + "extra_flags": [ + "-DARDUINO_ESP32C6_THING_PLUS", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MODE=1" + ] + }, + "connectivity": [ + "wifi", + "bluetooth", + "zigbee", + "thread" + ], + "debug": { + "openocd_target": "esp32c6.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Sparkfun ESP32-C6 Thing Plus", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/22924", + "vendor": "Sparkfun" +} From 9edf55d7247903a1b5252ac60f076b92a1caf476 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 9 Sep 2024 19:09:54 +0200 Subject: [PATCH 045/117] fix handling of cc fragments --- builder/frameworks/espidf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index db9c324..3b052b0 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -427,8 +427,8 @@ def get_app_flags(app_config, default_config): for cg in config["compileGroups"]: flags[cg["language"]] = [] for ccfragment in cg["compileCommandFragments"]: - fragment = ccfragment.get("fragment", "") - if not fragment.strip() or fragment.startswith("-D"): + fragment = ccfragment.get("fragment", "").strip("\" ") + if not fragment or fragment.startswith("-D"): continue flags[cg["language"]].extend( click.parser.split_arg_string(fragment.strip()) @@ -713,7 +713,7 @@ def prepare_build_envs(config, default_env, debug_allowed=True): build_env = default_env.Clone() build_env.SetOption("implicit_cache", 1) for cc in compile_commands: - build_flags = cc.get("fragment") + build_flags = cc.get("fragment", "").strip("\" ") if not build_flags.startswith("-D"): if build_flags.startswith("-include") and ".." in build_flags: source_index = cg.get("sourceIndexes")[0] From 5848b235cd1af428c2cc10f3e695fd2bcc46def4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 9 Sep 2024 19:15:13 +0200 Subject: [PATCH 046/117] better handling of complex cmake macros --- builder/frameworks/espidf.py | 37 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 775d1a4..daaf223 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -53,6 +53,9 @@ if os.environ.get("PYTHONPATH"): env = DefaultEnvironment() env.SConscript("_embed_files.py", exports="env") +# Allow changes in folders of managed components +os.environ["IDF_COMPONENT_OVERWRITE_MANAGED_COMPONENTS"] = "1" + platform = env.PioPlatform() board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") @@ -252,9 +255,6 @@ def populate_idf_env_vars(idf_env): os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), ) -# if IS_WINDOWS: -# additional_packages.append(platform.get_package_dir("tool-mconf")) - idf_env["PATH"] = os.pathsep.join(additional_packages + [idf_env["PATH"]]) # Some users reported that the `IDF_TOOLS_PATH` var can seep into the @@ -321,8 +321,9 @@ def extract_defines(compile_group): define_string = define_string.strip() if "=" in define_string: define, value = define_string.split("=", maxsplit=1) - if '"' in value and not value.startswith("\\"): - # Escape only raw values + if any(char in value for char in (' ', '<', '>')): + value = f'"{value}"' + elif '"' in value and not value.startswith("\\"): value = value.replace('"', '\\"') return (define, value) return define_string @@ -333,8 +334,11 @@ def extract_defines(compile_group): ] for f in compile_group.get("compileCommandFragments", []): - if f.get("fragment", "").startswith("-D"): - result.append(_normalize_define(f["fragment"][2:])) + fragment = f.get("fragment", "").strip() + if fragment.startswith('"'): + fragment = fragment.strip('"') + if fragment.startswith("-D"): + result.append(_normalize_define(fragment[2:])) return result @@ -420,8 +424,8 @@ def get_app_flags(app_config, default_config): for cg in config["compileGroups"]: flags[cg["language"]] = [] for ccfragment in cg["compileCommandFragments"]: - fragment = ccfragment.get("fragment", "") - if not fragment.strip() or fragment.startswith("-D"): + fragment = ccfragment.get("fragment", "").strip("\" ") + if not fragment or fragment.startswith("-D"): continue flags[cg["language"]].extend( click.parser.split_arg_string(fragment.strip()) @@ -706,7 +710,7 @@ def prepare_build_envs(config, default_env, debug_allowed=True): build_env = default_env.Clone() build_env.SetOption("implicit_cache", 1) for cc in compile_commands: - build_flags = cc.get("fragment") + build_flags = cc.get("fragment", "").strip("\" ") if not build_flags.startswith("-D"): if build_flags.startswith("-include") and ".." in build_flags: source_index = cg.get("sourceIndexes")[0] @@ -1255,7 +1259,7 @@ def install_python_deps(): "future": ">=0.18.3", "pyparsing": ">=3.1.0,<4" if IDF5 else ">=2.0.3,<2.4.0", "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", - "idf-component-manager": "~=1.5.2" if IDF5 else "~=1.0", + "idf-component-manager": "~=2.0.1" if IDF5 else "~=1.0", "esp-idf-kconfig": ">=1.4.2,<2.0.0" } @@ -1292,17 +1296,6 @@ def install_python_deps(): ) ) -# # A special "esp-windows-curses" python package is required on Windows -# # for Menuconfig on IDF <5 -# if not IDF5 and "esp-windows-curses" not in installed_packages: -# env.Execute( -# env.VerboseAction( -# '"%s" -m pip install "file://%s/tools/kconfig_new/esp-windows-curses"' -# % (python_exe_path, FRAMEWORK_DIR), -# "Installing windows-curses package", -# ) -# ) - def get_idf_venv_dir(): # The name of the IDF venv contains the IDF version to avoid possible conflicts and From fcc554f3e243734b50d74864f5320a640b01980d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 13 Sep 2024 17:32:46 +0200 Subject: [PATCH 047/117] add Arduino/IDF Matter example --- .../CMakeLists.txt | 23 ++ .../espidf-arduino-matter-light/README.md | 3 + .../include/README | 39 ++ .../espidf-arduino-matter-light/lib/README | 46 +++ .../main/CMakeLists.txt | 9 + .../main/builtinLED.cpp | 251 ++++++++++++ .../main/builtinLED.h | 76 ++++ .../main/idf_component.yml | 3 + .../main/matter_accessory_driver.cpp | 101 +++++ .../main/matter_accessory_driver.h | 28 ++ .../main/matter_light.cpp | 369 ++++++++++++++++++ .../partitions.csv | 9 + .../platformio.ini | 26 ++ .../sdkconfig.defaults | 66 ++++ .../espidf-arduino-matter-light/test/README | 11 + 15 files changed, 1060 insertions(+) create mode 100644 examples/espidf-arduino-matter-light/CMakeLists.txt create mode 100644 examples/espidf-arduino-matter-light/README.md create mode 100644 examples/espidf-arduino-matter-light/include/README create mode 100644 examples/espidf-arduino-matter-light/lib/README create mode 100644 examples/espidf-arduino-matter-light/main/CMakeLists.txt create mode 100644 examples/espidf-arduino-matter-light/main/builtinLED.cpp create mode 100644 examples/espidf-arduino-matter-light/main/builtinLED.h create mode 100644 examples/espidf-arduino-matter-light/main/idf_component.yml create mode 100644 examples/espidf-arduino-matter-light/main/matter_accessory_driver.cpp create mode 100644 examples/espidf-arduino-matter-light/main/matter_accessory_driver.h create mode 100644 examples/espidf-arduino-matter-light/main/matter_light.cpp create mode 100644 examples/espidf-arduino-matter-light/partitions.csv create mode 100644 examples/espidf-arduino-matter-light/platformio.ini create mode 100644 examples/espidf-arduino-matter-light/sdkconfig.defaults create mode 100644 examples/espidf-arduino-matter-light/test/README diff --git a/examples/espidf-arduino-matter-light/CMakeLists.txt b/examples/espidf-arduino-matter-light/CMakeLists.txt new file mode 100644 index 0000000..4a9c0c2 --- /dev/null +++ b/examples/espidf-arduino-matter-light/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.16.0) +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(PROJECT_VER "1.0") +set(PROJECT_VER_NUMBER 1) + +project(matter-light) + + +# WARNING: This is just an example for using key for decrypting the encrypted OTA image +# Please do not use it as is. +if(CONFIG_ENABLE_ENCRYPTED_OTA) + target_add_binary_data(light.elf "esp_image_encryption_key.pem" TEXT) +endif() + +if(CONFIG_IDF_TARGET_ESP32C2) + include(relinker) +endif() + +idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_H" APPEND) +idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND) +# For RISCV chips, project_include.cmake sets -Wno-format, but does not clear various +# flags that depend on -Wformat +idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security" APPEND) \ No newline at end of file diff --git a/examples/espidf-arduino-matter-light/README.md b/examples/espidf-arduino-matter-light/README.md new file mode 100644 index 0000000..fd3f77f --- /dev/null +++ b/examples/espidf-arduino-matter-light/README.md @@ -0,0 +1,3 @@ +## Arduino/IDF Matter Light example + +The needed Matter component is added via the IDF component manager -> `idf_component.yml`. diff --git a/examples/espidf-arduino-matter-light/include/README b/examples/espidf-arduino-matter-light/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/examples/espidf-arduino-matter-light/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/espidf-arduino-matter-light/lib/README b/examples/espidf-arduino-matter-light/lib/README new file mode 100644 index 0000000..2593a33 --- /dev/null +++ b/examples/espidf-arduino-matter-light/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/espidf-arduino-matter-light/main/CMakeLists.txt b/examples/espidf-arduino-matter-light/main/CMakeLists.txt new file mode 100644 index 0000000..dfe4b75 --- /dev/null +++ b/examples/espidf-arduino-matter-light/main/CMakeLists.txt @@ -0,0 +1,9 @@ +# This file was automatically generated for projects +# without default 'CMakeLists.txt' file. + +FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/main/*.*) + +idf_component_register(SRCS ${app_sources}) + +#set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) +#target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") \ No newline at end of file diff --git a/examples/espidf-arduino-matter-light/main/builtinLED.cpp b/examples/espidf-arduino-matter-light/main/builtinLED.cpp new file mode 100644 index 0000000..cb7135e --- /dev/null +++ b/examples/espidf-arduino-matter-light/main/builtinLED.cpp @@ -0,0 +1,251 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + + This will implement the onboard WS2812b LED as a LED indicator + It can be used to indicate some state or status of the device + The LED can be controlled using RGB, HSV or color temperature, brightness + + In this example, the LED Indicator class is used as the Matter light accessory +*/ + +#include +#include "builtinLED.h" + +typedef struct { + uint16_t hue; + uint8_t saturation; +} HS_color_t; + +static const HS_color_t temperatureTable[] = { + {4, 100}, {8, 100}, {11, 100}, {14, 100}, {16, 100}, {18, 100}, {20, 100}, {22, 100}, {24, 100}, {25, 100}, + {27, 100}, {28, 100}, {30, 100}, {31, 100}, {31, 95}, {30, 89}, {30, 85}, {29, 80}, {29, 76}, {29, 73}, + {29, 69}, {28, 66}, {28, 63}, {28, 60}, {28, 57}, {28, 54}, {28, 52}, {27, 49}, {27, 47}, {27, 45}, + {27, 43}, {27, 41}, {27, 39}, {27, 37}, {27, 35}, {27, 33}, {27, 31}, {27, 30}, {27, 28}, {27, 26}, + {27, 25}, {27, 23}, {27, 22}, {27, 21}, {27, 19}, {27, 18}, {27, 17}, {27, 15}, {28, 14}, {28, 13}, + {28, 12}, {29, 10}, {29, 9}, {30, 8}, {31, 7}, {32, 6}, {34, 5}, {36, 4}, {41, 3}, {49, 2}, + {0, 0}, {294, 2}, {265, 3}, {251, 4}, {242, 5}, {237, 6}, {233, 7}, {231, 8}, {229, 9}, {228, 10}, + {227, 11}, {226, 11}, {226, 12}, {225, 13}, {225, 13}, {224, 14}, {224, 14}, {224, 15}, {224, 15}, {223, 16}, + {223, 16}, {223, 17}, {223, 17}, {223, 17}, {222, 18}, {222, 18}, {222, 19}, {222, 19}, {222, 19}, {222, 19}, + {222, 20}, {222, 20}, {222, 20}, {222, 21}, {222, 21} +}; + +/* step brightness table: gamma = 2.3 */ +static const uint8_t gamma_table[MAX_PROGRESS] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, + 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, + 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, + 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25, 25, 26, + 26, 27, 28, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, + 38, 39, 40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 81, 82, 83, 84, 86, + 87, 88, 89, 91, 92, 93, 95, 96, 97, 99, 100, 101, 103, 104, 105, 107, + 108, 110, 111, 112, 114, 115, 117, 118, 120, 121, 123, 124, 126, 128, 129, 131, + 132, 134, 135, 137, 139, 140, 142, 144, 145, 147, 149, 150, 152, 154, 156, 157, + 159, 161, 163, 164, 166, 168, 170, 172, 174, 175, 177, 179, 181, 183, 185, 187, + 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, + 221, 223, 226, 228, 230, 232, 234, 236, 239, 241, 243, 245, 248, 250, 252, 255, +}; + +BuiltInLED::BuiltInLED() { + pin_number = (uint8_t) -1; // no pin number + state = false; // LED is off + hsv_color.value = 0; // black color +} + +BuiltInLED::~BuiltInLED(){ + end(); +} + +led_indicator_color_hsv_t BuiltInLED::rgb2hsv(led_indicator_color_rgb_t rgb) { + led_indicator_color_hsv_t hsv; + uint8_t minRGB, maxRGB; + uint8_t delta; + + minRGB = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b); + maxRGB = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b); + hsv.value = 0; + hsv.v = maxRGB; + delta = maxRGB - minRGB; + + if (delta == 0) { + hsv.h = 0; + hsv.s = 0; + } else { + hsv.s = delta * 255 / maxRGB; + + if (rgb.r == maxRGB) { + hsv.h = (60 * (rgb.g - rgb.b) / delta + 360) % 360; + } else if (rgb.g == maxRGB) { + hsv.h = (60 * (rgb.b - rgb.r) / delta + 120); + } else { + hsv.h = (60 * (rgb.r - rgb.g) / delta + 240); + } + } + return hsv; +} + +led_indicator_color_rgb_t BuiltInLED::hsv2rgb(led_indicator_color_hsv_t hsv) { + led_indicator_color_rgb_t rgb; + uint8_t rgb_max = hsv.v; + uint8_t rgb_min = rgb_max * (255 - hsv.s) / 255.0f; + + uint8_t i = hsv.h / 60; + uint8_t diff = hsv.h % 60; + + // RGB adjustment amount by hue + uint8_t rgb_adj = (rgb_max - rgb_min) * diff / 60; + rgb.value = 0; + switch (i) { + case 0: + rgb.r = rgb_max; + rgb.g = rgb_min + rgb_adj; + rgb.b = rgb_min; + break; + case 1: + rgb.r = rgb_max - rgb_adj; + rgb.g = rgb_max; + rgb.b = rgb_min; + break; + case 2: + rgb.r = rgb_min; + rgb.g = rgb_max; + rgb.b = rgb_min + rgb_adj; + break; + case 3: + rgb.r = rgb_min; + rgb.g = rgb_max - rgb_adj; + rgb.b = rgb_max; + break; + case 4: + rgb.r = rgb_min + rgb_adj; + rgb.g = rgb_min; + rgb.b = rgb_max; + break; + default: + rgb.r = rgb_max; + rgb.g = rgb_min; + rgb.b = rgb_max - rgb_adj; + break; + } + + // gamma correction + rgb.r = gamma_table[rgb.r]; + rgb.g = gamma_table[rgb.g]; + rgb.b = gamma_table[rgb.b]; + return rgb; +} + +void BuiltInLED::begin(uint8_t pin){ + if (pin < NUM_DIGITAL_PINS) { + pin_number = pin; + write(); + } else { + log_e("Invalid pin (%d) number", pin); + } +} +void BuiltInLED::end(){ + state = false; + write(); + if (pin_number < NUM_DIGITAL_PINS) { + if (!rmtDeinit(pin_number)) { + log_e("Failed to deinitialize RMT"); + } + } +} + +void BuiltInLED::on(){ + state = true; +} + +void BuiltInLED::off(){ + state = false; +} + +void BuiltInLED::toggle(){ + state = !state; +} + +bool BuiltInLED::getState(){ + return state; +} + +bool BuiltInLED::write(){ + led_indicator_color_rgb_t rgb_color = getRGB(); + log_d("Writing to pin %d with state = %s", pin_number, state ? "ON" : "OFF"); + log_d("HSV: %d, %d, %d", hsv_color.h, hsv_color.s, hsv_color.v); + log_d("RGB: %d, %d, %d", rgb_color.r, rgb_color.g, rgb_color.b); + if(pin_number < NUM_DIGITAL_PINS){ + if (state) { + rgbLedWrite(pin_number, rgb_color.r, rgb_color.g, rgb_color.b); + } else { + rgbLedWrite(pin_number, 0, 0, 0); + } + return true; + } else { + log_e("Invalid pin (%d) number", pin_number); + return false; + } +} + +void BuiltInLED::setBrightness(uint8_t brightness){ + hsv_color.v = brightness; +} + +uint8_t BuiltInLED::getBrightness(){ + return hsv_color.v; +} + +void BuiltInLED::setHSV(led_indicator_color_hsv_t hsv){ + if (hsv.h > MAX_HUE) { + hsv.h = MAX_HUE; + } + hsv_color.value = hsv.value; +} + +led_indicator_color_hsv_t BuiltInLED::getHSV(){ + return hsv_color; +} + +void BuiltInLED::setRGB(led_indicator_color_rgb_t rgb_color){ + hsv_color = rgb2hsv(rgb_color); +} + +led_indicator_color_rgb_t BuiltInLED::getRGB(){ + return hsv2rgb(hsv_color); +} + +void BuiltInLED::setTemperature(uint32_t temperature){ + uint16_t hue; + uint8_t saturation; + + log_d("Requested Temperature: %ld", temperature); + //hsv_color.v = gamma_table[((temperature >> 25) & 0x7F)]; + temperature &= 0xFFFFFF; + if (temperature < 600) { + hue = 0; + saturation = 100; + } else { + if (temperature > 10000) { + hue = 222; + saturation = 21 + (temperature - 10000) * 41 / 990000; + } else { + temperature -= 600; + temperature /= 100; + hue = temperatureTable[temperature].hue; + saturation = temperatureTable[temperature].saturation; + } + } + saturation = (saturation * 255) / 100; + // brightness is not changed + hsv_color.h = hue; + hsv_color.s = saturation; + log_d("Calculated Temperature: %ld, Hue: %d, Saturation: %d, Brightness: %d", temperature, hue, saturation, hsv_color.v); +} + diff --git a/examples/espidf-arduino-matter-light/main/builtinLED.h b/examples/espidf-arduino-matter-light/main/builtinLED.h new file mode 100644 index 0000000..85fc171 --- /dev/null +++ b/examples/espidf-arduino-matter-light/main/builtinLED.h @@ -0,0 +1,76 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + + This will implement the onboard WS2812b LED as a LED indicator + It can be used to indicate some state or status of the device + The LED can be controlled using RGB, HSV or color temperature, brightness + + In this example, the BuiltInLED class is used as the Matter light accessory +*/ + +#pragma once + +#include + +#define MAX_HUE 360 +#define MAX_SATURATION 255 +#define MAX_BRIGHTNESS 255 +#define MAX_PROGRESS 256 + +typedef struct { + union { + struct { + uint32_t v: 8; /*!< Brightness/Value of the LED. 0-255 */ + uint32_t s: 8; /*!< Saturation of the LED. 0-255 */ + uint32_t h: 9; /*!< Hue of the LED. 0-360 */ + }; + uint32_t value; /*!< IHSV value of the LED. */ + }; +} led_indicator_color_hsv_t; + +typedef struct { + union { + struct { + uint32_t r: 8; /*!< Red component of the LED color. Range: 0-255. */ + uint32_t g: 8; /*!< Green component of the LED color. Range: 0-255. */ + uint32_t b: 8; /*!< Blue component of the LED color. Range: 0-255. */ + }; + uint32_t value; /*!< Combined RGB value of the LED color. */ + }; +} led_indicator_color_rgb_t; + +class BuiltInLED { +private: + uint8_t pin_number; + bool state; + led_indicator_color_hsv_t hsv_color; + +public: + BuiltInLED(); + ~BuiltInLED(); + + static led_indicator_color_hsv_t rgb2hsv(led_indicator_color_rgb_t rgb_value); + static led_indicator_color_rgb_t hsv2rgb(led_indicator_color_hsv_t hsv); + + void begin(uint8_t pin); + void end(); + + void on(); + void off(); + void toggle(); + bool getState(); + + bool write(); + + void setBrightness(uint8_t brightness); + uint8_t getBrightness(); + void setHSV(led_indicator_color_hsv_t hsv); + led_indicator_color_hsv_t getHSV(); + void setRGB(led_indicator_color_rgb_t color); + led_indicator_color_rgb_t getRGB(); + void setTemperature(uint32_t temperature); +}; diff --git a/examples/espidf-arduino-matter-light/main/idf_component.yml b/examples/espidf-arduino-matter-light/main/idf_component.yml new file mode 100644 index 0000000..369a76b --- /dev/null +++ b/examples/espidf-arduino-matter-light/main/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + espressif/esp_matter: + version: "^1.3.0" \ No newline at end of file diff --git a/examples/espidf-arduino-matter-light/main/matter_accessory_driver.cpp b/examples/espidf-arduino-matter-light/main/matter_accessory_driver.cpp new file mode 100644 index 0000000..9fe2b16 --- /dev/null +++ b/examples/espidf-arduino-matter-light/main/matter_accessory_driver.cpp @@ -0,0 +1,101 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include +#include +#include "builtinLED.h" +#include "matter_accessory_driver.h" + +// set your board WS2812b pin here (e.g. 48 is the default pin for the ESP32-S3 devkit) +#define WS2812_PIN 48 + +/* Do any conversions/remapping for the actual value here */ +esp_err_t light_accessory_set_power(void *led, uint8_t val) +{ + BuiltInLED *builtinLED = (BuiltInLED *) led; + esp_err_t err = ESP_OK; + if (val) { + builtinLED->on(); + } else { + builtinLED->off(); + } + if (!builtinLED->write()) { + err = ESP_FAIL; + } + log_i("LED set power: %d", val); + return err; +} + +esp_err_t light_accessory_set_brightness(void *led, uint8_t val) +{ + esp_err_t err = ESP_OK; + BuiltInLED *builtinLED = (BuiltInLED *) led; + int value = REMAP_TO_RANGE(val, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS); + + builtinLED->setBrightness(value); + if (!builtinLED->write()) { + err = ESP_FAIL; + } + log_i("LED set brightness: %d", value); + return err; +} + +esp_err_t light_accessory_set_hue(void *led, uint8_t val) +{ + esp_err_t err = ESP_OK; + BuiltInLED *builtinLED = (BuiltInLED *) led; + int value = REMAP_TO_RANGE(val, MATTER_HUE, STANDARD_HUE); + led_indicator_color_hsv_t hsv = builtinLED->getHSV(); + hsv.h = value; + builtinLED->setHSV(hsv); + if (!builtinLED->write()) { + err = ESP_FAIL; + } + log_i("LED set hue: %d", value); + return err; +} + +esp_err_t light_accessory_set_saturation(void *led, uint8_t val) +{ + esp_err_t err = ESP_OK; + BuiltInLED *builtinLED = (BuiltInLED *) led; + int value = REMAP_TO_RANGE(val, MATTER_SATURATION, STANDARD_SATURATION); + led_indicator_color_hsv_t hsv = builtinLED->getHSV(); + hsv.s = value; + builtinLED->setHSV(hsv); + if (!builtinLED->write()) { + err = ESP_FAIL; + } + log_i("LED set saturation: %d", value); + return err; +} + +esp_err_t light_accessory_set_temperature(void *led, uint16_t val) +{ + esp_err_t err = ESP_OK; + BuiltInLED *builtinLED = (BuiltInLED *) led; + uint32_t value = REMAP_TO_RANGE_INVERSE(val, STANDARD_TEMPERATURE_FACTOR); + builtinLED->setTemperature(value); + if (!builtinLED->write()) { + err = ESP_FAIL; + } + log_i("LED set temperature: %ld", value); + return err; +} + +app_driver_handle_t light_accessory_init() +{ + /* Initialize led */ + static BuiltInLED builtinLED; + + const uint8_t pin = WS2812_PIN; // set your board WS2812b pin here + builtinLED.begin(pin); + builtinLED.setHSV({DEFAULT_HUE, DEFAULT_SATURATION, DEFAULT_BRIGHTNESS}); + builtinLED.write(); + return (app_driver_handle_t) &builtinLED; +} diff --git a/examples/espidf-arduino-matter-light/main/matter_accessory_driver.h b/examples/espidf-arduino-matter-light/main/matter_accessory_driver.h new file mode 100644 index 0000000..b3b6692 --- /dev/null +++ b/examples/espidf-arduino-matter-light/main/matter_accessory_driver.h @@ -0,0 +1,28 @@ +#include + +/** Standard max values (used for remapping attributes) */ +#define STANDARD_BRIGHTNESS 255 +#define STANDARD_HUE 360 +#define STANDARD_SATURATION 255 +#define STANDARD_TEMPERATURE_FACTOR 1000000 + +/** Matter max values (used for remapping attributes) */ +#define MATTER_BRIGHTNESS 254 +#define MATTER_HUE 254 +#define MATTER_SATURATION 254 +#define MATTER_TEMPERATURE_FACTOR 1000000 + +/** Default attribute values used during initialization */ +#define DEFAULT_POWER true +#define DEFAULT_BRIGHTNESS 64 +#define DEFAULT_HUE 128 +#define DEFAULT_SATURATION 254 + +typedef void *app_driver_handle_t; + +esp_err_t light_accessory_set_power(void *led, uint8_t val); +esp_err_t light_accessory_set_brightness(void *led, uint8_t val); +esp_err_t light_accessory_set_hue(void *led, uint8_t val); +esp_err_t light_accessory_set_saturation(void *led, uint8_t val); +esp_err_t light_accessory_set_temperature(void *led, uint16_t val); +app_driver_handle_t light_accessory_init(); diff --git a/examples/espidf-arduino-matter-light/main/matter_light.cpp b/examples/espidf-arduino-matter-light/main/matter_light.cpp new file mode 100644 index 0000000..76d5cfe --- /dev/null +++ b/examples/espidf-arduino-matter-light/main/matter_light.cpp @@ -0,0 +1,369 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "matter_accessory_driver.h" + +#include + +#include +#include +#include + +#include +#include + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#include +#include "esp_openthread_types.h" + +#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \ + { \ + .radio_mode = RADIO_MODE_NATIVE, \ + } + +#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ + { \ + .host_connection_mode = HOST_CONNECTION_MODE_NONE, \ + } + +#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ + { \ + .storage_partition_name = "nvs", .netif_queue_size = 10, .task_queue_size = 10, \ + } +#endif + +uint16_t light_endpoint_id = 0; + +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; + +#if CONFIG_ENABLE_ENCRYPTED_OTA +extern const char decryption_key_start[] asm("_binary_esp_image_encryption_key_pem_start"); +extern const char decryption_key_end[] asm("_binary_esp_image_encryption_key_pem_end"); + +static const char *s_decryption_key = decryption_key_start; +static const uint16_t s_decryption_key_len = decryption_key_end - decryption_key_start; +#endif // CONFIG_ENABLE_ENCRYPTED_OTA + +static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) +{ + switch (event->Type) { + case chip::DeviceLayer::DeviceEventType::kInterfaceIpAddressChanged: + log_i("Interface IP Address changed"); + 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) + { + chip::CommissioningWindowManager & commissionMgr = chip::Server::GetInstance().GetCommissioningWindowManager(); + constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds16(k_timeout_seconds); + if (!commissionMgr.IsCommissioningWindowOpen()) + { + /* After removing last fabric, this example 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; + } +} + +static uint32_t button_time_stamp = 0; +static void button_driver_down_cb() +{ + button_time_stamp = millis(); +} + + +static void button_driver_up_cb() +{ + uint32_t time_diff = millis() - button_time_stamp; + // Factory reset is triggered if the button is pressed for more than 3 seconds + if (time_diff > 3000) { + log_i("Factory reset triggered. Light will retored to factory settings."); + esp_matter::factory_reset(); + return; + } + + // Toggle button is pressed - toggle the light + log_i("Toggle button pressed"); + uint16_t endpoint_id = light_endpoint_id; + uint32_t cluster_id = OnOff::Id; + uint32_t attribute_id = OnOff::Attributes::OnOff::Id; + + node_t *node = node::get(); + endpoint_t *endpoint = endpoint::get(node, endpoint_id); + cluster_t *cluster = cluster::get(endpoint, cluster_id); + attribute_t *attribute = attribute::get(cluster, attribute_id); + + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + val.val.b = !val.val.b; + attribute::update(endpoint_id, cluster_id, attribute_id, &val); +} + +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) +{ + esp_err_t err = ESP_OK; + if (endpoint_id == light_endpoint_id) { + void *led = (void *)driver_handle; + if (cluster_id == OnOff::Id) { + if (attribute_id == OnOff::Attributes::OnOff::Id) { + err = light_accessory_set_power(led, val->val.b); + } + } else if (cluster_id == LevelControl::Id) { + if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) { + err = light_accessory_set_brightness(led, val->val.u8); + } + } else if (cluster_id == ColorControl::Id) { + if (attribute_id == ColorControl::Attributes::CurrentHue::Id) { + err = light_accessory_set_hue(led, val->val.u8); + } else if (attribute_id == ColorControl::Attributes::CurrentSaturation::Id) { + err = light_accessory_set_saturation(led, val->val.u8); + } else if (attribute_id == ColorControl::Attributes::ColorTemperatureMireds::Id) { + err = light_accessory_set_temperature(led, val->val.u16); + } + } + } + return err; +} + +esp_err_t matter_light_set_defaults(uint16_t endpoint_id) +{ + esp_err_t err = ESP_OK; + + void *led = endpoint::get_priv_data(endpoint_id); + node_t *node = node::get(); + endpoint_t *endpoint = endpoint::get(node, endpoint_id); + cluster_t *cluster = NULL; + attribute_t *attribute = NULL; + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + + /* Setting brightness */ + cluster = cluster::get(endpoint, LevelControl::Id); + attribute = attribute::get(cluster, LevelControl::Attributes::CurrentLevel::Id); + attribute::get_val(attribute, &val); + err |= light_accessory_set_brightness(led, val.val.u8); + + /* Setting color */ + cluster = cluster::get(endpoint, ColorControl::Id); + attribute = attribute::get(cluster, ColorControl::Attributes::ColorMode::Id); + attribute::get_val(attribute, &val); + if (val.val.u8 == (uint8_t)ColorControl::ColorMode::kCurrentHueAndCurrentSaturation) { + /* Setting hue */ + attribute = attribute::get(cluster, ColorControl::Attributes::CurrentHue::Id); + attribute::get_val(attribute, &val); + err |= light_accessory_set_hue(led, val.val.u8); + /* Setting saturation */ + attribute = attribute::get(cluster, ColorControl::Attributes::CurrentSaturation::Id); + attribute::get_val(attribute, &val); + err |= light_accessory_set_saturation(led, val.val.u8); + } else if (val.val.u8 == (uint8_t)ColorControl::ColorMode::kColorTemperature) { + /* Setting temperature */ + attribute = attribute::get(cluster, ColorControl::Attributes::ColorTemperatureMireds::Id); + attribute::get_val(attribute, &val); + err |= light_accessory_set_temperature(led, val.val.u16); + } else { + log_e("Color mode not supported"); + } + + /* Setting power */ + cluster = cluster::get(endpoint, OnOff::Id); + attribute = attribute::get(cluster, OnOff::Attributes::OnOff::Id); + attribute::get_val(attribute, &val); + err |= light_accessory_set_power(led, val.val.b); + + return err; +} + +void button_driver_init() +{ + /* Initialize button */ + uint8_t pin = 0; // set your board button pin here + pinMode(pin, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(pin), button_driver_down_cb, FALLING); // pressed + attachInterrupt(digitalPinToInterrupt(pin), button_driver_up_cb, RISING); // released +} + +// 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; + + if (type == PRE_UPDATE) { + /* Driver update */ + app_driver_handle_t driver_handle = (app_driver_handle_t)priv_data; + err = matter_light_attribute_update(driver_handle, endpoint_id, cluster_id, attribute_id, val); + } + + 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; +} + +void setup() +{ + esp_err_t err = ESP_OK; + + /* Initialize the ESP NVS layer */ + //nvs_flash_init(); + + /* Initialize driver */ + app_driver_handle_t light_handle = light_accessory_init(); + button_driver_init(); + + /* Create a Matter node and add the mandatory Root Node device type on endpoint 0 */ + node::config_t node_config; + + // node handle can be used to add/modify other endpoints. + node_t *node = node::create(&node_config, app_attribute_update_cb, app_identification_cb); + if (node == nullptr) { + log_e("Failed to create Matter node"); + abort(); + } + + extended_color_light::config_t light_config; + light_config.on_off.on_off = DEFAULT_POWER; + light_config.on_off.lighting.start_up_on_off = nullptr; + light_config.level_control.current_level = DEFAULT_BRIGHTNESS; + light_config.level_control.lighting.start_up_current_level = DEFAULT_BRIGHTNESS; + light_config.color_control.color_mode = (uint8_t)ColorControl::ColorMode::kColorTemperature; + light_config.color_control.enhanced_color_mode = (uint8_t)ColorControl::ColorMode::kColorTemperature; + light_config.color_control.color_temperature.startup_color_temperature_mireds = nullptr; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = extended_color_light::create(node, &light_config, ENDPOINT_FLAG_NONE, light_handle); + if (endpoint == nullptr) { + log_e("Failed to create extended color light endpoint"); + abort(); + } + + light_endpoint_id = endpoint::get_id(endpoint); + log_i("Light created with endpoint_id %d", light_endpoint_id); + + /* Mark deferred persistence for some attributes that might be changed rapidly */ + cluster_t *level_control_cluster = cluster::get(endpoint, LevelControl::Id); + attribute_t *current_level_attribute = attribute::get(level_control_cluster, LevelControl::Attributes::CurrentLevel::Id); + attribute::set_deferred_persistence(current_level_attribute); + + cluster_t *color_control_cluster = cluster::get(endpoint, ColorControl::Id); + attribute_t *current_x_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::CurrentX::Id); + attribute::set_deferred_persistence(current_x_attribute); + attribute_t *current_y_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::CurrentY::Id); + attribute::set_deferred_persistence(current_y_attribute); + attribute_t *color_temp_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::ColorTemperatureMireds::Id); + attribute::set_deferred_persistence(color_temp_attribute); + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + /* Set OpenThread platform config */ + esp_openthread_platform_config_t config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }; + set_openthread_platform_config(&config); +#endif + + /* Matter start */ + err = esp_matter::start(app_event_cb); + if (err != ESP_OK) { + log_e("Failed to start Matter, err:%d", err); + abort(); + } + + /* Starting driver with default values */ + matter_light_set_defaults(light_endpoint_id); + +#if CONFIG_ENABLE_ENCRYPTED_OTA + err = esp_matter_ota_requestor_encrypted_init(s_decryption_key, s_decryption_key_len); + if (err != ESP_OK) { + log_e("Failed to initialized the encrypted OTA, err: %d", err); + abort(); + } +#endif // CONFIG_ENABLE_ENCRYPTED_OTA + +#if CONFIG_ENABLE_CHIP_SHELL + esp_matter::console::diagnostics_register_commands(); + esp_matter::console::wifi_register_commands(); +#if CONFIG_OPENTHREAD_CLI + esp_matter::console::otcli_register_commands(); +#endif + esp_matter::console::init(); +#endif +} + +void loop() { + delay(1000); +} diff --git a/examples/espidf-arduino-matter-light/partitions.csv b/examples/espidf-arduino-matter-light/partitions.csv new file mode 100644 index 0000000..f0992fa --- /dev/null +++ b/examples/espidf-arduino-matter-light/partitions.csv @@ -0,0 +1,9 @@ +# Name, Type, SubType, Offset, Size, Flags +esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted +nvs, data, nvs, 0x10000, 0xC000, +nvs_keys, data, nvs_keys,, 0x1000, encrypted +otadata, data, ota, , 0x2000 +phy_init, data, phy, , 0x1000, +ota_0, app, ota_0, 0x20000, 0x1E0000, +ota_1, app, ota_1, 0x200000, 0x1E0000, +fctry, data, nvs, 0x3E0000, 0x6000 diff --git a/examples/espidf-arduino-matter-light/platformio.ini b/examples/espidf-arduino-matter-light/platformio.ini new file mode 100644 index 0000000..0a46669 --- /dev/null +++ b/examples/espidf-arduino-matter-light/platformio.ini @@ -0,0 +1,26 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html +[platformio] +src_dir = main + +[env] +platform = https://github.com/pioarduino/platform-espressif32.git#develop +framework = arduino, espidf +board_build.partitions = partitions.csv +monitor_speed = 115200 + + +[env:esp32s3] +board = esp32-s3-devkitc-1 +board_build.embed_txtfiles = + managed_components/espressif__esp_insights/server_certs/https_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt diff --git a/examples/espidf-arduino-matter-light/sdkconfig.defaults b/examples/espidf-arduino-matter-light/sdkconfig.defaults new file mode 100644 index 0000000..517a05a --- /dev/null +++ b/examples/espidf-arduino-matter-light/sdkconfig.defaults @@ -0,0 +1,66 @@ +# Arduino Settings +CONFIG_FREERTOS_HZ=1000 +CONFIG_AUTOSTART_ARDUINO=y + +# Log Levels +# Boot Messages - Log level +CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y +# Arduino Log Level +CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_VERBOSE=y +# IDF Log Level +CONFIG_LOG_DEFAULT_LEVEL_WARN=y + +#enable BT +CONFIG_BT_ENABLED=y +CONFIG_BT_NIMBLE_ENABLED=y + +#disable BT connection reattempt +CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n + +#enable lwip ipv6 autoconfig +CONFIG_LWIP_IPV6_AUTOCONFIG=y + +# Use a custom partition table +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0xC000 + +# Disable chip shell +CONFIG_ENABLE_CHIP_SHELL=n + +#enable lwIP route hooks +CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y +CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y + +# Button +CONFIG_BUTTON_PERIOD_TIME_MS=20 +CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000 + +# disable softap by default +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n + +# Disable DS Peripheral +CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n + +# Use compact attribute storage mode +CONFIG_ESP_MATTER_NVS_USE_COMPACT_ATTR_STORAGE=y + +# Enable HKDF in mbedtls +CONFIG_MBEDTLS_HKDF_C=y + +# Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1) +# unique local addresses for fabrics(MAX_FABRIC), a link local address(1) +CONFIG_LWIP_IPV6_NUM_ADDRESSES=6 + + +# ESP32-S3-DevKitC-1 Settings +# Buttons +CONFIG_BSP_BUTTONS_NUM=1 +CONFIG_BSP_BUTTON_1_TYPE_GPIO=y +CONFIG_BSP_BUTTON_1_GPIO=0 +CONFIG_BSP_BUTTON_1_LEVEL=0 +# LEDs +CONFIG_BSP_LEDS_NUM=1 +CONFIG_BSP_LED_TYPE_RGB=y +CONFIG_BSP_LED_RGB_GPIO=48 +CONFIG_BSP_LED_RGB_BACKEND_RMT=y \ No newline at end of file diff --git a/examples/espidf-arduino-matter-light/test/README b/examples/espidf-arduino-matter-light/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/examples/espidf-arduino-matter-light/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html From 01b8cb2ce1a67003072b779fb5ea989e9def3ac5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 13 Sep 2024 17:34:44 +0200 Subject: [PATCH 048/117] add matter example to CI --- .github/workflows/examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 8e8a32b..0ed9246 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -19,6 +19,7 @@ jobs: - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - "examples/espidf-arduino-h2zero-BLE_scan" + - "examples/espidf-arduino-matter-light" - "examples/espidf-arduino-blink" - "examples/espidf-arduino-littlefs" - "examples/espidf-blink" From 5ba53375e9e65dbcab1df9743b3f86603f0ed8a3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 13 Sep 2024 18:02:35 +0200 Subject: [PATCH 049/117] disable matter example Windows path length limit.... --- .github/workflows/examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 0ed9246..f7f6424 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -19,7 +19,7 @@ jobs: - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - "examples/espidf-arduino-h2zero-BLE_scan" - - "examples/espidf-arduino-matter-light" + #- "examples/espidf-arduino-matter-light" # Windows compile fails -> Path length limit - "examples/espidf-arduino-blink" - "examples/espidf-arduino-littlefs" - "examples/espidf-blink" From b2c29ec945ebe4a9cd8c819f4b96afdc21006244 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 13 Sep 2024 18:06:52 +0200 Subject: [PATCH 050/117] fix platform --- examples/espidf-arduino-matter-light/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/espidf-arduino-matter-light/platformio.ini b/examples/espidf-arduino-matter-light/platformio.ini index 0a46669..25874c6 100644 --- a/examples/espidf-arduino-matter-light/platformio.ini +++ b/examples/espidf-arduino-matter-light/platformio.ini @@ -11,7 +11,7 @@ src_dir = main [env] -platform = https://github.com/pioarduino/platform-espressif32.git#develop +platform = espressif32 framework = arduino, espidf board_build.partitions = partitions.csv monitor_speed = 115200 From 11e49522afcf586e18bfd3007005c2eebdf8da72 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Sep 2024 20:08:58 +0200 Subject: [PATCH 051/117] enable bootloader components build --- builder/frameworks/espidf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 3b052b0..23a69c9 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -873,6 +873,7 @@ def build_bootloader(sdk_config): "-DPYTHON=" + get_python_exe(), "-DIDF_PATH=" + FRAMEWORK_DIR, "-DSDKCONFIG=" + SDKCONFIG_PATH, + "-DPROJECT_SOURCE_DIR=" + PROJECT_DIR, "-DLEGACY_INCLUDE_COMMON_HEADERS=", "-DEXTRA_COMPONENT_DIRS=" + os.path.join(FRAMEWORK_DIR, "components", "bootloader"), From 14b56849116542fd18f016954c25847df4337b9d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:21:55 +0200 Subject: [PATCH 052/117] ULP LP support --- builder/frameworks/espidf.py | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 23a69c9..d6dd19b 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -250,13 +250,11 @@ def populate_idf_env_vars(idf_env): os.path.dirname(get_python_exe()), ] - if mcu not in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"): - additional_packages.append( - os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), - ) +# if mcu in ("esp32", "esp32s2", "esp32s3"): +# additional_packages.append( +# os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), +# ) -# if IS_WINDOWS: -# additional_packages.append(platform.get_package_dir("tool-mconf")) idf_env["PATH"] = os.pathsep.join(additional_packages + [idf_env["PATH"]]) @@ -1300,17 +1298,6 @@ def install_python_deps(): ) ) -# # A special "esp-windows-curses" python package is required on Windows -# # for Menuconfig on IDF <5 -# if not IDF5 and "esp-windows-curses" not in installed_packages: -# env.Execute( -# env.VerboseAction( -# '"%s" -m pip install "file://%s/tools/kconfig_new/esp-windows-curses"' -# % (python_exe_path, FRAMEWORK_DIR), -# "Installing windows-curses package", -# ) -# ) - def get_idf_venv_dir(): # The name of the IDF venv contains the IDF version to avoid possible conflicts and @@ -1786,8 +1773,8 @@ env["BUILDERS"]["ElfToBin"].action = action # ulp_dir = os.path.join(PROJECT_DIR, "ulp") -if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"): - env.SConscript("ulp.py", exports="env sdk_config project_config idf_variant") +if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c2", "esp32c3", "esp32h2"): + env.SConscript("ulp.py", exports="env sdk_config project_config app_includes idf_variant") # # Process OTA partition and image From 69227968b28a0a46f27a4b572ea08917bc389f9a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:23:45 +0200 Subject: [PATCH 053/117] LP ULP support --- builder/frameworks/ulp.py | 40 +++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 2233764..25266e5 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -21,7 +21,7 @@ from platformio.proc import where_is_program, exec_command from SCons.Script import Import -Import("env sdk_config project_config idf_variant") +Import("env sdk_config project_config app_includes idf_variant") ulp_env = env.Clone() platform = ulp_env.PioPlatform() @@ -37,22 +37,24 @@ def prepare_ulp_env_vars(env): toolchain_path = platform.get_package_dir( "toolchain-xtensa-%s" % idf_variant + if idf_variant not in ("esp32c6", "esp32p4") + else "toolchain-riscv32-esp" + ) + + toolchain_path_ulp = platform.get_package_dir( + "toolchain-esp32ulp" + if sdk_config.get("ULP_COPROC_TYPE_FSM", False) + else "" ) additional_packages = [ toolchain_path, - os.path.join( - platform.get_package_dir("toolchain-esp32ulp"), - "bin", - ), + toolchain_path_ulp, platform.get_package_dir("tool-ninja"), os.path.join(platform.get_package_dir("tool-cmake"), "bin"), os.path.dirname(where_is_program("python")), ] -# if "windows" in get_systype(): -# additional_packages.append(platform.get_package_dir("tool-mconf")) - for package in additional_packages: ulp_env.PrependENVPath("PATH", package) @@ -81,6 +83,19 @@ def get_component_includes(target_config): def generate_ulp_config(target_config): def _generate_ulp_configuration_action(env, target, source): riscv_ulp_enabled = sdk_config.get("ULP_COPROC_TYPE_RISCV", False) + lp_core_ulp_enabled = sdk_config.get("ULP_COPROC_TYPE_LP_CORE", False) + + if lp_core_ulp_enabled == False: + ulp_toolchain = "toolchain-%sulp%s.cmake"% ( + "" if riscv_ulp_enabled else idf_variant + "-", + "-riscv" if riscv_ulp_enabled else "", + ) + else: + ulp_toolchain = "toolchain-lp-core-riscv.cmake" + + comp_includes = ";".join(get_component_includes(target_config)) + plain_includes = ";".join(app_includes["plain_includes"]) + comp_includes = comp_includes + plain_includes cmd = ( os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"), @@ -91,21 +106,18 @@ def generate_ulp_config(target_config): "components", "ulp", "cmake", - "toolchain-%sulp%s.cmake" - % ( - "" if riscv_ulp_enabled else idf_variant + "-", - "-riscv" if riscv_ulp_enabled else "", - ), + ulp_toolchain, ), "-DULP_S_SOURCES=%s" % ";".join([fs.to_unix_path(s.get_abspath()) for s in source]), "-DULP_APP_NAME=ulp_main", "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), - "-DCOMPONENT_INCLUDES=%s" % ";".join(get_component_includes(target_config)), + "-DCOMPONENT_INCLUDES=" + comp_includes, "-DIDF_TARGET=%s" % idf_variant, "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), "-DPYTHON=" + env.subst("$PYTHONEXE"), "-DULP_COCPU_IS_RISCV=%s" % ("ON" if riscv_ulp_enabled else "OFF"), + "-DULP_COCPU_IS_LP_CORE=%s" % ("ON" if lp_core_ulp_enabled else "OFF"), "-GNinja", "-B", ULP_BUILD_DIR, From e8a35ec34dda6c8cc65e12c492310e9ec22c5311 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 17 Sep 2024 14:52:05 +0200 Subject: [PATCH 054/117] change bootloader offset macro --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index d6dd19b..66b3cc9 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1662,7 +1662,7 @@ env.Prepend( ( board.get( "upload.bootloader_offset", - "0x0" if mcu in ["esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2"] else ("0x2000" if mcu in ["esp32p4"] else "0x1000"), + "0x1000" if mcu in ["esp32", "esp32s2"] else ("0x2000" if mcu in ["esp32p4"] else "0x0"), ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), From ba1cffe12b016aab30341c38c65de23e885a6a98 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 17 Sep 2024 15:44:06 +0200 Subject: [PATCH 055/117] remove old wrong code --- builder/main.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/builder/main.py b/builder/main.py index 07a6bb0..bf33043 100644 --- a/builder/main.py +++ b/builder/main.py @@ -256,9 +256,6 @@ env.Replace( if mcu in ("esp32c2", "esp32c3", "esp32c6") else "tool-xtensa-esp-elf-gdb" ) - or "", - "bin", - "%s-elf-gdb" % toolchain_arch, ), OBJCOPY=join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), RANLIB="%s-elf-gcc-ranlib" % toolchain_arch, From ca926d8b18c0addcd080ab71bf222e5991498727 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 17 Sep 2024 17:17:00 +0200 Subject: [PATCH 056/117] update Matter example --- .../espidf-arduino-matter-light/README.md | 71 ++- .../main/Kconfig.projbuild | 102 ++++ .../main/builtinLED.cpp | 498 +++++++++--------- .../main/builtinLED.h | 150 +++--- .../main/matter_accessory_driver.cpp | 6 - .../main/matter_accessory_driver.h | 75 ++- .../main/matter_light.cpp | 148 ++++-- .../partitions.csv | 1 + .../platformio.ini | 2 + .../sdkconfig.defaults.c6_thread | 80 +++ .../sdkconfig.defaults.esp32c3 | 64 +++ .../sdkconfig.defaults.esp32c6 | 79 +++ .../sdkconfig.defaults.esp32s3 | 64 +++ 13 files changed, 928 insertions(+), 412 deletions(-) create mode 100644 examples/espidf-arduino-matter-light/main/Kconfig.projbuild create mode 100644 examples/espidf-arduino-matter-light/sdkconfig.defaults.c6_thread create mode 100644 examples/espidf-arduino-matter-light/sdkconfig.defaults.esp32c3 create mode 100644 examples/espidf-arduino-matter-light/sdkconfig.defaults.esp32c6 create mode 100644 examples/espidf-arduino-matter-light/sdkconfig.defaults.esp32s3 diff --git a/examples/espidf-arduino-matter-light/README.md b/examples/espidf-arduino-matter-light/README.md index fd3f77f..7d87688 100644 --- a/examples/espidf-arduino-matter-light/README.md +++ b/examples/espidf-arduino-matter-light/README.md @@ -1,3 +1,68 @@ -## Arduino/IDF Matter Light example - -The needed Matter component is added via the IDF component manager -> `idf_component.yml`. +| Supported Targets | ESP32-S3 | ESP32-C3 | ESP32-C6 | +| ----------------- | -------- | -------- | -------- | + + +# Managed Component Light + +This example is configured by default to work with the ESP32-S3, which has the RGB LED GPIO set as pin 48 and the BOOT button on GPIO 0. + +This example creates a Color Temperature Light device using the esp_matter component downloaded from the [Espressif Component Registry](https://components.espressif.com/) instead of an extra component locally, so the example can work without setting up the esp-matter environment. + +See the [docs](https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html) for more information about building and flashing the firmware. + +The code is based on the Arduino API and uses Arduino as an IDF Component. + +## How to use it + +Once the device runs for the first time, it must be commissioned to the Matter Fabric of the available Matter Environment. +Possible Matter Environments are: +- Amazon Alexa +- Google Home Assistant (*) +- Apple Home +- Open Source Home Assistant + +(*) Google Home Assistant requires the user to set up a Matter Light using the [Google Home Developer Console](https://developers.home.google.com/codelabs/matter-device#2). It is necessary to create a Matter Light device with VID = 0xFFF1 and PID = 0x8000. Otherwise, the Light won't show up in the GHA APP. This action is necessary because the Firmware uses Testing credentials and Google requires the user to create the testing device before using it. + +There is no QR Code to be used when the Smartphone APP wants to add the Matter Device. +Please enter the code manually: `34970112332` + +The devboard has a built-in LED that will be used as the Matter Light. +The default setting of the code uses pin 48 for the ESP32-S3. +Please change it in `main/matter_accessory_driver.h` or in the `sdkconfig.defaults.` file. + +## LED Status and Factory Mode + +The WS2812b built-in LED will turn purple as soon as the device is flashed and runs for the first time. +The purple color indicates that the Matter Accessory has not been commissioned yet. +After using a Matter provider Smartphone APP to add a Matter device to your Home Application, it may turn orange to indicate that it has no WiFi connection. + +Once it connects to the WiFi network, the LED will turn white to indicate that Matter is working and the device is connected to the Matter Environment. +Please note that Matter over WiFi using an ESP32 device will connect to a 2.4GHz WiFi SSID, therefore the Commissioner APP Smartphone shall be connected to this SSID. + +The Matter and WiFi configuration will be stored in NVS to ensure that it will connect to the Matter Fabric and WiFi Network again once it is reset. + +The Matter Smartphone APP will control the light state (ON/OFF), temperature (Warm/Cold White), and brightness. + +## On Board Light toggle button + +The built-in BOOT button will toggle On/Off and replicate the new state to the Matter Environment, making it visible in the Matter Smartphone APP as well. + +## Returning to the Factory State + +Holding the BOOT button pressed for more than 10 seconds and then releasing it will erase all Matter and WiFi configuration, forcing it to reset to factory state. After that, the device needs to be commissioned again. Previous setups done in the Smartphone APP won't work again; therefore, the virtual device shall be removed from the APP. + +## Building the Application using WiFi and Matter + +Use ESP-IDF 5.1.4 from https://github.com/espressif/esp-idf/tree/release/v5.1 +This example has been tested with Arduino Core 3.0.4 + +There is a configuration file for these SoC: esp32s3, esp32c3, esp32c6. +Those are the tested devices that have a WS2812 RGB LED and can run BLE, WiFi and Matter. + +In case it is necessary to change the Button Pin or the REG LED Pin, please use the `menuconfig` and change the Menu Option `Light Matter Accessory` + +## Using OpenThread with Matter + +This is possible with the ESP32-C6. +It is neessasy to have a Thread Border Routed in the Matter Environment. Check you matter hardware provider. + diff --git a/examples/espidf-arduino-matter-light/main/Kconfig.projbuild b/examples/espidf-arduino-matter-light/main/Kconfig.projbuild new file mode 100644 index 0000000..50e8914 --- /dev/null +++ b/examples/espidf-arduino-matter-light/main/Kconfig.projbuild @@ -0,0 +1,102 @@ +menu "Light Matter Accessory" + menu "On Board Light ON/OFF Button" + config BUTTON_PIN + int + prompt "Button 1 GPIO" + default ENV_GPIO_BOOT_BUTTON + range -1 ENV_GPIO_IN_RANGE_MAX + help + The GPIO pin for button that will be used to turn on/off the Matter Light. It shall be connected to a push button. It can use the BOOT button of the development board. + endmenu + + + menu "LEDs" + config WS2812_PIN + int + prompt "WS2812 RGB LED GPIO" + default ENV_GPIO_RGB_LED + range -1 ENV_GPIO_OUT_RANGE_MAX + help + The GPIO pin for the Matter Light that will be driven by RMT. It shall be connected to one single WS2812 RGB LED. + endmenu + + # TARGET CONFIGURATION + if IDF_TARGET_ESP32C3 + config ENV_GPIO_RANGE_MIN + int + default 0 + + config ENV_GPIO_RANGE_MAX + int + default 19 + # GPIOs 20/21 are always used by UART in examples + + config ENV_GPIO_IN_RANGE_MAX + int + default ENV_GPIO_RANGE_MAX + + config ENV_GPIO_OUT_RANGE_MAX + int + default ENV_GPIO_RANGE_MAX + + config ENV_GPIO_BOOT_BUTTON + int + default 9 + + config ENV_GPIO_RGB_LED + int + default 8 + endif + if IDF_TARGET_ESP32C6 + config ENV_GPIO_RANGE_MIN + int + default 0 + + config ENV_GPIO_RANGE_MAX + int + default 30 + # GPIOs 16/17 are always used by UART in examples + + config ENV_GPIO_IN_RANGE_MAX + int + default ENV_GPIO_RANGE_MAX + + config ENV_GPIO_OUT_RANGE_MAX + int + default ENV_GPIO_RANGE_MAX + + config ENV_GPIO_BOOT_BUTTON + int + default 9 + + config ENV_GPIO_RGB_LED + int + default 8 + endif + if IDF_TARGET_ESP32S3 + config ENV_GPIO_RANGE_MIN + int + default 0 + + config ENV_GPIO_RANGE_MAX + int + default 48 + + config ENV_GPIO_IN_RANGE_MAX + int + default ENV_GPIO_RANGE_MAX + + config ENV_GPIO_OUT_RANGE_MAX + int + default ENV_GPIO_RANGE_MAX + + config ENV_GPIO_BOOT_BUTTON + int + default 0 + + config ENV_GPIO_RGB_LED + int + default 48 + endif + +endmenu diff --git a/examples/espidf-arduino-matter-light/main/builtinLED.cpp b/examples/espidf-arduino-matter-light/main/builtinLED.cpp index cb7135e..9f2695b 100644 --- a/examples/espidf-arduino-matter-light/main/builtinLED.cpp +++ b/examples/espidf-arduino-matter-light/main/builtinLED.cpp @@ -1,251 +1,247 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. - - This will implement the onboard WS2812b LED as a LED indicator - It can be used to indicate some state or status of the device - The LED can be controlled using RGB, HSV or color temperature, brightness - - In this example, the LED Indicator class is used as the Matter light accessory -*/ - -#include -#include "builtinLED.h" - -typedef struct { - uint16_t hue; - uint8_t saturation; -} HS_color_t; - -static const HS_color_t temperatureTable[] = { - {4, 100}, {8, 100}, {11, 100}, {14, 100}, {16, 100}, {18, 100}, {20, 100}, {22, 100}, {24, 100}, {25, 100}, - {27, 100}, {28, 100}, {30, 100}, {31, 100}, {31, 95}, {30, 89}, {30, 85}, {29, 80}, {29, 76}, {29, 73}, - {29, 69}, {28, 66}, {28, 63}, {28, 60}, {28, 57}, {28, 54}, {28, 52}, {27, 49}, {27, 47}, {27, 45}, - {27, 43}, {27, 41}, {27, 39}, {27, 37}, {27, 35}, {27, 33}, {27, 31}, {27, 30}, {27, 28}, {27, 26}, - {27, 25}, {27, 23}, {27, 22}, {27, 21}, {27, 19}, {27, 18}, {27, 17}, {27, 15}, {28, 14}, {28, 13}, - {28, 12}, {29, 10}, {29, 9}, {30, 8}, {31, 7}, {32, 6}, {34, 5}, {36, 4}, {41, 3}, {49, 2}, - {0, 0}, {294, 2}, {265, 3}, {251, 4}, {242, 5}, {237, 6}, {233, 7}, {231, 8}, {229, 9}, {228, 10}, - {227, 11}, {226, 11}, {226, 12}, {225, 13}, {225, 13}, {224, 14}, {224, 14}, {224, 15}, {224, 15}, {223, 16}, - {223, 16}, {223, 17}, {223, 17}, {223, 17}, {222, 18}, {222, 18}, {222, 19}, {222, 19}, {222, 19}, {222, 19}, - {222, 20}, {222, 20}, {222, 20}, {222, 21}, {222, 21} -}; - -/* step brightness table: gamma = 2.3 */ -static const uint8_t gamma_table[MAX_PROGRESS] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, - 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, - 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, - 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25, 25, 26, - 26, 27, 28, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, - 38, 39, 40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 81, 82, 83, 84, 86, - 87, 88, 89, 91, 92, 93, 95, 96, 97, 99, 100, 101, 103, 104, 105, 107, - 108, 110, 111, 112, 114, 115, 117, 118, 120, 121, 123, 124, 126, 128, 129, 131, - 132, 134, 135, 137, 139, 140, 142, 144, 145, 147, 149, 150, 152, 154, 156, 157, - 159, 161, 163, 164, 166, 168, 170, 172, 174, 175, 177, 179, 181, 183, 185, 187, - 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, - 221, 223, 226, 228, 230, 232, 234, 236, 239, 241, 243, 245, 248, 250, 252, 255, -}; - -BuiltInLED::BuiltInLED() { - pin_number = (uint8_t) -1; // no pin number - state = false; // LED is off - hsv_color.value = 0; // black color -} - -BuiltInLED::~BuiltInLED(){ - end(); -} - -led_indicator_color_hsv_t BuiltInLED::rgb2hsv(led_indicator_color_rgb_t rgb) { - led_indicator_color_hsv_t hsv; - uint8_t minRGB, maxRGB; - uint8_t delta; - - minRGB = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b); - maxRGB = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b); - hsv.value = 0; - hsv.v = maxRGB; - delta = maxRGB - minRGB; - - if (delta == 0) { - hsv.h = 0; - hsv.s = 0; - } else { - hsv.s = delta * 255 / maxRGB; - - if (rgb.r == maxRGB) { - hsv.h = (60 * (rgb.g - rgb.b) / delta + 360) % 360; - } else if (rgb.g == maxRGB) { - hsv.h = (60 * (rgb.b - rgb.r) / delta + 120); - } else { - hsv.h = (60 * (rgb.r - rgb.g) / delta + 240); - } - } - return hsv; -} - -led_indicator_color_rgb_t BuiltInLED::hsv2rgb(led_indicator_color_hsv_t hsv) { - led_indicator_color_rgb_t rgb; - uint8_t rgb_max = hsv.v; - uint8_t rgb_min = rgb_max * (255 - hsv.s) / 255.0f; - - uint8_t i = hsv.h / 60; - uint8_t diff = hsv.h % 60; - - // RGB adjustment amount by hue - uint8_t rgb_adj = (rgb_max - rgb_min) * diff / 60; - rgb.value = 0; - switch (i) { - case 0: - rgb.r = rgb_max; - rgb.g = rgb_min + rgb_adj; - rgb.b = rgb_min; - break; - case 1: - rgb.r = rgb_max - rgb_adj; - rgb.g = rgb_max; - rgb.b = rgb_min; - break; - case 2: - rgb.r = rgb_min; - rgb.g = rgb_max; - rgb.b = rgb_min + rgb_adj; - break; - case 3: - rgb.r = rgb_min; - rgb.g = rgb_max - rgb_adj; - rgb.b = rgb_max; - break; - case 4: - rgb.r = rgb_min + rgb_adj; - rgb.g = rgb_min; - rgb.b = rgb_max; - break; - default: - rgb.r = rgb_max; - rgb.g = rgb_min; - rgb.b = rgb_max - rgb_adj; - break; - } - - // gamma correction - rgb.r = gamma_table[rgb.r]; - rgb.g = gamma_table[rgb.g]; - rgb.b = gamma_table[rgb.b]; - return rgb; -} - -void BuiltInLED::begin(uint8_t pin){ - if (pin < NUM_DIGITAL_PINS) { - pin_number = pin; - write(); - } else { - log_e("Invalid pin (%d) number", pin); - } -} -void BuiltInLED::end(){ - state = false; - write(); - if (pin_number < NUM_DIGITAL_PINS) { - if (!rmtDeinit(pin_number)) { - log_e("Failed to deinitialize RMT"); - } - } -} - -void BuiltInLED::on(){ - state = true; -} - -void BuiltInLED::off(){ - state = false; -} - -void BuiltInLED::toggle(){ - state = !state; -} - -bool BuiltInLED::getState(){ - return state; -} - -bool BuiltInLED::write(){ - led_indicator_color_rgb_t rgb_color = getRGB(); - log_d("Writing to pin %d with state = %s", pin_number, state ? "ON" : "OFF"); - log_d("HSV: %d, %d, %d", hsv_color.h, hsv_color.s, hsv_color.v); - log_d("RGB: %d, %d, %d", rgb_color.r, rgb_color.g, rgb_color.b); - if(pin_number < NUM_DIGITAL_PINS){ - if (state) { - rgbLedWrite(pin_number, rgb_color.r, rgb_color.g, rgb_color.b); - } else { - rgbLedWrite(pin_number, 0, 0, 0); - } - return true; - } else { - log_e("Invalid pin (%d) number", pin_number); - return false; - } -} - -void BuiltInLED::setBrightness(uint8_t brightness){ - hsv_color.v = brightness; -} - -uint8_t BuiltInLED::getBrightness(){ - return hsv_color.v; -} - -void BuiltInLED::setHSV(led_indicator_color_hsv_t hsv){ - if (hsv.h > MAX_HUE) { - hsv.h = MAX_HUE; - } - hsv_color.value = hsv.value; -} - -led_indicator_color_hsv_t BuiltInLED::getHSV(){ - return hsv_color; -} - -void BuiltInLED::setRGB(led_indicator_color_rgb_t rgb_color){ - hsv_color = rgb2hsv(rgb_color); -} - -led_indicator_color_rgb_t BuiltInLED::getRGB(){ - return hsv2rgb(hsv_color); -} - -void BuiltInLED::setTemperature(uint32_t temperature){ - uint16_t hue; - uint8_t saturation; - - log_d("Requested Temperature: %ld", temperature); - //hsv_color.v = gamma_table[((temperature >> 25) & 0x7F)]; - temperature &= 0xFFFFFF; - if (temperature < 600) { - hue = 0; - saturation = 100; - } else { - if (temperature > 10000) { - hue = 222; - saturation = 21 + (temperature - 10000) * 41 / 990000; - } else { - temperature -= 600; - temperature /= 100; - hue = temperatureTable[temperature].hue; - saturation = temperatureTable[temperature].saturation; - } - } - saturation = (saturation * 255) / 100; - // brightness is not changed - hsv_color.h = hue; - hsv_color.s = saturation; - log_d("Calculated Temperature: %ld, Hue: %d, Saturation: %d, Brightness: %d", temperature, hue, saturation, hsv_color.v); -} - +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + This will implement the onboard WS2812b LED as a LED indicator + It can be used to indicate some state or status of the device + The LED can be controlled using RGB, HSV or color temperature, brightness + + In this example, the LED Indicator class is used as the Matter light accessory +*/ + +#include "builtinLED.h" + +typedef struct { + uint16_t hue; + uint8_t saturation; +} HS_color_t; + +static const HS_color_t temperatureTable[] = { + {4, 100}, {8, 100}, {11, 100}, {14, 100}, {16, 100}, {18, 100}, {20, 100}, {22, 100}, {24, 100}, {25, 100}, + {27, 100}, {28, 100}, {30, 100}, {31, 100}, {31, 95}, {30, 89}, {30, 85}, {29, 80}, {29, 76}, {29, 73}, + {29, 69}, {28, 66}, {28, 63}, {28, 60}, {28, 57}, {28, 54}, {28, 52}, {27, 49}, {27, 47}, {27, 45}, + {27, 43}, {27, 41}, {27, 39}, {27, 37}, {27, 35}, {27, 33}, {27, 31}, {27, 30}, {27, 28}, {27, 26}, + {27, 25}, {27, 23}, {27, 22}, {27, 21}, {27, 19}, {27, 18}, {27, 17}, {27, 15}, {28, 14}, {28, 13}, + {28, 12}, {29, 10}, {29, 9}, {30, 8}, {31, 7}, {32, 6}, {34, 5}, {36, 4}, {41, 3}, {49, 2}, + {0, 0}, {294, 2}, {265, 3}, {251, 4}, {242, 5}, {237, 6}, {233, 7}, {231, 8}, {229, 9}, {228, 10}, + {227, 11}, {226, 11}, {226, 12}, {225, 13}, {225, 13}, {224, 14}, {224, 14}, {224, 15}, {224, 15}, {223, 16}, + {223, 16}, {223, 17}, {223, 17}, {223, 17}, {222, 18}, {222, 18}, {222, 19}, {222, 19}, {222, 19}, {222, 19}, + {222, 20}, {222, 20}, {222, 20}, {222, 21}, {222, 21} +}; + +/* step brightness table: gamma = 2.3 */ +static const uint8_t gamma_table[MAX_PROGRESS] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, + 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, + 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, + 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25, 25, 26, + 26, 27, 28, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, + 38, 39, 40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 81, 82, 83, 84, 86, + 87, 88, 89, 91, 92, 93, 95, 96, 97, 99, 100, 101, 103, 104, 105, 107, + 108, 110, 111, 112, 114, 115, 117, 118, 120, 121, 123, 124, 126, 128, 129, 131, + 132, 134, 135, 137, 139, 140, 142, 144, 145, 147, 149, 150, 152, 154, 156, 157, + 159, 161, 163, 164, 166, 168, 170, 172, 174, 175, 177, 179, 181, 183, 185, 187, + 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, + 221, 223, 226, 228, 230, 232, 234, 236, 239, 241, 243, 245, 248, 250, 252, 255, +}; + +BuiltInLED::BuiltInLED() { + pin_number = (uint8_t) -1; // no pin number + state = false; // LED is off + hsv_color.value = 0; // black color +} + +BuiltInLED::~BuiltInLED(){ + end(); +} + +led_indicator_color_hsv_t BuiltInLED::rgb2hsv(led_indicator_color_rgb_t rgb) { + led_indicator_color_hsv_t hsv; + uint8_t minRGB, maxRGB; + uint8_t delta; + + minRGB = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b); + maxRGB = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b); + hsv.value = 0; + hsv.v = maxRGB; + delta = maxRGB - minRGB; + + if (delta == 0) { + hsv.h = 0; + hsv.s = 0; + } else { + hsv.s = delta * 255 / maxRGB; + + if (rgb.r == maxRGB) { + hsv.h = (60 * (rgb.g - rgb.b) / delta + 360) % 360; + } else if (rgb.g == maxRGB) { + hsv.h = (60 * (rgb.b - rgb.r) / delta + 120); + } else { + hsv.h = (60 * (rgb.r - rgb.g) / delta + 240); + } + } + return hsv; +} + +led_indicator_color_rgb_t BuiltInLED::hsv2rgb(led_indicator_color_hsv_t hsv) { + led_indicator_color_rgb_t rgb; + uint8_t rgb_max = hsv.v; + uint8_t rgb_min = rgb_max * (255 - hsv.s) / 255.0f; + + uint8_t i = hsv.h / 60; + uint8_t diff = hsv.h % 60; + + // RGB adjustment amount by hue + uint8_t rgb_adj = (rgb_max - rgb_min) * diff / 60; + rgb.value = 0; + switch (i) { + case 0: + rgb.r = rgb_max; + rgb.g = rgb_min + rgb_adj; + rgb.b = rgb_min; + break; + case 1: + rgb.r = rgb_max - rgb_adj; + rgb.g = rgb_max; + rgb.b = rgb_min; + break; + case 2: + rgb.r = rgb_min; + rgb.g = rgb_max; + rgb.b = rgb_min + rgb_adj; + break; + case 3: + rgb.r = rgb_min; + rgb.g = rgb_max - rgb_adj; + rgb.b = rgb_max; + break; + case 4: + rgb.r = rgb_min + rgb_adj; + rgb.g = rgb_min; + rgb.b = rgb_max; + break; + default: + rgb.r = rgb_max; + rgb.g = rgb_min; + rgb.b = rgb_max - rgb_adj; + break; + } + + // gamma correction + rgb.r = gamma_table[rgb.r]; + rgb.g = gamma_table[rgb.g]; + rgb.b = gamma_table[rgb.b]; + return rgb; +} + +void BuiltInLED::begin(uint8_t pin){ + if (pin < NUM_DIGITAL_PINS) { + pin_number = pin; + log_i("Initializing pin %d", pin); + } else { + log_e("Invalid pin (%d) number", pin); + } +} +void BuiltInLED::end(){ + state = false; + write(); // turn off the LED + if (pin_number < NUM_DIGITAL_PINS) { + if (!rmtDeinit(pin_number)) { + log_e("Failed to deinitialize RMT"); + } + } +} + +void BuiltInLED::on(){ + state = true; +} + +void BuiltInLED::off(){ + state = false; +} + +void BuiltInLED::toggle(){ + state = !state; +} + +bool BuiltInLED::getState(){ + return state; +} + +bool BuiltInLED::write(){ + led_indicator_color_rgb_t rgb_color = getRGB(); + log_d("Writing to pin %d with state = %s", pin_number, state ? "ON" : "OFF"); + log_d("HSV: %d, %d, %d", hsv_color.h, hsv_color.s, hsv_color.v); + log_d("RGB: %d, %d, %d", rgb_color.r, rgb_color.g, rgb_color.b); + if(pin_number < NUM_DIGITAL_PINS){ + if (state) { + rgbLedWrite(pin_number, rgb_color.r, rgb_color.g, rgb_color.b); + } else { + rgbLedWrite(pin_number, 0, 0, 0); + } + return true; + } else { + log_e("Invalid pin (%d) number", pin_number); + return false; + } +} + +void BuiltInLED::setBrightness(uint8_t brightness){ + hsv_color.v = brightness; +} + +uint8_t BuiltInLED::getBrightness(){ + return hsv_color.v; +} + +void BuiltInLED::setHSV(led_indicator_color_hsv_t hsv){ + if (hsv.h > MAX_HUE) { + hsv.h = MAX_HUE; + } + hsv_color.value = hsv.value; +} + +led_indicator_color_hsv_t BuiltInLED::getHSV(){ + return hsv_color; +} + +void BuiltInLED::setRGB(led_indicator_color_rgb_t rgb_color){ + hsv_color = rgb2hsv(rgb_color); +} + +led_indicator_color_rgb_t BuiltInLED::getRGB(){ + return hsv2rgb(hsv_color); +} + +void BuiltInLED::setTemperature(uint32_t temperature){ + uint16_t hue; + uint8_t saturation; + + log_d("Requested Temperature: %ld", temperature); + //hsv_color.v = gamma_table[((temperature >> 25) & 0x7F)]; + temperature &= 0xFFFFFF; + if (temperature < 600) { + hue = 0; + saturation = 100; + } else { + if (temperature > 10000) { + hue = 222; + saturation = 21 + (temperature - 10000) * 41 / 990000; + } else { + temperature -= 600; + temperature /= 100; + hue = temperatureTable[temperature].hue; + saturation = temperatureTable[temperature].saturation; + } + } + saturation = (saturation * 255) / 100; + // brightness is not changed + hsv_color.h = hue; + hsv_color.s = saturation; + log_d("Calculated Temperature: %ld, Hue: %d, Saturation: %d, Brightness: %d", temperature, hue, saturation, hsv_color.v); +} \ No newline at end of file diff --git a/examples/espidf-arduino-matter-light/main/builtinLED.h b/examples/espidf-arduino-matter-light/main/builtinLED.h index 85fc171..7a2f2ec 100644 --- a/examples/espidf-arduino-matter-light/main/builtinLED.h +++ b/examples/espidf-arduino-matter-light/main/builtinLED.h @@ -1,76 +1,74 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. - - This will implement the onboard WS2812b LED as a LED indicator - It can be used to indicate some state or status of the device - The LED can be controlled using RGB, HSV or color temperature, brightness - - In this example, the BuiltInLED class is used as the Matter light accessory -*/ - -#pragma once - -#include - -#define MAX_HUE 360 -#define MAX_SATURATION 255 -#define MAX_BRIGHTNESS 255 -#define MAX_PROGRESS 256 - -typedef struct { - union { - struct { - uint32_t v: 8; /*!< Brightness/Value of the LED. 0-255 */ - uint32_t s: 8; /*!< Saturation of the LED. 0-255 */ - uint32_t h: 9; /*!< Hue of the LED. 0-360 */ - }; - uint32_t value; /*!< IHSV value of the LED. */ - }; -} led_indicator_color_hsv_t; - -typedef struct { - union { - struct { - uint32_t r: 8; /*!< Red component of the LED color. Range: 0-255. */ - uint32_t g: 8; /*!< Green component of the LED color. Range: 0-255. */ - uint32_t b: 8; /*!< Blue component of the LED color. Range: 0-255. */ - }; - uint32_t value; /*!< Combined RGB value of the LED color. */ - }; -} led_indicator_color_rgb_t; - -class BuiltInLED { -private: - uint8_t pin_number; - bool state; - led_indicator_color_hsv_t hsv_color; - -public: - BuiltInLED(); - ~BuiltInLED(); - - static led_indicator_color_hsv_t rgb2hsv(led_indicator_color_rgb_t rgb_value); - static led_indicator_color_rgb_t hsv2rgb(led_indicator_color_hsv_t hsv); - - void begin(uint8_t pin); - void end(); - - void on(); - void off(); - void toggle(); - bool getState(); - - bool write(); - - void setBrightness(uint8_t brightness); - uint8_t getBrightness(); - void setHSV(led_indicator_color_hsv_t hsv); - led_indicator_color_hsv_t getHSV(); - void setRGB(led_indicator_color_rgb_t color); - led_indicator_color_rgb_t getRGB(); - void setTemperature(uint32_t temperature); -}; +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + This will implement the onboard WS2812b LED as a LED indicator + It can be used to indicate some state or status of the device + The LED can be controlled using RGB, HSV or color temperature, brightness + + In this example, the BuiltInLED class is used as the Matter light accessory +*/ + +#pragma once + +#include + +#define MAX_HUE 360 +#define MAX_SATURATION 255 +#define MAX_BRIGHTNESS 255 +#define MAX_PROGRESS 256 + +typedef struct { + union { + struct { + uint32_t v: 8; /*!< Brightness/Value of the LED. 0-255 */ + uint32_t s: 8; /*!< Saturation of the LED. 0-255 */ + uint32_t h: 9; /*!< Hue of the LED. 0-360 */ + }; + uint32_t value; /*!< IHSV value of the LED. */ + }; +} led_indicator_color_hsv_t; + +typedef struct { + union { + struct { + uint32_t r: 8; /*!< Red component of the LED color. Range: 0-255. */ + uint32_t g: 8; /*!< Green component of the LED color. Range: 0-255. */ + uint32_t b: 8; /*!< Blue component of the LED color. Range: 0-255. */ + }; + uint32_t value; /*!< Combined RGB value of the LED color. */ + }; +} led_indicator_color_rgb_t; + +class BuiltInLED { +private: + uint8_t pin_number; + bool state; + led_indicator_color_hsv_t hsv_color; + +public: + BuiltInLED(); + ~BuiltInLED(); + + static led_indicator_color_hsv_t rgb2hsv(led_indicator_color_rgb_t rgb_value); + static led_indicator_color_rgb_t hsv2rgb(led_indicator_color_hsv_t hsv); + + void begin(uint8_t pin); + void end(); + + void on(); + void off(); + void toggle(); + bool getState(); + + bool write(); + + void setBrightness(uint8_t brightness); + uint8_t getBrightness(); + void setHSV(led_indicator_color_hsv_t hsv); + led_indicator_color_hsv_t getHSV(); + void setRGB(led_indicator_color_rgb_t color); + led_indicator_color_rgb_t getRGB(); + void setTemperature(uint32_t temperature); +}; \ No newline at end of file diff --git a/examples/espidf-arduino-matter-light/main/matter_accessory_driver.cpp b/examples/espidf-arduino-matter-light/main/matter_accessory_driver.cpp index 9fe2b16..8e3cc7e 100644 --- a/examples/espidf-arduino-matter-light/main/matter_accessory_driver.cpp +++ b/examples/espidf-arduino-matter-light/main/matter_accessory_driver.cpp @@ -1,6 +1,5 @@ /* This example code is in the Public Domain (or CC0 licensed, at your option.) - Unless required by applicable law or agreed to in writing, this software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -11,9 +10,6 @@ #include "builtinLED.h" #include "matter_accessory_driver.h" -// set your board WS2812b pin here (e.g. 48 is the default pin for the ESP32-S3 devkit) -#define WS2812_PIN 48 - /* Do any conversions/remapping for the actual value here */ esp_err_t light_accessory_set_power(void *led, uint8_t val) { @@ -95,7 +91,5 @@ app_driver_handle_t light_accessory_init() const uint8_t pin = WS2812_PIN; // set your board WS2812b pin here builtinLED.begin(pin); - builtinLED.setHSV({DEFAULT_HUE, DEFAULT_SATURATION, DEFAULT_BRIGHTNESS}); - builtinLED.write(); return (app_driver_handle_t) &builtinLED; } diff --git a/examples/espidf-arduino-matter-light/main/matter_accessory_driver.h b/examples/espidf-arduino-matter-light/main/matter_accessory_driver.h index b3b6692..8d816c7 100644 --- a/examples/espidf-arduino-matter-light/main/matter_accessory_driver.h +++ b/examples/espidf-arduino-matter-light/main/matter_accessory_driver.h @@ -1,28 +1,47 @@ -#include - -/** Standard max values (used for remapping attributes) */ -#define STANDARD_BRIGHTNESS 255 -#define STANDARD_HUE 360 -#define STANDARD_SATURATION 255 -#define STANDARD_TEMPERATURE_FACTOR 1000000 - -/** Matter max values (used for remapping attributes) */ -#define MATTER_BRIGHTNESS 254 -#define MATTER_HUE 254 -#define MATTER_SATURATION 254 -#define MATTER_TEMPERATURE_FACTOR 1000000 - -/** Default attribute values used during initialization */ -#define DEFAULT_POWER true -#define DEFAULT_BRIGHTNESS 64 -#define DEFAULT_HUE 128 -#define DEFAULT_SATURATION 254 - -typedef void *app_driver_handle_t; - -esp_err_t light_accessory_set_power(void *led, uint8_t val); -esp_err_t light_accessory_set_brightness(void *led, uint8_t val); -esp_err_t light_accessory_set_hue(void *led, uint8_t val); -esp_err_t light_accessory_set_saturation(void *led, uint8_t val); -esp_err_t light_accessory_set_temperature(void *led, uint16_t val); -app_driver_handle_t light_accessory_init(); +#include +#include + +// set your board WS2812b pin here (e.g. 48 is the default pin for the ESP32-S3 devkit) +#ifndef CONFIG_WS2812_PIN +#define WS2812_PIN 48 // ESP32-S3 DevKitC built-in LED +#else +#define WS2812_PIN CONFIG_WS2812_PIN // From sdkconfig.defaults. +#endif + +#ifndef RGB_BUILTIN +#define RGB_BUILTIN WS2812_PIN +#endif + +// Set your board button pin here (e.g. 0 is the default pin for the ESP32-S3 devkit) +#ifndef CONFIG_BUTTON_PIN +#define BUTTON_PIN 0 // ESP32-S3 DevKitC built-in button +#else +#define BUTTON_PIN CONFIG_BUTTON_PIN // From sdkconfig.defaults. +#endif + +/** Standard max values (used for remapping attributes) */ +#define STANDARD_BRIGHTNESS 255 +#define STANDARD_HUE 360 +#define STANDARD_SATURATION 255 +#define STANDARD_TEMPERATURE_FACTOR 1000000 + +/** Matter max values (used for remapping attributes) */ +#define MATTER_BRIGHTNESS 254 +#define MATTER_HUE 254 +#define MATTER_SATURATION 254 +#define MATTER_TEMPERATURE_FACTOR 1000000 + +/** Default attribute values used during initialization */ +#define DEFAULT_POWER true +#define DEFAULT_BRIGHTNESS 64 +#define DEFAULT_HUE 128 +#define DEFAULT_SATURATION 254 + +typedef void *app_driver_handle_t; + +esp_err_t light_accessory_set_power(void *led, uint8_t val); +esp_err_t light_accessory_set_brightness(void *led, uint8_t val); +esp_err_t light_accessory_set_hue(void *led, uint8_t val); +esp_err_t light_accessory_set_saturation(void *led, uint8_t val); +esp_err_t light_accessory_set_temperature(void *led, uint16_t val); +app_driver_handle_t light_accessory_init(); \ No newline at end of file diff --git a/examples/espidf-arduino-matter-light/main/matter_light.cpp b/examples/espidf-arduino-matter-light/main/matter_light.cpp index 76d5cfe..5f3898e 100644 --- a/examples/espidf-arduino-matter-light/main/matter_light.cpp +++ b/examples/espidf-arduino-matter-light/main/matter_light.cpp @@ -1,6 +1,5 @@ /* This example code is in the Public Domain (or CC0 licensed, at your option.) - Unless required by applicable law or agreed to in writing, this software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -37,6 +36,9 @@ } #endif +// set your board button pin here +const uint8_t button_gpio = BUTTON_PIN; // GPIO BOOT Button + uint16_t light_endpoint_id = 0; using namespace esp_matter; @@ -54,11 +56,29 @@ static const char *s_decryption_key = decryption_key_start; static const uint16_t s_decryption_key_len = decryption_key_end - decryption_key_start; #endif // CONFIG_ENABLE_ENCRYPTED_OTA +bool isAccessoryCommissioned() { + return chip::Server::GetInstance().GetFabricTable().FabricCount() > 0; +} + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION +bool isWifiConnected() { + return chip::DeviceLayer::ConnectivityMgr().IsWiFiStationConnected(); +} +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +bool isThreadConnected() { + return chip::DeviceLayer::ConnectivityMgr().IsThreadAttached(); +} +#endif + static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) { switch (event->Type) { case chip::DeviceLayer::DeviceEventType::kInterfaceIpAddressChanged: - log_i("Interface IP Address changed"); + log_i("Interface %s Address changed", + event->InterfaceIpAddressChanged.Type == chip::DeviceLayer::InterfaceIpChangeType::kIpV4_Assigned ? + "IPv4" : "IPV6" ); break; case chip::DeviceLayer::DeviceEventType::kCommissioningComplete: @@ -129,40 +149,6 @@ static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) } } -static uint32_t button_time_stamp = 0; -static void button_driver_down_cb() -{ - button_time_stamp = millis(); -} - - -static void button_driver_up_cb() -{ - uint32_t time_diff = millis() - button_time_stamp; - // Factory reset is triggered if the button is pressed for more than 3 seconds - if (time_diff > 3000) { - log_i("Factory reset triggered. Light will retored to factory settings."); - esp_matter::factory_reset(); - return; - } - - // Toggle button is pressed - toggle the light - log_i("Toggle button pressed"); - uint16_t endpoint_id = light_endpoint_id; - uint32_t cluster_id = OnOff::Id; - uint32_t attribute_id = OnOff::Attributes::OnOff::Id; - - node_t *node = node::get(); - endpoint_t *endpoint = endpoint::get(node, endpoint_id); - cluster_t *cluster = cluster::get(endpoint, cluster_id); - attribute_t *attribute = attribute::get(cluster, attribute_id); - - esp_matter_attr_val_t val = esp_matter_invalid(NULL); - attribute::get_val(attribute, &val); - val.val.b = !val.val.b; - attribute::update(endpoint_id, cluster_id, attribute_id, &val); -} - 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) { @@ -241,10 +227,7 @@ esp_err_t matter_light_set_defaults(uint16_t endpoint_id) void button_driver_init() { /* Initialize button */ - uint8_t pin = 0; // set your board button pin here - pinMode(pin, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(pin), button_driver_down_cb, FALLING); // pressed - attachInterrupt(digitalPinToInterrupt(pin), button_driver_up_cb, RISING); // released + pinMode(button_gpio, INPUT_PULLUP); } // This callback is called for every attribute update. The callback implementation shall @@ -277,9 +260,6 @@ void setup() { esp_err_t err = ESP_OK; - /* Initialize the ESP NVS layer */ - //nvs_flash_init(); - /* Initialize driver */ app_driver_handle_t light_handle = light_accessory_init(); button_driver_init(); @@ -309,7 +289,7 @@ void setup() log_e("Failed to create extended color light endpoint"); abort(); } - + light_endpoint_id = endpoint::get_id(endpoint); log_i("Light created with endpoint_id %d", light_endpoint_id); @@ -343,9 +323,6 @@ void setup() abort(); } - /* Starting driver with default values */ - matter_light_set_defaults(light_endpoint_id); - #if CONFIG_ENABLE_ENCRYPTED_OTA err = esp_matter_ota_requestor_encrypted_init(s_decryption_key, s_decryption_key_len); if (err != ESP_OK) { @@ -365,5 +342,80 @@ void setup() } void loop() { - delay(1000); + static uint32_t button_time_stamp = 0; + static bool button_state = false; + static bool started = false; + + if(!isAccessoryCommissioned()) { + log_w("Accessory not commissioned yet. Waiting for commissioning."); +#ifdef RGB_BUILTIN + rgbLedWrite(RGB_BUILTIN, 48, 0, 20); // Purple indicates accessory not commissioned +#endif + delay(5000); + return; + } + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION + if (!isWifiConnected()) { + log_w("Wi-Fi not connected yet. Waiting for connection."); +#ifdef RGB_BUILTIN + rgbLedWrite(RGB_BUILTIN, 48, 20, 0); // Orange indicates accessory not connected to Wi-Fi +#endif + delay(5000); + return; + } +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + if (!isThreadConnected()) { + log_w("Thread not connected yet. Waiting for connection."); +#ifdef RGB_BUILTIN + rgbLedWrite(RGB_BUILTIN, 0, 20, 48); // Blue indicates accessory not connected to Trhead +#endif + delay(5000); + return; + } +#endif + + // Once all network connections are established, the accessory is ready for use + // Run it only once + if (!started) { + log_i("Accessory is commissioned and connected to Wi-Fi. Ready for use."); + started = true; + // Starting driver with default values + matter_light_set_defaults(light_endpoint_id); + } + + // Check if the button is pressed and toggle the light right away + if (digitalRead(button_gpio) == LOW && !button_state) { + // deals with button debounce + button_time_stamp = millis(); // record the time while the button is pressed. + button_state = true; // pressed. + + // Toggle button is pressed - toggle the light + log_i("Toggle button pressed"); + + endpoint_t *endpoint = endpoint::get(node::get(), light_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); + val.val.b = !val.val.b; + attribute::update(light_endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, &val); + } + + // Check if the button is released and handle the factory reset + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > 100 && digitalRead(button_gpio) == HIGH) { + button_state = false; // released. It can be pressed again after 100ms debounce. + + // Factory reset is triggered if the button is pressed for more than 10 seconds + if (time_diff > 10000) { + log_i("Factory reset triggered. Light will retored to factory settings."); + esp_matter::factory_reset(); + } + } + + delay(50); // WDT is happier with a delay } diff --git a/examples/espidf-arduino-matter-light/partitions.csv b/examples/espidf-arduino-matter-light/partitions.csv index f0992fa..ffe5f24 100644 --- a/examples/espidf-arduino-matter-light/partitions.csv +++ b/examples/espidf-arduino-matter-light/partitions.csv @@ -1,4 +1,5 @@ # Name, Type, SubType, Offset, Size, Flags +# Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted nvs, data, nvs, 0x10000, 0xC000, nvs_keys, data, nvs_keys,, 0x1000, encrypted diff --git a/examples/espidf-arduino-matter-light/platformio.ini b/examples/espidf-arduino-matter-light/platformio.ini index 25874c6..2434a84 100644 --- a/examples/espidf-arduino-matter-light/platformio.ini +++ b/examples/espidf-arduino-matter-light/platformio.ini @@ -7,6 +7,8 @@ ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html + + [platformio] src_dir = main diff --git a/examples/espidf-arduino-matter-light/sdkconfig.defaults.c6_thread b/examples/espidf-arduino-matter-light/sdkconfig.defaults.c6_thread new file mode 100644 index 0000000..389c72c --- /dev/null +++ b/examples/espidf-arduino-matter-light/sdkconfig.defaults.c6_thread @@ -0,0 +1,80 @@ +CONFIG_IDF_TARGET="esp32c6" + +# Arduino Settings +CONFIG_FREERTOS_HZ=1000 +CONFIG_AUTOSTART_ARDUINO=y + +# Log Levels +# Boot Messages - Log level +CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y +# Arduino Log Level +CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO=y +# IDF Log Level +CONFIG_LOG_DEFAULT_LEVEL_ERROR=y + +# Default to 921600 baud when flashing and monitoring device +CONFIG_ESPTOOLPY_BAUD_921600B=y +CONFIG_ESPTOOLPY_BAUD=921600 +CONFIG_ESPTOOLPY_COMPRESSED=y +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y + +# libsodium +CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y + +# NIMBLE +CONFIG_BT_ENABLED=y +CONFIG_BT_NIMBLE_ENABLED=y +CONFIG_BT_NIMBLE_EXT_ADV=n +CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70 +CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=n + +# FreeRTOS should use legacy API +CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY=y + +# Enable OpenThread +CONFIG_OPENTHREAD_ENABLED=y +CONFIG_OPENTHREAD_SRP_CLIENT=y +CONFIG_OPENTHREAD_DNS_CLIENT=y +CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n +CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y +CONFIG_OPENTHREAD_CLI=n + +# Disable lwip ipv6 autoconfig +CONFIG_LWIP_IPV6_AUTOCONFIG=n + +# Use a custom partition table +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" + +# LwIP config for OpenThread +CONFIG_LWIP_IPV6_NUM_ADDRESSES=8 +CONFIG_LWIP_MULTICAST_PING=y + +# MDNS platform +CONFIG_USE_MINIMAL_MDNS=n +CONFIG_ENABLE_EXTENDED_DISCOVERY=y + +# Enable OTA Requestor +CONFIG_ENABLE_OTA_REQUESTOR=n + +# Disable STA and AP for ESP32C6 +CONFIG_ENABLE_WIFI_STATION=n +CONFIG_ENABLE_WIFI_AP=n + +# Enable chip shell +CONFIG_ENABLE_CHIP_SHELL=n + +# Disable persist subscriptions +CONFIG_ENABLE_PERSIST_SUBSCRIPTIONS=n + +# MRP configs +CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL_FOR_THREAD=5000 +CONFIG_MRP_LOCAL_IDLE_RETRY_INTERVAL_FOR_THREAD=5000 +CONFIG_MRP_RETRY_INTERVAL_SENDER_BOOST_FOR_THREAD=5000 +CONFIG_MRP_MAX_RETRANS=3 + +# Enable HKDF in mbedtls +CONFIG_MBEDTLS_HKDF_C=y + diff --git a/examples/espidf-arduino-matter-light/sdkconfig.defaults.esp32c3 b/examples/espidf-arduino-matter-light/sdkconfig.defaults.esp32c3 new file mode 100644 index 0000000..f534f3b --- /dev/null +++ b/examples/espidf-arduino-matter-light/sdkconfig.defaults.esp32c3 @@ -0,0 +1,64 @@ +CONFIG_IDF_TARGET="esp32c3" + +# Arduino Settings +CONFIG_FREERTOS_HZ=1000 +CONFIG_AUTOSTART_ARDUINO=y + +# Log Levels +# Boot Messages - Log level +CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y +# Arduino Log Level +CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO=y +# IDF Log Level +CONFIG_LOG_DEFAULT_LEVEL_ERROR=y + +# Default to 921600 baud when flashing and monitoring device +CONFIG_ESPTOOLPY_BAUD_921600B=y +CONFIG_ESPTOOLPY_BAUD=921600 +CONFIG_ESPTOOLPY_COMPRESSED=y +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y + +#enable BT +CONFIG_BT_ENABLED=y +CONFIG_BT_NIMBLE_ENABLED=y + +#disable BT connection reattempt +CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n + +#enable lwip ipv6 autoconfig +CONFIG_LWIP_IPV6_AUTOCONFIG=y + +# Use a custom partition table +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0xC000 + +# Disable chip shell +CONFIG_ENABLE_CHIP_SHELL=n + +# Enable OTA Requestor +CONFIG_ENABLE_OTA_REQUESTOR=n + +#enable lwIP route hooks +CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y +CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y + +# disable softap by default +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n +CONFIG_ENABLE_WIFI_STATION=y +CONFIG_ENABLE_WIFI_AP=n + +# Disable DS Peripheral +CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n + +# Use compact attribute storage mode +CONFIG_ESP_MATTER_NVS_USE_COMPACT_ATTR_STORAGE=y + +# Enable HKDF in mbedtls +CONFIG_MBEDTLS_HKDF_C=y + +# Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1) +# unique local addresses for fabrics(MAX_FABRIC), a link local address(1) +CONFIG_LWIP_IPV6_NUM_ADDRESSES=6 diff --git a/examples/espidf-arduino-matter-light/sdkconfig.defaults.esp32c6 b/examples/espidf-arduino-matter-light/sdkconfig.defaults.esp32c6 new file mode 100644 index 0000000..301ee1a --- /dev/null +++ b/examples/espidf-arduino-matter-light/sdkconfig.defaults.esp32c6 @@ -0,0 +1,79 @@ +CONFIG_IDF_TARGET="esp32c6" + +# Arduino Settings +CONFIG_FREERTOS_HZ=1000 +CONFIG_AUTOSTART_ARDUINO=y + +# Log Levels +# Boot Messages - Log level +CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y +# Arduino Log Level +CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO=y +# IDF Log Level +CONFIG_LOG_DEFAULT_LEVEL_ERROR=y + +# Default to 921600 baud when flashing and monitoring device +CONFIG_ESPTOOLPY_BAUD_921600B=y +CONFIG_ESPTOOLPY_BAUD=921600 +CONFIG_ESPTOOLPY_COMPRESSED=y +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y + +#enable BT +CONFIG_BT_ENABLED=y +CONFIG_BT_NIMBLE_ENABLED=y + +#disable BT connection reattempt +CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n + +#enable lwip ipv6 autoconfig +CONFIG_LWIP_IPV6_AUTOCONFIG=y + +# Use a custom partition table +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0xC000 + +# Disable chip shell +CONFIG_ENABLE_CHIP_SHELL=n + +# Enable OTA Requestor +CONFIG_ENABLE_OTA_REQUESTOR=n + +#enable lwIP route hooks +CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y +CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y + +# disable softap by default +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n +CONFIG_ENABLE_WIFI_STATION=y +CONFIG_ENABLE_WIFI_AP=n + +# Disable DS Peripheral +CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n + +# Use compact attribute storage mode +CONFIG_ESP_MATTER_NVS_USE_COMPACT_ATTR_STORAGE=y + +# Enable HKDF in mbedtls +CONFIG_MBEDTLS_HKDF_C=y + +# Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1) +# unique local addresses for fabrics(MAX_FABRIC), a link local address(1) +CONFIG_LWIP_IPV6_NUM_ADDRESSES=6 + +# libsodium +CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y + +# NIMBLE +CONFIG_BT_NIMBLE_EXT_ADV=n +CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70 +CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=y + +# FreeRTOS should use legacy API +CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY=y + +# Use minimal mDNS +CONFIG_USE_MINIMAL_MDNS=y +CONFIG_ENABLE_EXTENDED_DISCOVERY=y diff --git a/examples/espidf-arduino-matter-light/sdkconfig.defaults.esp32s3 b/examples/espidf-arduino-matter-light/sdkconfig.defaults.esp32s3 new file mode 100644 index 0000000..c7ecfa7 --- /dev/null +++ b/examples/espidf-arduino-matter-light/sdkconfig.defaults.esp32s3 @@ -0,0 +1,64 @@ +CONFIG_IDF_TARGET="esp32s3" + +# Arduino Settings +CONFIG_FREERTOS_HZ=1000 +CONFIG_AUTOSTART_ARDUINO=y + +# Log Levels +# Boot Messages - Log level +CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y +# Arduino Log Level +CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO=y +# IDF Log Level +CONFIG_LOG_DEFAULT_LEVEL_ERROR=y + +# Default to 921600 baud when flashing and monitoring device +CONFIG_ESPTOOLPY_BAUD_921600B=y +CONFIG_ESPTOOLPY_BAUD=921600 +CONFIG_ESPTOOLPY_COMPRESSED=y +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y + +#enable BT +CONFIG_BT_ENABLED=y +CONFIG_BT_NIMBLE_ENABLED=y + +#disable BT connection reattempt +CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n + +#enable lwip ipv6 autoconfig +CONFIG_LWIP_IPV6_AUTOCONFIG=y + +# Use a custom partition table +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0xC000 + +# Disable chip shell +CONFIG_ENABLE_CHIP_SHELL=n + +# Enable OTA Requestor +CONFIG_ENABLE_OTA_REQUESTOR=n + +#enable lwIP route hooks +CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y +CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y + +# disable softap by default +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n +CONFIG_ENABLE_WIFI_STATION=y +CONFIG_ENABLE_WIFI_AP=n + +# Disable DS Peripheral +CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n + +# Use compact attribute storage mode +CONFIG_ESP_MATTER_NVS_USE_COMPACT_ATTR_STORAGE=y + +# Enable HKDF in mbedtls +CONFIG_MBEDTLS_HKDF_C=y + +# Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1) +# unique local addresses for fabrics(MAX_FABRIC), a link local address(1) +CONFIG_LWIP_IPV6_NUM_ADDRESSES=6 From e0b31f6a411a6d11f17b31c4e1c349735321b2cd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 17 Sep 2024 17:39:28 +0200 Subject: [PATCH 057/117] add zigbee examples --- .github/workflows/examples.yml | 2 + examples/arduino-zigbee-light/README.md | 65 ++++++ examples/arduino-zigbee-light/include/README | 39 ++++ examples/arduino-zigbee-light/lib/README | 46 ++++ examples/arduino-zigbee-light/platformio.ini | 20 ++ .../src/Zigbee_On_Off_Light.ino | 89 ++++++++ examples/arduino-zigbee-light/test/README | 11 + examples/arduino-zigbee-switch/README.md | 65 ++++++ examples/arduino-zigbee-switch/include/README | 39 ++++ examples/arduino-zigbee-switch/lib/README | 46 ++++ examples/arduino-zigbee-switch/platformio.ini | 20 ++ .../src/Zigbee_On_Off_Switch.ino | 197 ++++++++++++++++++ examples/arduino-zigbee-switch/test/README | 11 + 13 files changed, 650 insertions(+) create mode 100644 examples/arduino-zigbee-light/README.md create mode 100644 examples/arduino-zigbee-light/include/README create mode 100644 examples/arduino-zigbee-light/lib/README create mode 100644 examples/arduino-zigbee-light/platformio.ini create mode 100644 examples/arduino-zigbee-light/src/Zigbee_On_Off_Light.ino create mode 100644 examples/arduino-zigbee-light/test/README create mode 100644 examples/arduino-zigbee-switch/README.md create mode 100644 examples/arduino-zigbee-switch/include/README create mode 100644 examples/arduino-zigbee-switch/lib/README create mode 100644 examples/arduino-zigbee-switch/platformio.ini create mode 100644 examples/arduino-zigbee-switch/src/Zigbee_On_Off_Switch.ino create mode 100644 examples/arduino-zigbee-switch/test/README diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index f7f6424..c26cd0f 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -18,6 +18,8 @@ jobs: - "examples/arduino-rmt-blink" - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" + - "examples/arduino-zigbee-light" + - "examples/arduino-zigbee-switch" - "examples/espidf-arduino-h2zero-BLE_scan" #- "examples/espidf-arduino-matter-light" # Windows compile fails -> Path length limit - "examples/espidf-arduino-blink" diff --git a/examples/arduino-zigbee-light/README.md b/examples/arduino-zigbee-light/README.md new file mode 100644 index 0000000..1b9d972 --- /dev/null +++ b/examples/arduino-zigbee-light/README.md @@ -0,0 +1,65 @@ +# Arduino-ESP32 Zigbee On/Off Light Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) on/off light. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with Zigbee_On_Off_switch example) +* A USB cable for power supply and programming +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device and upload the Zigbee_On_Off_Light example + +### Configure the Project + +Set the LED GPIO by changing the `LED_PIN` definition. By default, the LED_PIN is `RGB_BUILTIN`. +By default, the `neoPixelWrite` function is used to control the LED. You can change it to digitalWrite to control a simple LED. + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the End device Zigbee mode: `Tools -> Zigbee mode: Zigbee ED (end device)` +* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash before flashing it to the board. It is recommended to do this if you did changes to the coordinator. +You can do the following: + +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled` +* In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. + +By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. +You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +* **LED not blinking:** Check the wiring connection and the IO selection. +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) +* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/examples/arduino-zigbee-light/include/README b/examples/arduino-zigbee-light/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/examples/arduino-zigbee-light/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/arduino-zigbee-light/lib/README b/examples/arduino-zigbee-light/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/examples/arduino-zigbee-light/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/arduino-zigbee-light/platformio.ini b/examples/arduino-zigbee-light/platformio.ini new file mode 100644 index 0000000..50c013d --- /dev/null +++ b/examples/arduino-zigbee-light/platformio.ini @@ -0,0 +1,20 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter, extra scripting +; Upload options: custom port, speed and extra flags +; Library options: dependencies, extra library storages +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/page/projectconf.html + + +[env:esp32-h2-devkitm-1] +platform = https://github.com/pioarduino/platform-espressif32.git#develop +framework = arduino +board = esp32-h2-devkitm-1 +monitor_speed = 115200 +board_build.partitions = zigbee.csv +board_build.filesystem = spiffs +build_flags = + -DZIGBEE_MODE_ED + -DCORE_DEBUG_LEVEL=5 diff --git a/examples/arduino-zigbee-light/src/Zigbee_On_Off_Light.ino b/examples/arduino-zigbee-light/src/Zigbee_On_Off_Light.ino new file mode 100644 index 0000000..db22c3d --- /dev/null +++ b/examples/arduino-zigbee-light/src/Zigbee_On_Off_Light.ino @@ -0,0 +1,89 @@ +// 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. + +/** + * @brief This example demonstrates simple Zigbee light bulb. + * + * The example demonstrates how to use Zigbee library to create a end device light bulb. + * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. + * + * Proper Zigbee mode must be selected in Tools->Zigbee mode + * and also the correct partition scheme must be selected in Tools->Partition Scheme. + * + * Please check the README.md for instructions and more detailed description. + * + * Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/) + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "ZigbeeCore.h" +#include "ep/ZigbeeLight.h" + +#define LED_PIN RGB_BUILTIN +#define BUTTON_PIN 9 // C6/H2 Boot button +#define ZIGBEE_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ + +class MyZigbeeLight : public ZigbeeLight { +public: + // Constructor that passes parameters to the base class constructor + MyZigbeeLight(uint8_t endpoint) : ZigbeeLight(endpoint) {} + + // Override the set_on_off function + void setOnOff(bool value) override { + rgbLedWrite(LED_PIN, 255 * value, 255 * value, 255 * value); // Toggle light + } +}; + +MyZigbeeLight zbLight = MyZigbeeLight(ZIGBEE_LIGHT_ENDPOINT); + +/********************* Arduino functions **************************/ +void setup() { + // Init RMT and leave light OFF + rgbLedWrite(LED_PIN, 0, 0, 0); + + // Init button for factory reset + pinMode(BUTTON_PIN, INPUT); + + //Optional: set Zigbee device name and model + zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb"); + + //Add endpoint to Zigbee Core + log_d("Adding ZigbeeLight endpoint to Zigbee Core"); + Zigbee.addEndpoint(&zbLight); + + // When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE + log_d("Calling Zigbee.begin()"); + Zigbee.begin(); +} + +void loop() { + // Cheking button for factory reset + if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(BUTTON_PIN) == LOW) { + delay(50); + if((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.printf("Reseting Zigbee to factory settings, reboot.\n"); + Zigbee.factoryReset(); + } + } + } + delay(100); +} \ No newline at end of file diff --git a/examples/arduino-zigbee-light/test/README b/examples/arduino-zigbee-light/test/README new file mode 100644 index 0000000..df5066e --- /dev/null +++ b/examples/arduino-zigbee-light/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/examples/arduino-zigbee-switch/README.md b/examples/arduino-zigbee-switch/README.md new file mode 100644 index 0000000..90a95c3 --- /dev/null +++ b/examples/arduino-zigbee-switch/README.md @@ -0,0 +1,65 @@ +# Arduino-ESP32 Zigbee On/Off Light Switch Example + +This example shows how to configure Zigbee Coordinator and use it as a Home Automation (HA) on/off light switch. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee end device (loaded with Zigbee_On_Off_Light example). +* A USB cable for power supply and programming. +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee coordinator and upload the Zigbee_On_Off_Switch example. + +### Configure the Project + +Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, it's the pin `9` (BOOT button on ESP32-C6 and ESP32-H2). + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator/router)`. +* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs`. +* Select the COM port: `Tools -> Port: xxx where the `xxx` is the detected COM port. +* Optional: Set debug level to info to see logs from Zigbee stack: `Tools -> Core Debug Level: Info`. + +## Troubleshooting + +If the End device flashed with the example `Zigbee_Light_Bulb` is not connecting to the coordinator, erase the flash of the End device before flashing the example to the board. It is recommended to do this if you re-flash the coordinator. +You can do the following: + +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. +* In the `Zigbee_Light_Bulb` example sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. + +By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. +You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +* **LED not blinking:** Check the wiring connection and the IO selection. +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) +* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/examples/arduino-zigbee-switch/include/README b/examples/arduino-zigbee-switch/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/examples/arduino-zigbee-switch/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/arduino-zigbee-switch/lib/README b/examples/arduino-zigbee-switch/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/examples/arduino-zigbee-switch/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/arduino-zigbee-switch/platformio.ini b/examples/arduino-zigbee-switch/platformio.ini new file mode 100644 index 0000000..1ee3bee --- /dev/null +++ b/examples/arduino-zigbee-switch/platformio.ini @@ -0,0 +1,20 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter, extra scripting +; Upload options: custom port, speed and extra flags +; Library options: dependencies, extra library storages +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/page/projectconf.html + + +[env:esp32-c6-devkitc-1] +platform = https://github.com/pioarduino/platform-espressif32.git#develop +framework = arduino +board = esp32-c6-devkitc-1 +monitor_speed = 115200 +board_build.partitions = zigbee_zczr.csv +board_build.filesystem = spiffs +build_flags = + -DZIGBEE_MODE_ZCZR + -DCORE_DEBUG_LEVEL=5 diff --git a/examples/arduino-zigbee-switch/src/Zigbee_On_Off_Switch.ino b/examples/arduino-zigbee-switch/src/Zigbee_On_Off_Switch.ino new file mode 100644 index 0000000..27896f1 --- /dev/null +++ b/examples/arduino-zigbee-switch/src/Zigbee_On_Off_Switch.ino @@ -0,0 +1,197 @@ +// 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. + +/** + * @brief This example demonstrates simple Zigbee light switch. + * + * The example demonstrates how to use Zigbee library to control a light bulb. + * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator (Switch). + * Button switch and Zigbee runs in separate tasks. + * + * Proper Zigbee mode must be selected in Tools->Zigbee mode + * and also the correct partition scheme must be selected in Tools->Partition Scheme. + * + * Please check the README.md for instructions and more detailed description. + * + * Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/) + */ + +#ifndef ZIGBEE_MODE_ZCZR +#error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" +#endif + +#include "ZigbeeCore.h" +#include "ep/ZigbeeSwitch.h" + +#define SWITCH_ENDPOINT_NUMBER 5 + +/* Switch configuration */ +#define GPIO_INPUT_IO_TOGGLE_SWITCH 9 +#define PAIR_SIZE(TYPE_STR_PAIR) (sizeof(TYPE_STR_PAIR) / sizeof(TYPE_STR_PAIR[0])) + +typedef enum { + SWITCH_ON_CONTROL, + SWITCH_OFF_CONTROL, + SWITCH_ONOFF_TOGGLE_CONTROL, + SWITCH_LEVEL_UP_CONTROL, + SWITCH_LEVEL_DOWN_CONTROL, + SWITCH_LEVEL_CYCLE_CONTROL, + SWITCH_COLOR_CONTROL, +} SwitchFunction; + +typedef struct { + uint8_t pin; + SwitchFunction func; +} SwitchData; + +typedef enum { + SWITCH_IDLE, + SWITCH_PRESS_ARMED, + SWITCH_PRESS_DETECTED, + SWITCH_PRESSED, + SWITCH_RELEASE_DETECTED, +} SwitchState; + +static SwitchData buttonFunctionPair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; + +/* Zigbee switch */ +class MyZigbeeSwitch : public ZigbeeSwitch { +public: + // Constructor that passes parameters to the base class constructor + MyZigbeeSwitch(uint8_t endpoint) : ZigbeeSwitch(endpoint) {} + + // Override the set_on_off function + void readManufacturer(char* manufacturer) override { + //Do what you want with the manufacturer string + Serial.printf("Manufacturer: %s\n", manufacturer); + } + void readModel(char* model) override { + //Do what you want with the model string + Serial.printf("Model: %s\n", model); + } +}; + +MyZigbeeSwitch zbSwitch = MyZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); + +/********************* Zigbee functions **************************/ +static void onZbButton(SwitchData *button_func_pair) { + if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { + // Send toggle command to the light + zbSwitch.lightToggle(); + } +} + +/********************* GPIO functions **************************/ +static QueueHandle_t gpio_evt_queue = NULL; + +static void IRAM_ATTR onGpioInterrupt(void *arg) { + xQueueSendFromISR(gpio_evt_queue, (SwitchData *)arg, NULL); +} + +static void enableGpioInterrupt(bool enabled) { + for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); ++i) { + if (enabled) { + enableInterrupt((buttonFunctionPair[i]).pin); + } else { + disableInterrupt((buttonFunctionPair[i]).pin); + } + } +} + +/********************* Arduino functions **************************/ +void setup() { + + Serial.begin(115200); + + //Optional: set Zigbee device name and model + zbSwitch.setManufacturerAndModel("Espressif", "ZigbeeSwitch"); + + //Optional to allow multiple light to bind to the switch + zbSwitch.allowMultipleBinding(true); + + //Add endpoint to Zigbee Core + log_d("Adding ZigbeeSwitch endpoint to Zigbee Core"); + Zigbee.addEndpoint(&zbSwitch); + + //Open network for 180 seconds after boot + Zigbee.setRebootOpenNetwork(180); + + + // Init button switch + for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); i++) { + pinMode(buttonFunctionPair[i].pin, INPUT_PULLUP); + /* create a queue to handle gpio event from isr */ + gpio_evt_queue = xQueueCreate(10, sizeof(SwitchData)); + if (gpio_evt_queue == 0) { + log_e("Queue was not created and must not be used"); + while (1); + } + attachInterruptArg(buttonFunctionPair[i].pin, onGpioInterrupt, (void *)(buttonFunctionPair + i), FALLING); + } + + // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode + log_d("Calling Zigbee.begin()"); + Zigbee.begin(ZIGBEE_COORDINATOR); + + Serial.println("Waiting for Light to bound to the switch"); + //Wait for switch to bound to a light: + while(!zbSwitch.isBound()) + { + Serial.printf("."); + delay(500); + } + Serial.println(); +} + +void loop() { + // Handle button switch in loop() + uint8_t pin = 0; + SwitchData buttonSwitch; + static SwitchState buttonState = SWITCH_IDLE; + bool eventFlag = false; + + + /* check if there is any queue received, if yes read out the buttonSwitch */ + if (xQueueReceive(gpio_evt_queue, &buttonSwitch, portMAX_DELAY)) { + pin = buttonSwitch.pin; + enableGpioInterrupt(false); + eventFlag = true; + } + while (eventFlag) { + bool value = digitalRead(pin); + switch (buttonState) { + case SWITCH_IDLE: buttonState = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break; + case SWITCH_PRESS_DETECTED: buttonState = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break; + case SWITCH_RELEASE_DETECTED: + buttonState = SWITCH_IDLE; + /* callback to button_handler */ + (*onZbButton)(&buttonSwitch); + break; + default: break; + } + if (buttonState == SWITCH_IDLE) { + enableGpioInterrupt(true); + eventFlag = false; + break; + } + vTaskDelay(10 / portTICK_PERIOD_MS); + } + + // print the bound lights every 10 seconds + static uint32_t lastPrint = 0; + if (millis() - lastPrint > 10000) { + lastPrint = millis(); + zbSwitch.printBoundDevices(); + } +} diff --git a/examples/arduino-zigbee-switch/test/README b/examples/arduino-zigbee-switch/test/README new file mode 100644 index 0000000..df5066e --- /dev/null +++ b/examples/arduino-zigbee-switch/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html From 733426c49cb51d121435b570edd2c5440a2fed87 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 17 Sep 2024 18:14:24 +0200 Subject: [PATCH 058/117] disable zigbee examples needs merge of the open zigbee Arduino PR --- .github/workflows/examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index c26cd0f..e77614e 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -18,8 +18,8 @@ jobs: - "examples/arduino-rmt-blink" - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - - "examples/arduino-zigbee-light" - - "examples/arduino-zigbee-switch" + #- "examples/arduino-zigbee-light" + #- "examples/arduino-zigbee-switch" - "examples/espidf-arduino-h2zero-BLE_scan" #- "examples/espidf-arduino-matter-light" # Windows compile fails -> Path length limit - "examples/espidf-arduino-blink" From ff46b000394845fa869f1e11020015bb47d8000b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:04:17 +0200 Subject: [PATCH 059/117] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 764b3f6..770ed15 100644 --- a/README.md +++ b/README.md @@ -35,13 +35,13 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with 1. Configure a platform option in [platformio.ini](https://docs.platformio.org/page/projectconf.html) file: ### Stable version -espressif Arduino 3.0.4 and IDF 5.1.4 +espressif Arduino 3.0.5 and IDF 5.1.4+ See `platform` [documentation](https://docs.platformio.org/en/latest/projectconf/sections/env/options/platform/platform.html#projectconf-env-platform) for details. ```ini [env:stable] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip board = ... ... ``` From 4c02492d609f72f3cf842e1b51f2ece8fe00a83f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:08:15 +0200 Subject: [PATCH 060/117] v3.0.5 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index d50bbaa..ea0bae2 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "51.03.04+develop", + "version": "51.03.05", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/archive/refs/heads/master.zip" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.5/esp32-3.0.5.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "" + "version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.1/esp32-arduino-libs-idf-release_v5.1-33fbade6.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "pioarduino", - "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.4.240805/esp-idf-v5.1.4.zip" + "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.4.240801/esp-idf-v5.1.4.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 741b23d828e5a71452e28ca178cf51b51b7a5f20 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:09:46 +0200 Subject: [PATCH 061/117] Update platform.py --- platform.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/platform.py b/platform.py index f1b67fd..fb588ae 100644 --- a/platform.py +++ b/platform.py @@ -42,11 +42,6 @@ class Espressif32Platform(PlatformBase): if "arduino" in frameworks: self.packages["framework-arduinoespressif32"]["optional"] = False self.packages["framework-arduinoespressif32-libs"]["optional"] = False - # use latest espressif Arduino libs - URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/master/package/package_esp32_index.template.json" - packjdata = requests.get(URL).json() - dyn_lib_url = packjdata['packages'][0]['tools'][0]['systems'][0]['url'] - self.packages["framework-arduinoespressif32-libs"]["version"] = dyn_lib_url if "buildfs" in targets: filesystem = variables.get("board_build.filesystem", "littlefs") From a572bdee3cb44ec3460cebd2143770deb9bc70e2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:15:22 +0200 Subject: [PATCH 062/117] Update espidf.py --- builder/frameworks/espidf.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index daaf223..66b3cc9 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -250,10 +250,11 @@ def populate_idf_env_vars(idf_env): os.path.dirname(get_python_exe()), ] - if mcu not in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"): - additional_packages.append( - os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), - ) +# if mcu in ("esp32", "esp32s2", "esp32s3"): +# additional_packages.append( +# os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), +# ) + idf_env["PATH"] = os.pathsep.join(additional_packages + [idf_env["PATH"]]) @@ -870,6 +871,7 @@ def build_bootloader(sdk_config): "-DPYTHON=" + get_python_exe(), "-DIDF_PATH=" + FRAMEWORK_DIR, "-DSDKCONFIG=" + SDKCONFIG_PATH, + "-DPROJECT_SOURCE_DIR=" + PROJECT_DIR, "-DLEGACY_INCLUDE_COMMON_HEADERS=", "-DEXTRA_COMPONENT_DIRS=" + os.path.join(FRAMEWORK_DIR, "components", "bootloader"), @@ -1660,7 +1662,7 @@ env.Prepend( ( board.get( "upload.bootloader_offset", - "0x0" if mcu in ["esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2"] else ("0x2000" if mcu in ["esp32p4"] else "0x1000"), + "0x1000" if mcu in ["esp32", "esp32s2"] else ("0x2000" if mcu in ["esp32p4"] else "0x0"), ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), @@ -1771,8 +1773,8 @@ env["BUILDERS"]["ElfToBin"].action = action # ulp_dir = os.path.join(PROJECT_DIR, "ulp") -if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"): - env.SConscript("ulp.py", exports="env sdk_config project_config idf_variant") +if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c2", "esp32c3", "esp32h2"): + env.SConscript("ulp.py", exports="env sdk_config project_config app_includes idf_variant") # # Process OTA partition and image From a872d0f11d681fa77c08c883fe6dae1d81fccf35 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:16:18 +0200 Subject: [PATCH 063/117] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0a71d07..770ed15 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with integrated Wi-Fi and Bluetooth. ESP32 integrates an antenna switch, RF balun, power amplifier, low-noise receive amplifier, filters, and power management modules. * [Documentation](https://docs.platformio.org/page/platforms/espressif32.html) (advanced usage, packages, boards, frameworks, etc.) -* Issues with boards (wrong / missing). All issues caused from boards will not be fixed from the maintainer(s). A PR needs to be provided to solve. +* Issues with boards (wrong / missing). All issues caused from boards will **not** be fixed from the maintainer(s). A PR needs to be provided to solve. ## IDE Preparation @@ -35,13 +35,13 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with 1. Configure a platform option in [platformio.ini](https://docs.platformio.org/page/projectconf.html) file: ### Stable version -espressif Arduino 3.0.4 and IDF 5.1.4 +espressif Arduino 3.0.5 and IDF 5.1.4+ See `platform` [documentation](https://docs.platformio.org/en/latest/projectconf/sections/env/options/platform/platform.html#projectconf-env-platform) for details. ```ini [env:stable] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip board = ... ... ``` From d9b282c37a7b62bff8c5ab98d101d8359ae87238 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:17:27 +0200 Subject: [PATCH 064/117] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index f034560..ea0bae2 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "51.03.04", + "version": "51.03.05", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.4/esp32-3.0.4.zip" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.5/esp32-3.0.5.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.4/esp32-arduino-libs-3.0.4.zip" + "version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.1/esp32-arduino-libs-idf-release_v5.1-33fbade6.zip" }, "framework-espidf": { "type": "framework", From 5e73fe06f41447693e6d2773379fab7ae2d20c34 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 12 Oct 2024 16:53:52 +0200 Subject: [PATCH 065/117] Update main.py --- builder/main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/builder/main.py b/builder/main.py index bf33043..07a6bb0 100644 --- a/builder/main.py +++ b/builder/main.py @@ -256,6 +256,9 @@ env.Replace( if mcu in ("esp32c2", "esp32c3", "esp32c6") else "tool-xtensa-esp-elf-gdb" ) + or "", + "bin", + "%s-elf-gdb" % toolchain_arch, ), OBJCOPY=join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), RANLIB="%s-elf-gcc-ranlib" % toolchain_arch, From c673965f58f0b34d82e79ec13716de79a35dae23 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 22 Oct 2024 18:58:10 +0200 Subject: [PATCH 066/117] Arduino core 3.0.6 (#40) * Update README.md * esptool.py v4.8.0 * add cmake_utilities for C2 * add auto select "espidf" when pio var "custom_sdkconfig" is set * Update main.py * revert changes * Update platformio.ini * Update platformio.ini * Update Zigbee_On_Off_Switch.ino * Update Zigbee_On_Off_Light.ino * Update examples.yml * IDF v5.1.4.241008 * Arduino Core 3.0.6 * Update README.md --- .github/workflows/examples.yml | 4 +- README.md | 4 +- examples/arduino-zigbee-light/platformio.ini | 2 +- .../src/Zigbee_On_Off_Light.ino | 42 ++++++++--------- examples/arduino-zigbee-switch/platformio.ini | 2 +- .../src/Zigbee_On_Off_Switch.ino | 47 +++++++++---------- .../main/idf_component.yml | 6 ++- platform.json | 12 ++--- platform.py | 3 ++ 9 files changed, 62 insertions(+), 60 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index e77614e..c26cd0f 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -18,8 +18,8 @@ jobs: - "examples/arduino-rmt-blink" - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - #- "examples/arduino-zigbee-light" - #- "examples/arduino-zigbee-switch" + - "examples/arduino-zigbee-light" + - "examples/arduino-zigbee-switch" - "examples/espidf-arduino-h2zero-BLE_scan" #- "examples/espidf-arduino-matter-light" # Windows compile fails -> Path length limit - "examples/espidf-arduino-blink" diff --git a/README.md b/README.md index 770ed15..e6d2212 100644 --- a/README.md +++ b/README.md @@ -35,13 +35,13 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with 1. Configure a platform option in [platformio.ini](https://docs.platformio.org/page/projectconf.html) file: ### Stable version -espressif Arduino 3.0.5 and IDF 5.1.4+ +espressif Arduino 3.0.6 and IDF 5.1.4+ See `platform` [documentation](https://docs.platformio.org/en/latest/projectconf/sections/env/options/platform/platform.html#projectconf-env-platform) for details. ```ini [env:stable] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.06/platform-espressif32.zip board = ... ... ``` diff --git a/examples/arduino-zigbee-light/platformio.ini b/examples/arduino-zigbee-light/platformio.ini index 50c013d..2160dc3 100644 --- a/examples/arduino-zigbee-light/platformio.ini +++ b/examples/arduino-zigbee-light/platformio.ini @@ -9,7 +9,7 @@ [env:esp32-h2-devkitm-1] -platform = https://github.com/pioarduino/platform-espressif32.git#develop +platform = espressif32 framework = arduino board = esp32-h2-devkitm-1 monitor_speed = 115200 diff --git a/examples/arduino-zigbee-light/src/Zigbee_On_Off_Light.ino b/examples/arduino-zigbee-light/src/Zigbee_On_Off_Light.ino index db22c3d..2f13357 100644 --- a/examples/arduino-zigbee-light/src/Zigbee_On_Off_Light.ino +++ b/examples/arduino-zigbee-light/src/Zigbee_On_Off_Light.ino @@ -22,7 +22,7 @@ * and also the correct partition scheme must be selected in Tools->Partition Scheme. * * Please check the README.md for instructions and more detailed description. - * + * * Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/) */ @@ -33,27 +33,22 @@ #include "ZigbeeCore.h" #include "ep/ZigbeeLight.h" -#define LED_PIN RGB_BUILTIN -#define BUTTON_PIN 9 // C6/H2 Boot button -#define ZIGBEE_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ +#define LED_PIN RGB_BUILTIN +#define BUTTON_PIN 9 // ESP32-C6/H2 Boot button +#define ZIGBEE_LIGHT_ENDPOINT 10 -class MyZigbeeLight : public ZigbeeLight { -public: - // Constructor that passes parameters to the base class constructor - MyZigbeeLight(uint8_t endpoint) : ZigbeeLight(endpoint) {} +ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT); - // Override the set_on_off function - void setOnOff(bool value) override { - rgbLedWrite(LED_PIN, 255 * value, 255 * value, 255 * value); // Toggle light - } -}; - -MyZigbeeLight zbLight = MyZigbeeLight(ZIGBEE_LIGHT_ENDPOINT); +/********************* RGB LED functions **************************/ +void setLED(bool value) { + digitalWrite(LED_PIN, value); +} /********************* Arduino functions **************************/ void setup() { - // Init RMT and leave light OFF - rgbLedWrite(LED_PIN, 0, 0, 0); + // Init LED and turn it OFF (if LED_PIN == RGB_BUILTIN, the rgbLedWrite() will be used under the hood) + pinMode(LED_PIN, OUTPUT); + digitalWrite(LED_PIN, LOW); // Init button for factory reset pinMode(BUTTON_PIN, INPUT); @@ -61,29 +56,32 @@ void setup() { //Optional: set Zigbee device name and model zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb"); + // Set callback function for light change + zbLight.onLightChange(setLED); + //Add endpoint to Zigbee Core log_d("Adding ZigbeeLight endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbLight); - + // When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE log_d("Calling Zigbee.begin()"); Zigbee.begin(); } void loop() { - // Cheking button for factory reset + // Checking button for factory reset if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed // Key debounce handling delay(100); int startTime = millis(); while (digitalRead(BUTTON_PIN) == LOW) { delay(50); - if((millis() - startTime) > 3000) { + if ((millis() - startTime) > 3000) { // If key pressed for more than 3secs, factory reset Zigbee and reboot - Serial.printf("Reseting Zigbee to factory settings, reboot.\n"); + Serial.printf("Resetting Zigbee to factory settings, reboot.\n"); Zigbee.factoryReset(); } } } delay(100); -} \ No newline at end of file +} diff --git a/examples/arduino-zigbee-switch/platformio.ini b/examples/arduino-zigbee-switch/platformio.ini index 1ee3bee..0c3ce6a 100644 --- a/examples/arduino-zigbee-switch/platformio.ini +++ b/examples/arduino-zigbee-switch/platformio.ini @@ -9,7 +9,7 @@ [env:esp32-c6-devkitc-1] -platform = https://github.com/pioarduino/platform-espressif32.git#develop +platform = espressif32 framework = arduino board = esp32-c6-devkitc-1 monitor_speed = 115200 diff --git a/examples/arduino-zigbee-switch/src/Zigbee_On_Off_Switch.ino b/examples/arduino-zigbee-switch/src/Zigbee_On_Off_Switch.ino index 27896f1..09487de 100644 --- a/examples/arduino-zigbee-switch/src/Zigbee_On_Off_Switch.ino +++ b/examples/arduino-zigbee-switch/src/Zigbee_On_Off_Switch.ino @@ -23,7 +23,7 @@ * and also the correct partition scheme must be selected in Tools->Partition Scheme. * * Please check the README.md for instructions and more detailed description. - * + * * Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/) */ @@ -65,24 +65,7 @@ typedef enum { static SwitchData buttonFunctionPair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; -/* Zigbee switch */ -class MyZigbeeSwitch : public ZigbeeSwitch { -public: - // Constructor that passes parameters to the base class constructor - MyZigbeeSwitch(uint8_t endpoint) : ZigbeeSwitch(endpoint) {} - - // Override the set_on_off function - void readManufacturer(char* manufacturer) override { - //Do what you want with the manufacturer string - Serial.printf("Manufacturer: %s\n", manufacturer); - } - void readModel(char* model) override { - //Do what you want with the model string - Serial.printf("Model: %s\n", model); - } -}; - -MyZigbeeSwitch zbSwitch = MyZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); +ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); /********************* Zigbee functions **************************/ static void onZbButton(SwitchData *button_func_pair) { @@ -111,8 +94,11 @@ static void enableGpioInterrupt(bool enabled) { /********************* Arduino functions **************************/ void setup() { - + Serial.begin(115200); + while (!Serial) { + delay(10); + } //Optional: set Zigbee device name and model zbSwitch.setManufacturerAndModel("Espressif", "ZigbeeSwitch"); @@ -126,7 +112,6 @@ void setup() { //Open network for 180 seconds after boot Zigbee.setRebootOpenNetwork(180); - // Init button switch for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); i++) { @@ -143,14 +128,27 @@ void setup() { // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode log_d("Calling Zigbee.begin()"); Zigbee.begin(ZIGBEE_COORDINATOR); - + Serial.println("Waiting for Light to bound to the switch"); //Wait for switch to bound to a light: - while(!zbSwitch.isBound()) - { + while (!zbSwitch.isBound()) { Serial.printf("."); delay(500); } + + // Optional: read manufacturer and model name from the bound light + std::list boundLights = zbSwitch.getBoundDevices(); + //List all bound lights + for (const auto &device : boundLights) { + Serial.printf("Device on endpoint %d, short address: 0x%x\n", device->endpoint, device->short_addr); + Serial.printf( + "IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", device->ieee_addr[0], device->ieee_addr[1], device->ieee_addr[2], device->ieee_addr[3], + device->ieee_addr[4], device->ieee_addr[5], device->ieee_addr[6], device->ieee_addr[7] + ); + Serial.printf("Light manufacturer: %s", zbSwitch.readManufacturer(device->endpoint, device->short_addr)); + Serial.printf("Light model: %s", zbSwitch.readModel(device->endpoint, device->short_addr)); + } + Serial.println(); } @@ -160,7 +158,6 @@ void loop() { SwitchData buttonSwitch; static SwitchState buttonState = SWITCH_IDLE; bool eventFlag = false; - /* check if there is any queue received, if yes read out the buttonSwitch */ if (xQueueReceive(gpio_evt_queue, &buttonSwitch, portMAX_DELAY)) { diff --git a/examples/espidf-arduino-matter-light/main/idf_component.yml b/examples/espidf-arduino-matter-light/main/idf_component.yml index 369a76b..0caf8ff 100644 --- a/examples/espidf-arduino-matter-light/main/idf_component.yml +++ b/examples/espidf-arduino-matter-light/main/idf_component.yml @@ -1,3 +1,7 @@ dependencies: espressif/esp_matter: - version: "^1.3.0" \ No newline at end of file + version: "^1.3.0" + espressif/cmake_utilities: + version: "0.*" + rules: + - if: "target in [esp32c2]" diff --git a/platform.json b/platform.json index ea0bae2..68f4494 100644 --- a/platform.json +++ b/platform.json @@ -12,13 +12,13 @@ "RISC-V" ], "engines": { - "platformio": ">=6.1.15" + "platformio": ">=6.1.16" }, "repository": { "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "51.03.05", + "version": "51.03.06", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.5/esp32-3.0.5.zip" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.6/esp32-3.0.6.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.1/esp32-arduino-libs-idf-release_v5.1-33fbade6.zip" + "version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.1/esp32-arduino-libs-idf-release_v5.1-632e0c2a.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "pioarduino", - "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.4.240801/esp-idf-v5.1.4.zip" + "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.4.241008/esp-idf-v5.1.4.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", @@ -92,7 +92,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "pioarduino", - "version": "https://github.com/pioarduino/esptool/releases/download/v4.7.5/esptool.zip" + "version": "https://github.com/pioarduino/esptool/releases/download/v4.8.1/esptool.zip" }, "tool-dfuutil-arduino": { "type": "uploader", diff --git a/platform.py b/platform.py index fb588ae..4767ca3 100644 --- a/platform.py +++ b/platform.py @@ -39,6 +39,9 @@ class Espressif32Platform(PlatformBase): mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32")) frameworks = variables.get("pioframework", []) + if variables.get("custom_sdkconfig") is not None: + frameworks.append("espidf") + if "arduino" in frameworks: self.packages["framework-arduinoespressif32"]["optional"] = False self.packages["framework-arduinoespressif32-libs"]["optional"] = False From 95018a62d942ca719ffd315d1e3bd48876792a15 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 23 Oct 2024 13:12:36 +0200 Subject: [PATCH 067/117] Arduino core 3.0.7 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 68f4494..90c8738 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.6/esp32-3.0.6.zip" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.7/esp32-3.0.7.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", From 4d652c6bb429b0d0343acf3ed4013379b85c029e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 23 Oct 2024 13:16:01 +0200 Subject: [PATCH 068/117] esptool.py v4.8.1.1 s2 s3 reset fix for USB / JTAG mode --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 90c8738..7846eba 100644 --- a/platform.json +++ b/platform.json @@ -92,7 +92,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "pioarduino", - "version": "https://github.com/pioarduino/esptool/releases/download/v4.8.1/esptool.zip" + "version": "https://github.com/pioarduino/esptool/releases/download/v4.8.1.1/esptool.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From ec17486ffa451374e108b72be07e9c8fa83338e8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 23 Oct 2024 13:18:22 +0200 Subject: [PATCH 069/117] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e6d2212..35187a7 100644 --- a/README.md +++ b/README.md @@ -35,13 +35,13 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with 1. Configure a platform option in [platformio.ini](https://docs.platformio.org/page/projectconf.html) file: ### Stable version -espressif Arduino 3.0.6 and IDF 5.1.4+ +espressif Arduino 3.0.7 and IDF 5.1.4+ See `platform` [documentation](https://docs.platformio.org/en/latest/projectconf/sections/env/options/platform/platform.html#projectconf-env-platform) for details. ```ini [env:stable] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.06/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip board = ... ... ``` From ad415d755ba725dc0b0b889129b0c48bcd1f9b31 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 31 Oct 2024 18:20:41 +0100 Subject: [PATCH 070/117] pioarduino IDF 5.1.5 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 7846eba..08de2ed 100644 --- a/platform.json +++ b/platform.json @@ -45,7 +45,7 @@ "type": "framework", "optional": true, "owner": "pioarduino", - "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.4.241008/esp-idf-v5.1.4.zip" + "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.5/esp-idf-v5.1.5.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From e5990e4b87589af230b75b5b438724f41ceff1b9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 19 Nov 2024 23:35:21 +0100 Subject: [PATCH 071/117] Platform 51.03.07 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 08de2ed..e7acba6 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "51.03.06", + "version": "51.03.07", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" From 411e19040b2c658b910d7ba759504d37b8a3e847 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:42:06 +0100 Subject: [PATCH 072/117] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 35187a7..4aa6b93 100644 --- a/README.md +++ b/README.md @@ -35,13 +35,13 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with 1. Configure a platform option in [platformio.ini](https://docs.platformio.org/page/projectconf.html) file: ### Stable version -espressif Arduino 3.0.7 and IDF 5.1.4+ +currently espressif Arduino 3.0.7 and IDF 5.1.4+ See `platform` [documentation](https://docs.platformio.org/en/latest/projectconf/sections/env/options/platform/platform.html#projectconf-env-platform) for details. ```ini [env:stable] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.0x-stable/platform-espressif32.zip board = ... ... ``` From 8af67edb6b64d3a924a559f26b68f97b93546792 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:44:10 +0100 Subject: [PATCH 073/117] Install latest stable Arduino core version (#59) * Update platform.json * Fetch stable release from GH API / Arduino package json * use get * Update platform.py * use matching Arduino libs to release * silence debug prints --- platform.json | 6 +++--- platform.py | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index e7acba6..8762a55 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "51.03.07", + "version": "51.03.0x-stable", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.7/esp32-3.0.7.zip" + "version": "" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.1/esp32-arduino-libs-idf-release_v5.1-632e0c2a.zip" + "version": "" }, "framework-espidf": { "type": "framework", diff --git a/platform.py b/platform.py index 4767ca3..3a3e514 100644 --- a/platform.py +++ b/platform.py @@ -45,6 +45,18 @@ class Espressif32Platform(PlatformBase): if "arduino" in frameworks: self.packages["framework-arduinoespressif32"]["optional"] = False self.packages["framework-arduinoespressif32-libs"]["optional"] = False + # use latest stable release Arduino core + ARDUINO_CORE_API_URL = "https://api.github.com/repos/espressif/Arduino-esp32/releases/latest" + api_data = requests.get(ARDUINO_CORE_API_URL, timeout=10).json() + zipball = api_data.get("zipball_url") + tag = api_data.get("tag_name") + # print("Latest release Arduino core URL:", zipball) + self.packages["framework-arduinoespressif32"]["version"] = zipball + # use corresponding espressif Arduino libs to release + URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/" + tag + "/package/package_esp32_index.template.json" + packjdata = requests.get(URL, timeout=10).json() + dyn_lib_url = packjdata['packages'][0]['tools'][0]['systems'][0]['url'] + self.packages["framework-arduinoespressif32-libs"]["version"] = dyn_lib_url if "buildfs" in targets: filesystem = variables.get("board_build.filesystem", "littlefs") From d416a6a36007f62bea56d1052defed8423d6484b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:53:18 +0100 Subject: [PATCH 074/117] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4aa6b93..01ac2d4 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ See `platform` [documentation](https://docs.platformio.org/en/latest/projectconf ```ini [env:stable] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.0x-stable/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip board = ... ... ``` From 9a07688651b759718e226fcfd293aaa2b8ce6cd7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:54:31 +0100 Subject: [PATCH 075/117] Update release_zips.yml --- .github/workflows/release_zips.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release_zips.yml b/.github/workflows/release_zips.yml index 2c50ca2..1dd899a 100644 --- a/.github/workflows/release_zips.yml +++ b/.github/workflows/release_zips.yml @@ -3,7 +3,7 @@ name: Create zip file with recursive source clone for release on: push: tags: - - 51* + - stable jobs: release_zips: From 9ad58a5a27b77f9b2922053666193df18165d897 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 24 Nov 2024 17:14:48 +0100 Subject: [PATCH 076/117] Make offline use possible again * make more failsafe when no Internet connection --- platform.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/platform.py b/platform.py index 3a3e514..421360c 100644 --- a/platform.py +++ b/platform.py @@ -45,18 +45,22 @@ class Espressif32Platform(PlatformBase): if "arduino" in frameworks: self.packages["framework-arduinoespressif32"]["optional"] = False self.packages["framework-arduinoespressif32-libs"]["optional"] = False - # use latest stable release Arduino core - ARDUINO_CORE_API_URL = "https://api.github.com/repos/espressif/Arduino-esp32/releases/latest" - api_data = requests.get(ARDUINO_CORE_API_URL, timeout=10).json() - zipball = api_data.get("zipball_url") - tag = api_data.get("tag_name") - # print("Latest release Arduino core URL:", zipball) - self.packages["framework-arduinoespressif32"]["version"] = zipball - # use corresponding espressif Arduino libs to release - URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/" + tag + "/package/package_esp32_index.template.json" - packjdata = requests.get(URL, timeout=10).json() - dyn_lib_url = packjdata['packages'][0]['tools'][0]['systems'][0]['url'] - self.packages["framework-arduinoespressif32-libs"]["version"] = dyn_lib_url + try: + # use latest stable release Arduino core + ARDUINO_CORE_API_URL = "https://api.github.com/repos/espressif/Arduino-esp32/releases/latest" + api_data = requests.get(ARDUINO_CORE_API_URL, timeout=2).json() + zipball = api_data.get("zipball_url") + tag = api_data.get("tag_name") + if tag is not None: + # print("Latest release Arduino core URL:", zipball) + self.packages["framework-arduinoespressif32"]["version"] = zipball + # use corresponding espressif Arduino libs to release + URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/" + tag + "/package/package_esp32_index.template.json" + packjdata = requests.get(URL, timeout=10).json() + dyn_lib_url = packjdata['packages'][0]['tools'][0]['systems'][0]['url'] + self.packages["framework-arduinoespressif32-libs"]["version"] = dyn_lib_url + except: + pass if "buildfs" in targets: filesystem = variables.get("board_build.filesystem", "littlefs") From 68bbf047a1363d219088deed4842f57cb00232a5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:18:01 +0100 Subject: [PATCH 077/117] only do a online request for framework when folder does not exists --- platform.py | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/platform.py b/platform.py index 421360c..372d229 100644 --- a/platform.py +++ b/platform.py @@ -18,8 +18,10 @@ import sys import json import re import requests +from os.path import isfile, join from platformio.public import PlatformBase, to_unix_path +from platformio.project.config import ProjectConfig IS_WINDOWS = sys.platform.startswith("win") @@ -45,22 +47,24 @@ class Espressif32Platform(PlatformBase): if "arduino" in frameworks: self.packages["framework-arduinoespressif32"]["optional"] = False self.packages["framework-arduinoespressif32-libs"]["optional"] = False - try: - # use latest stable release Arduino core - ARDUINO_CORE_API_URL = "https://api.github.com/repos/espressif/Arduino-esp32/releases/latest" - api_data = requests.get(ARDUINO_CORE_API_URL, timeout=2).json() - zipball = api_data.get("zipball_url") - tag = api_data.get("tag_name") - if tag is not None: - # print("Latest release Arduino core URL:", zipball) - self.packages["framework-arduinoespressif32"]["version"] = zipball - # use corresponding espressif Arduino libs to release - URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/" + tag + "/package/package_esp32_index.template.json" - packjdata = requests.get(URL, timeout=10).json() - dyn_lib_url = packjdata['packages'][0]['tools'][0]['systems'][0]['url'] - self.packages["framework-arduinoespressif32-libs"]["version"] = dyn_lib_url - except: - pass + ARDUINO_FRAMEWORK_DIR = os.path.join(ProjectConfig.get_instance().get("platformio", "packages_dir"), "framework-arduinoespressif32") + if not bool(os.path.exists(ARDUINO_FRAMEWORK_DIR)): + try: + # use latest stable release Arduino core + ARDUINO_CORE_API_URL = "https://api.github.com/repos/espressif/Arduino-esp32/releases/latest" + api_data = requests.get(ARDUINO_CORE_API_URL, timeout=2).json() + zipball = api_data.get("zipball_url") + tag = api_data.get("tag_name") + if tag is not None: + # print("Latest release Arduino core URL:", zipball) + self.packages["framework-arduinoespressif32"]["version"] = zipball + # use corresponding espressif Arduino libs to release + URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/" + tag + "/package/package_esp32_index.template.json" + packjdata = requests.get(URL, timeout=10).json() + dyn_lib_url = packjdata['packages'][0]['tools'][0]['systems'][0]['url'] + self.packages["framework-arduinoespressif32-libs"]["version"] = dyn_lib_url + except: + pass if "buildfs" in targets: filesystem = variables.get("board_build.filesystem", "littlefs") @@ -132,10 +136,10 @@ class Espressif32Platform(PlatformBase): # and RISC-V targets. for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"): self.packages[gdb_package]["optional"] = False - if IS_WINDOWS: + #if IS_WINDOWS: # Note: On Windows GDB v12 is not able to # launch a GDB server in pipe mode while v11 works fine - self.packages[gdb_package]["version"] = "~11.2.0" + # self.packages[gdb_package]["version"] = "~11.2.0" # Common packages for IDF and mixed Arduino+IDF projects if "espidf" in frameworks: From 4d2147dce3f208060cf5a36d5d22e7c371c53fce Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 13 Dec 2024 16:09:37 +0100 Subject: [PATCH 078/117] esptool.py v4.8.5 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 8762a55..4461d67 100644 --- a/platform.json +++ b/platform.json @@ -92,7 +92,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "pioarduino", - "version": "https://github.com/pioarduino/esptool/releases/download/v4.8.1.1/esptool.zip" + "version": "https://github.com/pioarduino/esptool/releases/download/v4.8.5/esptool.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From c3828a6f61a9341d19bce67b867451d1d5c1a1cd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:40:35 +0100 Subject: [PATCH 079/117] Update release_zips.yml --- .github/workflows/release_zips.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release_zips.yml b/.github/workflows/release_zips.yml index 1dd899a..5f25ce2 100644 --- a/.github/workflows/release_zips.yml +++ b/.github/workflows/release_zips.yml @@ -3,7 +3,7 @@ name: Create zip file with recursive source clone for release on: push: tags: - - stable + - 53* jobs: release_zips: From f40a96229c779fcfdf216bc3d14e896dc5222715 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:41:30 +0100 Subject: [PATCH 080/117] Update examples.yml --- .github/workflows/examples.yml | 36 +++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index c26cd0f..901393b 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -20,8 +20,9 @@ jobs: - "examples/arduino-wifiscan" - "examples/arduino-zigbee-light" - "examples/arduino-zigbee-switch" + - "examples/tasmota" - "examples/espidf-arduino-h2zero-BLE_scan" - #- "examples/espidf-arduino-matter-light" # Windows compile fails -> Path length limit + - "examples/espidf-arduino-matter-light" - "examples/espidf-arduino-blink" - "examples/espidf-arduino-littlefs" - "examples/espidf-blink" @@ -34,6 +35,7 @@ jobs: - "examples/espidf-storage-sdcard" - "examples/espidf-ulp" - "examples/espidf-ulp-riscv" + - "examples/espidf-ulp-lp" runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -43,12 +45,36 @@ jobs: uses: actions/setup-python@v5 with: python-version: "3.11" - - name: Install dependencies + - name: Install Windows dependencies run: | python -m pip install --upgrade pip pip install wheel pip install -U https://github.com/platformio/platformio/archive/develop.zip - pio pkg install --global --platform symlink://. - - name: Build examples + pio pkg install --global --platform file://. + if: "matrix.os == 'windows-2022'" + env: + PLATFORMIO_CORE_DIR: C:\plat + PLATFORMIO_PACKAGES_DIR: C:\plat\pack + PLATFORMIO_PLATFORMS_DIR: C:\plat\plat + - name: Build Windows examples + run: pio run -d ${{ matrix.example }} + if: "matrix.example != 'examples/tasmota' && matrix.os == 'windows-2022'" + env: + PLATFORMIO_CORE_DIR: C:\plat + PLATFORMIO_PACKAGES_DIR: C:\plat\pack + PLATFORMIO_PLATFORMS_DIR: C:\plat\plat + - name: Install Ubuntu Mac dependencies run: | - pio run -d ${{ matrix.example }} + python -m pip install --upgrade pip + pip install wheel + pip install -U https://github.com/platformio/platformio/archive/develop.zip + pio pkg install --global --platform file://. + if: "matrix.os != 'windows-2022'" + - name: git clone Tasmota and add to examples + run: | + git clone -b development --depth 1 https://github.com/arendst/Tasmota.git examples/tasmota + cp examples/tasmota_platformio_override.ini examples/tasmota/platformio_override.ini + if: "matrix.example == 'examples/tasmota' && matrix.os != 'windows-2022'" + - name: Build Ubuntu Mac examples + run: pio run -d ${{ matrix.example }} + if: "matrix.os != 'windows-2022'" From 7feba13db8501c5cff3191472ed0f2276a7f2760 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:43:05 +0100 Subject: [PATCH 081/117] Update espidf.py --- builder/frameworks/espidf.py | 422 +++++++++++++++++++++++++++++++++-- 1 file changed, 404 insertions(+), 18 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 66b3cc9..d9b2c33 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -26,7 +26,9 @@ import subprocess import sys import shutil import os +from os.path import join import re +import requests import platform as sys_platform import click @@ -42,6 +44,7 @@ from platformio import fs, __version__ from platformio.compat import IS_WINDOWS from platformio.proc import exec_command from platformio.builder.tools.piolib import ProjectAsLibBuilder +from platformio.project.config import ProjectConfig from platformio.package.version import get_original_version, pepver_to_semver # Added to avoid conflicts between installed Python packages from @@ -53,13 +56,78 @@ if os.environ.get("PYTHONPATH"): env = DefaultEnvironment() env.SConscript("_embed_files.py", exports="env") +def install_standard_python_deps(): + def _get_installed_standard_pip_packages(): + result = {} + packages = {} + pip_output = subprocess.check_output( + [ + env.subst("$PYTHONEXE"), + "-m", + "pip", + "list", + "--format=json", + "--disable-pip-version-check", + ] + ) + try: + packages = json.loads(pip_output) + except: + print("Warning! Couldn't extract the list of installed Python packages.") + return {} + for p in packages: + result[p["name"]] = pepver_to_semver(p["version"]) + + return result + + deps = { + "wheel": ">=0.35.1", + "PyYAML": ">=6.0.2" + } + + installed_packages = _get_installed_standard_pip_packages() + packages_to_install = [] + for package, spec in deps.items(): + if package not in installed_packages: + packages_to_install.append(package) + else: + version_spec = semantic_version.Spec(spec) + if not version_spec.match(installed_packages[package]): + packages_to_install.append(package) + + if packages_to_install: + env.Execute( + env.VerboseAction( + ( + '"$PYTHONEXE" -m pip install -U ' + + " ".join( + [ + '"%s%s"' % (p, deps[p]) + for p in packages_to_install + ] + ) + ), + "Installing standard Python dependencies", + ) + ) + return + +install_standard_python_deps() + # Allow changes in folders of managed components os.environ["IDF_COMPONENT_OVERWRITE_MANAGED_COMPONENTS"] = "1" platform = env.PioPlatform() +config = env.GetProjectConfig() board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") +flash_speed = board.get("build.f_flash", "40000000L") +flash_frequency = str(flash_speed.replace("000000L", "m")) +flash_mode = board.get("build.flash_mode", "dio") idf_variant = mcu.lower() +flag_custom_sdkonfig = False +flag_custom_component_add = False +flag_custom_component_remove = False IDF5 = ( platform.get_package_version("framework-espidf") @@ -69,14 +137,15 @@ IDF5 = ( IDF_ENV_VERSION = "1.0.0" FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" % ("riscv32-esp" if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2") else ("xtensa-%s" % mcu)) + "toolchain-xtensa-esp-elf" + if mcu in ("esp32", "esp32s2", "esp32s3") + else "toolchain-riscv32-esp" ) assert os.path.isdir(FRAMEWORK_DIR) assert os.path.isdir(TOOLCHAIN_DIR) -# The latest IDF uses a standalone GDB package which requires at least PlatformIO 6.1.11 if ( ["espidf"] == env.get("PIOFRAMEWORK") and semantic_version.Version.coerce(__version__) @@ -85,9 +154,10 @@ if ( ): print("Warning! Debugging an IDF project requires PlatformIO Core >= 6.1.11!") -# Arduino framework as a component is not compatible with ESP-IDF >5.2 +# Arduino framework as a component is not compatible with ESP-IDF >5.3 if "arduino" in env.subst("$PIOFRAMEWORK"): ARDUINO_FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") + ARDUINO_FRMWRK_LIB_DIR = platform.get_package_dir("framework-arduinoespressif32-libs") # Possible package names in 'package@version' format is not compatible with CMake if "@" in os.path.basename(ARDUINO_FRAMEWORK_DIR): new_path = os.path.join( @@ -107,6 +177,208 @@ SDKCONFIG_PATH = os.path.expandvars(board.get( os.path.join(PROJECT_DIR, "sdkconfig.%s" % env.subst("$PIOENV")), )) +# +# generate modified Arduino IDF sdkconfig, applying settings from "custom_sdkconfig" +# +if config.has_option("env:"+env["PIOENV"], "custom_component_add"): + flag_custom_component_add = True +if config.has_option("env:"+env["PIOENV"], "custom_component_remove"): + flag_custom_component_remove = True + +if config.has_option("env:"+env["PIOENV"], "custom_sdkconfig"): + flag_custom_sdkonfig = True +if "espidf.custom_sdkconfig" in board: + flag_custom_sdkonfig = True + +def HandleArduinoIDFsettings(env): + def get_MD5_hash(phrase): + import hashlib + return hashlib.md5((phrase).encode('utf-8')).hexdigest()[:16] + + def custom_sdkconfig_file(string): + if not config.has_option("env:"+env["PIOENV"], "custom_sdkconfig"): + return "" + sdkconfig_entrys = env.GetProjectOption("custom_sdkconfig").splitlines() + for file in sdkconfig_entrys: + if "http" in file and "://" in file: + response = requests.get(file.split(" ")[0]) + if response.ok: + target = str(response.content.decode('utf-8')) + else: + print("Failed to download:", file) + return "" + return target + if "file://" in file: + file_path = join(PROJECT_DIR,file.lstrip("file://").split(os.path.sep)[-1]) + if os.path.exists(file_path): + with open(file_path, 'r') as file: + target = file.read() + else: + print("File not found:", file_path) + return "" + return target + return "" + + + custom_sdk_config_flags = "" + board_idf_config_flags = "" + sdkconfig_file_flags = "" + custom_sdkconfig_file_str = "" + + if config.has_option("env:"+env["PIOENV"], "custom_sdkconfig"): + flag_custom_sdkonfig = True + custom_sdk_config_flags = (env.GetProjectOption("custom_sdkconfig").rstrip("\n")) + "\n" + custom_sdkconfig_file_str = custom_sdkconfig_file(sdkconfig_file_flags) + + if "espidf.custom_sdkconfig" in board: + board_idf_config_flags = ('\n'.join([element for element in board.get("espidf.custom_sdkconfig", "")])).rstrip("\n") + "\n" + flag_custom_sdkonfig = True + + if flag_custom_sdkonfig == True: # TDOO duplicated + print("*** Add \"custom_sdkconfig\" settings to IDF sdkconfig.defaults ***") + idf_config_flags = custom_sdk_config_flags + if custom_sdkconfig_file_str != "": + sdkconfig_file_flags = custom_sdkconfig_file_str + "\n" + idf_config_flags = sdkconfig_file_flags + idf_config_flags + idf_config_flags = board_idf_config_flags + idf_config_flags + if flash_frequency != "80m": + idf_config_flags = idf_config_flags + "# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set\n" + esptool_flashfreq_y = "CONFIG_ESPTOOLPY_FLASHFREQ_%s=y\n" % flash_frequency.upper() + esptool_flashfreq_M = "CONFIG_ESPTOOLPY_FLASHFREQ=\"%s\"\n" % flash_frequency + idf_config_flags = idf_config_flags + esptool_flashfreq_y + esptool_flashfreq_M + if flash_mode != "qio": + idf_config_flags = idf_config_flags + "# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set\n" + esptool_flashmode = "CONFIG_ESPTOOLPY_FLASHMODE_%s=y\n" % flash_mode.upper() + if esptool_flashmode not in idf_config_flags: + idf_config_flags = idf_config_flags + esptool_flashmode + if mcu in ("esp32") and "CONFIG_FREERTOS_UNICORE=y" in idf_config_flags: + idf_config_flags = idf_config_flags + "# CONFIG_SPIRAM is not set\n" + + idf_config_flags = idf_config_flags.splitlines() + sdkconfig_src = join(ARDUINO_FRMWRK_LIB_DIR,mcu,"sdkconfig") + + def get_flag(line): + if line.startswith("#") and "is not set" in line: + return line.split(" ")[1] + elif not line.startswith("#") and len(line.split("=")) > 1: + return line.split("=")[0] + else: + return None + + with open(sdkconfig_src) as src: + sdkconfig_dst = os.path.join(PROJECT_DIR, "sdkconfig.defaults") + dst = open(sdkconfig_dst,"w") + dst.write("# TASMOTA__"+ get_MD5_hash(''.join(custom_sdk_config_flags).strip() + mcu) +"\n") + while line := src.readline(): + flag = get_flag(line) + if flag is None: + dst.write(line) + else: + no_match = True + for item in idf_config_flags: + if flag == get_flag(item.replace("\'", "")): + dst.write(item.replace("\'", "")+"\n") + no_match = False + print("Replace:",line,"with:",item.replace("\'", "")) + idf_config_flags.remove(item) + if no_match: + dst.write(line) + for item in idf_config_flags: # are there new flags? + print("Add:",item.replace("\'", "")) + dst.write(item.replace("\'", "")+"\n") + dst.close() + return + else: + return + +def HandleCOMPONENTsettings(env): + if flag_custom_component_add == True or flag_custom_component_remove == True: # todo remove duplicated + import yaml + from yaml import SafeLoader + print("*** \"custom_component\" is used to select managed idf components ***") + if flag_custom_component_remove == True: + idf_custom_component_remove = env.GetProjectOption("custom_component_remove").splitlines() + else: + idf_custom_component_remove = "" + if flag_custom_component_add == True: + idf_custom_component_add = env.GetProjectOption("custom_component_add").splitlines() + else: + idf_custom_component_add = "" + + # search "idf_component.yml" file + try: # 1.st in Arduino framework + idf_component_yml_src = os.path.join(ARDUINO_FRAMEWORK_DIR, "idf_component.yml") + shutil.copy(join(ARDUINO_FRAMEWORK_DIR,"idf_component.yml"),join(ARDUINO_FRAMEWORK_DIR,"idf_component.yml.orig")) + yml_file_dir = idf_component_yml_src + except: # 2.nd Project source + try: + idf_component_yml_src = os.path.join(PROJECT_SRC_DIR, "idf_component.yml") + shutil.copy(join(PROJECT_SRC_DIR,"idf_component.yml"),join(PROJECT_SRC_DIR,"idf_component.yml.orig")) + yml_file_dir = idf_component_yml_src + except: # no idf_component.yml in Project source -> create + idf_component_yml_src = os.path.join(PROJECT_SRC_DIR, "idf_component.yml") + yml_file_dir = idf_component_yml_src + idf_component_yml_str = """ + dependencies: + idf: \">=5.1\" + """ + idf_component_yml = yaml.safe_load(idf_component_yml_str) + with open(idf_component_yml_src, 'w',) as f : + yaml.dump(idf_component_yml,f) + + yaml_file=open(idf_component_yml_src,"r") + idf_component=yaml.load(yaml_file, Loader=SafeLoader) + idf_component_str=json.dumps(idf_component) # convert to json string + idf_component_json=json.loads(idf_component_str) # convert string to json dict + + if idf_custom_component_remove != "": + for entry in idf_custom_component_remove: + # checking if the entry exists before removing + if entry in idf_component_json["dependencies"]: + print("*** Removing component:",entry) + del idf_component_json["dependencies"][entry] + + if idf_custom_component_add != "": + for entry in idf_custom_component_add: + if len(str(entry)) > 4: # too short or empty entry + # add new entrys to json + if "@" in entry: + idf_comp_entry = str(entry.split("@")[0]).replace(" ", "") + idf_comp_vers = str(entry.split("@")[1]).replace(" ", "") + else: + idf_comp_entry = str(entry).replace(" ", "") + idf_comp_vers = "*" + if idf_comp_entry not in idf_component_json["dependencies"]: + print("*** Adding component:", idf_comp_entry, idf_comp_vers) + new_entry = {idf_comp_entry: {"version": idf_comp_vers}} + idf_component_json["dependencies"].update(new_entry) + + idf_component_yml_file = open(yml_file_dir,"w") + yaml.dump(idf_component_json, idf_component_yml_file) + idf_component_yml_file.close() + # print("JSON from modified idf_component.yml:") + # print(json.dumps(idf_component_json)) + return + return + +if flag_custom_component_add == True or flag_custom_component_remove == True: + HandleCOMPONENTsettings(env) + +if flag_custom_sdkonfig == True and "arduino" in env.subst("$PIOFRAMEWORK"): + HandleArduinoIDFsettings(env) + LIB_SOURCE = os.path.join(ProjectConfig.get_instance().get("platformio", "platforms_dir"), "espressif32", "builder", "build_lib") + if not bool(os.path.exists(os.path.join(PROJECT_DIR, ".dummy"))): + shutil.copytree(LIB_SOURCE, os.path.join(PROJECT_DIR, ".dummy")) + PROJECT_SRC_DIR = os.path.join(PROJECT_DIR, ".dummy") + env.Replace( + PROJECT_SRC_DIR=PROJECT_SRC_DIR, + BUILD_FLAGS="", + BUILD_UNFLAGS="", + LINKFLAGS="", + PIOFRAMEWORK="arduino", + ARDUINO_LIB_COMPILE_FLAG="Build", + ) + env["INTEGRATION_EXTRA_DATA"].update({"arduino_lib_compile_flag": env.subst("$ARDUINO_LIB_COMPILE_FLAG")}) def get_project_lib_includes(env): project = ProjectAsLibBuilder(env, "$PROJECT_DIR") @@ -250,12 +522,6 @@ def populate_idf_env_vars(idf_env): os.path.dirname(get_python_exe()), ] -# if mcu in ("esp32", "esp32s2", "esp32s3"): -# additional_packages.append( -# os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), -# ) - - idf_env["PATH"] = os.pathsep.join(additional_packages + [idf_env["PATH"]]) # Some users reported that the `IDF_TOOLS_PATH` var can seep into the @@ -507,7 +773,7 @@ def extract_linker_script_fragments_backup(framework_components_dir, sdk_config) sys.stderr.write("Error: Failed to extract paths to linker script fragments\n") env.Exit(1) - if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"): + if mcu not in ("esp32", "esp32s2", "esp32s3"): result.append(os.path.join(framework_components_dir, "riscv", "linker.lf")) # Add extra linker fragments @@ -1064,7 +1330,8 @@ def generate_empty_partition_image(binary_path, image_size): ), ) - env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", empty_partition) + if flag_custom_sdkonfig == False: + env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", empty_partition) def get_partition_info(pt_path, pt_offset, pt_params): @@ -1561,7 +1828,8 @@ app_includes = get_app_includes(elf_config) # Compile bootloader # -env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", build_bootloader(sdk_config)) +if flag_custom_sdkonfig == False: + env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", build_bootloader(sdk_config)) # # Target: ESP-IDF menuconfig @@ -1777,6 +2045,78 @@ if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c2", "es env.SConscript("ulp.py", exports="env sdk_config project_config app_includes idf_variant") # +# Compile Arduino IDF sources +# + +if "arduino" in env.get("PIOFRAMEWORK") and "espidf" not in env.get("PIOFRAMEWORK"): + def idf_lib_copy(source, target, env): + env_build = join(env["PROJECT_BUILD_DIR"],env["PIOENV"]) + sdkconfig_h_path = join(env_build,"config","sdkconfig.h") + arduino_libs = ARDUINO_FRMWRK_LIB_DIR + lib_src = join(env_build,"esp-idf") + lib_dst = join(arduino_libs,mcu,"lib") + ld_dst = join(arduino_libs,mcu,"ld") + mem_var = join(arduino_libs,mcu,board.get("build.arduino.memory_type", (board.get("build.flash_mode", "dio") + "_qspi"))) + src = [join(lib_src,x) for x in os.listdir(lib_src)] + src = [folder for folder in src if not os.path.isfile(folder)] # folders only + for folder in src: + files = [join(folder,x) for x in os.listdir(folder)] + for file in files: + if file.strip().endswith(".a"): + shutil.copyfile(file,join(lib_dst,file.split(os.path.sep)[-1])) + + shutil.move(join(lib_dst,"libspi_flash.a"),join(mem_var,"libspi_flash.a")) + shutil.move(join(env_build,"memory.ld"),join(ld_dst,"memory.ld")) + if mcu == "esp32s3": + shutil.move(join(lib_dst,"libesp_psram.a"),join(mem_var,"libesp_psram.a")) + shutil.move(join(lib_dst,"libesp_system.a"),join(mem_var,"libesp_system.a")) + shutil.move(join(lib_dst,"libfreertos.a"),join(mem_var,"libfreertos.a")) + shutil.move(join(lib_dst,"libbootloader_support.a"),join(mem_var,"libbootloader_support.a")) + shutil.move(join(lib_dst,"libesp_hw_support.a"),join(mem_var,"libesp_hw_support.a")) + + shutil.copyfile(sdkconfig_h_path,join(mem_var,"include","sdkconfig.h")) + if not bool(os.path.isfile(join(arduino_libs,mcu,"sdkconfig.orig"))): + shutil.move(join(arduino_libs,mcu,"sdkconfig"),join(arduino_libs,mcu,"sdkconfig.orig")) + shutil.copyfile(join(env.subst("$PROJECT_DIR"),"sdkconfig."+env["PIOENV"]),join(arduino_libs,mcu,"sdkconfig")) + shutil.copyfile(join(env.subst("$PROJECT_DIR"),"sdkconfig."+env["PIOENV"]),join(arduino_libs,"sdkconfig")) + print("*** Copied compiled %s IDF libraries to Arduino framework ***" % idf_variant) + + pio_exe_path = shutil.which("platformio"+(".exe" if IS_WINDOWS else "")) + pio_cmd = env["PIOENV"] + env.Execute( + env.VerboseAction( + ( + '"%s" run -e ' % pio_exe_path + + " ".join(['"%s"' % pio_cmd]) + ), + "*** Starting Arduino compile %s with custom libraries ***" % pio_cmd, + ) + ) + if flag_custom_component_add == True or flag_custom_component_remove == True: + try: + shutil.copy(join(ARDUINO_FRAMEWORK_DIR,"idf_component.yml.orig"),join(ARDUINO_FRAMEWORK_DIR,"idf_component.yml")) + print("*** Original Arduino \"idf_component.yml\" restored ***") + except: + print("*** Original Arduino \"idf_component.yml\" couldnt be restored ***") + env.AddPostAction("checkprogsize", idf_lib_copy) + +if "espidf" in env.get("PIOFRAMEWORK") and (flag_custom_component_add == True or flag_custom_component_remove == True): + def idf_custom_component(source, target, env): + try: + shutil.copy(join(ARDUINO_FRAMEWORK_DIR,"idf_component.yml.orig"),join(ARDUINO_FRAMEWORK_DIR,"idf_component.yml")) + print("*** Original Arduino \"idf_component.yml\" restored ***") + except: + try: + shutil.copy(join(PROJECT_SRC_DIR,"idf_component.yml.orig"),join(PROJECT_SRC_DIR,"idf_component.yml")) + print("*** Original \"idf_component.yml\" restored ***") + except: # no "idf_component.yml" in source folder + try: + os.remove(join(PROJECT_SRC_DIR,"idf_component.yml")) + print("*** pioarduino generated \"idf_component.yml\" removed ***") + except: + print("*** \"idf_component.yml\" couldnt be removed ***") + env.AddPostAction("checkprogsize", idf_custom_component) +# # Process OTA partition and image # @@ -1789,7 +2129,10 @@ ota_partition_params = get_partition_info( if ota_partition_params["size"] and ota_partition_params["offset"]: # Generate an empty image if OTA is enabled in partition table ota_partition_image = os.path.join("$BUILD_DIR", "ota_data_initial.bin") - generate_empty_partition_image(ota_partition_image, ota_partition_params["size"]) + if "arduino" in env.subst("$PIOFRAMEWORK"): + ota_partition_image = os.path.join(ARDUINO_FRAMEWORK_DIR, "tools", "partitions", "boot_app0.bin") + else: + generate_empty_partition_image(ota_partition_image, ota_partition_params["size"]) env.Append( FLASH_EXTRA_IMAGES=[ @@ -1801,18 +2144,61 @@ if ota_partition_params["size"] and ota_partition_params["offset"]: ) ] ) + EXTRA_IMG_DIR = join(env.subst("$PROJECT_DIR"), "variants", "tasmota") + env.Append( + FLASH_EXTRA_IMAGES=[ + (offset, join(EXTRA_IMG_DIR, img)) for offset, img in board.get("upload.arduino.flash_extra_images", []) + ] + ) + +def _parse_size(value): + if isinstance(value, int): + return value + elif value.isdigit(): + return int(value) + elif value.startswith("0x"): + return int(value, 16) + elif value[-1].upper() in ("K", "M"): + base = 1024 if value[-1].upper() == "K" else 1024 * 1024 + return int(value[:-1]) * base + return value # # Configure application partition offset # -env.Replace( - ESP32_APP_OFFSET=get_app_partition_offset( - env.subst("$PARTITIONS_TABLE_CSV"), partition_table_offset - ) -) +partitions_csv = env.subst("$PARTITIONS_TABLE_CSV") +result = [] +next_offset = 0 +bound = int(board.get("upload.offset_address", "0x10000"), 16) # default 0x10000 +with open(partitions_csv) as fp: + for line in fp.readlines(): + line = line.strip() + if not line or line.startswith("#"): + continue + tokens = [t.strip() for t in line.split(",")] + if len(tokens) < 5: + continue + partition = { + "name": tokens[0], + "type": tokens[1], + "subtype": tokens[2], + "offset": tokens[3] or next_offset, + "size": tokens[4], + "flags": tokens[5] if len(tokens) > 5 else None + } + result.append(partition) + next_offset = _parse_size(partition["offset"]) + if (partition["subtype"] == "ota_0"): + bound = next_offset + next_offset = (next_offset + bound - 1) & ~(bound - 1) +env.Replace(ESP32_APP_OFFSET=str(hex(bound))) + +# # Propagate application offset to debug configurations +# + env["INTEGRATION_EXTRA_DATA"].update( {"application_offset": env.subst("$ESP32_APP_OFFSET")} ) From adc0a17a065b7edfa17e032ebb29e6691cd9ea88 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:43:51 +0100 Subject: [PATCH 082/117] Update arduino.py --- builder/frameworks/arduino.py | 174 ++++++++++++++++++++++++++++++++-- 1 file changed, 168 insertions(+), 6 deletions(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 4af76df..b58527f 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -22,17 +22,179 @@ kinds of creative coding, interactive objects, spaces or physical experiences. http://arduino.cc/en/Reference/HomePage """ +import subprocess +import json +import semantic_version +import os +import shutil from os.path import join -from SCons.Script import DefaultEnvironment, SConscript +from SCons.Script import COMMAND_LINE_TARGETS, DefaultEnvironment, SConscript +from platformio.package.version import pepver_to_semver +from platformio.project.config import ProjectConfig +from platformio.package.manager.tool import ToolPackageManager env = DefaultEnvironment() +pm = ToolPackageManager() +platform = env.PioPlatform() +config = env.GetProjectConfig() board = env.BoardConfig() -build_core = board.get("build.core", "").lower() +mcu = board.get("build.mcu", "esp32") +board_sdkconfig = board.get("espidf.custom_sdkconfig", "") +entry_custom_sdkconfig = "\n" +flag_custom_sdkconfig = False + +if config.has_option("env:"+env["PIOENV"], "custom_sdkconfig"): + entry_custom_sdkconfig = env.GetProjectOption("custom_sdkconfig") + flag_custom_sdkconfig = True + +if len(str(board_sdkconfig)) > 2: + flag_custom_sdkconfig = True + +extra_flags = (''.join([element for element in board.get("build.extra_flags", "")])).replace("-D", " ") +framework_reinstall = False +flag_any_custom_sdkconfig = False SConscript("_embed_files.py", exports="env") -if "espidf" not in env.subst("$PIOFRAMEWORK"): - SConscript( - join(DefaultEnvironment().PioPlatform().get_package_dir( - "framework-arduinoespressif32"), "tools", "platformio-build.py")) +flag_any_custom_sdkconfig = os.path.exists(join(platform.get_package_dir("framework-arduinoespressif32-libs"),"sdkconfig")) + +# Esp32-solo1 libs needs adopted settings +if flag_custom_sdkconfig == True and ("CORE32SOLO1" in extra_flags or "CONFIG_FREERTOS_UNICORE=y" in entry_custom_sdkconfig or "CONFIG_FREERTOS_UNICORE=y" in board_sdkconfig): + if len(str(env.GetProjectOption("build_unflags"))) == 2: # No valid env, needs init + env['BUILD_UNFLAGS'] = {} + build_unflags = " ".join(env['BUILD_UNFLAGS']) + build_unflags = build_unflags + " -mdisable-hardware-atomics -ustart_app_other_cores" + new_build_unflags = build_unflags.split() + env.Replace( + BUILD_UNFLAGS=new_build_unflags + ) + +def install_python_deps(): + def _get_installed_pip_packages(): + result = {} + packages = {} + pip_output = subprocess.check_output( + [ + env.subst("$PYTHONEXE"), + "-m", + "pip", + "list", + "--format=json", + "--disable-pip-version-check", + ] + ) + try: + packages = json.loads(pip_output) + except: + print("Warning! Couldn't extract the list of installed Python packages.") + return {} + for p in packages: + result[p["name"]] = pepver_to_semver(p["version"]) + + return result + + deps = { + "wheel": ">=0.35.1", + "PyYAML": ">=6.0.2", + "intelhex": ">=2.3.0" + } + + installed_packages = _get_installed_pip_packages() + packages_to_install = [] + for package, spec in deps.items(): + if package not in installed_packages: + packages_to_install.append(package) + else: + version_spec = semantic_version.Spec(spec) + if not version_spec.match(installed_packages[package]): + packages_to_install.append(package) + + if packages_to_install: + env.Execute( + env.VerboseAction( + ( + '"$PYTHONEXE" -m pip install -U ' + + " ".join( + [ + '"%s%s"' % (p, deps[p]) + for p in packages_to_install + ] + ) + ), + "Installing Arduino Python dependencies", + ) + ) + return + +install_python_deps() + +def get_MD5_hash(phrase): + import hashlib + return hashlib.md5((phrase).encode('utf-8')).hexdigest()[:16] + + +def matching_custom_sdkconfig(): + # check if current env is matching to existing sdkconfig + cust_sdk_is_present = False + matching_sdkconfig = False + last_sdkconfig_path = join(env.subst("$PROJECT_DIR"),"sdkconfig.defaults") + if flag_any_custom_sdkconfig == False: + matching_sdkconfig = True + return matching_sdkconfig, cust_sdk_is_present + if os.path.exists(last_sdkconfig_path) == False: + return matching_sdkconfig, cust_sdk_is_present + if flag_custom_sdkconfig == False: + matching_sdkconfig = False + return matching_sdkconfig, cust_sdk_is_present + with open(last_sdkconfig_path) as src: + line = src.readline() + if line.startswith("# TASMOTA__"): + cust_sdk_is_present = True; + costum_options = entry_custom_sdkconfig + if (line.split("__")[1]).strip() == get_MD5_hash((costum_options).strip() + mcu): + matching_sdkconfig = True + + return matching_sdkconfig, cust_sdk_is_present + +def check_reinstall_frwrk(): + framework_reinstall = False + cust_sdk_is_present = False + matching_sdkconfig = False + if flag_custom_sdkconfig == True: + matching_sdkconfig, cust_sdk_is_present = matching_custom_sdkconfig() + if flag_custom_sdkconfig == False and flag_any_custom_sdkconfig == True: + # case custom sdkconfig exists and a env without "custom_sdkconfig" + framework_reinstall = True + if flag_custom_sdkconfig == True and matching_sdkconfig == False: + # check if current custom sdkconfig is different from existing + framework_reinstall = True + return framework_reinstall + +def call_compile_libs(): + if mcu == "esp32c2": + ARDUINO_FRMWRK_C2_LIB_DIR = join(platform.get_package_dir("framework-arduinoespressif32-libs"),mcu) + ARDUINO_C2_DIR = join(platform.get_package_dir("framework-arduino-c2-skeleton-lib"),mcu) + shutil.copytree(ARDUINO_C2_DIR, ARDUINO_FRMWRK_C2_LIB_DIR, dirs_exist_ok=True) + print("*** Compile Arduino IDF libs for %s ***" % env["PIOENV"]) + SConscript("espidf.py") + +if check_reinstall_frwrk() == True: + print("*** Reinstall Arduino framework libs ***") + shutil.rmtree(platform.get_package_dir("framework-arduinoespressif32-libs")) + ARDUINO_FRMWRK_LIB_URL = str(platform.get_package_spec("framework-arduinoespressif32-libs")).split("uri=",1)[1][:-1] + pm.install(ARDUINO_FRMWRK_LIB_URL) + if flag_custom_sdkconfig == True: + call_compile_libs() + flag_custom_sdkconfig = False + +if flag_custom_sdkconfig == True and flag_any_custom_sdkconfig == False: + call_compile_libs() + +if "arduino" in env.subst("$PIOFRAMEWORK") and "espidf" not in env.subst("$PIOFRAMEWORK") and env.subst("$ARDUINO_LIB_COMPILE_FLAG") in ("Inactive", "True"): + if os.path.exists(join(platform.get_package_dir( + "framework-arduinoespressif32"), "tools", "platformio-build.py")): + PIO_BUILD = "platformio-build.py" + else: + PIO_BUILD = "pioarduino-build.py" + SConscript(join(platform.get_package_dir("framework-arduinoespressif32"), "tools", PIO_BUILD)) From 592e664412d6a7747b13df0622e27873be465bc0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:44:49 +0100 Subject: [PATCH 083/117] Update ulp.py --- builder/frameworks/ulp.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 25266e5..7965df1 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -36,7 +36,7 @@ def prepare_ulp_env_vars(env): ulp_env.PrependENVPath("IDF_PATH", FRAMEWORK_DIR) toolchain_path = platform.get_package_dir( - "toolchain-xtensa-%s" % idf_variant + "toolchain-xtensa-esp-elf" if idf_variant not in ("esp32c6", "esp32p4") else "toolchain-riscv32-esp" ) @@ -116,8 +116,7 @@ def generate_ulp_config(target_config): "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), "-DPYTHON=" + env.subst("$PYTHONEXE"), - "-DULP_COCPU_IS_RISCV=%s" % ("ON" if riscv_ulp_enabled else "OFF"), - "-DULP_COCPU_IS_LP_CORE=%s" % ("ON" if lp_core_ulp_enabled else "OFF"), + "-DSDKCONFIG_CMAKE=" + os.path.join(BUILD_DIR, "config", "sdkconfig.cmake"), "-GNinja", "-B", ULP_BUILD_DIR, From 36c9d77fb24931d375b0993259e4e7348b99ae8a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:45:55 +0100 Subject: [PATCH 084/117] Update platform.py --- platform.py | 210 +++++++--------------------------------------------- 1 file changed, 25 insertions(+), 185 deletions(-) diff --git a/platform.py b/platform.py index 372d229..b220baa 100644 --- a/platform.py +++ b/platform.py @@ -18,10 +18,8 @@ import sys import json import re import requests -from os.path import isfile, join from platformio.public import PlatformBase, to_unix_path -from platformio.project.config import ProjectConfig IS_WINDOWS = sys.platform.startswith("win") @@ -39,32 +37,26 @@ class Espressif32Platform(PlatformBase): board_config = self.board_config(variables.get("board")) mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32")) + board_sdkconfig = variables.get("board_espidf.custom_sdkconfig", board_config.get("espidf.custom_sdkconfig", "")) + core_variant_board = ''.join(variables.get("board_build.extra_flags", board_config.get("build.extra_flags", ""))) + core_variant_board = core_variant_board.replace("-D", " ") + core_variant_build = (''.join(variables.get("build_flags", []))).replace("-D", " ") frameworks = variables.get("pioframework", []) - if variables.get("custom_sdkconfig") is not None: - frameworks.append("espidf") - if "arduino" in frameworks: self.packages["framework-arduinoespressif32"]["optional"] = False self.packages["framework-arduinoespressif32-libs"]["optional"] = False - ARDUINO_FRAMEWORK_DIR = os.path.join(ProjectConfig.get_instance().get("platformio", "packages_dir"), "framework-arduinoespressif32") - if not bool(os.path.exists(ARDUINO_FRAMEWORK_DIR)): - try: - # use latest stable release Arduino core - ARDUINO_CORE_API_URL = "https://api.github.com/repos/espressif/Arduino-esp32/releases/latest" - api_data = requests.get(ARDUINO_CORE_API_URL, timeout=2).json() - zipball = api_data.get("zipball_url") - tag = api_data.get("tag_name") - if tag is not None: - # print("Latest release Arduino core URL:", zipball) - self.packages["framework-arduinoespressif32"]["version"] = zipball - # use corresponding espressif Arduino libs to release - URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/" + tag + "/package/package_esp32_index.template.json" - packjdata = requests.get(URL, timeout=10).json() - dyn_lib_url = packjdata['packages'][0]['tools'][0]['systems'][0]['url'] - self.packages["framework-arduinoespressif32-libs"]["version"] = dyn_lib_url - except: - pass + # use latest espressif Arduino libs + URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/release/v3.1.x/package/package_esp32_index.template.json" + packjdata = requests.get(URL).json() + dyn_lib_url = packjdata['packages'][0]['tools'][0]['systems'][0]['url'] + self.packages["framework-arduinoespressif32-libs"]["version"] = dyn_lib_url + + if variables.get("custom_sdkconfig") is not None or len(str(board_sdkconfig)) > 3: + frameworks.append("espidf") + self.packages["framework-espidf"]["optional"] = False + if mcu == "esp32c2": + self.packages["framework-arduino-c2-skeleton-lib"]["optional"] = False if "buildfs" in targets: filesystem = variables.get("board_build.filesystem", "littlefs") @@ -91,52 +83,12 @@ class Espressif32Platform(PlatformBase): else: del self.packages["tool-dfuutil-arduino"] - build_core = variables.get( - "board_build.core", board_config.get("build.core", "arduino") - ).lower() - - if frameworks == ["arduino"] and build_core == "esp32": - # In case the upstream Arduino framework is specified in the configuration - # file then we need to dynamically extract toolchain versions from the - # Arduino index file. This feature can be disabled via a special option: - if ( - variables.get( - "board_build.arduino.upstream_packages", - board_config.get("build.arduino.upstream_packages", "no"), - ).lower() - == "yes" - ): - package_version = self.packages["framework-arduinoespressif32"][ - "version" - ] - - url_items = urllib.parse.urlparse(package_version) - # Only GitHub repositories support dynamic packages - if ( - url_items.scheme in ("http", "https") - and url_items.netloc.startswith("github") - and url_items.path.endswith(".git") - ): - try: - self.configure_upstream_arduino_packages(url_items) - except Exception as e: - sys.stderr.write( - "Error! Failed to extract upstream toolchain" - "configurations:\n%s\n" % str(e) - ) - sys.stderr.write( - "You can disable this feature via the " - "`board_build.arduino.upstream_packages = no` setting in " - "your `platformio.ini` file.\n" - ) - sys.exit(1) - # Starting from v12, Espressif's toolchains are shipped without # bundled GDB. Instead, it's distributed as separate packages for Xtensa # and RISC-V targets. for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"): self.packages[gdb_package]["optional"] = False - #if IS_WINDOWS: + # if IS_WINDOWS: # Note: On Windows GDB v12 is not able to # launch a GDB server in pipe mode while v11 works fine # self.packages[gdb_package]["version"] = "~11.2.0" @@ -145,19 +97,18 @@ class Espressif32Platform(PlatformBase): if "espidf" in frameworks: self.packages["toolchain-esp32ulp"]["optional"] = False for p in self.packages: - if p in ("tool-cmake", "tool-ninja"): + if p in ("tool-scons", "tool-cmake", "tool-ninja"): self.packages[p]["optional"] = False -# elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: -# self.packages[p]["optional"] = False + # elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: + # self.packages[p]["optional"] = False - for available_mcu in ("esp32", "esp32s2", "esp32s3"): - if available_mcu == mcu: - self.packages["toolchain-xtensa-%s" % mcu]["optional"] = False - else: - self.packages.pop("toolchain-xtensa-%s" % available_mcu, None) + if mcu in ("esp32", "esp32s2", "esp32s3"): + self.packages["toolchain-xtensa-esp-elf"]["optional"] = False + else: + self.packages.pop("toolchain-xtensa-esp-elf", None) - if mcu in ("esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2"): - if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2"): + if mcu in ("esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"): + if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"): self.packages.pop("toolchain-esp32ulp", None) # RISC-V based toolchain for ESP32C3, ESP32C6 ESP32S2, ESP32S3 ULP self.packages["toolchain-riscv32-esp"]["optional"] = False @@ -310,114 +261,3 @@ class Espressif32Platform(PlatformBase): ) ) debug_config.load_cmds = load_cmds - - - @staticmethod - def extract_toolchain_versions(tool_deps): - def _parse_version(original_version): - assert original_version - version_patterns = ( - r"^gcc(?P\d+)_(?P\d+)_(?P\d+)-esp-(?P.+)$", - r"^esp-(?P.+)-(?P\d+)\.(?P\d+)\.?(?P\d+)$", - r"^esp-(?P\d+)\.(?P\d+)\.(?P\d+)(_(?P.+))?$", - ) - for pattern in version_patterns: - match = re.search(pattern, original_version) - if match: - result = "%s.%s.%s" % ( - match.group("MAJOR"), - match.group("MINOR"), - match.group("PATCH"), - ) - if match.group("EXTRA"): - result = result + "+%s" % match.group("EXTRA") - return result - - raise ValueError("Bad package version `%s`" % original_version) - - if not tool_deps: - raise ValueError( - ("Failed to extract tool dependencies from the remote package file") - ) - - toolchain_remap = { - "xtensa-esp32-elf-gcc": "toolchain-xtensa-esp32", - "xtensa-esp32s2-elf-gcc": "toolchain-xtensa-esp32s2", - "xtensa-esp32s3-elf-gcc": "toolchain-xtensa-esp32s3", - "riscv32-esp-elf-gcc": "toolchain-riscv32-esp", - } - - result = dict() - for tool in tool_deps: - if tool["name"] in toolchain_remap: - result[toolchain_remap[tool["name"]]] = _parse_version(tool["version"]) - - return result - - @staticmethod - def parse_tool_dependencies(index_data): - for package in index_data.get("packages", []): - if package["name"] == "esp32": - for platform in package["platforms"]: - if platform["name"] == "esp32": - return platform["toolsDependencies"] - - return [] - - @staticmethod - def download_remote_package_index(url_items): - def _prepare_url_for_index_file(url_items): - tag = "master" - if url_items.fragment: - tag = url_items.fragment - return ( - "https://raw.githubusercontent.com/%s/" - "%s/package/package_esp32_index.template.json" - % (url_items.path.replace(".git", ""), tag) - ) - - index_file_url = _prepare_url_for_index_file(url_items) - - try: - from platformio.public import fetch_http_content - content = fetch_http_content(index_file_url) - except ImportError: - import requests - content = requests.get(index_file_url, timeout=5).text - - return json.loads(content) - - def configure_arduino_toolchains(self, package_index): - if not package_index: - return - - toolchain_packages = self.extract_toolchain_versions( - self.parse_tool_dependencies(package_index) - ) - for toolchain_package, version in toolchain_packages.items(): - if toolchain_package not in self.packages: - self.packages[toolchain_package] = dict() - self.packages[toolchain_package]["version"] = version - self.packages[toolchain_package]["owner"] = "espressif" - self.packages[toolchain_package]["type"] = "toolchain" - - def configure_upstream_arduino_packages(self, url_items): - framework_index_file = os.path.join( - self.get_package_dir("framework-arduinoespressif32") or "", - "package", - "package_esp32_index.template.json", - ) - - # Detect whether the remote is already cloned - if os.path.isfile(framework_index_file) and os.path.isdir( - os.path.join( - self.get_package_dir("framework-arduinoespressif32") or "", ".git" - ) - ): - with open(framework_index_file) as fp: - self.configure_arduino_toolchains(json.load(fp)) - else: - print("Configuring toolchain packages from a remote source...") - self.configure_arduino_toolchains( - self.download_remote_package_index(url_items) - ) From 37d976f539cd3b708f2791ce5e2d536ffc1f8c97 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:46:40 +0100 Subject: [PATCH 085/117] Update platform.json --- platform.json | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/platform.json b/platform.json index 4461d67..7659969 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "51.03.0x-stable", + "version": "53.03.10+develop", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "" + "version": "https://github.com/espressif/arduino-esp32/archive/refs/heads/release/v3.1.x.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", @@ -41,53 +41,47 @@ "owner": "espressif", "version": "" }, + "framework-arduino-c2-skeleton-lib": { + "type": "framework", + "optional": true, + "owner": "espressif", + "version": "https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/c2_arduino_compile_skeleton.zip" + }, "framework-espidf": { "type": "framework", "optional": true, "owner": "pioarduino", - "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.1.5/esp-idf-v5.1.5.zip" + "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.3.2.241012/esp-idf-v5.3.2.zip" }, - "toolchain-xtensa-esp32": { + "toolchain-xtensa-esp-elf": { "type": "toolchain", "optional": true, - "owner": "espressif", - "version": "12.2.0+20230208" - }, - "toolchain-xtensa-esp32s2": { - "type": "toolchain", - "optional": true, - "owner": "espressif", - "version": "12.2.0+20230208" - }, - "toolchain-xtensa-esp32s3": { - "type": "toolchain", - "optional": true, - "owner": "espressif", - "version": "12.2.0+20230208" + "owner": "platformio", + "version": "13.2.0+20240530" }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, - "owner": "espressif", - "version": "12.2.0+20230208" + "owner": "platformio", + "version": "13.2.0+20240530" }, "toolchain-esp32ulp": { "type": "toolchain", "optional": true, "owner": "platformio", - "version": "~1.23500.0" + "version": "~1.23800.0" }, "tool-xtensa-esp-elf-gdb": { "type": "debugger", "optional": true, - "owner": "espressif", - "version": "~12.1.0" + "owner": "platformio", + "version": "14.2.0+20240403" }, "tool-riscv32-esp-elf-gdb": { "type": "debugger", "optional": true, - "owner": "espressif", - "version": "~12.1.0" + "owner": "platformio", + "version": "14.2.0+20240403" }, "tool-esptoolpy": { "type": "uploader", From 817a1d5881a4559b500a30cb1cec5228ecbd13d2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:47:52 +0100 Subject: [PATCH 086/117] Update Zigbee_On_Off_Light.ino --- .../src/Zigbee_On_Off_Light.ino | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/examples/arduino-zigbee-light/src/Zigbee_On_Off_Light.ino b/examples/arduino-zigbee-light/src/Zigbee_On_Off_Light.ino index 2f13357..6db8bd7 100644 --- a/examples/arduino-zigbee-light/src/Zigbee_On_Off_Light.ino +++ b/examples/arduino-zigbee-light/src/Zigbee_On_Off_Light.ino @@ -30,28 +30,30 @@ #error "Zigbee end device mode is not selected in Tools->Zigbee mode" #endif -#include "ZigbeeCore.h" -#include "ep/ZigbeeLight.h" +#include "Zigbee.h" -#define LED_PIN RGB_BUILTIN -#define BUTTON_PIN 9 // ESP32-C6/H2 Boot button +/* Zigbee light bulb configuration */ #define ZIGBEE_LIGHT_ENDPOINT 10 +uint8_t led = RGB_BUILTIN; +uint8_t button = BOOT_PIN; ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT); /********************* RGB LED functions **************************/ void setLED(bool value) { - digitalWrite(LED_PIN, value); + digitalWrite(led, value); } /********************* Arduino functions **************************/ void setup() { + Serial.begin(115200); + // Init LED and turn it OFF (if LED_PIN == RGB_BUILTIN, the rgbLedWrite() will be used under the hood) - pinMode(LED_PIN, OUTPUT); - digitalWrite(LED_PIN, LOW); + pinMode(led, OUTPUT); + digitalWrite(led, LOW); // Init button for factory reset - pinMode(BUTTON_PIN, INPUT); + pinMode(button, INPUT_PULLUP); //Optional: set Zigbee device name and model zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb"); @@ -60,28 +62,40 @@ void setup() { zbLight.onLightChange(setLED); //Add endpoint to Zigbee Core - log_d("Adding ZigbeeLight endpoint to Zigbee Core"); + Serial.println("Adding ZigbeeLight endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbLight); // When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE - log_d("Calling Zigbee.begin()"); - Zigbee.begin(); + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); } void loop() { // Checking button for factory reset - if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed + if (digitalRead(button) == LOW) { // Push button pressed // Key debounce handling delay(100); int startTime = millis(); - while (digitalRead(BUTTON_PIN) == LOW) { + while (digitalRead(button) == LOW) { delay(50); if ((millis() - startTime) > 3000) { // If key pressed for more than 3secs, factory reset Zigbee and reboot - Serial.printf("Resetting Zigbee to factory settings, reboot.\n"); + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); Zigbee.factoryReset(); } } + // Toggle light by pressing the button + zbLight.setLight(!zbLight.getLightState()); } delay(100); } From 36a9b3c1f8a304841362462b97a00bdce2290081 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:48:40 +0100 Subject: [PATCH 087/117] Update Zigbee_On_Off_Switch.ino --- .../src/Zigbee_On_Off_Switch.ino | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/examples/arduino-zigbee-switch/src/Zigbee_On_Off_Switch.ino b/examples/arduino-zigbee-switch/src/Zigbee_On_Off_Switch.ino index 09487de..56d23cd 100644 --- a/examples/arduino-zigbee-switch/src/Zigbee_On_Off_Switch.ino +++ b/examples/arduino-zigbee-switch/src/Zigbee_On_Off_Switch.ino @@ -31,13 +31,12 @@ #error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" #endif -#include "ZigbeeCore.h" -#include "ep/ZigbeeSwitch.h" +#include "Zigbee.h" +/* Zigbee switch configuration */ #define SWITCH_ENDPOINT_NUMBER 5 -/* Switch configuration */ -#define GPIO_INPUT_IO_TOGGLE_SWITCH 9 +#define GPIO_INPUT_IO_TOGGLE_SWITCH BOOT_PIN #define PAIR_SIZE(TYPE_STR_PAIR) (sizeof(TYPE_STR_PAIR) / sizeof(TYPE_STR_PAIR[0])) typedef enum { @@ -71,6 +70,7 @@ ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); static void onZbButton(SwitchData *button_func_pair) { if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { // Send toggle command to the light + Serial.println("Toggling light"); zbSwitch.lightToggle(); } } @@ -94,11 +94,7 @@ static void enableGpioInterrupt(bool enabled) { /********************* Arduino functions **************************/ void setup() { - Serial.begin(115200); - while (!Serial) { - delay(10); - } //Optional: set Zigbee device name and model zbSwitch.setManufacturerAndModel("Espressif", "ZigbeeSwitch"); @@ -107,7 +103,7 @@ void setup() { zbSwitch.allowMultipleBinding(true); //Add endpoint to Zigbee Core - log_d("Adding ZigbeeSwitch endpoint to Zigbee Core"); + Serial.println("Adding ZigbeeSwitch endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbSwitch); //Open network for 180 seconds after boot @@ -119,34 +115,36 @@ void setup() { /* create a queue to handle gpio event from isr */ gpio_evt_queue = xQueueCreate(10, sizeof(SwitchData)); if (gpio_evt_queue == 0) { - log_e("Queue was not created and must not be used"); - while (1); + Serial.println("Queue creating failed, rebooting..."); + ESP.restart(); } attachInterruptArg(buttonFunctionPair[i].pin, onGpioInterrupt, (void *)(buttonFunctionPair + i), FALLING); } // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode - log_d("Calling Zigbee.begin()"); - Zigbee.begin(ZIGBEE_COORDINATOR); + if (!Zigbee.begin(ZIGBEE_COORDINATOR)) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } Serial.println("Waiting for Light to bound to the switch"); //Wait for switch to bound to a light: - while (!zbSwitch.isBound()) { + while (!zbSwitch.bound()) { Serial.printf("."); delay(500); } - // Optional: read manufacturer and model name from the bound light + // Optional: List all bound devices and read manufacturer and model name std::list boundLights = zbSwitch.getBoundDevices(); - //List all bound lights for (const auto &device : boundLights) { - Serial.printf("Device on endpoint %d, short address: 0x%x\n", device->endpoint, device->short_addr); + Serial.printf("Device on endpoint %d, short address: 0x%x\r\n", device->endpoint, device->short_addr); Serial.printf( - "IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", device->ieee_addr[0], device->ieee_addr[1], device->ieee_addr[2], device->ieee_addr[3], - device->ieee_addr[4], device->ieee_addr[5], device->ieee_addr[6], device->ieee_addr[7] + "IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\r\n", device->ieee_addr[7], device->ieee_addr[6], device->ieee_addr[5], device->ieee_addr[4], + device->ieee_addr[3], device->ieee_addr[2], device->ieee_addr[1], device->ieee_addr[0] ); - Serial.printf("Light manufacturer: %s", zbSwitch.readManufacturer(device->endpoint, device->short_addr)); - Serial.printf("Light model: %s", zbSwitch.readModel(device->endpoint, device->short_addr)); + Serial.printf("Light manufacturer: %s\r\n", zbSwitch.readManufacturer(device->endpoint, device->short_addr, device->ieee_addr)); + Serial.printf("Light model: %s\r\n", zbSwitch.readModel(device->endpoint, device->short_addr, device->ieee_addr)); } Serial.println(); @@ -189,6 +187,6 @@ void loop() { static uint32_t lastPrint = 0; if (millis() - lastPrint > 10000) { lastPrint = millis(); - zbSwitch.printBoundDevices(); + zbSwitch.printBoundDevices(Serial); } } From 8dfbd3c2dd897ed9809a9d214eb358cae1b1dc72 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:49:36 +0100 Subject: [PATCH 088/117] Update idf_component.yml --- examples/espidf-arduino-h2zero-BLE_scan/src/idf_component.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/espidf-arduino-h2zero-BLE_scan/src/idf_component.yml b/examples/espidf-arduino-h2zero-BLE_scan/src/idf_component.yml index 98b4cbf..0d925b9 100644 --- a/examples/espidf-arduino-h2zero-BLE_scan/src/idf_component.yml +++ b/examples/espidf-arduino-h2zero-BLE_scan/src/idf_component.yml @@ -4,6 +4,7 @@ dependencies: esp-nimble-cpp: git: https://github.com/h2zero/esp-nimble-cpp.git + version: 877a29a8b1d0022c5e8f67ba8b879316e67b6c3d # # Defining a dependency from the registry: From a7fb6cdad7047e3c1bf4b0c61928c8a749b50ff9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:50:17 +0100 Subject: [PATCH 089/117] Update README.md --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 01ac2d4..417f812 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with integrated Wi-Fi and Bluetooth. ESP32 integrates an antenna switch, RF balun, power amplifier, low-noise receive amplifier, filters, and power management modules. * [Documentation](https://docs.platformio.org/page/platforms/espressif32.html) (advanced usage, packages, boards, frameworks, etc.) -* Issues with boards (wrong / missing). All issues caused from boards will **not** be fixed from the maintainer(s). A PR needs to be provided to solve. +* Issues with boards (wrong / missing). All issues caused from boards will not be fixed from the maintainer(s). A PR needs to be provided to solve. ## IDE Preparation @@ -35,7 +35,6 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with 1. Configure a platform option in [platformio.ini](https://docs.platformio.org/page/projectconf.html) file: ### Stable version -currently espressif Arduino 3.0.7 and IDF 5.1.4+ See `platform` [documentation](https://docs.platformio.org/en/latest/projectconf/sections/env/options/platform/platform.html#projectconf-env-platform) for details. @@ -47,11 +46,11 @@ board = ... ``` ### Development version -espressif Arduino repo branch master and latest compiled Arduino libs +based on devel branch Arduino 3.1.0 and IDF 5.3.2 ```ini [env:development] -platform = https://github.com/pioarduino/platform-espressif32.git#develop +platform = https://github.com/pioarduino/platform-espressif32.git#Arduino/IDF53 board = ... ... ``` From e4ac072ea981b2b05283a092882203237dede69e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:50:40 +0100 Subject: [PATCH 090/117] Arduino 3.1.x based on IDF 5.3.x (#74) * IDF 5.3 support * IDF 5.3 * IDF 5.3 toolchains remove dynamic toolchains support, currently only older incompatible are possible to fetch. * Fix owner of * ULP compability for IDF 5.3 * remove debug print * Fix bootloader offset code retrieve * Update esp32-c6-devkitc-1.json * use espressif Arduino branch `release/v3.1.x` * Update README.md * Update README.md * Fix compile issue with managed components * use latest Arduino 3.1.0 libs * fetch Arduino libs dl URL from manifest json * fetch Arduino libs dl URL from manifest json * Update README.md * Fix IDF 5.3 ULP compile * Use espressif Arduino branch release/v3.1.x * Update platform.py * better handling of complex Macros from cmake model * IDF 5.3.1 release * fix handling of cc fragments * unchanged IDF 5.3.1 * ULP has now a cmake build script * add arduino/idf examples * fix used platform * prepare LP ULP support * enable bootloader components build * ULP LP support * add missing P4 * add P4 * change some if checks * Update README.md * remove wrong left over code * add ULP LP example / update Matter example * fix path * add zigbee examples * disable zigbee examples needs merge of the open zigbee Arduino PR * esptool.py v4.8.0 * add cmake_utilities for C2 * add auto select "espidf" when pio var "custom_sdkconfig" is set * IDF v5.3.1.240924 * Update main.py * matter example currently broken * Update platformio.ini * Update platformio.ini * Update platformio.ini * Update platformio.ini * Update examples.yml * IDF v5.3.1.241016 * Update Zigbee_On_Off_Light.ino * Update Zigbee_On_Off_Switch.ino * Update examples.yml * Update platformio.ini * Update platformio.ini * Update examples.yml * esptool.py v4.8.1.1 s2 s3 usb jtag reset fix * Update platform.py * Update gdb 14.2.0+20240403 * fix owner for gdb * Update IDF v5.3.1.241024 * Update adafruit_matrixportal_esp32s3.json * Use compatible h2zero NimBLE git commit * Update Zigbee_On_Off_Light.ino * Update Zigbee_On_Off_Switch.ino * fix custom partiton table offset calculation * Update README.md * Create esp32-p4.json * add P4 to blink example * Update Zigbee_On_Off_Switch.ino * Update Zigbee_On_Off_Light.ino * Update sdkconfig.defaults * add P4 to LP example * Create esp32-p4-evboard.json * IDF 5.3.2 release * prep for "pioarduino-build.py" script * add missing import os * fix not defined var * Update Zigbee_On_Off_Switch.ino * esptool.py v4.8.5 * Update Zigbee_On_Off_Light.ino * add Hybrid Compile (#73) * Update README.md * set Arduino compile option `UPDATE_NOCRYPT` in example Tasmota * Update C2 Hybrid compile skeleton * Update IDF v5.3.2.241210 * Revert to IDF 5.3.2 * Update pioarduino IDF 5.2 * Update release_zips.yml --- boards/adafruit_matrixportal_esp32s3.json | 4 +- boards/esp32-p4-evboard.json | 37 ++++++++ boards/esp32-p4.json | 34 +++++++ boards/esp32-solo1.json | 7 +- boards/esp32s3_120_16_8-qio_opi.json | 50 ++++++++++ builder/build_lib/CMakeLists.txt | 1 + builder/build_lib/arduino-lib-builder-as.S | 0 builder/build_lib/arduino-lib-builder-cpp.cpp | 0 builder/build_lib/arduino-lib-builder-gcc.c | 0 builder/build_lib/idf_component.yml | 12 +++ builder/build_lib/sketch.cpp | 10 ++ builder/frameworks/_embed_files.py | 6 +- builder/main.py | 19 ++-- examples/arduino-blink/platformio.ini | 92 ++++++++++++++++++- examples/espidf-ulp-lp/CMakeLists.txt | 4 + examples/espidf-ulp-lp/README.md | 51 ++++++++++ examples/espidf-ulp-lp/platformio.ini | 18 ++++ examples/espidf-ulp-lp/pytest_lp_core_pcnt.py | 30 ++++++ examples/espidf-ulp-lp/sdkconfig.defaults | 11 +++ examples/espidf-ulp-lp/src/CMakeLists.txt | 23 +++++ examples/espidf-ulp-lp/src/Kconfig.projbuild | 20 ++++ .../src/lp_core_pulse_counter_example_main.c | 85 +++++++++++++++++ examples/espidf-ulp-lp/ulp/main.c | 64 +++++++++++++ examples/tasmota_platformio_override.ini | 38 ++++++++ 24 files changed, 597 insertions(+), 19 deletions(-) create mode 100644 boards/esp32-p4-evboard.json create mode 100644 boards/esp32-p4.json create mode 100644 boards/esp32s3_120_16_8-qio_opi.json create mode 100644 builder/build_lib/CMakeLists.txt create mode 100644 builder/build_lib/arduino-lib-builder-as.S create mode 100644 builder/build_lib/arduino-lib-builder-cpp.cpp create mode 100644 builder/build_lib/arduino-lib-builder-gcc.c create mode 100644 builder/build_lib/idf_component.yml create mode 100644 builder/build_lib/sketch.cpp create mode 100644 examples/espidf-ulp-lp/CMakeLists.txt create mode 100644 examples/espidf-ulp-lp/README.md create mode 100644 examples/espidf-ulp-lp/platformio.ini create mode 100644 examples/espidf-ulp-lp/pytest_lp_core_pcnt.py create mode 100644 examples/espidf-ulp-lp/sdkconfig.defaults create mode 100644 examples/espidf-ulp-lp/src/CMakeLists.txt create mode 100644 examples/espidf-ulp-lp/src/Kconfig.projbuild create mode 100644 examples/espidf-ulp-lp/src/lp_core_pulse_counter_example_main.c create mode 100644 examples/espidf-ulp-lp/ulp/main.c create mode 100644 examples/tasmota_platformio_override.ini diff --git a/boards/adafruit_matrixportal_esp32s3.json b/boards/adafruit_matrixportal_esp32s3.json index df10505..12bb6b7 100644 --- a/boards/adafruit_matrixportal_esp32s3.json +++ b/boards/adafruit_matrixportal_esp32s3.json @@ -1,8 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld", - "partitions": "partitions-8MB-tinyuf2.csv" + "partitions": "tinyuf2-partitions-8MB.csv", + "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": [ diff --git a/boards/esp32-p4-evboard.json b/boards/esp32-p4-evboard.json new file mode 100644 index 0000000..1ea9283 --- /dev/null +++ b/boards/esp32-p4-evboard.json @@ -0,0 +1,37 @@ +{ + "build": { + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "360000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32p4", + "variant": "esp32p4" + }, + "arduino": { + "partitions": "default_16MB.csv" + }, + "connectivity": [ + "bluetooth", + "openthread" + ], + "debug": { + "openocd_target": "esp32p4.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-P4 Function EV Board", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 512000, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 1500000 + }, + "url": "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4-function-ev-board/index.html", + "vendor": "Espressif" +} diff --git a/boards/esp32-p4.json b/boards/esp32-p4.json new file mode 100644 index 0000000..0a05148 --- /dev/null +++ b/boards/esp32-p4.json @@ -0,0 +1,34 @@ +{ + "build": { + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "360000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32p4", + "variant": "esp32p4" + }, + "connectivity": [ + "bluetooth", + "openthread" + ], + "debug": { + "openocd_target": "esp32p4.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-P4 generic", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com", + "vendor": "Espressif" +} diff --git a/boards/esp32-solo1.json b/boards/esp32-solo1.json index 7ec0f3a..906772b 100644 --- a/boards/esp32-solo1.json +++ b/boards/esp32-solo1.json @@ -2,7 +2,7 @@ "build": { "core": "esp32", "extra_flags": "-DARDUINO_ESP32_DEV -DARDUINO_USB_CDC_ON_BOOT=0 -DCORE32SOLO1", - "f_cpu": "80000000L", + "f_cpu": "160000000L", "f_flash": "40000000L", "flash_mode": "dio", "mcu": "esp32", @@ -29,6 +29,11 @@ "require_upload_port": true, "speed": 460800 }, + "espidf": { + "custom_sdkconfig": [ + "CONFIG_FREERTOS_UNICORE=y" + ] + }, "url": "https://en.wikipedia.org/wiki/ESP32", "vendor": "Espressif" } diff --git a/boards/esp32s3_120_16_8-qio_opi.json b/boards/esp32s3_120_16_8-qio_opi.json new file mode 100644 index 0000000..e4d20f4 --- /dev/null +++ b/boards/esp32s3_120_16_8-qio_opi.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino": { + "memory_type": "qio_opi", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "f_boot": "120000000L", + "boot": "qio", + "flash_mode": "qio", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ESP32-S3 16MB QIO, 8MB OPI PSRAM", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf", + "vendor": "espressif" +} diff --git a/builder/build_lib/CMakeLists.txt b/builder/build_lib/CMakeLists.txt new file mode 100644 index 0000000..1ab83d3 --- /dev/null +++ b/builder/build_lib/CMakeLists.txt @@ -0,0 +1 @@ +idf_component_register(SRCS "sketch.cpp" "arduino-lib-builder-gcc.c" "arduino-lib-builder-cpp.cpp" "arduino-lib-builder-as.S" INCLUDE_DIRS ".") diff --git a/builder/build_lib/arduino-lib-builder-as.S b/builder/build_lib/arduino-lib-builder-as.S new file mode 100644 index 0000000..e69de29 diff --git a/builder/build_lib/arduino-lib-builder-cpp.cpp b/builder/build_lib/arduino-lib-builder-cpp.cpp new file mode 100644 index 0000000..e69de29 diff --git a/builder/build_lib/arduino-lib-builder-gcc.c b/builder/build_lib/arduino-lib-builder-gcc.c new file mode 100644 index 0000000..e69de29 diff --git a/builder/build_lib/idf_component.yml b/builder/build_lib/idf_component.yml new file mode 100644 index 0000000..9402459 --- /dev/null +++ b/builder/build_lib/idf_component.yml @@ -0,0 +1,12 @@ +dependencies: + # Required IDF version + idf: ">=5.1" + espressif/cmake_utilities: + version: "0.*" + espressif/fb_gfx: + version: "master" + path: components/fb_gfx + git: https://github.com/espressif/esp32-arduino-lib-builder.git + require: public + rules: + - if: "target in [esp32, esp32s2, esp32s3, esp32p4]" diff --git a/builder/build_lib/sketch.cpp b/builder/build_lib/sketch.cpp new file mode 100644 index 0000000..10a17a8 --- /dev/null +++ b/builder/build_lib/sketch.cpp @@ -0,0 +1,10 @@ +#include "Arduino.h" + +void setup() { + Serial.begin(115200); +} + +void loop() { + Serial.println("Hello World!"); + delay(1000); +} diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index caa12c4..d8d9a35 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -110,14 +110,14 @@ env.Append( " ".join( [ "riscv32-esp-elf-objcopy" - if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2") + if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2","esp32p4") else "xtensa-%s-elf-objcopy" % mcu, "--input-target", "binary", "--output-target", - "elf32-littleriscv" if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2") else "elf32-xtensa-le", + "elf32-littleriscv" if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2","esp32p4") else "elf32-xtensa-le", "--binary-architecture", - "riscv" if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2") else "xtensa", + "riscv" if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2","esp32p4") else "xtensa", "--rename-section", ".data=.rodata.embedded", "$SOURCE", diff --git a/builder/main.py b/builder/main.py index 07a6bb0..4c770f0 100644 --- a/builder/main.py +++ b/builder/main.py @@ -131,7 +131,7 @@ def _parse_partitions(env): result = [] next_offset = 0 - bound = int(board.get("upload.offset_address", "0x10000"), 16) # default 0x10000 + app_offset = int(board.get("upload.offset_address", "0x10000"), 16) # default 0x10000 with open(partitions_csv) as fp: for line in fp.readlines(): line = line.strip() @@ -140,23 +140,25 @@ def _parse_partitions(env): tokens = [t.strip() for t in line.split(",")] if len(tokens) < 5: continue + bound = 0x10000 if tokens[1] in ("0", "app") else 4 + calculated_offset = (next_offset + bound - 1) & ~(bound - 1) partition = { "name": tokens[0], "type": tokens[1], "subtype": tokens[2], - "offset": tokens[3] or next_offset, + "offset": tokens[3] or calculated_offset, "size": tokens[4], "flags": tokens[5] if len(tokens) > 5 else None } result.append(partition) next_offset = _parse_size(partition["offset"]) if (partition["subtype"] == "ota_0"): - bound = next_offset - next_offset = (next_offset + bound - 1) & ~(bound - 1) + app_offset = next_offset + next_offset = next_offset + _parse_size(partition["size"]) # Configure application partition offset - env.Replace(ESP32_APP_OFFSET=str(hex(bound))) + env.Replace(ESP32_APP_OFFSET=str(hex(app_offset))) # Propagate application offset to debug configurations - env["INTEGRATION_EXTRA_DATA"].update({"application_offset": str(hex(bound))}) + env["INTEGRATION_EXTRA_DATA"].update({"application_offset": str(hex(app_offset))}) return result @@ -232,7 +234,7 @@ board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") toolchain_arch = "xtensa-%s" % mcu filesystem = board.get("build.filesystem", "spiffs") -if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2"): +if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"): toolchain_arch = "riscv32-esp" if "INTEGRATION_EXTRA_DATA" not in env: @@ -253,7 +255,7 @@ env.Replace( GDB=join( platform.get_package_dir( "tool-riscv32-esp-elf-gdb" - if mcu in ("esp32c2", "esp32c3", "esp32c6") + if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4") else "tool-xtensa-esp-elf-gdb" ) or "", @@ -298,6 +300,7 @@ env.Replace( ), ESP32_APP_OFFSET=env.get("INTEGRATION_EXTRA_DATA").get("application_offset"), + ARDUINO_LIB_COMPILE_FLAG="Inactive", PROGSUFFIX=".elf" ) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 03eaf2c..bd12d55 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -7,22 +7,104 @@ ; Please visit documentation for the other options and examples ; http://docs.platformio.org/page/projectconf.html -[env:esp-wrover-kit] +[env:esp32solo1] platform = espressif32 framework = arduino -board = esp-wrover-kit +board = esp32-solo1 +build_flags = -DLED_BUILTIN=2 +custom_component_remove = + espressif/esp_hosted + espressif/esp_wifi_remote + espressif/esp-dsp + espressif/esp32-camera + espressif/libsodium + espressif/esp-modbus + espressif/qrcode + espressif/esp_insights + espressif/esp_diag_data_store + espressif/esp_diagnostics + espressif/esp_rainmaker + espressif/rmaker_common + +[env:esp32-c2-devkitm-1] +platform = espressif32 +framework = arduino +board = esp32-c2-devkitm-1 monitor_speed = 115200 -build_flags = - -DLED_BUILTIN=2 - +custom_sdkconfig = 'CONFIG_IDF_TARGET="esp32c2"' +custom_component_remove = espressif/esp_hosted + espressif/esp_wifi_remote + espressif/esp-dsp + espressif/esp32-camera + espressif/libsodium + espressif/esp-modbus + espressif/qrcode + espressif/esp_insights + espressif/esp_diag_data_store + espressif/esp_diagnostics + espressif/esp_rainmaker + espressif/rmaker_common + +[env:esp32s3-qio_opi_per] +; OPI Performance settings -> Display use +platform = espressif32 +framework = arduino +board = esp32s3_120_16_8-qio_opi +custom_sdkconfig = CONFIG_SPIRAM_MODE_OCT=y + CONFIG_SPIRAM_SPEED_120M=y + CONFIG_LCD_RGB_ISR_IRAM_SAFE=y + CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y + CONFIG_I2S_ISR_IRAM_SAFE=y + CONFIG_GDMA_ISR_IRAM_SAFE=y + CONFIG_SPIRAM_XIP_FROM_PSRAM=y + CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y + CONFIG_SPIRAM_RODATA=y + CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y + CONFIG_ESP32S3_DATA_CACHE_64KB=y + CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y +custom_component_remove = espressif/esp_hosted + espressif/esp_wifi_remote + espressif/qrcode + espressif/esp_insights + espressif/esp_diag_data_store + espressif/esp_diagnostics + espressif/esp_rainmaker + espressif/rmaker_common +custom_component_add = lvgl/lvgl @ ^9.2.2 + [env:esp32-c6-devkitc-1] platform = espressif32 framework = arduino board = esp32-c6-devkitc-1 monitor_speed = 115200 +custom_component_remove = espressif/esp_hosted + espressif/esp_wifi_remote + espressif/mdns + espressif/esp-dsp + espressif/esp_modem + espressif/esp32-camera [env:esp32-h2-devkitm-1] platform = espressif32 framework = arduino board = esp32-h2-devkitm-1 monitor_speed = 115200 +custom_component_remove = espressif/esp_hosted + espressif/esp_wifi_remote + espressif/mdns + espressif/esp-dsp + espressif/esp_modem + espressif/esp32-camera + +[env:esp32-p4] +platform = espressif32 +framework = arduino +board = esp32-p4 +build_flags = -DLED_BUILTIN=2 +monitor_speed = 115200 +custom_component_remove = espressif/esp_hosted + espressif/esp_wifi_remote + espressif/mdns + espressif/esp-dsp + espressif/esp_modem + espressif/esp32-camera diff --git a/examples/espidf-ulp-lp/CMakeLists.txt b/examples/espidf-ulp-lp/CMakeLists.txt new file mode 100644 index 0000000..3db148b --- /dev/null +++ b/examples/espidf-ulp-lp/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(lp_core_pulse_counter) diff --git a/examples/espidf-ulp-lp/README.md b/examples/espidf-ulp-lp/README.md new file mode 100644 index 0000000..32318f0 --- /dev/null +++ b/examples/espidf-ulp-lp/README.md @@ -0,0 +1,51 @@ +| Supported Targets | ESP32-C6 | +| ----------------- | -------- | + +This example demonstrates how to program the ULP Core coprocessor to count pulses on an IO while the main CPUs are either running some other code or are in deep sleep. See the README.md file in the upper level 'examples' directory for more information about examples. + +At runtime, the main code running on the ESP (found in lp_core_pulse_counter_example_main.c) loads ULP program into the `RTC_SLOW_MEM` memory region using `ulp_lp_core_load_binary` function. Main code configures the ULP program by setting up values of some variables and then starts it using `ulp_lp_core_run`. Once the ULP program is started, it monitors the IO pin for pulses. + +When the ULP program finds an edge in the input signal, it performs debouncing and increments the variable maintaining the total edge count. Once the edge count reaches certain value, ULP triggers wake up from deep sleep. Note that the ULP program keeps running and monitoring the input signal even when the SoC is woken up. + +### Hardware Required + +To run this example, you should have a development board based on any of the chips listed in the supported targets table at the top and a host machine with a serial input connection. + +#### Pin Assignment: + +**Note:** The following pin assignments are used by default. + + +| | Uart Tx | Pulse Count Input | +| ----------------------- | ------- | ----------------- | +| ESP32-C6 | GPIO5 | GPIO6 | +| Host machine | Rx | N/A | + + +## Example Output + +The log output from the serial monitor connected to the main core should indicate that the LP core and the LP UART peripheral have been successfully initialized. The main CPU would then enter deep sleep mode. + +```bash +Using pin 6 as pulse counter input +ULP will wake up processor after every 10 pulses +Not a ULP wakeup, initializing it! +Entering in deep sleep +... +rst:0x5 (SLEEP_WAKEUP),boot:0xc (SPI_FAST_FLASH_BOOT) +... +ULP woke up the main CPU! +Pulse count: 11 +Entering in deep sleep +``` + +The log output from the serial monitor connected to the LP core should display output as below - + +```bash +LP Core pulse counter started +Pulse count: 10, wake-up main CPU +``` + +## Troubleshooting + +(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.) diff --git a/examples/espidf-ulp-lp/platformio.ini b/examples/espidf-ulp-lp/platformio.ini new file mode 100644 index 0000000..2dd34c5 --- /dev/null +++ b/examples/espidf-ulp-lp/platformio.ini @@ -0,0 +1,18 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter, extra scripting +; Upload options: custom port, speed and extra flags +; Library options: dependencies, extra library storages +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/page/projectconf.html + +[env:esp32-c6] +platform = espressif32 +framework = espidf +board = esp32-c6-devkitc-1 + +[env:esp32-p4] +platform = espressif32 +framework = espidf +board = esp32-p4 diff --git a/examples/espidf-ulp-lp/pytest_lp_core_pcnt.py b/examples/espidf-ulp-lp/pytest_lp_core_pcnt.py new file mode 100644 index 0000000..a4d8c0c --- /dev/null +++ b/examples/espidf-ulp-lp/pytest_lp_core_pcnt.py @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 +import logging + +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32c6 +@pytest.mark.esp32p4 +@pytest.mark.generic +def test_lp_core_pcnt(dut: Dut) -> None: + + res = dut.expect(r'ULP will wake up processor after every (\d+) pulses') + wakeup_limit = res.group(1).decode('utf-8') + assert (int(wakeup_limit) > 0) + logging.info(f'Wake-up limit: {wakeup_limit} pulses') + + dut.expect_exact('Not a ULP wakeup, initializing it!') + dut.expect_exact('Entering in deep sleep') + + dut.expect_exact('ULP woke up the main CPU!') + + res = dut.expect(r'Pulse count: (\d+)') + pulse_count = res.group(1).decode('utf-8') + logging.info(f'Pulse count: {pulse_count}') + + # Check that pulse count is correct, we could have gotten pulses between triggering + # the wakeup signal and printing the count, but it should at be equal to or greater + assert (int(pulse_count) >= int(wakeup_limit)) diff --git a/examples/espidf-ulp-lp/sdkconfig.defaults b/examples/espidf-ulp-lp/sdkconfig.defaults new file mode 100644 index 0000000..054ff6c --- /dev/null +++ b/examples/espidf-ulp-lp/sdkconfig.defaults @@ -0,0 +1,11 @@ +# +# Ultra Low Power (ULP) Co-processor +# +CONFIG_ULP_COPROC_ENABLED=y +CONFIG_ULP_COPROC_TYPE_LP_CORE=y +CONFIG_ULP_COPROC_RESERVE_MEM=8128 +# Set log level to Warning to produce clean output +CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y +CONFIG_BOOTLOADER_LOG_LEVEL=2 +CONFIG_LOG_DEFAULT_LEVEL_WARN=y +CONFIG_LOG_DEFAULT_LEVEL=2 diff --git a/examples/espidf-ulp-lp/src/CMakeLists.txt b/examples/espidf-ulp-lp/src/CMakeLists.txt new file mode 100644 index 0000000..b3825ab --- /dev/null +++ b/examples/espidf-ulp-lp/src/CMakeLists.txt @@ -0,0 +1,23 @@ +idf_component_register(SRCS "lp_core_pulse_counter_example_main.c" + INCLUDE_DIRS ".") + +# +# ULP support additions to component CMakeLists.txt. +# +# 1. The ULP app name must be unique (if multiple components use ULP). +set(ulp_app_name ulp_main) +# +# 2. Specify all C and Assembly source files. +# Files should be placed into a separate directory (in this case, ulp/), +# which should not be added to COMPONENT_SRCS. +set(ulp_sources "../ulp/main.c") + +# +# 3. List all the component source files which include automatically +# generated ULP export file, ${ulp_app_name}.h: +set(ulp_exp_dep_srcs "lp_core_pulse_counter_example_main.c") + +# +# 4. Call function to build ULP binary and embed in project using the argument +# values above. +ulp_embed_binary(${ulp_app_name} "${ulp_sources}" "${ulp_exp_dep_srcs}") diff --git a/examples/espidf-ulp-lp/src/Kconfig.projbuild b/examples/espidf-ulp-lp/src/Kconfig.projbuild new file mode 100644 index 0000000..88618ce --- /dev/null +++ b/examples/espidf-ulp-lp/src/Kconfig.projbuild @@ -0,0 +1,20 @@ +menu "Example Configuration" + config EXAMPLE_PULSE_COUNT_PIN + int "Input pin for the pulse counter" + default 6 + help + GPIO pin used as the input for the pulse counter + + config EXAMPLE_PULSE_COUNT_WAKEUP_LIMIT + int "Wake-up pulse count limit" + default 10 + help + Number of pulses counted after which the ULP will wake up the main CPU + + config EXAMPLE_PULSE_COUNT_SIMULATE + bool "Simulate pulses on input pin" + default n + help + The ULP will periodically toggle the input pin to simulate pulses + +endmenu diff --git a/examples/espidf-ulp-lp/src/lp_core_pulse_counter_example_main.c b/examples/espidf-ulp-lp/src/lp_core_pulse_counter_example_main.c new file mode 100644 index 0000000..65bef47 --- /dev/null +++ b/examples/espidf-ulp-lp/src/lp_core_pulse_counter_example_main.c @@ -0,0 +1,85 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* LP core gpio example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include "esp_sleep.h" +#include "driver/gpio.h" +#include "driver/rtc_io.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "ulp_lp_core.h" +#include "ulp_main.h" +#include "lp_core_uart.h" + +extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start"); +extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end"); + + +static void init_ulp_program(void); + +void app_main(void) +{ + /* If user is using USB-serial-jtag then idf monitor needs some time to + * re-connect to the USB port. We wait 1 sec here to allow for it to make the reconnection + * before we print anything. Otherwise the chip will go back to sleep again before the user + * has time to monitor any output. + */ + vTaskDelay(pdMS_TO_TICKS(1000)); + + /* Initialize selected GPIO as RTC IO, enable input/output, disable pullup and pulldown */ + printf("Using pin %d as pulse counter input\n", CONFIG_EXAMPLE_PULSE_COUNT_PIN); + rtc_gpio_init(CONFIG_EXAMPLE_PULSE_COUNT_PIN); + rtc_gpio_set_direction(CONFIG_EXAMPLE_PULSE_COUNT_PIN, RTC_GPIO_MODE_INPUT_OUTPUT); + rtc_gpio_pulldown_dis(CONFIG_EXAMPLE_PULSE_COUNT_PIN); + rtc_gpio_pullup_dis(CONFIG_EXAMPLE_PULSE_COUNT_PIN); + + printf("ULP will wake up processor after every %d pulses\n", CONFIG_EXAMPLE_PULSE_COUNT_WAKEUP_LIMIT); + + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + /* not a wakeup from ULP, load the firmware */ + if (cause != ESP_SLEEP_WAKEUP_ULP) { + printf("Not a ULP wakeup, initializing it! \n"); + init_ulp_program(); + } else { + printf("ULP woke up the main CPU!\n"); + printf("Pulse count: %"PRIu32"\n", ulp_pulse_count); + } + + /* Go back to sleep, only the ULP will run */ + printf("Entering in deep sleep\n\n"); + + /* Small delay to ensure the messages are printed */ + ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup()); + + esp_deep_sleep_start(); +} + +static void init_ulp_program(void) +{ + lp_core_uart_cfg_t uart_cfg = LP_CORE_UART_DEFAULT_CONFIG(); + + ESP_ERROR_CHECK(lp_core_uart_init(&uart_cfg)); + + esp_err_t err = ulp_lp_core_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start)); + ESP_ERROR_CHECK(err); + + /* Start the program */ + ulp_lp_core_cfg_t cfg = { + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU, + }; + + err = ulp_lp_core_run(&cfg); + ESP_ERROR_CHECK(err); +} diff --git a/examples/espidf-ulp-lp/ulp/main.c b/examples/espidf-ulp-lp/ulp/main.c new file mode 100644 index 0000000..6a45c04 --- /dev/null +++ b/examples/espidf-ulp-lp/ulp/main.c @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include "sdkconfig.h" +#include "ulp_lp_core.h" +#include "ulp_lp_core_utils.h" +#include "ulp_lp_core_gpio.h" +#include "ulp_lp_core_interrupts.h" +#include "ulp_lp_core_print.h" +#include "riscv/csr.h" + +#define DEBOUNCE_INTERVAL_CYCLES 10 // 10 cycles is about 0.625 us at 16 MHz + +#define SIMULATED_PULSE_FREQUENCY_HZ 2 +#define SIMULATED_PULSE_DELAY_US (1000000 / SIMULATED_PULSE_FREQUENCY_HZ) / 2 + +uint32_t pulse_count; +static uint32_t last_trigger_time_cycles; + +void LP_CORE_ISR_ATTR ulp_lp_core_lp_io_intr_handler(void) +{ + ulp_lp_core_gpio_clear_intr_status(); + uint32_t trigger_time_cycles = RV_READ_CSR(mcycle); + /* Do some simple debouncing, do not count spurious pulses */ + if (trigger_time_cycles - last_trigger_time_cycles > DEBOUNCE_INTERVAL_CYCLES) { + pulse_count++; + last_trigger_time_cycles = trigger_time_cycles; + } + + if (pulse_count % CONFIG_EXAMPLE_PULSE_COUNT_WAKEUP_LIMIT == 0) { + lp_core_printf("Pulse count: %d, wake-up main CPU\n", pulse_count); + ulp_lp_core_wakeup_main_processor(); + } + +} + + + +int main (void) +{ + lp_core_printf("LP Core pulse counter started\n"); + ulp_lp_core_intr_enable(); + ulp_lp_core_gpio_intr_enable(CONFIG_EXAMPLE_PULSE_COUNT_PIN, LP_IO_INTR_POSEDGE); + + while(1) { + +#if CONFIG_EXAMPLE_PULSE_COUNT_SIMULATE + /* No external device connected to generate pulses, we simulate them ourselves instead */ + ulp_lp_core_delay_us(SIMULATED_PULSE_DELAY_US); + ulp_lp_core_gpio_set_level(CONFIG_EXAMPLE_PULSE_COUNT_PIN, 1); + ulp_lp_core_delay_us(SIMULATED_PULSE_DELAY_US); + ulp_lp_core_gpio_set_level(CONFIG_EXAMPLE_PULSE_COUNT_PIN, 0); +#else + /* Put CPU into a wait state to reduce power consumption while waiting for pulses */ + ulp_lp_core_wait_for_intr(); +#endif //CONFIG_EXAMPLE_PULSE_COUNT_SIMULATE + } + + return 0; +} diff --git a/examples/tasmota_platformio_override.ini b/examples/tasmota_platformio_override.ini new file mode 100644 index 0000000..3c13dfc --- /dev/null +++ b/examples/tasmota_platformio_override.ini @@ -0,0 +1,38 @@ +[platformio] +default_envs = tasmota32-hybrid + +[env:tasmota32_base] +platform = file://. + +[env:tasmota32-hybrid] +extends = env:tasmota32_base +board = esp32 +build_flags = ${env:tasmota32_base.build_flags} + -DHTTPCLIENT_NOSECURE + -DUPDATE_NOCRYPT +lib_ignore = ${env:tasmota32_base.lib_ignore} + Micro-RTSP + epdiy +custom_sdkconfig = https://raw.githubusercontent.com/pioarduino/sdkconfig/refs/heads/main/sdkconfig_tasmota_esp32 + '# CONFIG_ETH_USE_ESP32_EMAC is not set' + '# CONFIG_ETH_PHY_INTERFACE_RMII is not set' + '# CONFIG_ETH_RMII_CLK_INPUT is not set' + '# CONFIG_ETH_RMII_CLK_IN_GPIO is not set' +custom_component_remove = espressif/esp_hosted + espressif/esp_wifi_remote + espressif/esp-dsp + espressif/network_provisioning + espressif/esp-zboss-lib + espressif/esp-zigbee-lib + espressif/esp_rainmaker + espressif/rmaker_common + espressif/esp_insights + espressif/esp_diag_data_store + espressif/esp_diagnostics + espressif/cbor + espressif/qrcode + espressif/esp-sr + espressif/libsodium + espressif/esp-modbus + chmorgan/esp-libhelix-mp3 + espressif/esp32-camera From 1ba2fdd45fc4670cfac2fc271b88c2c5ebdbb941 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:52:20 +0100 Subject: [PATCH 091/117] Update README.md --- README.md | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 417f812..5b4f5f0 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,26 @@ # pioarduino (p)eople (i)nitiated (o)ptimized (arduino) -# Fork of Platformio Espressif 32: development platform for [PlatformIO](https://platformio.org) [![Build Status](https://github.com/pioarduino/platform-espressif32/workflows/Examples/badge.svg)](https://github.com/pioarduino/platform-espressif32/actions) [![Discord](https://img.shields.io/discord/1263397951829708871.svg?logo=discord&logoColor=white&color=5865F2&label=Discord)](https://discord.gg/Nutz9crnZr) [![GitHub Releases](https://img.shields.io/github/downloads/pioarduino/platform-espressif32/total?label=downloads)](https://github.com/pioarduino/platform-espressif32/releases/latest) -> [!NOTE] -> This fork was created due to the lack of ongoing development for the Espressif 32 Arduino Core for PlatformIO. -> -> For additional information, please refer to these GitHub links: -> -> https://github.com/espressif/arduino-esp32/discussions/10039 -> https://github.com/platformio/platform-espressif32/issues/1225 -> https://github.com/espressif/arduino-esp32/pull/8606 -> -> The discussions are self-explanatory, allowing you to draw your own conclusions. - ESP32 is a series of low-cost, low-power system on a chip microcontrollers with integrated Wi-Fi and Bluetooth. ESP32 integrates an antenna switch, RF balun, power amplifier, low-noise receive amplifier, filters, and power management modules. -* [Documentation](https://docs.platformio.org/page/platforms/espressif32.html) (advanced usage, packages, boards, frameworks, etc.) -* Issues with boards (wrong / missing). All issues caused from boards will not be fixed from the maintainer(s). A PR needs to be provided to solve. +* Issues with boards (wrong / missing). All issues caused from boards will **not** be fixed from the maintainer(s). A PR needs to be provided to solve. ## IDE Preparation -- [Download and install official Microsoft Visual Studio Code](https://code.visualstudio.com/). PlatformIO IDE is built on top of it. +- [Download and install official Microsoft Visual Studio Code](https://code.visualstudio.com/). pioarduino IDE is built on top of it. - Open the extension manager. -- Search for the official `platformio ide` extension. -- Install PlatformIO IDE extension. - -![image](idesetup.png) +- Search for the `pioarduino ide` extension. +- Install pioarduino IDE extension. # Usage -1. Setup new VSCode PlatformIO project. -1. Configure a platform option in [platformio.ini](https://docs.platformio.org/page/projectconf.html) file: +1. Setup new VSCode pioarduino project. +1. Configure a platform option in platformio.ini file: ### Stable version - -See `platform` [documentation](https://docs.platformio.org/en/latest/projectconf/sections/env/options/platform/platform.html#projectconf-env-platform) for details. +currently espressif Arduino 3.1.0 and IDF 5.3.2.241210 ```ini [env:stable] @@ -46,15 +30,11 @@ board = ... ``` ### Development version -based on devel branch Arduino 3.1.0 and IDF 5.3.2 +espressif Arduino repo branch master and latest compiled Arduino libs ```ini [env:development] -platform = https://github.com/pioarduino/platform-espressif32.git#Arduino/IDF53 +platform = https://github.com/pioarduino/platform-espressif32.git#develop board = ... ... ``` - -# Configuration - -Please navigate to [documentation](https://docs.platformio.org/page/platforms/espressif32.html). From 3845e00743607a5cd2b1fdffb4eeca9066fad35d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 22:09:16 +0100 Subject: [PATCH 092/117] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 7659969..2f28a1d 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "53.03.10+develop", + "version": "53.03.10", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/archive/refs/heads/release/v3.1.x.zip" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0/esp32-3.1.0.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "" + "version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip" }, "framework-arduino-c2-skeleton-lib": { "type": "framework", From 875924b43a451d21c929cac84bf5d6cfac968390 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 Dec 2024 22:11:01 +0100 Subject: [PATCH 093/117] Update platform.py --- platform.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/platform.py b/platform.py index b220baa..625a98d 100644 --- a/platform.py +++ b/platform.py @@ -46,11 +46,6 @@ class Espressif32Platform(PlatformBase): if "arduino" in frameworks: self.packages["framework-arduinoespressif32"]["optional"] = False self.packages["framework-arduinoespressif32-libs"]["optional"] = False - # use latest espressif Arduino libs - URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/release/v3.1.x/package/package_esp32_index.template.json" - packjdata = requests.get(URL).json() - dyn_lib_url = packjdata['packages'][0]['tools'][0]['systems'][0]['url'] - self.packages["framework-arduinoespressif32-libs"]["version"] = dyn_lib_url if variables.get("custom_sdkconfig") is not None or len(str(board_sdkconfig)) > 3: frameworks.append("espidf") From 7a6003760d43759e5581614f78723abe0d0ab877 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 17 Dec 2024 10:12:07 +0100 Subject: [PATCH 094/117] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b4f5f0..52d5308 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ board = ... ``` ### Development version -espressif Arduino repo branch master and latest compiled Arduino libs +espressif Arduino repo branch release/v3.1.x and latest compiled Arduino libs ```ini [env:development] From 95d72d424182715dcf005d3032aaf73558e8f7c9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:50:43 +0100 Subject: [PATCH 095/117] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 52d5308..5b4f5f0 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ board = ... ``` ### Development version -espressif Arduino repo branch release/v3.1.x and latest compiled Arduino libs +espressif Arduino repo branch master and latest compiled Arduino libs ```ini [env:development] From 55ef55906f4c3c9e577d790d3f2adc79d266f9a1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 19 Dec 2024 16:22:58 +0100 Subject: [PATCH 096/117] Boards update --- .../adafruit_feather_esp32s3_reversetft.json | 3 +- boards/adafruit_feather_esp32s3_tft.json | 7 +-- boards/adafruit_matrixportal_esp32s3.json | 2 +- boards/airm2m_core_esp32c3.json | 6 ++- boards/dfrobot_romeo_esp32s3.json | 4 +- boards/freenove_esp32_s3_wroom.json | 54 +++++++++++++++++++ boards/freenove_esp32_wrover.json | 39 ++++++++++++++ boards/heltec_wifi_kit_32_V3.json | 1 - boards/heltec_wifi_kit_32_v2.json | 35 ++++++++++++ boards/heltec_wireless_stick_lite.json | 5 +- boards/m5stick-c.json | 5 +- boards/rymcu-esp32-s3-devkitc-1.json | 51 ++++++++++++++++++ boards/seeed_xiao_esp32c6.json | 48 +++++++++++++++++ boards/sparkfun_qwiic_pocket_esp32c6.json | 38 +++++++++++++ boards/weactstudio_esp32c3coreboard.json | 42 +++++++++++++++ boards/wt32-sc01-plus.json | 50 +++++++++++++++++ 16 files changed, 375 insertions(+), 15 deletions(-) create mode 100644 boards/freenove_esp32_s3_wroom.json create mode 100644 boards/freenove_esp32_wrover.json create mode 100644 boards/heltec_wifi_kit_32_v2.json create mode 100644 boards/rymcu-esp32-s3-devkitc-1.json create mode 100644 boards/seeed_xiao_esp32c6.json create mode 100644 boards/sparkfun_qwiic_pocket_esp32c6.json create mode 100644 boards/weactstudio_esp32c3coreboard.json create mode 100644 boards/wt32-sc01-plus.json diff --git a/boards/adafruit_feather_esp32s3_reversetft.json b/boards/adafruit_feather_esp32s3_reversetft.json index 8de715f..c9209de 100644 --- a/boards/adafruit_feather_esp32s3_reversetft.json +++ b/boards/adafruit_feather_esp32s3_reversetft.json @@ -1,7 +1,8 @@ { "build": { "arduino": { - "partitions": "tinyuf2-partitions-4MB.csv", + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv", "memory_type": "qio_qspi" }, "core": "esp32", diff --git a/boards/adafruit_feather_esp32s3_tft.json b/boards/adafruit_feather_esp32s3_tft.json index 0b1d943..a37b7e4 100644 --- a/boards/adafruit_feather_esp32s3_tft.json +++ b/boards/adafruit_feather_esp32s3_tft.json @@ -1,15 +1,16 @@ { "build": { "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv" + "partitions": "partitions-4MB-tinyuf2.csv", + "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT", "-DARDUINO_USB_CDC_ON_BOOT=1", "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/adafruit_matrixportal_esp32s3.json b/boards/adafruit_matrixportal_esp32s3.json index 12bb6b7..dfdb07c 100644 --- a/boards/adafruit_matrixportal_esp32s3.json +++ b/boards/adafruit_matrixportal_esp32s3.json @@ -1,7 +1,7 @@ { "build": { "arduino":{ - "partitions": "tinyuf2-partitions-8MB.csv", + "partitions": "partitions-8MB-tinyuf2.csv", "memory_type": "qio_qspi" }, "core": "esp32", diff --git a/boards/airm2m_core_esp32c3.json b/boards/airm2m_core_esp32c3.json index d2d5b30..e227fad 100644 --- a/boards/airm2m_core_esp32c3.json +++ b/boards/airm2m_core_esp32c3.json @@ -1,13 +1,15 @@ { "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, "core": "esp32", "f_cpu": "160000000L", "f_flash": "80000000L", "flash_mode": "dio", "extra_flags": [ "-DARDUINO_AirM2M_CORE_ESP32C3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_MODE=1" ], "mcu": "esp32c3", "variant": "AirM2M_CORE_ESP32C3" diff --git a/boards/dfrobot_romeo_esp32s3.json b/boards/dfrobot_romeo_esp32s3.json index 55e69db..f0810d8 100644 --- a/boards/dfrobot_romeo_esp32s3.json +++ b/boards/dfrobot_romeo_esp32s3.json @@ -1,7 +1,6 @@ { "build": { "arduino": { - "ldscript": "esp32s3_out.ld", "partitions": "app3M_fat9M_16MB.csv", "memory_type": "qio_opi" }, @@ -10,7 +9,8 @@ "-DARDUINO_DFROBOT_ROMEO_ESP32S3", "-DARDUINO_USB_MODE=1", "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/freenove_esp32_s3_wroom.json b/boards/freenove_esp32_s3_wroom.json new file mode 100644 index 0000000..ea439ab --- /dev/null +++ b/boards/freenove_esp32_s3_wroom.json @@ -0,0 +1,54 @@ +{ + "build": { + "arduino": { + "partitions": "default_8MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=0", + "-DARDUINO_USB_CDC_ON_BOOT=0" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "psram_type": "opi", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Freenove ESP32-S3 WROOM N8R8 (8MB Flash / 8MB PSRAM)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://github.com/Freenove/Freenove_ESP32_S3_WROOM_Board", + "vendor": "Freenove" +} diff --git a/boards/freenove_esp32_wrover.json b/boards/freenove_esp32_wrover.json new file mode 100644 index 0000000..7f1aeba --- /dev/null +++ b/boards/freenove_esp32_wrover.json @@ -0,0 +1,39 @@ +{ + "build": { + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_DEV", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wrover-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Freenove ESP32-Wrover", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://store.freenove.com/products/fnk0060", + "vendor": "Freenove" +} diff --git a/boards/heltec_wifi_kit_32_V3.json b/boards/heltec_wifi_kit_32_V3.json index 62d7301..ba83700 100644 --- a/boards/heltec_wifi_kit_32_V3.json +++ b/boards/heltec_wifi_kit_32_V3.json @@ -1,7 +1,6 @@ { "build": { "arduino": { - "ldscript": "esp32s3_out.ld", "partitions": "default_8MB.csv" }, "core": "esp32", diff --git a/boards/heltec_wifi_kit_32_v2.json b/boards/heltec_wifi_kit_32_v2.json new file mode 100644 index 0000000..eb80db6 --- /dev/null +++ b/boards/heltec_wifi_kit_32_v2.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_HELTEC_WIFI_KIT_32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "heltec_wifi_kit_32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Heltec WiFi Kit 32 (V2)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.heltec.cn/project/wifi-kit-32/?lang=en", + "vendor": "Heltec Automation" +} diff --git a/boards/heltec_wireless_stick_lite.json b/boards/heltec_wireless_stick_lite.json index 6ffac9a..c7ec8bc 100644 --- a/boards/heltec_wireless_stick_lite.json +++ b/boards/heltec_wireless_stick_lite.json @@ -1,12 +1,9 @@ { "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, "core": "esp32", "extra_flags": "-DARDUINO_HELTEC_WIRELESS_STICK_LITE", "f_cpu": "240000000L", - "f_flash": "40000000L", + "f_flash": "80000000L", "flash_mode": "dio", "mcu": "esp32", "variant": "heltec_wireless_stick_lite" diff --git a/boards/m5stick-c.json b/boards/m5stick-c.json index e27d82a..5c96d7e 100644 --- a/boards/m5stick-c.json +++ b/boards/m5stick-c.json @@ -1,12 +1,15 @@ { "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, "core": "esp32", "extra_flags": "-DARDUINO_M5Stick_C", "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", "mcu": "esp32", - "variant": "m5stack_stickc" + "variant": "m5stick_c" }, "connectivity": [ "wifi", diff --git a/boards/rymcu-esp32-s3-devkitc-1.json b/boards/rymcu-esp32-s3-devkitc-1.json new file mode 100644 index 0000000..848537a --- /dev/null +++ b/boards/rymcu-esp32-s3-devkitc-1.json @@ -0,0 +1,51 @@ +{ + "build": { + "arduino":{ + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "RYMCU ESP32-S3-DevKitC-1-N8R2 (8 MB QD, 2 MB PSRAM)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://rymcu.com/products", + "vendor": "RYMCU" +} diff --git a/boards/seeed_xiao_esp32c6.json b/boards/seeed_xiao_esp32c6.json new file mode 100644 index 0000000..224f0e2 --- /dev/null +++ b/boards/seeed_xiao_esp32c6.json @@ -0,0 +1,48 @@ +{ + "build": { + "core": "esp32", + "extra_flags": [ + "-DARDUINO_XIAO_ESP32C6", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x2886", + "0x0046" + ], + [ + "0x303a", + "0x1001" + ] + ], + "mcu": "esp32c6", + "variant": "XIAO_ESP32C6" + }, + "connectivity": [ + "wifi", + "bluetooth", + "zigbee", + "thread" + ], + "debug": { + "openocd_target": "esp32c6.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Seeed Studio XIAO ESP32C6", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.seeedstudio.com/XIAO_ESP32C6_Getting_Started/", + "vendor": "Seeed Studio" +} diff --git a/boards/sparkfun_qwiic_pocket_esp32c6.json b/boards/sparkfun_qwiic_pocket_esp32c6.json new file mode 100644 index 0000000..c627d24 --- /dev/null +++ b/boards/sparkfun_qwiic_pocket_esp32c6.json @@ -0,0 +1,38 @@ +{ + "build": { + "core": "esp32", + "extra_flags": [ + "-DARDUINO_SFE_QWIIC_POCKET_ESP32C6", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c6", + "variant": "sparkfun_esp32c6_qwiic_pocket" + }, + "connectivity": [ + "wifi", + "bluetooth", + "zigbee", + "thread" + ], + "debug": { + "openocd_target": "esp32c6.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32-C6 Qwiic Pocket", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/22925", + "vendor": "SparkFun" +} diff --git a/boards/weactstudio_esp32c3coreboard.json b/boards/weactstudio_esp32c3coreboard.json new file mode 100644 index 0000000..50f9873 --- /dev/null +++ b/boards/weactstudio_esp32c3coreboard.json @@ -0,0 +1,42 @@ +{ + "build": { + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32C3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "esp32c3" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WeAct Studio ESP32C3CoreBoard", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 409600, + "maximum_size": 393216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/WeActStudio/WeActStudio.ESP32C3CoreBoard", + "vendor": "WeAct Studio" +} diff --git a/boards/wt32-sc01-plus.json b/boards/wt32-sc01-plus.json new file mode 100644 index 0000000..bc9eb99 --- /dev/null +++ b/boards/wt32-sc01-plus.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino":{ + "partitions": "tinyuf2-partitions-16MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_WT32_SC01_PLUS", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "wt32-sc01-plus" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "wt32-sc01-plus", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.wireless-tag.com/portfolio/wt32-eth01", + "vendor": "Wireless-Tag" +} From a035e99ebff463c9594ec19d0a673c5bfe44514a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Dec 2024 13:08:27 +0100 Subject: [PATCH 097/117] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5b4f5f0..1cf8d79 100644 --- a/README.md +++ b/README.md @@ -38,3 +38,5 @@ platform = https://github.com/pioarduino/platform-espressif32.git#develop board = ... ... ``` + +Looking for sponsor button? There is none. If you want to donate, please spend a litte to a charity organization. From 325c56fb75c91c496ffcc904e712730e52de4b47 Mon Sep 17 00:00:00 2001 From: Kyle Mohr <6644803+kylefmohr@users.noreply.github.com> Date: Tue, 31 Dec 2024 03:31:35 -0600 Subject: [PATCH 098/117] Fix the link to the CLA (#97) --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 65cb3bb..8438f07 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,4 +6,4 @@ - [ ] The pull request is done against the latest develop branch - [ ] Only relevant files were touched - [ ] Only one feature/fix was added per PR, more changes are allowed when changing boards.json - - [ ] I accept the [CLA](https://github.com/pioarduino/platform-espressif32/blob/develop/CONTRIBUTING.md). + - [ ] I accept the [CLA](https://github.com/pioarduino/platform-espressif32/blob/main/CONTRIBUTING.md#contributor-license-agreement-cla) From 68e9df1a8bdbee59e8ea0077096033b60ba6bf1a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 9 Jan 2025 13:52:26 +0100 Subject: [PATCH 099/117] Update platform.json --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 2f28a1d..5922b56 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "53.03.10", + "version": "53.03.11", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0/esp32-3.1.0.zip" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.1.1/esp32-3.1.1.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip" + "version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-cfea4f7c-v1.zip" }, "framework-arduino-c2-skeleton-lib": { "type": "framework", @@ -51,7 +51,7 @@ "type": "framework", "optional": true, "owner": "pioarduino", - "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.3.2.241012/esp-idf-v5.3.2.zip" + "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.3.2.250106/esp-idf-v5.3.2.zip" }, "toolchain-xtensa-esp-elf": { "type": "toolchain", From 5156766e73bd3bd83c4fe687cf9d2e13cacc07f9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 9 Jan 2025 13:54:05 +0100 Subject: [PATCH 100/117] Arduino espressif32 core 3.1.1 --- boards/adafruit_qualia_s3_rgb666.json | 3 +- boards/huidu_hd_wf2.json | 55 +++++++++++++++++++++++++ boards/huidu_hd_wf4.json | 55 +++++++++++++++++++++++++ boards/jczn_2432s028r.json | 32 ++++++++++++++ boards/lilygo-t3-s3.json | 42 +++++++++++++++++++ boards/sparkfun_esp32s3_thing_plus.json | 52 +++++++++++++++++++++++ boards/waveshare_esp32_s3_zero.json | 41 ++++++++++++++++++ boards/ws_esp32_s3_matrix.json | 32 ++++++++++++++ builder/frameworks/espidf.py | 8 +++- 9 files changed, 317 insertions(+), 3 deletions(-) create mode 100644 boards/huidu_hd_wf2.json create mode 100644 boards/huidu_hd_wf4.json create mode 100644 boards/jczn_2432s028r.json create mode 100644 boards/lilygo-t3-s3.json create mode 100644 boards/sparkfun_esp32s3_thing_plus.json create mode 100644 boards/waveshare_esp32_s3_zero.json create mode 100644 boards/ws_esp32_s3_matrix.json diff --git a/boards/adafruit_qualia_s3_rgb666.json b/boards/adafruit_qualia_s3_rgb666.json index e1607a9..c122ae7 100644 --- a/boards/adafruit_qualia_s3_rgb666.json +++ b/boards/adafruit_qualia_s3_rgb666.json @@ -1,9 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld", "memory_type": "qio_opi", - "partitions": "partitions-16MB-tinyuf2.csv" + "partitions": "tinyuf2-partitions-16MB.csv" }, "core": "esp32", "extra_flags": [ diff --git a/boards/huidu_hd_wf2.json b/boards/huidu_hd_wf2.json new file mode 100644 index 0000000..eecb9d6 --- /dev/null +++ b/boards/huidu_hd_wf2.json @@ -0,0 +1,55 @@ +{ + "build": { + "arduino": { + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_HUIDU_HD_WF2", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "huidu_hd_wf2" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Huidu HD-WF2", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.hdwell.com/Product/index46.html", + "vendor": "Huidu Tech", + "information_urls": [ + "https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/discussions/667", + "https://github.com/vortigont/FireLamp_JeeUI/wiki/Huidu-HD%E2%80%90WF2" + ] +} diff --git a/boards/huidu_hd_wf4.json b/boards/huidu_hd_wf4.json new file mode 100644 index 0000000..b0acdff --- /dev/null +++ b/boards/huidu_hd_wf4.json @@ -0,0 +1,55 @@ +{ + "build": { + "arduino": { + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_HUIDU_HD_WF4", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "huidu_hd_wf4" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Huidu HD-WF4", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.hdwell.com/Product/index46.html", + "vendor": "Huidu Tech", + "information_urls": [ + "https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/discussions/667", + "https://github.com/vortigont/FireLamp_JeeUI/wiki/Huidu-HD%E2%80%90WF4" + ] +} diff --git a/boards/jczn_2432s028r.json b/boards/jczn_2432s028r.json new file mode 100644 index 0000000..b5c10fa --- /dev/null +++ b/boards/jczn_2432s028r.json @@ -0,0 +1,32 @@ +{ + "build": { + "core": "esp32", + "extra_flags": "-DARDUINO_JCZN_2432S028R", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "jczn_2432s028r" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ESP32-2432S028R CYD", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://pan.jczn1688.com/directlink/1/ESP32%20module/2.8inch_ESP32-2432S028R.rar", + "vendor": "JCZN" +} diff --git a/boards/lilygo-t3-s3.json b/boards/lilygo-t3-s3.json new file mode 100644 index 0000000..6a00b6f --- /dev/null +++ b/boards/lilygo-t3-s3.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LILYGO_T3_S3_V1_X", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "LilyGo T3-S3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://lilygo.cc/products/t3s3-v1-0", + "vendor": "LilyGo" +} diff --git a/boards/sparkfun_esp32s3_thing_plus.json b/boards/sparkfun_esp32s3_thing_plus.json new file mode 100644 index 0000000..5dcaefb --- /dev/null +++ b/boards/sparkfun_esp32s3_thing_plus.json @@ -0,0 +1,52 @@ +{ + "build": { + "arduino": { + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "sparkfun_esp32s3_thing_plus" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SPARKFUN_ESP32S3_THING_PLUS", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/24408", + "vendor": "SparkFun" +} diff --git a/boards/waveshare_esp32_s3_zero.json b/boards/waveshare_esp32_s3_zero.json new file mode 100644 index 0000000..5965e45 --- /dev/null +++ b/boards/waveshare_esp32_s3_zero.json @@ -0,0 +1,41 @@ +{ + "build": { + "arduino":{ + "memory_type": "qio_qspi" + }, + "core": "esp32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s3", + "variant": "waveshare_esp32_s3_zero", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ] + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Waveshare ESP32-S3-Zero", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.waveshare.com/wiki/ESP32-S3-Zero", + "vendor": "Waveshare" +} diff --git a/boards/ws_esp32_s3_matrix.json b/boards/ws_esp32_s3_matrix.json new file mode 100644 index 0000000..d116bc5 --- /dev/null +++ b/boards/ws_esp32_s3_matrix.json @@ -0,0 +1,32 @@ +{ + "build": { + "core": "esp32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "memory_type": "qio_qspi", + "mcu": "esp32s3", + "variant": "ws_esp32_s3_matrix" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Waveshare ESP32-S3-Matrix", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.waveshare.com/wiki/ESP32-S3-Matrix", + "vendor": "Waveshare" +} diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index d9b2c33..a1ff9c2 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -405,13 +405,15 @@ def is_cmake_reconfigure_required(cmake_api_reply_dir): ] cmake_preconf_dir = os.path.join(BUILD_DIR, "config") deafult_sdk_config = os.path.join(PROJECT_DIR, "sdkconfig.defaults") + idf_deps_lock = os.path.join(PROJECT_DIR, "dependencies.lock") + ninja_buildfile = os.path.join(BUILD_DIR, "build.ninja") for d in (cmake_api_reply_dir, cmake_preconf_dir): if not os.path.isdir(d) or not os.listdir(d): return True if not os.path.isfile(cmake_cache_file): return True - if not os.path.isfile(os.path.join(BUILD_DIR, "build.ninja")): + if not os.path.isfile(ninja_buildfile): return True if not os.path.isfile(SDKCONFIG_PATH) or os.path.getmtime( SDKCONFIG_PATH @@ -421,6 +423,10 @@ def is_cmake_reconfigure_required(cmake_api_reply_dir): deafult_sdk_config ) > os.path.getmtime(cmake_cache_file): return True + if os.path.isfile(idf_deps_lock) and os.path.getmtime( + idf_deps_lock + ) > os.path.getmtime(ninja_buildfile): + return True if any( os.path.getmtime(f) > os.path.getmtime(cmake_cache_file) for f in cmake_txt_files + [cmake_preconf_dir, FRAMEWORK_DIR] From 54ed341fa5bd0ebf0e1a64237f0b8e806a580d99 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 9 Jan 2025 13:57:50 +0100 Subject: [PATCH 101/117] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1cf8d79..6c5ca1f 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with 1. Configure a platform option in platformio.ini file: ### Stable version -currently espressif Arduino 3.1.0 and IDF 5.3.2.241210 +currently espressif Arduino 3.1.1 and IDF 5.3.2.250106 ```ini [env:stable] From 9c58358cc6d171b25f700e96282c7626b51b8828 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 9 Jan 2025 14:12:27 +0100 Subject: [PATCH 102/117] IDF 5.3.2.241224 is used for Arduino core 3.1.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 5922b56..d0378a7 100644 --- a/platform.json +++ b/platform.json @@ -51,7 +51,7 @@ "type": "framework", "optional": true, "owner": "pioarduino", - "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.3.2.250106/esp-idf-v5.3.2.zip" + "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.3.2.241224/esp-idf-v5.3.2.zip" }, "toolchain-xtensa-esp-elf": { "type": "toolchain", From ccf2dba11e81ab1d6f8dd9b527890e4fbbcd57a6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 9 Jan 2025 14:13:02 +0100 Subject: [PATCH 103/117] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c5ca1f..5693a48 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with 1. Configure a platform option in platformio.ini file: ### Stable version -currently espressif Arduino 3.1.1 and IDF 5.3.2.250106 +currently espressif Arduino 3.1.1 and IDF 5.3.2.241224 ```ini [env:stable] From b25f39bbe94a07b4cfc29d68c6ca4c2dcaeff383 Mon Sep 17 00:00:00 2001 From: "Thomas J." Date: Fri, 10 Jan 2025 15:19:02 +0100 Subject: [PATCH 104/117] feat(board): Add boards YB-ESP32-S3-AMP-V2, YB-ESP32-S3-AMP-V3 and YB-ESP32-S3-ETH (#103) * board definition files added * "ldscript": "esp32s3_out.ld" removed * "memory_type": "qio_qspi" added --- boards/yb_esp32s3_amp_v2.json | 47 ++++++++++++++++++++++++++++++++ boards/yb_esp32s3_amp_v3.json | 48 +++++++++++++++++++++++++++++++++ boards/yb_esp32s3_eth.json | 51 +++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 boards/yb_esp32s3_amp_v2.json create mode 100644 boards/yb_esp32s3_amp_v3.json create mode 100644 boards/yb_esp32s3_eth.json diff --git a/boards/yb_esp32s3_amp_v2.json b/boards/yb_esp32s3_amp_v2.json new file mode 100644 index 0000000..645a8d5 --- /dev/null +++ b/boards/yb_esp32s3_amp_v2.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino":{ + "partitions": "default_8MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_YB_ESP32S3_AMP_V2", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x1A86", + "0x7523" + ] + ], + "mcu": "esp32s3", + "variant": "yb_esp32s3_amp_v2" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "YelloByte YB-ESP32-S3-AMP (Rev.2)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/yellobyte/ESP32-DevBoards-Getting-Started/tree/main/boards/YB-ESP32-S3-AMP", + "vendor": "YelloByte" +} diff --git a/boards/yb_esp32s3_amp_v3.json b/boards/yb_esp32s3_amp_v3.json new file mode 100644 index 0000000..8297e8b --- /dev/null +++ b/boards/yb_esp32s3_amp_v3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino":{ + "partitions": "default_8MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_YB_ESP32S3_AMP_V3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "yb_esp32s3_amp_v3" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "YelloByte YB-ESP32-S3-AMP (Rev.3)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/yellobyte/ESP32-DevBoards-Getting-Started/tree/main/boards/YB-ESP32-S3-AMP", + "vendor": "YelloByte" +} diff --git a/boards/yb_esp32s3_eth.json b/boards/yb_esp32s3_eth.json new file mode 100644 index 0000000..1d99b67 --- /dev/null +++ b/boards/yb_esp32s3_eth.json @@ -0,0 +1,51 @@ +{ + "build": { + "arduino":{ + "partitions": "default.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_YB_ESP32S3_ETH", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "yb_esp32s3_eth" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "YelloByte YB-ESP32-S3-ETH", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/yellobyte/ESP32-DevBoards-Getting-Started/tree/main/boards/YB-ESP32-S3-ETH", + "vendor": "YelloByte" +} From 53d73e3734d1784fc7f3f5689598a320cdaf4c24 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 10 Jan 2025 15:59:58 +0100 Subject: [PATCH 105/117] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5693a48..8e67248 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with integrated Wi-Fi and Bluetooth. ESP32 integrates an antenna switch, RF balun, power amplifier, low-noise receive amplifier, filters, and power management modules. -* Issues with boards (wrong / missing). All issues caused from boards will **not** be fixed from the maintainer(s). A PR needs to be provided to solve. +* Issues with boards (wrong / missing). All issues caused from boards will **not** be fixed from the maintainer(s). A PR needs to be provided against branch `develop` to solve. ## IDE Preparation From 5920b375a85c3f289bfa72cf7e79755b9315cf7d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:54:33 +0100 Subject: [PATCH 106/117] Delete idesetup.png --- idesetup.png | Bin 71133 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 idesetup.png diff --git a/idesetup.png b/idesetup.png deleted file mode 100644 index faff8fe4f1f4401249a0b47873324858df2dec18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71133 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 i;!H=7?La$$_E*%=UcPsnS2d zpc)IkfO}d>n)2aPz$M)YG2H~gl?;C8-XQ+9%i}zsDNLjvRths3YD*!oAzKuRS|Jk% z_ifp-*xINvnE0DU_*clw%qey|Ytu-||4030!ydPVPcr2v)ND!yIERwvk1wd^0LjZE z>m(vQ9aM z^RRNaSEszQwe{6XGYENMPr&zh>+>m-7xFIX7_sb^rk#2trGG+9ZXz4HFHgCD#|}>p zZNLPQBf@M~+&Zd?D|FAS2DYqxess6HirF)Co)&V`_5Ot}P<%Ve^~fp)f0R??pRUf43nv} z`&tQMSCqf`9cF*T2*Fr7>2s8;5mDGf;HM3$t&}z_%B=iTy;^<}rw_|zX5tiE%dqN7 zDWC`qwuz@^;3j=SdO?QC-X}XGCdQ^;M9qFcY?irxUwQA=>;4CtxxhY}wFB{LY_GSP zUHUmRbpf>_Or2=z+M^+hG&1veQMD4V?YsOnzTb1Tpa^y}LTUfm1!%ld=Uqw_j@Dd$ z37^}|fhQ^csr&+EEyF$$4XwB7$>^nTap}#}u4X6&WcTB48+8ZYs$3RVw$6$tyE==s zg#UIF`@{O{z$vFdzbGcc7vB2uC}#9G#)a6w$C1aTW~a7&lXy9q#}4uv$NqbaB`KAP zW`v%cOS*-o0e{6e`hv=Q6CIF>@yyk#vxIju7fWhk)ZU>9H{UOxIw_D z(*F9x`jrIm6fWYdHgqGUy7A(md)>^2~SEMO=Fw+4aC zat`FXC%rbpR+y28YU*x%dUCR(lJ&<->&(r!)m0O3}) zM^|8J3>Ms~z%vA`!zNXXIp;ZFj|MiN7gzn{>rX?PX$iCaF_)rJcK-uvDgWOo7}ebP zMyw7S!L!Puy$+qa<~FFNyY4^P|1vQou*(QpVtMRnYIpEXeg4ZOmo^98{KMMgAh~!Y zSPIwTWRI!}e(PR>f+%RTiLtnYp1`TOYugBt5=~7yR%*R6yR*)8L^{uH`|G{P01z(s zm0QXz|I}VT(JlXyqMPgkxr3(%USxZ)krAKLUDHonKl&lnXG+($AuHe1TXNKKC&-nw zf)lOvl4bEyB|RW*bZFv(DhWu({TKCP4=;G@XBjdQjnOsp;H?CtbWQs_nLc}1M-Fp@ zK{CE?Bd1;&QWKi)ujwZAeJy>wzqH6SuOEy5>VHa+?(48~eK*InT@kyF8I7(tZHkk; zN5&fn`M$2NW$@?Xwn@A>f5p^Wg$N<=nMnAXKg4ng#Eb(+eMDmhGQTds3^L1NW;~em zt)C!hh^90;{e}=;nm%Ln&tNcgGw7kh7k{2z$pbB8-V(L1$gQE8=~D9ixIpjOMwH1* zU%v7e82p6JY<;-?myVRm??n&IIEwNPU8R0SaccI@$Nn)1i{1SlTy|8_S920wlT##W$f)^RiU z*vC%%-C8{q*N%{k{%rO;XNBe($G)QC)2020Pj{K3bxMcC*&eMV%Y}#EWjmd~Ji6ia z%K49C#MXEpA*auc%nyn8al~>--7+tYZj;ARrKFd%i6ue}{eOttD}I9e;(ge!=xygZ zz9kwJBYnkM4Ha0K#9R}Zm_)h*l*4IlzI+f3)u>8Ocn2@OwZS~E-qrsD4Y?AU)=D+$ zeVN%_yM#;C-N*d7-IHP<>aHpD!LH4pILW>C>;4J1P{-B{n9dtWcYB;tj{q@*2a_rp z7r|L=(0aENJ=;a+y*Dp4$hPdFn26<>gqcPpMaSP}yllB08swc=bRNCKP%^84o^9$C zyKf)BZctx+vvM-6J zFY^uCaLJ2IKx9{|&he2&7hqG}{a0=q=pXXA_Zyqi?uDa6Zt&!{#AepDFZ|oothZHG z8(H^F!O_?D@<{39d+N0>eK!|;GaZZ??wv!_n(wuwomxBzGqZ3$A?*HQpEGE0_oRBX z76H-_La8eZtV=J@@aJ(m+NBdB1QYsa8`831Y1+!m@fyL`^}_>%8JIY1vbi{Gc^a4* zWD{Sz@S2k+EkgKh@olUcF+jR*(-nU^gO>SbP$X@*_?2T7Ln(u~*%yV!(gzK#tt+qE zVlTf?l=4Ts9vG<33G{X%vba{Aa)EtQ_D#f#9e(L18z*48y&5W{01Nh89Xh6}1YW`- z;mk=sOa#NBIy=ODxIB{wn4LUV7sGEt&tr~crccySdmlJS5Tv~1)9)C-=+Obw!KX0` zy0dbP8n|YM*r31_o|4AJF_aEBnb$|BSw?}~>(W!k8%0gSqjoWc9bzs2L*lYG0?8|{ zg#uL48~0YFV_Y!9I@OSVcx4pZ*7jN4B-=qEn~IR-&%K?w?;ISve(K#}-3PYJO-_)`Py)pMokpwgLXV zUt}u&@?_=f5RmE`ocVWj>TBm3z9p}W0;dtTt@f}@PT7fAWZB+_3PzHwui6MmKlV$9 z-2v%c@kph2AJldy#Uu;Po9=lB>?307*(tSkk$bd-TSVCH)>y>_dUW8`xMEUqoAAp> z^z?T-IZNZ{=Kfs55)no!ai0zX^-qU@9~3e*bfqA@)?br1JPHHc8sXISOgo7|KxWIx zqJj#?95X?yqQPX}LyH z3U;`Wh51*E7vP8MG9DbyGxw(+=3i;3uz9FT%?8up-8D%25hRX#$1HiTF7#CV&rPK_;{(R zrPwS1G(4wXmlmS$zpuy7sZBsF@-pjbtx1;cNezFX_~m13+cc3U!5Z-h3{JqKTmFT? zccIgVd^&cJtRisX6O@<_Al9Qg0TytOtr0dGDO1`Nm)tJQu-~P)p@hK%NHJ_@gu=nc z*M1LKM?LUD?=zO~ky9T_r7GN|Y{o)fm2((zG~G4+t>EvoPH7tjfI5|bbz{cv4^SkK z>Y39Yf3~MhE5=b@^mD)+zrmj2A9y5w*AGb!%2R9x?^SC(THy0`;+4DWD#2(7=kwl7 z&tT=^SlZ{zPx%ojfR?I1F7;f=&EACySTV`}NzM|c<`TX{8=ZLRKLs9vl>3XGOPC~EX zp)poWt+PGUW$3l)q}8!PRMicK2{UxWwsrg)`bxGdeVg~}bEbO`uYNMJdw zaqhS`7>J_VnkB5#hdE)ir9M7OO#;!a%VV-9e?@>RDf8oU5i0@nV8ak4-&glTJ_v(P z)|B@em|X_+Z+?71?DTbafAx` zq7>gm?gP!Asa~>z-uDqJlm6#=-jtal#L$?WQ=1{X|6~LXZ%}g;Y&fYtqon{LIhppc z9zEopTtw>*k~h-kkmf4B)-Hj3u1Y3e3>K)q>(G%F>UHQ-ng_E>;hLp0vab-L_30(v zI7v8n)0iIoA&b%V__{nj|JA4^OG1>~L?-jhl|Z08Dr~4{L1C9)iGR`y*=&=sTh#9V zt1Ke_Yr3$MKNxed4LX<0?thj+ApF;!IpOta?;5DyU<&P>I@`?M~j6#?|f0CqhjF4!p5Z1pV0z zM)GsiUrZG?#If6i1_3ga*+6of4JvWuw$%0MN89bhujo-E2gJoT&Ng2!$H&fIcf!fv zAk`*hVO7=pv}#{ZF#c}`K;uDxe4C9xYMRORePBqnoV@IXa8G9QZ8Q=P;!^AnmfWRCrV1Z`i}X1d+iVnq=8v7r_e zrSI!C3mAA^bRz}49hbqdt$fY@ zc@doPs{a(y$@Vv!^>)bD&t+Aiv7>r)j_F(&r9l_P=kia7Wk-bt>3 zJA>TF((>icJnOyg#+_JCGw7)p)mA>mJy&q=;pw`kWkYlBdF8>g%I^IQ>0lN$FnmHaKQR&Y7eLkM%;)*iwV<& zqBB&(`xC5e5c0L24;HI~Q+Q^|V1CCm7QWdImKPk?qXv-#$%=3kvtH@%h6^Ufss3^OpW1wR`SPv1!jTsNtG@IcSzz+vQu zZ~n*e?-nJX(+zq#>=4_X^=&qc3bI=~x9GJUNGY0GXjS9$>Wp^mCv@4yb|YgHXobx+ z3XLN)(Fu{e8M|G~bX~wgkjs^rP&S|e4Kct# z0cxk6Sh7BP@L&l?Hla!w+qKwZ^mdAu>zB$s6+(L>d*c}fW?lEtFQu>%UA~D)RBJ3I z{Bfgdl$I9k0R0#pF%}E;K|yw=O793muKxoLq_b^a2NKRc0fW zy-z$Iumbtr7Q&I%uV!)f)t7-2Lv-X?^i|Pn4)!&pYKGF_606H+_2r!;J9J+c$`@sYS=F>*vPq^^ztPNiOpJ z74a9&HP`2xVva8Et=8jBDcdGpIY@7rkkg}ix%eeyFryF8x7Ep=>=mVNsU06e>kgMU z)LuS+E?Z97S1g65=um+E=Z(a^`sVzwMoL=~b02$ZR&4{vwkQKJ`P zf$>emu_B}EIV`mBdC*1CeqLT2>rt#)ww$jR+AdTQ2Ng~IczY%x#vWmBf-WzA22`YX zK50!=eK<88Q++=G+2JBTXkqE*I*>t&7`--$pUvTGB?He`gUHzpYZ-(HeI&8YM z!*|owPg(w4ZB{n`>Na@g3z!Pm}sEY})1TqV(6#-T)WrK}Q~s z`y8#WEN7=0b}8*dRs%>+zkSW0l+_F5nhku2=S-M*KVWanmBiab+beE0Ew7LkQ;mx1 zPpTE>V$}O%FYELJsA?7t0CUDZHqNBDjV_ON-KZFQI0WIj_|#OHG#94;9=AdqC%bf3 ztpEuYMnJNQ3*)vR30U}||8FeJgy(8J8j|Ebqy6HP6;`=zB0g8kLS6sM6#(xBN7)Y| zkjEJ?sLn_4r{k`DdeLE{p$aphA~%z}tQAsw;)*1SYJo8yEerd^jnO?$-uW^C&#vakzVgF)PUwRow)`-SsdC^EVF&@$=K-tA2c5L2?^!gfT@?^;}a zdU7=Iy$hB{Kuy$o$YLDFoKhcQm9|64+wt}JT|*I4_{#LzufM(SV8@xIYSRXh^&RV; zPkgzr8+Y@}dM9ldET;P6M}Z!60PvK4BUr2rpLFJ)q>lj#jZub2-0Hku4R@8;R@1cn zwg{8;XRx z8m9+qtq}rz*Mi@}{Swn7gqm?;MBl}q5HeM6a)i*+)EIj5l|AKX4&{<2T7~fQ3AZz1 z{MO|r+(i=CQjAwJwES@Z3!tih-^uR?aLMNW9SC6RHZuRJ{RZyg5Yo5K^Kd$(P9ub} zPt@0E=~Qybx+3nVN&$YjS$qiV}1+ z_3`jBZ4!Z0gXkjG=7tH!$=V`i4ndR)qkIlLoK?(|ZbqjeU3a>%K$0N}-s<0df&8nl6&L(U*%b-wV)E`V7h-QXIU|<^Htgk zcpQha)s@!G65wtXMu4OY6*p?XPo&B@s6OWibVb>P8YCj5;QL+6Gmn%B&=ST7^ibPZ zg3n(lobbAy0?RuXLb%-63zG6y1>J81+-7m>2JTIh(p52ZiNF3t%5?Vob`2tZ5hGUF z_7aVAGYQX~2RjL0`9eZbkehC@K>W-1>Us~3JA)C8zeS)@m#95uiI<yuF1498qh6QvXa*{w6D286D*6>C3NQV24r%Aaz_e*f76 zF8C6cgvzfEf+G@AfphB~yeVwkCwG6hJLFJ7cKtlT|e{X-mfDb(hrFI?o+Csu^zyCYAe4cz13Nf$MYzQFIRlTSXl*a z4s1l9&u35Z51_7?FAT9D@tdhFv|{0c2~)i%R*7h{``z#4n0Sk7x9{OhlT84)y)@bd zI9H44PhIGW@%w}y-{Pp*Zfl{dm)%Qz&*WKkDy&{#N2Ox+C5Tkyw`~_Jlbl*~li?2P zJt2lp=1No4ajd0_6jfaXI;E4bDwp;)c)62R$LFu>-KPVkPJtAFAk!fMhx2QMX@a+Y zs?Woh0b%;B1!v|f$Fyf3@~?W^b+w<|=X-=xg}v;3j9?H-#1s~Ep$LbNQZCDQJ97nk_d?UN@-wdV*+Z>d>ZaW1}BPIQ4TE|vGl zcmK@Zhazu{qPzaAzNgM&dY>~X_W^ACkBGOkX{3B7buD=Csr7g%e?{x`2J-~AmGu76 z{j1?dPbODzsV|2u2iPt9UWpeL5z-EM{qd+;CjsyM??={X5d}&38!f4gc1Zb5YkJ82 zhlx>>wMvE`YI}vg)ko~XQeF>^!VTqend%1Hi1uw0=-3!y|AfFyoFT3&swWw1;EFAQ%| z7Aj?5qQJZ&jn7(RylKfSgR_-(ma_p+d4TWwkL3r18+S9=+6Ms$r1QiCy$2Go%cMob zCKU{sJOy3tf24WgNkFSF+*kkfyv~zDX{1D&x@YZF1G8W)Lu_0H#&?=$FRx*jPC7NlbmNH}y+9^3cRR`PzV5##x%wePzBTOeHQiN0`*`V*R` zNO)eLAsu^yvB=%;zJPD5ab0K$Jk*>?>vS+`D}@dSQyfhXc>=X*Yj?y&S*p`pJ=2@Q40}-k{O7-5p>X~X7H01^+d!0Ew+Q2e;$(jw^P?AsR7Y3Qm zweO<|?3~7jjRm(5!QM_2=Far;Oj3xGVHEa5+)sc3)y5t~D`pg5u9upo&b#W!LdyIU zetS%=aw#L?*BGKielf`p(alWdQqSVKf@{L|wOe=j=_PE;y@oA9ULuDHm0*v# zcjZn2tOXfUQ+17$So=Q?cP6=;UhtS)7`BKoxx!9O7S*(fB{P^v%Al)Q^4=HUJV)%0 z_A$SS-AP`Z8EcwkuGQ~BMpB=cC7=R#7&Pekn3MX-E`?Q22lIxbo`E@&YL}cwPH{-93I>5;yg+8;j3me*&C&#o3M#pv28_In2d?J4UN_t|u(yq86c<_*Pd)?sZ zNZYfOfA)E_1__^o$uimq@Z_BYa~D=ZFFG8|^Y<0;j063h@V}~m(;phFVwc^|z1*PA zMRNV5^)ukBvYffMqJBYj0{y^Th3XD`L;affoKN12)@4nTFNdmKbPz#)ih^w_zh)X@QZ`;7|KRk-VsGzg^0M+vhlfUK7c}V!h87a%e zyYy!H`|~@5yAwd+8D!tc#C{EC4wjIg;xt!!5IQTtBi+;F{;8sWZVpue$Rbv^emLFn zV+HR6RlX^S2RT&&Vz&l$C zRJ}tj&0Jtqur1XbcJX2Z*wD5Wz-V5aD@uH^59yf&Ew zqEVjx2OId|0(bNaux8nG`+x5)KtewUPt9mhwZg}o61DQ^Gfw=O1RqbO5lvUnWo#GY zb%I#Wp}#}Tq#M>D^&T6k5u!g&)3KH7ngaAgLH93zX_I2&c%A&J{0x_>bX!x9RGX7u zp7^lc2i2#p#&0mnVcBQzND|Z)v#(sIm1DmC)*h1Pz%SIEs%VL1RO7V1pms)#CgF_v zdDbcqMHaCuu8J(-kWlp?8sLO`(#m&zlBwu#SYiA1f!s9Tf0u1BzvY&1TK2^NkZKGY z`B4;-R_|2@7gyRf|2YZJz0>BSV8dr=j;bdX0ZxrDDsaLuaD90;!@{KJbs>k4jJBI( z|1b`*_`^g$ZLa0HZXcgSdS{h%1_^cPo}Z8zXu@HJ4b??gD!m0qNx_ZL?-wHLxo!t9 z#e1;qxHzeLbXt~bI$vMyqS&Wl8C{)BevlTsBng)&cT%nx_oyS#=Cvyls@rbY{5KcT zQ|b9O>Z#r(ZEPwWG}XKKmZMP1!t#YtPu>lQ3m-Sl(yVjSctU`9Ic7(n^mBPtt#J6h zl`fz9TyUj#Q0v$D&OW>WO?rj|6IXXLb?k#BRq)nCrX^JryoCmH$EO5G!z9zK=|n|) z@zR@18?}c9aLL=L-Cc-^YvI+MFE6?5_VMxlI=9G<_Fa(afc<0z{Cz2>9cq7;JA9D&KyVv5r0&yi_!- zS(7=*1la_0xx4Qpmk zv=LRz5?>BuRn~g%GUi0!Djo4m)$gW~^jy_oH*;+@vY4{uq2(w|S8_~`Vx+cvd6~h| zNzj&C)g2Bb%}I7|om0Y(H#Lf1MgG`Hcj%Na{yIR@aWcSs;l0d3eIx5Y_{VSh#y!1j z;`>{hI(UbcDf#Xjnl-&eyVBe@s_(Y1bcwd13^mw&6m{{xf`0_EPVS@p^`QyFcc2|5GvhCVaz5E=eziRuMMdt3mj){c{q;m+1K}WOoOnYyWbdHd@Gj z`Deo8E*3~`O3ed!FsZ0C4SpLbZFY-__R5`Z8t%!DiHq#V>FkY0ujl%AF1xGxW9jFE zm2#5xQ^rf4M%oGg7N4_e$7;$p5WIqp8hCyhd93OUf_mjo4!b^_ZDyvqb;85R$D9Akkr-_|JmdZIdGadtr8nDX34f)UU3tv?MM~xe z;e8hc97FFC3X)~TL34!j`H~iizOa{5sl6yuK=YJ5Z*A*giP*$XpPX^+CXg%VNW(K< z4g-amTf)KxH~qM7Z_B76`U$`F^YJvKA9;WtzVihPE~$3hMBb3707fSS|JyZFKO?Co zNT`!VH*^x&R>l?*(5EV(YZ<;=3q*Y*+Njl*D|?L&Txa(;cn`j@Ee;y_J`Q@9G2Aef zr#w+(t?yJ$&^JqXbU~*jC$*L%ey21a8>);>ggX{RUwvVRh=7t?_(28bi>l9^bz7Vs z=vPGahtquG16A$`Yt=2C!62^BTKI|**69xSFM>ul&zXE)>kGIiF>;n)4{Qq`|%&4r`2sql4+n2eIbicd#Y zkz^j!CuQ$h@y8{pG8x#5(5g-E zWAOZ{`1_W?p6hSth$1hX=;QQu*>Eu;bSVRVCa-Nu={E(n_|z}xKwy~l zgZ15GubWBl_Tz&&vMeVR*uUiI36jO1r`h)Q|GXH9)VK-Gx*A7NM~+@l{Wd&s4|IGJ zdm&N3wWJGWsk`jHb!gmhR@tua7kg8qSFqTeYrd1jg^J5IKO+YWMYDr`3j6Z7fn^-!OW9Q;Oe{@M!8*-jx2NjsIaSK@033~+hV zm)^T?GwH*i@apkK+-yQ@`t*>g-E8k~<|LqBM6L%FkKNHh<+^0VcM@>6^H-5TWaA zB7X;Q1pRZGc+gsuZ?h-e1eu!#G3*gM(Z22Wl(^a)i1>F((5$$fQ~U4Nq;D~`?6Dx# zw~{^=G_c-^Qh{mR)8vB&W)OhVu!NBhzBnvb8d+gFk0$^4GjQtbx;t*%7K_ycW6FGP z1DP>)483_=sy7{bR4qtVCy|KGqX0&l@ky-1k+?n#ae9_|x5p4!_lV!?JA?mLqg=T$V}L{C*0~#N z(;-Z1#j0k9FV63tn{rQ6F=%e})89=z*vU$S6=5>Y_=VK=k^=leyCn~4oL-)PL0yq0 z_-1&aIqP1k0Mk84C+x^>oPKF`$bg-mmU(IFA_$m0w&fQlL54cb;GcyUViO4Lu%#*y zo;S51n?2f@G--bms$%R8hsL+OBC|{&-{OlyD+F7vf8))4m_S#_R_k7lN`TW>H<-m; zyE$}32dX=eZ*pM~vZHpPxrrKK5kc=^dHto`79Yd2PeBJT`v+>e`N4kt1%nOpuY0uz ziaxXNzBL)1qC_L6K}T0ur-VKyn4@MQ)fgv2hBf`ppY$Nt9;JtX7;J*n?Y+Vqp{IQ5 zGu&jzi(eNgDi7!UlhX8OqbL9cUB>qXfqy1{_x5D8`~nXJ-*ggr(R#^esB5|QPz9Az z(No!v{qhO8imLT7a!l{tjjsxHKijK;S&4{<%pYC!6>*$E@dAyVYg&Z6Yfa=WNgiq! z1a8uvK3Q=>yyGzM#jH!jeu&FlU{`Vuu?l`EVEY4?io2=|U*fq@;vpx4WN+E!Tl$ZR zvj0k=(*F&u`s+)6y(FxH=W+MEhgTC>0sA=PuDr@wyno{o|EU4Pr$oZE2K%!;RSCu7 zC=;aGN!@F1JHv1vt!p!|+hIVe17v#kyiY@5$jP+YN69oQ$($-yd>D>fH9X?3QlskR z**Lu)9H}WAsxT*u$R}qLx~J55b}?$81E92 zwxL<6*$=7vEQi5gTWnuQJ=IZ1Wu*RR>L&@Z3jE2hqdR0P-t}1%<26+557c8y+fkUd zxX(NP8LGKZf4aHX&b-eC-hou58GjMter&0fT=u&_hDQ}~xgai%tGK=$f z-9lCCKL_whTPZlhQ*76)RW*wNZ7x^kk(KOS}#1m2qQ;q&KWi+cbzGXvwz`s?^qx z4f&QTEnSvC>igqzzEJvTHp^bf57_Cv7@ySfxgVJqgGA@v!PB5fJzA1b$Xr)vI?`8_ zm+R^6-#nMODb1woUF&2Ra-G;ce#6#5;<4=ze1iKqXC7i-)?Jw`G zK$`ExYzs>UzvA1{I{@&puSWh_@VaNhEz^WAtcJYimXB``#mB49xvtdnSsq-xFEdzJ z^JlO&C~Z*O7cm#^0L)K*KxpLWl-CE)up+u#G44PqWc*mnz=R2h8|`2G&8%Y@U(iz4 zanOk861Yn67qF3-|0_^_vE8^U^)}&VhC;9gucDc2=f|4?2t3M3K*&ey58Z=B`gd^e z@)MtL?R&Oq4z-ir*adlwVX~|xUy(PjM|$X6;(MFkC}DY8;!U)(v@c_dTmgXVVh z4pKjNbnDqNy9aok&`ZBYS#$+`mT#YfYqk?u2jypdA2dPLEfFP))%>&J8v{SByN`ys>j{5@)ouS_04>Vi z9W)>RU_Cu^I{h2+Y6R_T_@3eHsq&k9Pg_Gt2h#w@i4FxO5jS+5?&H<^PT3^xng>{F z{f6)E)no$^=N*tR&Fui_mpV7Ug|H6Sbr8X-hG0!yh((9gb&89o0L1JY23GLpZpNN= z$Cf=3L!?k|v*C}mkaDDwy)J7|p*w5kQm=k#vu$8%=|)M3$gIkc$H|%adPMLODnNjS zsCxF+@Yd#s|HIXL$5Z|P|NmsK4oQ@8NTFn$lod`C8iW+ec0^^bGR`^n-joqJRv~+j zIJQG(A>-KV*c|%|{GQ(5%j@-ie|~?vaJhJn$Mf;H-)^_-jlN;_*9bPzK*c4P&%A0E z0geO38$HXH-)54ic)}u@SW@=wU27g0=N*s0TU^eDc705ASDMZkwe3BK;X*6|q?`od ze>B3gfa;qZkJ$9^%hf0Ebgt5qs@Fri#-9~ahZ1u1V+QOXFWIPzkH)Y`-ba;OqjMuL zi<1m`ztLX2qq3*;u{QKVsa%bu>lJpD6j1Pld|m;zGw=!k7ceFX*u_l@PbIXV+<0W; z3T%`t0p?sJeWMQhB6^qi#c6X1CZRey_e@AL_E>!BsY)LPF1PNtqKS!_7+;v~=umGk zbxUUG!jJ2V&!V?=|8m(x$RU5})v4aZ>Vfphc! z$8rC0GAe$>mPDu$fAsJ~VYAGzG!u3mVH56IP0%=x_}LR5yk-i^I|fGfZz!o}HEJ}N$W$hdZwxaoix1NvL<|$5m{K|UoLCyi+?&2^V1YKhv z@-+5`~YkxfK-7IEF5bqda)Y( zu$?3q&9!m(Pm2!LxtwBy{~G{&aqNV6i+uyI!A&PLfky9qlZM>4y{9YZI@#m*C0gDR zY&bdN$fi?i#aCw=nRf?eiX`rQBKCU2MZLG*{XHpftkoxTaK)(uw_eO|=&g(SLb+3? zzXTt4q22soD)d}dtmz}Z+GmHPX>+Y@=^}O&t9c%4-Di*s+)en7#aH2)*xITg1!1Y5Owd2D{~bCB4gfC?EA0&`(V5Dr6UM}0QXvmoEK?d_E$dozm-aYTj6`nc0V8GR>INpy>6)J`q2=xPLAXxk+a)SDStGYQpd|J7(eZ%$qQUMB>*ZRRtC}Pb;zqv{w_S zjp8`fZ;u^vF35{S3^bzZk;Z=$IJJ;R+n+M;u7mB5m8am$6U=j&A*74s5%D7pxee|O z0rrsRn7OQvjHmKNVtUbXA)LRgQu2BClC*401qcNA1HL(oYDiS5t*$1&W^J~^pxcc6 z!5jg%%ggq&&8ii9o%gZ*?wh$ky9CL_($WW^y{*dgvg{LdfXPW$ef%R}nhh;-j;A;t zHwYlg?Av}QCHQGir$>5+iX&~SRDbRp0s8j;C3{%7d+U+?brO${EsWa+R9P?HNmKk5 zqwO1jq!gMD?Fzhhs_vZ5#9KESyKzbm4pc*52nZ7t`Bd*>-Z0>Yh&x_jnNQ&EhaQ^^ z4cda#Dvd6_64t4Ytm@TgFQ2S**cF)F<@WFWJHp4VTL#&Hk=rR6rKcf~>yyfhw*GS* z#gR;h$~f3Aw6g|rbU=7}x%Hk?9Qi;|Z<}*|@Vm`PW~5JLqxjFH38Gq9FV@0Y%FVbc zCRV|VCCv;A-}#`cUY1uKSp2t?k`z;OK}j)D;ZD#)Zmc*Sh+cC4@521;n9eN))!AOI zxN}wgB)-~UKV!;6F!6YP+v4$4hjpoJ_m63xj;_h)1&Kjwlhkk{BCB_LK)Ya7V zWRQJj;6_otdQ&U#H>DI}+Wq!oQ!yXdkJvR;_WW0#a(7=kfl?uo7t<8}l-0qaE$q6A-=u zn3{FY!fvZ`;ket$4AJIogG#@xD!f96Wf&^^_g<$q#+}B-4xf1x_T24i7xgq~Cqqsu z`Y;@=Lh!^y)Wm!-5mVlw#|usV~V}J$)t04p&Hv`t7bo%e;o^vXKsS8 z-Y0}i&94fHfc&q0W^GvQHa#gjlfQ?ZFubO}$N|fN#4tJ>mR(CB1K4??$@<1u`?<*) zn}EUc+m!n}iyL4N&5te35A}32Iu2d7Nm$FvN&7x6O4|I1D$vc^TLc?Z1TUqUn< zjIZtW_ZBq*CnSq`r*5(8WfWym*VBdic}AMEkhkwplnnWvMF>t!7Zue7xH$C5&skSw z;UF45(_i1-GePYyHKZT1jg4CbF7eOq0==ZP|F&dCNM|Eo&a`656vbPnkkX?(EV!dE zS9`jqy6Vb92bgMT=}s#-*g8O)Egxn$c@zmr&Arz8m`sQiL5?0LS0m29lBQOIS$l z;hg0t&q_#UI9-VsVKH$yD_ZGCzstI*OYdD3os4Zx*GM-}SUjv#HLCO*9H_~Cv&N8_h66d1E4nVHv_miR4+}oh)`cHu| z>vtsrEYUoHtS9xX#uPW)PxA&DBbORcXeVCLq=iR~T=U0?`)s9WA-y?+HXnzHemR`c zU5}kv&+GI;5IXP+I1|d4!s2D;m^CU(xD+t*MA>63S8}tW&U9S`Y=86^;28b^T(Y_$ zUojySK+iM57b1&BMEopm%eua=7L@n>@mR>$-ua**Da89l>uu*q-#smnMFTV-nwuw2 zb&Q{!>B<{@3cEe8`vQi*C4iG84}her1Cg8$ug{w<3tPTzrKXlc;gKyzAZisxiqbp2&)~tG=_A!RT?=g^>+Gweqs2DeKzTy-8kf1@24B; z?;G#XwgHJ2sp*tNj9hizLdgS@PEwDQ^=Fvh%gX~8{2WnMkIS(0hf4dSWNxBM$7O3v zn0wJ{hXyhtQpw0;@pE0SkJG5R*Iv$v38p5K!WnQfBp%c3yJVfPcz-6{c-14-J+I3D zQR7AaWBj8f2l%d$Xf!*=xim3G%1wHqh4ZoKc@DLk-dByU51@_^D+K? zPWAmVlde(?k(m!(R&?)c$x?2G?v|nLi}n5PgnM!<)9t9EWTttxHtJbm<>T*dhW26x zftyftNWf=T0TvAt&bQl#I6&Gjirk3Rjrt?Eh$&qi0XzbKaExE|fq3T+Y_#mvY4t{z z<6l8iPFIh=7J#L8x=+)#YbfNd3KKP&A#%W_NKR8MN>LtdBQpPXh|i%Qky#Oc7cM9+ z0#NnW|7VDyxz2eG82!I9ZVNe1HagzIY9+Qu*OxRSAxmFZ<@gpG9VQG{f%yp|j{`Rd z`ptU_>h?YlLl~Q$(tjIpYIv}{Dc{fXm+0!EaA!%ji}S%z&=>SRZB6coYRsHo01$Ql zyO5MUhjr6Ej-0RC@W zSm@ieRweO*+Egqc;lYS0?&Fxa4;l;U4r?IGqf00>L0C?R7e(mt9H*;pt)4EKts!cN zUXXlu?ec+jPtq)JH}F@~ae*r5h)jmd^Bnmsl1}YyDP%ufnwN>hRxoodY)mO}+Od^| zi14qU3C9IubsV2kYzTsGrY2z+Z|@qUFW+~z)k>07o&?NKZ@6dTZGBu?_QKIW`&bsv zU*@&3h27Rv`VB3ox7fwFbTLu(-*x_!x8Qm*5RfPfIO{5k6%R(A_IPAPO8>2n+D>&O z=dwPGe-vkKt9{>>8OK@ON~oWY+RuFXEKQgg1Um*2fFtYw349tzlA=EIDo7_OdR4jC zYu}mkeDSajuzuNWY|9{su44Cq1*Ad@igMyJN0Abz2A>ODP-Q)ma%tVr5YZ4Ysq_?- za5wKc%aIxS{J1InlWPJ4$) z*ANEf(%tQy(_d?z&*#`bI2ALj&k%nL7(Cv;=`0fl6)Or`UPdY?K#Rs@-r8rk+hDfDlQOi;~RHSRF}Bee^h zjRxaU!;~@e7ROIbiE)67gi<`{-C`54y~s-tH~t~;3*6kd@N{$%sx?}AGZhI31jPIlM@iyd8p&F;GRGQpS^s3RJ|`Ge3))KkfHJ? zl#oqV2N?VEHbIOumf^>wO|ScBWrpJpNwD*h5bs6h8Yo=1_t@Mo0XqQn7qP}{ zq$piC^Pk8c7A)iK2X+TSYpDc$Yg+;sx;`(>%M-mn0?uKwD*--6UT&o{=n`jINa+qG zi3_)6Ddnx2=B~#;)bOmCWW+m73Gzw!rMn02($QRwFiq=rc^wUw2n)t#3_#RwdG^mL zV6K5lcjPci9Ab`2T1h2O3t6^SD*wJ#N1W`UB>F|$RDUx%uOx7mwG--r;nSM6KR;i` zn?cPE8@Z}HM`a9)cX$ta_i85qMz1g>BYgRYp~zYI4^HKsU14wz*+YPwlyM*b=cxo| zexTZrwNiOel&`@OUIAEL_D=xJK*1ppolrWSQiZqG&iFC8J`-8bZ1PVn@g^+lTglrj zLz+ru$=iZ^HG=1z)8yTLoNxymQbsZD6z=ppFty0};Y|?xch4q;8M`%riPO#YC=dmU zl9RrtWV4pZwji=JD@Ah~{@u1=|1Z(u)*OGaCtHAEW&58Fb+D7-9Y&6j%Tlz6N&vmQ z_&@v09gyS70|l}_Z-3`~9hC;saHbI}ehasi_r~R&8y$yoNG6x_8fq067;}D{0%#O# z^0h{iv6ZO5)papF3u5H#t$s4d%#Pem46;rfMbTZLO}ITj_X+xtwcp~tA$o|Qph&nc zK-ry%-w+b_acaINo&txJ(Hbjt<#gQ^vZIg=@pllPWpZAgQ@I>JuXxy_f3+vs<#94q z;g_bi0EEDrnH=)%e!;mR?gdp`JZ%_o5P2-Kozvq?XKk*eIFTX1U%>2fp=YfvS2<+a&3& za!{AJ1rE_C?0V;MHZ0Hqh1Zl0<4NLb*55VYY7elDqm_f}$9E7(Uod{m_;iOfZUQ9P zG)njG_ufYKfo55=79&D_6y>41-F|(o7HL|*Q;D{t_GE%edkml2CDSL$14V|@btFZB zIo_Wo>Wx2ThH~`Dr9uq^d{wB0(k-Kv(rbJf?luJ+0OzCSF38S8HL;*pZIcf7p@G#0 z8IgMy`kD^%bNM1v-VtY$*|$QP<$Uc1FE|{n_^w(!fxho@kVLIsNTtvTA~!%n3Q-s@@*>#Z+g3L?` zOjTEN_S&I)VLV4YP10fFpM+1MVp9*T z&F(OQ_^*ktSQcl320otL`aZhZk~8?R=>N`_9v#Qcf;aa;M8Fd$C!uY&sFvbAZSwq* zG%(=ys;tD%1&Ifg4D(%qf#n;IzMtw_W_vGlTR1dq3fmw+!eFT{J}=l;;g@AJV+1hQ z()`0e!k>mP$RWZ*=@?7^lSr?Kp6~#TOtrt(=p5Gii~HciOW2x_9G)Mc?k3c}ieXe$ zJi8n4b8j~Xv*U$U6oi{dt>G*adRj5%;T9LUZB->-*s-tqboI+yU25D5suYQf+gBR<1xW@;GIek&lUVQ35Kn z18J@GbyooYN%T3dne_EUybwOLTXc$u)elOaDX&AfQ{(QRXg1`vZkd z0M2urGRn0(^Q!0`AVkXc^QQBQ>QS@j5iWjJE*^;I#?$@!mU!3`B~3#U*XEn&`Jy{G zZchcnZGYf0fUhP?0PNGLJoDk_cwE_;S{taSSiiWRI^H$?*NA zh4M4I4{&F*L8q~xqs6w>kG`0&(6vFkH5nkruKHhS(<M$i{x}{^bdqeGmPS+Q1W$Fo8N;0wvleX$u88F~!!hO;{KGAPF_xYp zKNOx78E#*omL7VyKQ^INP(2REzQqP>{PGBp+r7M3+i8z}?DPnCCfzaHc~m7wkgXxr zd$w}s&Mo55cM`ZjX^CS{Z6zs7f0lB@Lj1Ief0qMr6@))z_anApl*!4$&N+`Q<_$Q~ zd5f*=k33!|Wd!kfSa48Q3rhxh6ew`Mu8qZXW0FzauC|1vzg^J+nn|_LFA=}R%*mG} zI{i5vZhBt|JG_W|&VhagMW|^aSHA7;)tF!CbXki3O|02|Nz1)#7~RQfPik)CYQHo( z@0)zBwNN9(zst#`EE&Z)Bx6FYOnJWj!d_xAbp}?dgk{JX00YmiQN7T$&}6{KVDj&X!3uU4@)Tib)Sa^)`ljos=g_zp%FWTWJU{H z{K2=4?#`>p%_^p0fj`S^5y)WC#-Y3;?Spk(R#dJ!`biB0i>bX~rIDY-F4Ao=#o_E; z7Rc964#nDP9J6w_2)T^03dlcXB@2qmdLUtBDEb;cObrL1hcy8O2=t3eS*Lp1wGj`E}f(?nYxY zxL>a6!Cic$@PQLpPV+k(i1W|UK66`JIomTOf~8`q3XjnM?9aJ->+=Gc?)H?nPTWkk z@8%+}(#`!rzo5qN)3wuTJjoTIH2lR*5|IYpzPpa7MvwCVk2v_!7ewFwE^4B8eo<7` z7IuR}Ik%BQ6lUh%!eBAW{eFF(0~YX^Kgn@1pX-MT8$8J)8Br9*&r~4+f50pk#Zjoz z#Pvr?+1-91r;ASrn#3<4p%5W+`Z@Of`Xdyhcty1P_PaFhBUP50?_a>i1GJJ5C!Ms2 zB@f+u_VFzbFX8wa-2$5kfd<>rsoEv!nHDE@r**fiCsg7{-#=>-@b`*7kR>7NQAxJ2 z#U`B6M?Y}`v)lE%efQR2zM;2-k_?=vp}>&HZpl!5%8dE#H%g&lSuOMEoP@Q6)4-R~MVPCvljFmWh5H|}4hkD^o3m9&zb zl0|JR`AGPD1}07~%x%I4-n1V#H_bnh+k5=B5q8;iD)eE?zff)2tPIxYTe_Wr6w}4s zXs=bS%7R6z=PT1?!5;=`f@$C21tomaBg1%xe?`AXbp!UN{uZyF-rYd2JUV_~Y^(T= z+J!iisUV!Z*>k^eBct58G;gDU=WLYF_$SUjkNMNG?jyHZ6)R@_!0hJl0jc@4{lZbl z0_SbA!cF+xWtvgULx%XPe*!h2B>s4Fi%98PBf@fFT%V{k`SY#)1`2QY0^bwk zbnuH${J^8hE)c=8o*i0U-mlsm3O6T1y5{hbdA3oDkHm^Sz4Kjs_$Z#1uFPh4GQ^uK zd?w{HssglpH=Q)jjlo~^qq{BCQ5>d4AY+Y=m|%}vX5sT{Am6qhTpCx*gS+(a3j89O zcVxPY#Npjt?fLaJ9P=S|7SEE5Pu%%BQ;K~kju>DXo01s`X;hSsQ|4DSPbmBBUL)FE zmeB9q*vDp$bTVk5I>godVY%>KRG))JOdhWpjrInobJ@wZp}Y1>MhnLdKM=77e5O%w zyav;{gh5Gq4^y$Ml5Eh6h4iBs^9Uzm3XCYKAUwoKey9D9}{hDV%aR)M7z<+`C-Z9LA&T4J5H|QaJdF>8}26a zzuX*c1P*~uP+U}i{q~}Ar^J{J8#RU%-LH_fde1ql|I_>Hk2plrSiN+Gg{*9m#w4jn zdJ7XkUn1@QYO)DFN_o+^G|j2nwlg)i%Tv z<2i8`O|Za^C-USk5j#k)m0>>m(@9Q~@UnL%%r5*RPb(XyYli1r)D9+lK%Ph6Q!(ib z_k;$H_AiK8OUoq}r#qa>PkQ71-Z?Wlh1(QmcVaO=Aa%p?UIeJ)@ut3cD<-eCI%gT& zdFY|!geW^DK50;d${Z9`b_KNeA1C9U8*PefyS6@IHIZ~Bfp0`jr~RD|PIY-T2(tWB zJfAd^`Y<*~h$sLsBug^Jk@pU#gIQ<%!@zPwpxw{@(s`4h4))`COD=V!Xl%+&BX}26dSN~;XLDIgUh}SxYowcpml5NS??^{+gXb45rW$dpx13} zM}s#%!&PJRk3c-I!KWx=82Cwg^lNk+z#LS!N6h^SwtNnjKgb$!`3VyT_UmE)9k)C> z-Vro*UBCw0;?+G$E%0ip*E3ohKTc_bO{Bl;(P!BCSg3o5GE+fgN!?owuVmky0*P&n zy&IbeUfUfqiHGE$rViYmb;MgF=jk?#T4jZ zB_323R{a9^$=5i|AQ6y9d|#OMR1j4U;h^B7h?NJAQdpKdmR*2a+(tWjU&waWK!(-r(p8m zK)s43?N33qf*pl)1LgMzWa_`bF8TOqHl;d9B~1fz!s$nW6H=-g~)m%j$WzhwPf-77J!nJhtPFE|!_;ez^m;j43MUt4Vrv5%cpU@4vz0Oa^i z)I+OqGH~JvWxF8N7EL{pVYfT{@V$CUd(j|CC5+<j3U++os=TyILxUF$UiE)K zl>TYp4FMPjSfJR@QhNIQFPDC6;Vv;de|L!yxTkYrLyqzNU`Z?i$&}fV9_)Ts<+ygw z;td4R>FVEqk98j4X5Z5K=S|EI14cT9Ux2a7f4u2#ObQP{X54l$%IaksD#IuwbfMbB z;m!U@0fextJhg(fVFXqn$L#G3U~aryIWL0?y+qE@_p0F^^Er5ph&Z?Lw0<4k*|1ih!!YB4*VOhT#V3 z5<-dC;{!TEbm-t+;S@yf^k^z}xxIrQ*tdG!5TBMd^-@7$szy_l=IV&7<5uUsvMR>+ zbPzx8K&h%Ap>`n3ssNzN1hAh-{tHnv&>n5_7s*?mrK&?*dXSA&g{~N-?nS=zvfT@< zXLUY)^5mEttok_v<=u^Ls7S;ihfdzeUDaQx$8>m`tc7cI$|lQ?I>0!eMj#4`^0Y|O zP-z4fT|DW(dvzLDo<9+6-q@n?NQE?9by^Z$x>yIPN=}pgZV6r$zSsq};qJum?^Etb zAKSvHuKlb+)2B3yZH7N^K3OfFO(IT!D%&lHci!w***7Z8m5Esj;NGt7Ce2}YB(bI7 zKhhd?9VThD!WY1b|J*Nupfl3vB#=I@Jcp@xH#h_+EQM$NXKnyXG+jt5tw7&DhR@cl z8xhGZQ&a_hl4bfg{A&!zS=Tz7IA(NFWol#PZ;~?E3zsjiKJi{E3-3~+)+nh~D9$Ja z9giX>7xU!V6^sMQ$ndz0x6m}F^Qha%OxJ zFM=Q$Mr+ooYj07K2x z=6ukgRRtoAhWjuh*kZ82hH>&r`MFCf+7vf{xJ6MFvLbj)Mm$Pm`oI8?$+J8+Do2I@ z3#D$=SqgM@Sl{#|Aei`l0VLv+%bjNcSu5eeh%-&)2e8{!F09@p1{HLjzqg+4QVT=} z%Mgc0sQ^b{b$`UPnk-L?*}#PEXO?fjir3|-zYsTJ%l*4C$=@`&iEA2w;Q|W%rnbz4 zBb6xqqbg~mI_b-mq`4$#w8U6Y)#8Tich{m}?}K40Dx=#B;b^Av)zZvO!A?mi?}*wcF`yi#-Y zc)LEz10(;c%SrS6a&oU?3ytbMc#J8U=4~z}RAY$Mxne~p7dPH${3#y`sA8KiJ-B($ z`(~?UTalG{x)0Xs>K`p&YfAu?nF2d;wSOiM0X{EzUUWA7h|-jqtoWpJPsm^*$ba~1 zwsjGG=(km^PP(c+Ux%tLq@ztwwAE7Ml`NC5x-Y;9r%)nCQi-A25A@4vlP|}gNv6ST z0n0c*lzx3Cv}c})()%ap?=7gt3Zvl9IR(#HsQcH}dZetRZPz+$rvXLY^R}G*L{Mhx z)>g&fv$_(9!xUVn?@%YzV?I)52+&lSYne8~t29r=87FfYLKhmRg06M~ID}l1e<@v3 zt_2wC|I2M&5*7@UBrxLwuI01BUtz8fF5cDw@(REeuXJH429n)juf30*Sd8oE;LWv_ z)5xR(=|xBq`md3T-GAcojS}_kern!u80;5pw{XvCQvs0RR{=y>(T-*5*@zRtmjR{& z!$ZEvxg;PRv{Gxd@^n{r6>R0kTs08m)s-ouxR{J1%rK|f@z4G$#WGd;-q4L2q7mx^+#6ON zUhKT#_0unb%qx&Mzf4%fowKmWgwOcWy}`8~J^wJIqg#0rDx8*7&4613JV&h^iVpMh zCTZcXQUSL|;@9w6rLQ)!oTc)#Fdr9g94$d`KtDBKmJ@i2$wqW3wzsF8kxN?~sWw)P zYv_X!I|AwI)+t~I?%T0P2U9RQZvzH_Qcp0ZZD=;t_0Nshr`xR%fXCX0eH<@j^YgNl z)w03<;j^h=sXo~UVCzmac~N2{oS(+vRiH}WpKnjye)~JmR<{m#NC6~8PnAYsVK1*D z8@;yXO?@i33b=KL2!BcoreL+jEHV=!_w>|1JFSugJ?npij}}y^NTfFfeQT-f3VD5p zOJ2D|!^G|q`K3-l{Nc8g{6VZb-#3z58=I~xJmTYBJ;ItY9d7|F3tI7OJ?6oAv3)Zp zxhbt}ntQ2P74J8fvvP*}bf)yLK;wW{>Lj^%cTesi+WFNtDI?FQHL(jmO0bS2#>+OH zH4_tw%Qrz8ATR*YVfp7UHsjCd7lwVUeN+QDruLOMRMPzs<;&)qRCRZ0l{8<8Ja7Cm zsxlUR~yDY%+IwPX76cQxi#@JoU2w0kcxYLwKq+Y_s`w5+ad49?SD8w9s$rqT^knHo05b5Ej)FW zZ|8{r>FND;0z&y6J$p1*GhfBhNjRD@3Xss~`yK7Ednp(AM*O@43cL)+P4ij{qH5BP ze4H9(8JG>=(Ubqp*~c9rJjEHZ_KO=m8%&}YXn%k1S8`LKG}*ux_(Cd%m%l#XQ&7jw zHmKjW&Egjxd#En)mPT4onILd~&Je#ul~M}GZ@SJXCC?vy zG&o^+MvP??X#MS7#*PFcrTEWv=Ssqo;qopD+XUVcbOHpyl}5K~4;p8-0Od1ri-kvY zlL-}@ea5(c4d?M*2RnCOQ;Y)WHjjEgbj4Zk)dop0x!>dUr(wD@M4lyM3iCn&l^nS{ zKTMR0^n`gIrX1Uy<3;fe{&u=WjO4kdXm|@SDMgruav4*t;Y11RGb!{Z%nlDg1R!i8 z^6#Qaqi3t_>#yhVD3Dd-X6~{t4tdL{Mte&)wrx=&!5;ia-0)EK*BOJ0NZbQ#NF10h+?oVk_Lf3Yvo}4khi)A}4kJLEOl3mT!Jqz6IBJg_=U2Ho^zxv0&SW8N*QvTckbEiBR4Q2_%>Pp(4zU zK6o}=rAw)a`)b@{3czscwvr~4qvpd98hSTO{W=iGnaea_KsS@w`zrLyRouk;c;6F@ zyGrzhTr+O-E#9cYnyh`9F$z3^U>2&Gb*3GSBsUEv1G*$!9V3bw4(gnDBI~tBo4L$Y zo}!}^r4MQ3?4>e7#rnBPpJc)q3|7uHx;Hj+68-Rj3KFbC)2-#!rs*VA)f);qR0kri zW@NK!cf5tMS@VYIC?<(tTS_2Otj2}E^ zbFLWHn|_#ZvQ|9km zb-{5~YkFt*YRF3dpRcA!-RLesdzmKcNFm7q^`4v0(&*5tpY{A=Boqo_$0Y?aRQx3_ zXfSf2fR{ufm{MZ|Rp_jHg!mrmv4 z24O8khaX@M574DDUCWVHg!Bs?%O*;SFAE>Uf_SwS{4KhG6JEMQq%R*M_^si`$$iG3 zG~XQRgB{OjIQppg+u1syv-)MHb(phvd0_!9+yud8_#z@5_840tEXT;fj<%Re9GdgLx0V%Q!;H^tG`hBGzRxl-}qZK9%)==8T$7!6e)F_)`71BG^V<@ zUrEA0l*XJ^0*U+<`v`Zk922#%ivWogirBl?5uArTdu(oj{<}VM+{!j}1JH`O%aq%q zx4-iq|6+!xl(GIgxg+iw0NVRI#HlOD{ZQ3*&8B}M0 z$8T>g{s3KsmaJyuyCtrFLJ@8XbQuvNY*XLPsjv$-376fuk>f|P0=w$pW%8CSz!IJr zg)o|#PxEY3&hVY1z$f#o_HBnhzFVmu|Iz!F#wEzu45H&2r=7uX3OUzrSLxe#=*z>Q8m@d#FT)+o+oUXr8 z+Vp@EU#1y(2XGARC_o-BmQwEF?PN4BFkJZvV0#xj>4={UKL_X2$33WeQIn34(yEwE zy)SN{<8uvN{`PnLO(w%Ie+d`)j*nhPZ}}Axir&o4mneo1dGE3 zpf}SNJYJ}>+RiIvIQ1_Q>~xn(DXe_&-}FldU6a6y1CbM6q(W&l)~F=?0u)jw(;cX`~(7`e7}snDy%Mg`NNg_9qD4ODa>G{WKSqjvBxx+rO7oB5Zd? z3P+B!>ntoxDhBc&gk231k1%Qkx+MNWUjljL^7>9n`|c`A%h$yNz4vu!&{ZZ5i&s1N z8CJY1fA|UY`tT)$*yYimLugn^&e8*1)%dGn2s8D}NFRC@R+wq=?%k@Y0 zS%^~H8?!t`A==KTaq+w+5D#B*KGw&#;jIx2^o4-QA))3$5L!^?=)2MsU{?*aL;DFt zH{6fW$FJ57JJ10@Jp2LVb^?_B+UW=IfvotpFN|7FLW5#LkHQeC@H>%+RLX06=!X0& z^Uf&$r8wai8yV4L$9yek{)ezaBqr>A6*BYzvOsTA z?npS5tNn~}&c%4WbZv;g&$Muwy9yXfuDwB!h~STo0kkziiTCg&skPPmy!04M9&rk2 zAE-zsxr+Z*vS0CqR%D0-aqx2qU)&f78s>F(gaEzen$HO_;ryRdaghg;AE$M@-A^g> ze%=Sq`y(!1iHSF&zMSt6uB>Fh>qqxVC2`uyWuuZ%_>4=iE^swOFlxa03drR;J@3@@7r&NUGwD~aKPr1r^8#=D?VGk{&!d?3rB!1T4<~+p4|f1eR}M&>iuI5CXBlHYvQ20pK-S?onV-c^_PJktOcD(ka>+siRC!OgA69a2pRi*Wxf}H zS;KUj5N6$L+lbf%f#TaYp2fhxn0Ej-^Do*_VSC_Z!CZ^dl=^ny;hh8FX9Y;!9NymD z`?Q|>rJt&=PdJ;hwcX+yWu&WbnE24?&W)+Cv*jFJf66GgM-NOnzoC5_>F2mVQha4? z08A8||DIO;I7NFhX-;d63OGsTc3dn4-gj2FUQe#o+Y% zuHs23a*~P@M-hMNRxIWk)$NJ67Jb-28*R0}*>nHUt5J6ob=U$JZ@Jpg^HDP*_?Wse z0#r#AG0gEJC*=N#QGj(N z_+m`Y3BSYw_2eqo;=CHEq71+c4SZa97BBaUm&RY=!?C_sZX-bEbO}$JZBi~EZ8bIy zj9xO5=?{-z}vEtE|j0Y;K5-%E3_QZbwz ztQbBgM-%N>np<5{rrWB{5!}&ll-L98_nV|7kKE&Vs@3q)fAZ28o&!}`wDBJ!qzda= z>^?2u3u7GcWtp6#k&GJ1N$oAADVfEwk!M}PEu6J;0l&8RiBNhp{5rjJ5U5k&L309p z_R^hYZ65MfR$dT~K2j7knILW5cYPe~5mofv`$-ZxmPN^djfn>Ii)tpdTR(Q8J!^GT zhV+WgxhURltzR8wtVWP~QWsdvr=O5cuhQ-_Y@r7Ysntmd)m$pOOc9y7MqUm3!9R4% zuVTgYfBTJR{1~}w0t2fDT@*tGROoFpg6)=_Q5ir?Jy`aXAIQZF`ybBrY~{TE8?Ns~ zu32o9HvV~fGK1c=(@1doZBi*^3*&N|HEe&Fs-RaMJ>Ow|`{ttg@}*LU(`Wla{vQT$ z@a*M}=!uC4-$fjpL4G00%-s1A6w9bh-IPr|ZKb~>`jlI|f46Ub$R%sE7xJ#^vApz6 z<2@Q+`Epz5$DOpmTR~_-qU8lwp#G3UAo5<~p%#MqJ*Hh2^N!iWkmUnBW#b_S2)%u{ z^GO#lN@-I!2YjfW{2+nV*v?lIfV~oq9^;v=t5=*ztGbSglI?J3-**abXbrZ?uK11n znX5~w=%SF98~##LBQz;sX``)qjSdUS#l^3Worr+QCT^=zBV3do6f5?vD;}Zy4 z-|H57vCwsXVZmZ?OiA1DNDTg$tI7_2-`#6M=Bpn{dvh1L=DITk4@MTt#j%$0_|;#c z#Xzp6FL|uonlpYgrd~D~Ippz2h&I@^cjTP4IHeQ!fx@%WLN{ttoq2x$mtc1@yOVnE z8>WBt!i85Zh`*vR#@wOb@gG6MgKj@BqRs41CTn$qmDLegu5nNrD9(;hmG;() zWKFz{?}An@6ME{fu& zFK_OY;Exs;tFY#>5MWdDh&kn-+Xf)Axc7W?r^Rm7)1Pw}psxNk!+{y zUM{_LE!1);{|1g^m7=L z9Z)95_NJ2@*k?xzb|L#?YS8LfeLqKU!a+@Wz6w<^=gn-3hqe9VmG(N>B1{~rUcKLA z9@~8{VyM18`GfxXK5Eci^2fe|lMDO|lJIZhAi(D{pNN@Ho^DQbtHJ|cH?RIXr%loK6q!1MQd`isZf8i{U6-^KL&v~_$r zFYQT7$Xa3}ErM!Im$iQqo?zjPwh|VPr7J)Dff4h8<^0;cQ^Jp=VeWi2v$ZR_zEdY> z&$ISF`*(qhC*?IYh3!VYz8@~$bLU11eVlCx{PvX~DrFZ#95yomFZ9X&X;<&0dAy+d zl+}Ox-2f@+@Ux3PG~?hqANFIU<_*E)QMfS?f=*9iLp)O-*zP@c+q0{*-niJP3w~^m zF1l|(;{1}YDN$9-Mtt7)hMOEC(VVmEej%gwk!O8xZ189l!mpa-xNs;}ZKQ!;NcJ)NDvaeB9OjkB~z$^G;AwnS} z*r*Xj-1M5(kwDJVRN_7I^V^FjznyFxZ{@RZ$yW^tOmEk&8k9S@0q+C#*Cj41lJZtE zV25J<_e#(f%+2J>YcngG!&(9uUPrwIAC28FxRhZXN&zH_&+0aQy)(HL%1ri4o{i+V zLgzYcH@fB^i``m0-l{3&^C6)>La0?tf`5Z&dD zlQVUs;s$w`p+7QSi`5zXzD&EaHr7>TonCpw<2>f*eEXu*HNF*hSO1gq0W;kU&bk=u z`Sh1lrFbJk(9u=Ei&Sql^#3t+-tkoa@!v1Ilo2_~PEpD#*^ZScgjAGqaF96m9_Ls^ zWv7g6Dk~0|$2#`0N5(lE969#P<{XFn()a$|zx!W29v;_qea3sd-p?1Q*^|*1<$Oud zeaWkBA*H)i*CkC~N1-WZf8r+WL4Bp~*^DAxUQqlouhonm`u#PKs@uV17Llhg-$AL_Rn`KmG%cChHE#_IkuC^>W&^$TDOSEuWEtq zGx5Vn<)bg8zQ6zz%n8W^V#Fs#*6;O)6^nJb5HgQ-V&{EO5&V`!ZDNrda+IAGk-1IZ3Tl0xSpYPbka-ex3^FfFo1ahx}fC?z5rC∨` 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%0AfDIr^S zq8fP1H;fhQ~ z`=-3wy}E$!a(FO%2U@m5-j6ZX?$vbHlomIhr*qN{_FbgcTtq>+fQSv}-uXq4eq>?Q z(UDH%UbS_Q9`DEAj2xv!%KMJhqC0iFX^7n1wLR*Qcw*Uh!8TCea@lhW6-wv zY$w_41Ni$8NbwPV?|ZpT=vi`fjALa$hWtXNcftP&nFMD0M^0ZwE$7CAX~Sa$HjkY? zRDJV+cdG5Sgas^@nrD=bF z@fqTq>Nc5I4PUVzVj8E(@$eBF%V$@&55&HBZKz*3uA2*%`*abt-=oI1>!T=m<^6^0 z{n-bts~*;KNA@)tJr}sJTfDD`Q&2kRxxSz_@B2gRVx5XU_Rqya zcw-sBkH=R9MqeBc(?Hw;BcnR#xX4lBCy_`DBvKJ1k!S%Zf~@Rt{pw&_C{TK}NU+&* z?Y!=;<3_2IKfb=Y?n`T`2TmKRW}P=gExvTHT6(!&zLfeto`ea;_b)#N=Le8c*SCbUl)_VwZVZj<$pEH^G5%}1J3Ozy_UW*ZXULgh86=`WE;1d)m$ zi9`!TsRNf~Nzd7RTh0CWeUO+wtU=w4P zNF;hqDuN^uEx;8ORyMl*iJj1!wsZM2GNNM^O5z0*Mf;O1z9l*=NMD*`P@h8c!Q{4C z9PFo#PZykDXbXww%QM7R47T`^xS={t`2;}E=-O;t?VQY}PjTr{nK}0P207M|+Vz5% znDuPzciYtIzsoi>o-_|%Oikn0!CbfSi*0TDO=A3p`seh0zFao>K0ChD4jof{&K|e1 z{taAyraeaH!q~ZNjSO#zzOz3DSByj=(JN9BB#~$VuBfoGQJ&1{q}{_wT(pRgz~xvs zZ0Q_NFE`&E~p=z4{k?om4!A1^sqhW%LcV&VB;H`kXQ)Yg4GJugX759 zEH;0*Ehb)bIpX)3?LEi0$Kdf3dQN)v4buE2dKMjVEka~Bme*a07*qoM6N<$f^`hfZ2$lO From 82cfbe0e73f5266d70faafbe016898d719d83031 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 25 Jan 2025 13:51:33 +0100 Subject: [PATCH 107/117] enable always Hybrid Compile for C2 --- boards/esp32-c2-devkitm-1.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/boards/esp32-c2-devkitm-1.json b/boards/esp32-c2-devkitm-1.json index eb3a58c..dcf2ca4 100644 --- a/boards/esp32-c2-devkitm-1.json +++ b/boards/esp32-c2-devkitm-1.json @@ -25,6 +25,11 @@ "require_upload_port": true, "speed": 460800 }, + "espidf": { + "custom_sdkconfig": [ + "CONFIG_IDF_TARGET=\"esp32c2\"" + ] + }, "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp8684/esp8684-devkitm-1/user_guide.html", "vendor": "Espressif" } From c0d31661c4a118951fb3598116f398ef25511de7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 25 Jan 2025 14:06:13 +0100 Subject: [PATCH 108/117] Update platformio.ini --- examples/espidf-arduino-littlefs/platformio.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/espidf-arduino-littlefs/platformio.ini b/examples/espidf-arduino-littlefs/platformio.ini index 986a2db..0ae6edc 100644 --- a/examples/espidf-arduino-littlefs/platformio.ini +++ b/examples/espidf-arduino-littlefs/platformio.ini @@ -22,6 +22,3 @@ board_build.embed_txtfiles = managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt - -[env:esp32-c2-devkitm-1] -board = esp32-c2-devkitm-1 From 6a5e1fcf97c3a378b20c48853667b017f05fc942 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 25 Jan 2025 15:36:12 +0100 Subject: [PATCH 109/117] Update examples.yml --- .github/workflows/examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 901393b..60e6f2e 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -22,7 +22,7 @@ jobs: - "examples/arduino-zigbee-switch" - "examples/tasmota" - "examples/espidf-arduino-h2zero-BLE_scan" - - "examples/espidf-arduino-matter-light" + #- "examples/espidf-arduino-matter-light" - "examples/espidf-arduino-blink" - "examples/espidf-arduino-littlefs" - "examples/espidf-blink" From b0e120fd7cb18ffc63ca72bbe3bb76d5df764634 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 13 Feb 2025 14:20:42 +0100 Subject: [PATCH 110/117] Arduino core 3.1.2 --- .github/workflows/examples.yml | 34 +--- README.md | 25 ++- boards/lolin_s3_mini.json | 4 +- boards/lolin_s3_mini_pro.json | 47 +++++ boards/waveshare_esp32s3_touch_lcd_128.json | 52 +++++ builder/frameworks/arduino.py | 65 ++++++- builder/frameworks/espidf.py | 48 ++++- examples/arduino-blink/platformio.ini | 1 - examples/arduino-matter-light/include/README | 39 ++++ examples/arduino-matter-light/lib/README | 46 +++++ examples/arduino-matter-light/platformio.ini | 17 ++ examples/arduino-matter-light/src/.gitignore | 5 + .../src/MatterColorLight.ino | 180 ++++++++++++++++++ examples/arduino-matter-light/test/README | 11 ++ platform.json | 27 ++- platform.py | 5 + 16 files changed, 559 insertions(+), 47 deletions(-) create mode 100644 boards/lolin_s3_mini_pro.json create mode 100644 boards/waveshare_esp32s3_touch_lcd_128.json create mode 100644 examples/arduino-matter-light/include/README create mode 100644 examples/arduino-matter-light/lib/README create mode 100644 examples/arduino-matter-light/platformio.ini create mode 100644 examples/arduino-matter-light/src/.gitignore create mode 100644 examples/arduino-matter-light/src/MatterColorLight.ino create mode 100644 examples/arduino-matter-light/test/README diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 60e6f2e..ab64b14 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -1,4 +1,4 @@ -name: Examples +name: CI Examples on: workflow_dispatch: # Manually start a workflow @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, windows-2022, macos-14] + os: [ubuntu-24.04, windows-2022, macos-15] example: - "examples/arduino-blink" - "examples/arduino-rmt-blink" @@ -23,6 +23,7 @@ jobs: - "examples/tasmota" - "examples/espidf-arduino-h2zero-BLE_scan" #- "examples/espidf-arduino-matter-light" + - "examples/arduino-matter-light" - "examples/espidf-arduino-blink" - "examples/espidf-arduino-littlefs" - "examples/espidf-blink" @@ -44,37 +45,16 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.11" - - name: Install Windows dependencies + python-version: "3.13" + - name: Install dependencies run: | python -m pip install --upgrade pip pip install wheel - pip install -U https://github.com/platformio/platformio/archive/develop.zip + pip install -U https://github.com/pioarduino/platformio-core/archive/refs/tags/v6.1.17b2.zip pio pkg install --global --platform file://. - if: "matrix.os == 'windows-2022'" - env: - PLATFORMIO_CORE_DIR: C:\plat - PLATFORMIO_PACKAGES_DIR: C:\plat\pack - PLATFORMIO_PLATFORMS_DIR: C:\plat\plat - - name: Build Windows examples - run: pio run -d ${{ matrix.example }} - if: "matrix.example != 'examples/tasmota' && matrix.os == 'windows-2022'" - env: - PLATFORMIO_CORE_DIR: C:\plat - PLATFORMIO_PACKAGES_DIR: C:\plat\pack - PLATFORMIO_PLATFORMS_DIR: C:\plat\plat - - name: Install Ubuntu Mac dependencies - run: | - python -m pip install --upgrade pip - pip install wheel - pip install -U https://github.com/platformio/platformio/archive/develop.zip - pio pkg install --global --platform file://. - if: "matrix.os != 'windows-2022'" - name: git clone Tasmota and add to examples run: | git clone -b development --depth 1 https://github.com/arendst/Tasmota.git examples/tasmota cp examples/tasmota_platformio_override.ini examples/tasmota/platformio_override.ini - if: "matrix.example == 'examples/tasmota' && matrix.os != 'windows-2022'" - - name: Build Ubuntu Mac examples + - name: Build examples run: pio run -d ${{ matrix.example }} - if: "matrix.os != 'windows-2022'" diff --git a/README.md b/README.md index 8e67248..718d3aa 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with integrated Wi-Fi and Bluetooth. ESP32 integrates an antenna switch, RF balun, power amplifier, low-noise receive amplifier, filters, and power management modules. -* Issues with boards (wrong / missing). All issues caused from boards will **not** be fixed from the maintainer(s). A PR needs to be provided against branch `develop` to solve. +* Issues with boards (wrong / missing). All issues caused from boards will not be fixed from the maintainer(s). A PR needs to be provided against branch `develop` to solve. ## IDE Preparation @@ -19,8 +19,8 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with 1. Setup new VSCode pioarduino project. 1. Configure a platform option in platformio.ini file: -### Stable version -currently espressif Arduino 3.1.1 and IDF 5.3.2.241224 +### Stable Arduino +currently espressif Arduino 3.1.2 and IDF 5.3.2.250210 ```ini [env:stable] @@ -29,7 +29,7 @@ board = ... ... ``` -### Development version +### Development Arduino espressif Arduino repo branch master and latest compiled Arduino libs ```ini @@ -39,4 +39,21 @@ board = ... ... ``` +### ESP32-solo1 and ESP32-C2 Arduino support (with pioarduino only feature: *Hybrid compile*) +Example configuration: + +```ini +[env:esp32solo1] +platform = https://github.com/pioarduino/platform-espressif32.git#develop +framework = arduino +board = esp32-solo1 +monitor_speed = 115200 + +[env:esp32-c2-devkitm-1] +platform = https://github.com/pioarduino/platform-espressif32.git#develop +framework = arduino +board = esp32-c2-devkitm-1 +monitor_speed = 115200 +``` + Looking for sponsor button? There is none. If you want to donate, please spend a litte to a charity organization. diff --git a/boards/lolin_s3_mini.json b/boards/lolin_s3_mini.json index 7f55f0b..c68309a 100644 --- a/boards/lolin_s3_mini.json +++ b/boards/lolin_s3_mini.json @@ -1,18 +1,18 @@ { "build": { "arduino": { - "ldscript": "esp32s3_out.ld", "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": [ "-DBOARD_HAS_PSRAM", "-DARDUINO_LOLIN_S3_MINI", - "-DARDUINO_USB_MODE=1" + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", + "psram_type" : "qio", "hwids": [ [ "0x303A", diff --git a/boards/lolin_s3_mini_pro.json b/boards/lolin_s3_mini_pro.json new file mode 100644 index 0000000..3afcb49 --- /dev/null +++ b/boards/lolin_s3_mini_pro.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino": { + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_LOLIN_S3_MINI_PRO", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "psram_type" : "qio", + "hwids": [ + [ + "0x303A", + "0x8167" + ] + ], + "mcu": "esp32s3", + "variant": "lolin_s3_mini_pro" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN S3 Mini Pro", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc/en/latest/s3/index.html", + "vendor": "WEMOS" +} + \ No newline at end of file diff --git a/boards/waveshare_esp32s3_touch_lcd_128.json b/boards/waveshare_esp32s3_touch_lcd_128.json new file mode 100644 index 0000000..d619940 --- /dev/null +++ b/boards/waveshare_esp32s3_touch_lcd_128.json @@ -0,0 +1,52 @@ +{ + "build": { + "arduino":{ + "memory_type": "qio_qspi", + "partitions": "default.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_WAVESHARE_ESP32S3_TOUCH_LCD_128", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x1a86", + "0x55d3" + ] + ], + "mcu": "esp32s3", + "variant": "waveshare_esp32s3_touch_lcd_128" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Waveshare ESP32-S3-Touch-LCD-1.28 (16 MB QD, 2MB PSRAM)", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-1.28", + "vendor": "Waveshare" + } diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index b58527f..96fbff6 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -26,10 +26,12 @@ import subprocess import json import semantic_version import os +import sys import shutil from os.path import join from SCons.Script import COMMAND_LINE_TARGETS, DefaultEnvironment, SConscript +from platformio import fs from platformio.package.version import pepver_to_semver from platformio.project.config import ProjectConfig from platformio.package.manager.tool import ToolPackageManager @@ -43,6 +45,7 @@ mcu = board.get("build.mcu", "esp32") board_sdkconfig = board.get("espidf.custom_sdkconfig", "") entry_custom_sdkconfig = "\n" flag_custom_sdkconfig = False +IS_WINDOWS = sys.platform.startswith("win") if config.has_option("env:"+env["PIOENV"], "custom_sdkconfig"): entry_custom_sdkconfig = env.GetProjectOption("custom_sdkconfig") @@ -55,6 +58,8 @@ extra_flags = (''.join([element for element in board.get("build.extra_flags", "" framework_reinstall = False flag_any_custom_sdkconfig = False +FRAMEWORK_LIB_DIR = platform.get_package_dir("framework-arduinoespressif32-libs") + SConscript("_embed_files.py", exports="env") flag_any_custom_sdkconfig = os.path.exists(join(platform.get_package_dir("framework-arduinoespressif32-libs"),"sdkconfig")) @@ -171,11 +176,65 @@ def check_reinstall_frwrk(): framework_reinstall = True return framework_reinstall + +FRAMEWORK_SDK_DIR = fs.to_unix_path( + os.path.join( + FRAMEWORK_LIB_DIR, + mcu, + "include", + ) +) + +IS_INTEGRATION_DUMP = env.IsIntegrationDump() + + +def is_framework_subfolder(potential_subfolder): + if not os.path.isabs(potential_subfolder): + return False + if ( + os.path.splitdrive(FRAMEWORK_SDK_DIR)[0] + != os.path.splitdrive(potential_subfolder)[0] + ): + return False + return os.path.commonpath([FRAMEWORK_SDK_DIR]) == os.path.commonpath( + [FRAMEWORK_SDK_DIR, potential_subfolder] + ) + + +def shorthen_includes(env, node): + if IS_INTEGRATION_DUMP: + # Don't shorten include paths for IDE integrations + return node + + includes = [fs.to_unix_path(inc) for inc in env.get("CPPPATH", [])] + shortened_includes = [] + generic_includes = [] + for inc in includes: + if is_framework_subfolder(inc): + shortened_includes.append( + "-iwithprefix/" + + fs.to_unix_path(os.path.relpath(inc, FRAMEWORK_SDK_DIR)) + ) + else: + generic_includes.append(inc) + + return env.Object( + node, + CPPPATH=generic_includes, + CCFLAGS=env["CCFLAGS"] + + ["-iprefix", FRAMEWORK_SDK_DIR] + + shortened_includes, + ASFLAGS=env["ASFLAGS"] + + ["-iprefix", FRAMEWORK_SDK_DIR] + + shortened_includes, + ) + def call_compile_libs(): if mcu == "esp32c2": ARDUINO_FRMWRK_C2_LIB_DIR = join(platform.get_package_dir("framework-arduinoespressif32-libs"),mcu) - ARDUINO_C2_DIR = join(platform.get_package_dir("framework-arduino-c2-skeleton-lib"),mcu) - shutil.copytree(ARDUINO_C2_DIR, ARDUINO_FRMWRK_C2_LIB_DIR, dirs_exist_ok=True) + if not os.path.exists(ARDUINO_FRMWRK_C2_LIB_DIR): + ARDUINO_C2_DIR = join(platform.get_package_dir("framework-arduino-c2-skeleton-lib"),mcu) + shutil.copytree(ARDUINO_C2_DIR, ARDUINO_FRMWRK_C2_LIB_DIR, dirs_exist_ok=True) print("*** Compile Arduino IDF libs for %s ***" % env["PIOENV"]) SConscript("espidf.py") @@ -192,6 +251,8 @@ if flag_custom_sdkconfig == True and flag_any_custom_sdkconfig == False: call_compile_libs() if "arduino" in env.subst("$PIOFRAMEWORK") and "espidf" not in env.subst("$PIOFRAMEWORK") and env.subst("$ARDUINO_LIB_COMPILE_FLAG") in ("Inactive", "True"): + if IS_WINDOWS: + env.AddBuildMiddleware(shorthen_includes) if os.path.exists(join(platform.get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")): PIO_BUILD = "platformio-build.py" diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index a1ff9c2..aa32f05 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1585,11 +1585,37 @@ def get_idf_venv_dir(): def ensure_python_venv_available(): + def _get_idf_venv_python_version(): + try: + version = subprocess.check_output( + [ + get_python_exe(), + "-c", + "import sys;print('{0}.{1}.{2}-{3}.{4}'.format(*list(sys.version_info)))" + ], text=True + ) + return version.strip() + except subprocess.CalledProcessError as e: + print("Failed to extract Python version from IDF virtual env!") + return None + def _is_venv_outdated(venv_data_file): try: with open(venv_data_file, "r", encoding="utf8") as fp: venv_data = json.load(fp) if venv_data.get("version", "") != IDF_ENV_VERSION: + print( + "Warning! IDF virtual environment version changed!" + ) + return True + if ( + venv_data.get("python_version", "") + != _get_idf_venv_python_version() + ): + print( + "Warning! Python version in the IDF virtual environment" + " differs from the current Python!" + ) return True return False except: @@ -1604,7 +1630,7 @@ def ensure_python_venv_available(): if os.path.isdir(venv_dir): try: - print("Removing an oudated IDF virtual environment") + print("Removing an outdated IDF virtual environment") shutil.rmtree(venv_dir) except OSError: print( @@ -1629,8 +1655,12 @@ def ensure_python_venv_available(): venv_data_file = os.path.join(venv_dir, "pio-idf-venv.json") if not os.path.isfile(venv_data_file) or _is_venv_outdated(venv_data_file): _create_venv(venv_dir) + install_python_deps() with open(venv_data_file, "w", encoding="utf8") as fp: - venv_info = {"version": IDF_ENV_VERSION} + venv_info = { + "version": IDF_ENV_VERSION, + "python_version": _get_idf_venv_python_version() + } json.dump(venv_info, fp, indent=2) @@ -1649,11 +1679,10 @@ def get_python_exe(): # -# ESP-IDF requires Python packages with specific versions in a virtual environment +# Ensure Python environment contains everything required for IDF # ensure_python_venv_available() -install_python_deps() # ESP-IDF package doesn't contain .git folder, instead package version is specified # in a special file "version.h" in the root folder of the package @@ -1859,7 +1888,15 @@ libs = find_lib_deps( # Extra flags which need to be explicitly specified in LINKFLAGS section because SCons # cannot merge them correctly extra_flags = filter_args( - link_args["LINKFLAGS"], ["-T", "-u", "-Wl,--start-group", "-Wl,--end-group"] + link_args["LINKFLAGS"], + [ + "-T", + "-u", + "-Wl,--start-group", + "-Wl,--end-group", + "-Wl,--whole-archive", + "-Wl,--no-whole-archive", + ], ) link_args["LINKFLAGS"] = sorted(list(set(link_args["LINKFLAGS"]) - set(extra_flags))) @@ -2079,6 +2116,7 @@ if "arduino" in env.get("PIOFRAMEWORK") and "espidf" not in env.get("PIOFRAMEWOR shutil.move(join(lib_dst,"libfreertos.a"),join(mem_var,"libfreertos.a")) shutil.move(join(lib_dst,"libbootloader_support.a"),join(mem_var,"libbootloader_support.a")) shutil.move(join(lib_dst,"libesp_hw_support.a"),join(mem_var,"libesp_hw_support.a")) + shutil.move(join(lib_dst,"libesp_lcd.a"),join(mem_var,"libesp_lcd.a")) shutil.copyfile(sdkconfig_h_path,join(mem_var,"include","sdkconfig.h")) if not bool(os.path.isfile(join(arduino_libs,mcu,"sdkconfig.orig"))): diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index bd12d55..26bd6f1 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -31,7 +31,6 @@ platform = espressif32 framework = arduino board = esp32-c2-devkitm-1 monitor_speed = 115200 -custom_sdkconfig = 'CONFIG_IDF_TARGET="esp32c2"' custom_component_remove = espressif/esp_hosted espressif/esp_wifi_remote espressif/esp-dsp diff --git a/examples/arduino-matter-light/include/README b/examples/arduino-matter-light/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/examples/arduino-matter-light/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/arduino-matter-light/lib/README b/examples/arduino-matter-light/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/examples/arduino-matter-light/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/arduino-matter-light/platformio.ini b/examples/arduino-matter-light/platformio.ini new file mode 100644 index 0000000..9c624da --- /dev/null +++ b/examples/arduino-matter-light/platformio.ini @@ -0,0 +1,17 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter, extra scripting +; Upload options: custom port, speed and extra flags +; Library options: dependencies, extra library storages +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/page/projectconf.html + + +[env:esp32-c6-devkitc-1] +platform = espressif32 +framework = arduino +board_build.partitions = huge_app.csv +build_flags = -DCHIP_HAVE_CONFIG_H +board = esp32-c6-devkitc-1 +monitor_speed = 115200 diff --git a/examples/arduino-matter-light/src/.gitignore b/examples/arduino-matter-light/src/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/examples/arduino-matter-light/src/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/examples/arduino-matter-light/src/MatterColorLight.ino b/examples/arduino-matter-light/src/MatterColorLight.ino new file mode 100644 index 0000000..dd1724f --- /dev/null +++ b/examples/arduino-matter-light/src/MatterColorLight.ino @@ -0,0 +1,180 @@ +// 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. + +// Matter Manager +#include +#include +#include + +// List of Matter Endpoints for this Node +// Color Light Endpoint +MatterColorLight ColorLight; + +// 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 + +// it will keep last OnOff & HSV Color state stored, using Preferences +Preferences matterPref; +const char *onOffPrefKey = "OnOff"; +const char *hsvColorPrefKey = "HSV"; + +// set your board RGB LED pin here +#ifdef RGB_BUILTIN +const uint8_t ledPin = RGB_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 RGB LED pin" +#endif + +// set your board USER BUTTON pin here +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + +// 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 = 5000; // keep the button pressed for 5s, or longer, to decommission + +// Set the RGB LED Light based on the current state of the Color Light +bool setLightState(bool state, espHsvColor_t colorHSV) { + + if (state) { +#ifdef RGB_BUILTIN + espRgbColor_t rgbColor = espHsvColorToRgbColor(colorHSV); + // set the RGB LED + rgbLedWrite(ledPin, rgbColor.r, rgbColor.g, rgbColor.b); +#else + // No Color RGB LED, just use the HSV value (brightness) to control the LED + analogWrite(ledPin, colorHSV.v); +#endif + } else { + digitalWrite(ledPin, LOW); + } + // store last HSV Color and OnOff state for when the Light is restarted / power goes off + matterPref.putBool(onOffPrefKey, state); + matterPref.putUInt(hsvColorPrefKey, colorHSV.h << 16 | colorHSV.s << 8 | colorHSV.v); + // This callback must return the success state to Matter core + return true; +} + +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); + + // We start by connecting to a WiFi network + Serial.print("Connecting to "); + Serial.println(ssid); + // 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 + matterPref.begin("MatterPrefs", false); + // default OnOff state is ON if not stored before + bool lastOnOffState = matterPref.getBool(onOffPrefKey, true); + // default HSV color is blue HSV(169, 254, 254) + uint32_t prefHsvColor = matterPref.getUInt(hsvColorPrefKey, 169 << 16 | 254 << 8 | 254); + espHsvColor_t lastHsvColor = {uint8_t(prefHsvColor >> 16), uint8_t(prefHsvColor >> 8), uint8_t(prefHsvColor)}; + ColorLight.begin(lastOnOffState, lastHsvColor); + // set the callback function to handle the Light state change + ColorLight.onChange(setLightState); + + // lambda functions are used to set the attribute change callbacks + ColorLight.onChangeOnOff([](bool state) { + Serial.printf("Light OnOff changed to %s\r\n", state ? "ON" : "OFF"); + return true; + }); + ColorLight.onChangeColorHSV([](HsvColor_t hsvColor) { + Serial.printf("Light HSV Color changed to (%d,%d,%d)\r\n", hsvColor.h, hsvColor.s, hsvColor.v); + return true; + }); + + // 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 | RGB Color: (%d,%d,%d) \r\n", ColorLight ? "ON" : "OFF", ColorLight.getColorRGB().r, ColorLight.getColorRGB().g, + ColorLight.getColorRGB().b + ); + // configure the Light based on initial on-off state and its color + ColorLight.updateAccessory(); + } +} + +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 | RGB Color: (%d,%d,%d) \r\n", ColorLight ? "ON" : "OFF", ColorLight.getColorRGB().r, ColorLight.getColorRGB().g, + ColorLight.getColorRGB().b + ); + // configure the Light based on initial on-off state and its color + ColorLight.updateAccessory(); + 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 (digitalRead(buttonPin) == HIGH && button_state && time_diff > debouceTime) { + // Toggle button is released - toggle the light + Serial.println("User button released. Toggling Light!"); + ColorLight.toggle(); // Matter Controller also can see the change + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again."); + ColorLight = false; // turn the light off + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } +} diff --git a/examples/arduino-matter-light/test/README b/examples/arduino-matter-light/test/README new file mode 100644 index 0000000..df5066e --- /dev/null +++ b/examples/arduino-matter-light/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/platform.json b/platform.json index d0378a7..5989566 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "53.03.11", + "version": "53.03.12", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.1.1/esp32-3.1.1.zip" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.1.2/esp32-3.1.2.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-cfea4f7c-v1.zip" + "version": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-489d7a2b-v1.zip" }, "framework-arduino-c2-skeleton-lib": { "type": "framework", @@ -51,7 +51,7 @@ "type": "framework", "optional": true, "owner": "pioarduino", - "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.3.2.241224/esp-idf-v5.3.2.zip" + "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.3.2.250210/esp-idf-v5.3.2.zip" }, "toolchain-xtensa-esp-elf": { "type": "toolchain", @@ -86,7 +86,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "pioarduino", - "version": "https://github.com/pioarduino/esptool/releases/download/v4.8.5/esptool.zip" + "version": "https://github.com/pioarduino/esptool/releases/download/v4.8.6/esptool.zip" }, "tool-dfuutil-arduino": { "type": "uploader", @@ -117,10 +117,25 @@ "owner": "platformio", "version": "~2.230.0" }, + "tool-cppcheck": { + "optional": true, + "owner": "platformio", + "version": "~1.21100" + }, + "tool-clangtidy": { + "optional": true, + "owner": "platformio", + "version": "^1.190100.0" + }, + "tool-pvs-studio": { + "optional": true, + "owner": "platformio", + "version": "^7.18.59866" + }, "tool-cmake": { "optional": true, "owner": "platformio", - "version": "~3.21.0" + "version": "~3.30.2" }, "tool-ninja": { "optional": true, diff --git a/platform.py b/platform.py index 625a98d..e1b3273 100644 --- a/platform.py +++ b/platform.py @@ -53,6 +53,11 @@ class Espressif32Platform(PlatformBase): if mcu == "esp32c2": self.packages["framework-arduino-c2-skeleton-lib"]["optional"] = False + # Enable check tools only when "check_tool" is active + for p in self.packages: + if p in ("tool-cppcheck", "tool-clangtidy", "tool-pvs-studio"): + self.packages[p]["optional"] = False if str(variables.get("check_tool")).strip("['']") in p else True + if "buildfs" in targets: filesystem = variables.get("board_build.filesystem", "littlefs") if filesystem == "littlefs": From d2f1607cb561cf3da3f2cc03ceb94d25255e6fe4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 17 Feb 2025 15:08:19 +0100 Subject: [PATCH 111/117] Arduino core 3.1.3 * core 3.1.3 * Update platform.json * Update README.md --- README.md | 2 +- platform.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 718d3aa..aab8fe1 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with 1. Configure a platform option in platformio.ini file: ### Stable Arduino -currently espressif Arduino 3.1.2 and IDF 5.3.2.250210 +currently espressif Arduino 3.1.3 and IDF 5.3.2.250210 ```ini [env:stable] diff --git a/platform.json b/platform.json index 5989566..74651b7 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "53.03.12", + "version": "53.03.13", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.1.2/esp32-3.1.2.zip" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.1.3/esp32-3.1.3.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", From 15e5639a18f2fd1924da48dff09c50c6f25cddfc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 25 Feb 2025 17:32:02 +0100 Subject: [PATCH 112/117] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aab8fe1..6324a8a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # pioarduino (p)eople (i)nitiated (o)ptimized (arduino) -[![Build Status](https://github.com/pioarduino/platform-espressif32/workflows/Examples/badge.svg)](https://github.com/pioarduino/platform-espressif32/actions) +[![Build Status](https://github.com/pioarduino/platform-espressif32/actions/workflows/examples.yml/badge.svg)](https://github.com/pioarduino/platform-espressif32/actions) [![Discord](https://img.shields.io/discord/1263397951829708871.svg?logo=discord&logoColor=white&color=5865F2&label=Discord)](https://discord.gg/Nutz9crnZr) [![GitHub Releases](https://img.shields.io/github/downloads/pioarduino/platform-espressif32/total?label=downloads)](https://github.com/pioarduino/platform-espressif32/releases/latest) From 12a5d8e1202dfcc064c0fb39fbc58442f416e917 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Mar 2025 15:40:52 +0100 Subject: [PATCH 113/117] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6324a8a..0bd395d 100644 --- a/README.md +++ b/README.md @@ -39,18 +39,18 @@ board = ... ... ``` -### ESP32-solo1 and ESP32-C2 Arduino support (with pioarduino only feature: *Hybrid compile*) -Example configuration: +### pioarduino only feature +ESP32-solo1 and ESP32-C2 support via **Hybrid compile** ```ini [env:esp32solo1] -platform = https://github.com/pioarduino/platform-espressif32.git#develop +platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip framework = arduino board = esp32-solo1 monitor_speed = 115200 [env:esp32-c2-devkitm-1] -platform = https://github.com/pioarduino/platform-espressif32.git#develop +platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip framework = arduino board = esp32-c2-devkitm-1 monitor_speed = 115200 From bc922e3bc42ad15a4d628026d1f89e0a2acc029a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 9 Mar 2025 18:17:57 +0100 Subject: [PATCH 114/117] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bd395d..e252e75 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with ## IDE Preparation -- [Download and install official Microsoft Visual Studio Code](https://code.visualstudio.com/). pioarduino IDE is built on top of it. +- [Download and install Microsoft Visual Studio Code](https://code.visualstudio.com/). pioarduino IDE is built on top of it. - Open the extension manager. - Search for the `pioarduino ide` extension. - Install pioarduino IDE extension. From 88b037b13366df57e30dc032622466457a9d4b45 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 9 Mar 2025 18:19:58 +0100 Subject: [PATCH 115/117] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e252e75..7644ed6 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with ## IDE Preparation -- [Download and install Microsoft Visual Studio Code](https://code.visualstudio.com/). pioarduino IDE is built on top of it. +- [Download and install Microsoft Visual Studio Code](https://code.visualstudio.com/). pioarduino IDE is on top of it. - Open the extension manager. - Search for the `pioarduino ide` extension. - Install pioarduino IDE extension. From ee3b8e15a92ba8200a463b838c3b82c016063a06 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 24 Mar 2025 12:48:01 +0100 Subject: [PATCH 116/117] Update arduino_nano_esp32.json --- boards/arduino_nano_esp32.json | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/boards/arduino_nano_esp32.json b/boards/arduino_nano_esp32.json index e1bf757..4d72679 100644 --- a/boards/arduino_nano_esp32.json +++ b/boards/arduino_nano_esp32.json @@ -1,14 +1,13 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld", "partitions": "app3M_fat9M_fact512k_16MB.csv", "memory_type": "qio_opi" }, "core": "esp32", "extra_flags": [ "-DARDUINO_NANO_ESP32", - "-DBOARD_HAS_PIN_REMAP", + "-DBOARD_USES_HW_GPIO_NUMBERS", "-DBOARD_HAS_PSRAM", "-DUSB_MANUFACTURER=\\\"Arduino\\\"", "-DUSB_PRODUCT=\\\"NanoESP32\\\"", @@ -42,6 +41,14 @@ ], "name": "Arduino Nano ESP32", "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0xf70000", + "variants/arduino_nano_nora/extra/nora_recovery/nora_recovery.ino.bin" + ] + ] + }, "flash_size": "16MB", "maximum_ram_size": 327680, "maximum_size": 16777216, From dd8ea2d31d43228c4b6cc94b4c7b2eb3d8ae6506 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 24 Mar 2025 12:56:00 +0100 Subject: [PATCH 117/117] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7644ed6..554f8b9 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ESP32 is a series of low-cost, low-power system on a chip microcontrollers with integrated Wi-Fi and Bluetooth. ESP32 integrates an antenna switch, RF balun, power amplifier, low-noise receive amplifier, filters, and power management modules. * Issues with boards (wrong / missing). All issues caused from boards will not be fixed from the maintainer(s). A PR needs to be provided against branch `develop` to solve. - +* No support for the Arduino Nora Nano board, issues needs to be solved by the community ## IDE Preparation - [Download and install Microsoft Visual Studio Code](https://code.visualstudio.com/). pioarduino IDE is on top of it.