diff --git a/.codespellrc b/.codespellrc index 690782793dd..d3b9b45cb1e 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,9 +1,8 @@ [codespell] # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/spell-check/.codespellrc # In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here: -ignore-words-list = ba,licence,ot,dout,als,exten,acount,totaly,pasttime +ignore-words-list = ba,licence,ot,dout,als,exten,emac skip = ./.git,./.licenses,__pycache__,.clang-format,.codespellrc,.editorconfig,.flake8,.prettierignore,.yamllint.yml,.gitignore,boards.txt,platform.txt,programmers.txt builtin = clear,informal,en-GB_to_en-US check-filenames = check-hidden = -write-changes = diff --git a/.editorconfig b/.editorconfig index eda8544321b..e22936cb1fe 100644 --- a/.editorconfig +++ b/.editorconfig @@ -18,7 +18,7 @@ indent_size = 2 indent_style = space [*.{bash,sh}] -indent_size = 2 +indent_size = 4 indent_style = space [*.{c,cc,cp,cpp,cxx,h,hh,hpp,hxx,ii,inl,ino,ixx,pde,tpl,tpp,txx}] diff --git a/.github/ISSUE_TEMPLATE/Feature-request.yml b/.github/ISSUE_TEMPLATE/Feature-request.yml index 0788288036c..8849a407a39 100644 --- a/.github/ISSUE_TEMPLATE/Feature-request.yml +++ b/.github/ISSUE_TEMPLATE/Feature-request.yml @@ -5,6 +5,7 @@ body: - type: markdown attributes: value: | + * Please note that we can only process feature requests reported in English to ensure effective communication and support. Feature requests written in other languages will be closed, with a request to rewrite them in English. * We welcome any ideas or feature requests! It is helpful if you can explain exactly why the feature would be useful. * There are usually some outstanding feature requests in the [existing issues list](https://github.com/espressif/arduino-esp32/issues?q=is%3Aopen+is%3Aissue+label%3A%22Type%3A+Feature+request%22), feel free to add comments to them. * If you would like to contribute, please read the [contributions guide](https://docs.espressif.com/projects/arduino-esp32/en/latest/contributing.html). diff --git a/.github/ISSUE_TEMPLATE/Issue-report.yml b/.github/ISSUE_TEMPLATE/Issue-report.yml index fb8d9c072d9..9dba5e0ca8f 100644 --- a/.github/ISSUE_TEMPLATE/Issue-report.yml +++ b/.github/ISSUE_TEMPLATE/Issue-report.yml @@ -5,7 +5,8 @@ body: - type: markdown attributes: value: | - * Before reporting a new issue please check and search in [List of existing issues](https://github.com/espressif/arduino-esp32/issues?q=is%3Aissue) + * Please note that we can only process issues reported in English to ensure effective communication and support. Issues written in other languages will be closed, with a request to rewrite them in English. + * Before reporting a new issue please check and search in [List of existing issues](https://github.com/espressif/arduino-esp32/issues?q=is%3Aissue) * Please check [Online Documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/index.html) * Take a look on [Troubleshooting guide](https://docs.espressif.com/projects/arduino-esp32/en/latest/troubleshooting.html) * If still experiencing the issue, please provide as many details as possible below about your hardware, computer setup and code. @@ -24,7 +25,7 @@ body: description: What development board or other hardware is the chip attached to? placeholder: ex. DevKitC, plain module on breadboard, etc. If your hardware is custom or unusual, please attach a photo. validations: - required: true + required: true - type: textarea id: other-hw attributes: @@ -39,8 +40,20 @@ body: label: Version description: What version of Arduino ESP32 are you running? If possible, consider updating to the latest version. options: - - latest master (checkout manually) + - latest stable Release (if not listed below) - latest development Release Candidate (RC-X) + - latest master (checkout manually) + - v3.2.0 + - v3.1.3 + - v3.1.2 + - v3.1.1 + - v3.1.0 + - v3.0.7 + - v3.0.6 + - v3.0.5 + - v3.0.4 + - v3.0.3 + - v3.0.2 - v3.0.1 - v3.0.0 - v2.0.17 @@ -55,7 +68,7 @@ body: - v2.0.8 - v2.0.7 - v2.0.6 - - v2.0.5 + - v2.0.5 - v2.0.4 - v2.0.3 - v2.0.2 @@ -70,9 +83,9 @@ body: attributes: label: IDE Name description: What IDE are you using? - placeholder: eg. Arduino IDE, PlatformIO, Sloeber... + placeholder: eg. Arduino IDE, VSCode, Sloeber... validations: - required: true + required: true - type: input id: os attributes: @@ -90,13 +103,13 @@ body: validations: required: true - type: dropdown - id: PSRAM + id: PSRAM attributes: label: PSRAM enabled description: Is PSRAM enabled? options: - - 'yes' - - 'no' + - "yes" + - "no" validations: required: true - type: input @@ -111,8 +124,8 @@ body: id: Description attributes: label: Description - description: Please describe your problem here and expected behaviour - placeholder: ex. Can't connect/weird behaviour/wrong function/missing parameter.. + description: Please describe your problem here and expected behavior + placeholder: ex. Can't connect/weird behavior/wrong function/missing parameter.. validations: required: true - type: textarea @@ -123,7 +136,7 @@ body: placeholder: ex. Related part of the code to replicate the issue render: cpp validations: - required: true + required: true - type: textarea id: Debug attributes: @@ -132,11 +145,11 @@ body: placeholder: Enable Core debug level - Debug on tools menu of Arduino IDE, then put the serial output here. render: plain validations: - required: true + required: true - type: textarea id: other-remarks attributes: - label: Other Steps to Reproduce + label: Other Steps to Reproduce description: Is there any other information you can think of which will help us reproduce this problem? Any additional info can be added as well. placeholder: ex. I also tried on other OS, HW...it works correctly on that setup. - type: checkboxes diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 2a9b0ef82e0..e879b09bec2 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,8 @@ blank_issues_enabled: false contact_links: - - name: Arduino ESP32 Gitter Channel - url: https://gitter.im/espressif/arduino-esp32 - about: Community channel for questions and help + - name: Arduino Core for Espressif Discord Server + url: https://discord.gg/8xY6e9crwv + about: Community Discord server for questions and help - name: ESP32 Forum - Arduino url: https://esp32.com/viewforum.php?f=19 - about: Official Forum for questions \ No newline at end of file + about: Official Forum for questions diff --git a/.github/scripts/check-cmakelists.sh b/.github/scripts/check-cmakelists.sh index 98d9722ad83..7d4f6b4e2d9 100755 --- a/.github/scripts/check-cmakelists.sh +++ b/.github/scripts/check-cmakelists.sh @@ -1,4 +1,5 @@ #!/bin/bash + # # This script is used in the CI workflow. It checks all non-examples source files in libraries/ and cores/ are listed in # CMakeLists.txt for the cmake-based IDF component @@ -12,10 +13,10 @@ set -e git submodule update --init --recursive # find all source files in repo -REPO_SRCS=`find cores/esp32/ libraries/ -name 'examples' -prune -o -name '*.c' -print -o -name '*.cpp' -print | sort` +REPO_SRCS=$(find cores/esp32/ libraries/ -name 'examples' -prune -o -name '*.c' -print -o -name '*.cpp' -print | sort) # find all source files named in CMakeLists.txt COMPONENT_SRCS -CMAKE_SRCS=`cmake --trace-expand -P CMakeLists.txt 2>&1 | grep set\(srcs | cut -d'(' -f3 | sed 's/ )//' | sed 's/srcs //' | tr ' ;' '\n' | sort` +CMAKE_SRCS=$(cmake --trace-expand -P CMakeLists.txt 2>&1 | grep set\(srcs | cut -d'(' -f3 | sed 's/ )//' | sed 's/srcs //' | tr ' ;' '\n' | sort) if ! diff -u0 --label "Repo Files" --label "srcs" <(echo "$REPO_SRCS") <(echo "$CMAKE_SRCS"); then echo "Source files in repo (-) and source files in CMakeLists.txt (+) don't match" diff --git a/.github/scripts/find_all_boards.sh b/.github/scripts/find_all_boards.sh index b474a49bc2e..67b46661ca5 100755 --- a/.github/scripts/find_all_boards.sh +++ b/.github/scripts/find_all_boards.sh @@ -3,7 +3,9 @@ # Get all boards boards_array=() -for line in `grep '.tarch=' boards.txt`; do +boards_list=$(grep '.tarch=' boards.txt) + +while read -r line; do board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1) # skip esp32c2 as we dont build libs for it if [ "$board_name" == "esp32c2" ]; then @@ -12,29 +14,26 @@ for line in `grep '.tarch=' boards.txt`; do fi boards_array+=("espressif:esp32:$board_name") echo "Added 'espressif:esp32:$board_name' to array" -done +done <<< "$boards_list" # Create JSON like string with all boards found and pass it to env variable board_count=${#boards_array[@]} echo "Boards found: $board_count" -echo "BOARD-COUNT=$board_count" >> $GITHUB_ENV +echo "BOARD-COUNT=$board_count" >> "$GITHUB_ENV" -if [ $board_count -gt 0 ] -then +if [ "$board_count" -gt 0 ]; then json_matrix='[' - for board in ${boards_array[@]} - do + for board in "${boards_array[@]}"; do json_matrix+='"'$board'"' - if [ $board_count -gt 1 ] - then + if [ "$board_count" -gt 1 ]; then json_matrix+="," fi - board_count=$(($board_count - 1)) + board_count=$((board_count - 1)) done json_matrix+=']' - echo $json_matrix - echo "FQBNS=${json_matrix}" >> $GITHUB_ENV + echo "$json_matrix" + echo "FQBNS=${json_matrix}" >> "$GITHUB_ENV" else - echo "FQBNS=" >> $GITHUB_ENV + echo "FQBNS=" >> "$GITHUB_ENV" fi diff --git a/.github/scripts/find_new_boards.sh b/.github/scripts/find_new_boards.sh index 77c98877d2a..4482aa2b1da 100755 --- a/.github/scripts/find_new_boards.sh +++ b/.github/scripts/find_new_boards.sh @@ -2,89 +2,61 @@ # Get inputs from command owner_repository=$1 -pr_number=$2 +base_ref=$2 -url="https://api.github.com/repos/$owner_repository/pulls/$pr_number/files" -echo $url +# Download the boards.txt file from the base branch +curl -L -o boards_base.txt https://raw.githubusercontent.com/"$owner_repository"/"$base_ref"/boards.txt -# Get changes in boards.txt file from PR -Patch=$(curl $url | jq -r '.[] | select(.filename == "boards.txt") | .patch ') +# Compare boards.txt file in the repo with the modified file from PR +diff=$(diff -u boards_base.txt boards.txt) -# Extract only changed lines number and count -substring_patch=$(echo "$Patch" | grep -o '@@[^@]*@@') +# Check if the diff is empty +if [ -z "$diff" ]; then + echo "No changes in boards.txt file" + echo "FQBNS=" + exit 0 +fi -params_array=() +# Extract added or modified lines (lines starting with '+' or '-') +modified_lines=$(echo "$diff" | grep -E '^[+-][^+-]') -IFS=$'\n' read -d '' -ra params <<< $(echo "$substring_patch" | grep -oE '[-+][0-9]+,[0-9]+') - -for param in "${params[@]}" -do - echo "The parameter is $param" - params_array+=("$param") -done +# Print the modified lines for debugging +echo "Modified lines:" +echo "$modified_lines" boards_array=() previous_board="" -file="boards.txt" - -# Loop through boards.txt file and extract all boards that were added -for (( c=0; c<${#params_array[@]}; c+=2 )) -do - deletion_count=$( echo "${params_array[c]}" | cut -d',' -f2 | cut -d' ' -f1 ) - addition_line=$( echo "${params_array[c+1]}" | cut -d'+' -f2 | cut -d',' -f1 ) - addition_count=$( echo "${params_array[c+1]}" | cut -d'+' -f2 | cut -d',' -f2 | cut -d' ' -f1 ) - addition_end=$(($addition_line+$addition_count)) - - addition_line=$(($addition_line + 3)) - addition_end=$(($addition_end - $deletion_count)) - - echo $addition_line - echo $addition_end - i=0 - - while read -r line - do - i=$((i+1)) - if [ $i -lt $addition_line ] - then - continue - elif [ $i -gt $addition_end ] - then - break - fi +# Extract board names from the modified lines, and add them to the boards_array +while read -r line; do board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1) - if [ "$board_name" != "" ] && [ "$board_name" != "esp32_family" ] - then - if [ "$board_name" != "$previous_board" ] - then + # remove + or - from the board name at the beginning + board_name=${board_name#[-+]} + if [ "$board_name" != "" ] && [ "$board_name" != "+" ] && [ "$board_name" != "-" ] && [ "$board_name" != "esp32_family" ]; then + if [ "$board_name" != "$previous_board" ]; then boards_array+=("espressif:esp32:$board_name") previous_board="$board_name" echo "Added 'espressif:esp32:$board_name' to array" fi fi - done < "$file" -done +done <<< "$modified_lines" # Create JSON like string with all boards found and pass it to env variable board_count=${#boards_array[@]} -if [ $board_count -gt 0 ] -then +if [ "$board_count" -gt 0 ]; then json_matrix='{"fqbn": [' - for board in ${boards_array[@]} - do + for board in "${boards_array[@]}"; do json_matrix+='"'$board'"' - if [ $board_count -gt 1 ] - then + if [ "$board_count" -gt 1 ]; then json_matrix+="," fi - board_count=$(($board_count - 1)) + board_count=$((board_count - 1)) done json_matrix+=']}' - echo $json_matrix - echo "FQBNS=${json_matrix}" >> $GITHUB_ENV + echo "$json_matrix" + echo "FQBNS=${json_matrix}" >> "$GITHUB_ENV" else - echo "FQBNS=" >> $GITHUB_ENV -fi \ No newline at end of file + echo "FQBNS=" >> "$GITHUB_ENV" +fi diff --git a/.github/scripts/install-arduino-cli.sh b/.github/scripts/install-arduino-cli.sh index 8ee0c5cd791..bb7f544e752 100755 --- a/.github/scripts/install-arduino-cli.sh +++ b/.github/scripts/install-arduino-cli.sh @@ -1,6 +1,6 @@ #!/bin/bash -OSBITS=`uname -m` +OSBITS=$(uname -m) if [[ "$OSTYPE" == "linux"* ]]; then export OS_IS_LINUX="1" if [[ "$OSBITS" == "i686" ]]; then @@ -41,6 +41,11 @@ fi if [ ! -d "$ARDUINO_IDE_PATH" ] || [ ! -f "$ARDUINO_IDE_PATH/arduino-cli" ]; then echo "Installing Arduino CLI on $OS_NAME ..." mkdir -p "$ARDUINO_IDE_PATH" - curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR="$ARDUINO_IDE_PATH" sh + if [ "$OS_IS_WINDOWS" == "1" ]; then + curl -fsSL https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Windows_64bit.zip -o arduino-cli.zip + unzip -q arduino-cli.zip -d "$ARDUINO_IDE_PATH" + rm arduino-cli.zip + else + curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR="$ARDUINO_IDE_PATH" sh + fi fi - diff --git a/.github/scripts/install-arduino-core-esp32.sh b/.github/scripts/install-arduino-core-esp32.sh index 8584da5b6e2..e0071a0eb83 100755 --- a/.github/scripts/install-arduino-core-esp32.sh +++ b/.github/scripts/install-arduino-core-esp32.sh @@ -5,7 +5,7 @@ if [ ! -d "$ARDUINO_ESP32_PATH" ]; then echo "Installing ESP32 Arduino Core ..." script_init_path="$PWD" mkdir -p "$ARDUINO_USR_PATH/hardware/espressif" - cd "$ARDUINO_USR_PATH/hardware/espressif" + cd "$ARDUINO_USR_PATH/hardware/espressif" || exit echo "Installing Python Serial ..." pip install pyserial > /dev/null @@ -15,21 +15,25 @@ if [ ! -d "$ARDUINO_ESP32_PATH" ]; then pip install requests > /dev/null fi - if [ ! -z "$GITHUB_REPOSITORY" ]; then + if [ -n "$GITHUB_REPOSITORY" ]; then echo "Linking Core..." - ln -s $GITHUB_WORKSPACE esp32 + ln -s "$GITHUB_WORKSPACE" esp32 else echo "Cloning Core Repository..." git clone https://github.com/espressif/arduino-esp32.git esp32 > /dev/null 2>&1 fi #echo "Updating Submodules ..." - cd esp32 + cd esp32 || exit #git submodule update --init --recursive > /dev/null 2>&1 echo "Installing Platform Tools ..." - cd tools && python get.py - cd $script_init_path + if [ "$OS_IS_WINDOWS" == "1" ]; then + cd tools && ./get.exe + else + cd tools && python get.py + fi + cd "$script_init_path" || exit echo "ESP32 Arduino has been installed in '$ARDUINO_ESP32_PATH'" echo "" diff --git a/.github/scripts/install-arduino-ide.sh b/.github/scripts/install-arduino-ide.sh index 7fd95797834..5b3bcb1791e 100755 --- a/.github/scripts/install-arduino-ide.sh +++ b/.github/scripts/install-arduino-ide.sh @@ -4,7 +4,7 @@ #OSTYPE: 'msys', ARCH: 'x86_64' => win32 #OSTYPE: 'darwin18', ARCH: 'i386' => macos -OSBITS=`uname -m` +OSBITS=$(uname -m) if [[ "$OSTYPE" == "linux"* ]]; then export OS_IS_LINUX="1" ARCHIVE_FORMAT="tar.xz" @@ -77,4 +77,3 @@ if [ ! -d "$ARDUINO_IDE_PATH" ]; then echo "Arduino IDE Installed in '$ARDUINO_IDE_PATH'" echo "" fi - diff --git a/.github/scripts/install-platformio-esp32.sh b/.github/scripts/install-platformio-esp32.sh deleted file mode 100755 index a92e1103770..00000000000 --- a/.github/scripts/install-platformio-esp32.sh +++ /dev/null @@ -1,184 +0,0 @@ -#!/bin/bash - -export PLATFORMIO_ESP32_PATH="$HOME/.platformio/packages/framework-arduinoespressif32" -PLATFORMIO_ESP32_URL="https://github.com/platformio/platform-espressif32.git" - -TOOLCHAIN_VERSION="12.2.0+20230208" -ESPTOOLPY_VERSION="~1.40501.0" -ESPRESSIF_ORGANIZATION_NAME="espressif" - -echo "Installing Python Wheel ..." -pip install wheel > /dev/null 2>&1 - -echo "Installing PlatformIO ..." -pip install -U https://github.com/platformio/platformio/archive/master.zip > /dev/null 2>&1 - -echo "Installing Platform ESP32 ..." -python -m platformio platform install $PLATFORMIO_ESP32_URL > /dev/null 2>&1 - -echo "Replacing the package versions ..." -replace_script="import json; import os;" -replace_script+="fp=open(os.path.expanduser('~/.platformio/platforms/espressif32/platform.json'), 'r+');" -replace_script+="data=json.load(fp);" -# Use framework sources from the repository -replace_script+="data['packages']['framework-arduinoespressif32']['version'] = '*';" -replace_script+="del data['packages']['framework-arduinoespressif32']['owner'];" -# Use toolchain packages from the "espressif" organization -replace_script+="data['packages']['toolchain-xtensa-esp32']['owner']='$ESPRESSIF_ORGANIZATION_NAME';" -replace_script+="data['packages']['toolchain-xtensa-esp32s2']['owner']='$ESPRESSIF_ORGANIZATION_NAME';" -replace_script+="data['packages']['toolchain-riscv32-esp']['owner']='$ESPRESSIF_ORGANIZATION_NAME';" -# Update versions to use the upstream -replace_script+="data['packages']['toolchain-xtensa-esp32']['version']='$TOOLCHAIN_VERSION';" -replace_script+="data['packages']['toolchain-xtensa-esp32s2']['version']='$TOOLCHAIN_VERSION';" -replace_script+="data['packages']['toolchain-xtensa-esp32s3']['version']='$TOOLCHAIN_VERSION';" -replace_script+="data['packages']['toolchain-riscv32-esp']['version']='$TOOLCHAIN_VERSION';" -# Add new "framework-arduinoespressif32-libs" package -# Read "package_esp32_index.template.json" to extract a url to a zip package for "esp32-arduino-libs" -replace_script+="fpackage=open(os.path.join('package', 'package_esp32_index.template.json'), 'r+');" -replace_script+="package_data=json.load(fpackage);" -replace_script+="fpackage.close();" -replace_script+="libs_package_archive_url=next(next(system['url'] for system in tool['systems'] if system['host'] == 'x86_64-pc-linux-gnu') for tool in package_data['packages'][0]['tools'] if tool['name'] == 'esp32-arduino-libs');" -replace_script+="data['packages'].update({'framework-arduinoespressif32-libs':{'type':'framework','optional':False,'version':libs_package_archive_url}});" -replace_script+="data['packages']['toolchain-xtensa-esp32'].update({'optional':False});" -# esptool.py may require an upstream version (for now platformio is the owner) -replace_script+="data['packages']['tool-esptoolpy']['version']='$ESPTOOLPY_VERSION';" -# Save results -replace_script+="fp.seek(0);fp.truncate();json.dump(data, fp, indent=2);fp.close()" -python -c "$replace_script" - -if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then - echo "Linking Core..." - ln -s $GITHUB_WORKSPACE "$PLATFORMIO_ESP32_PATH" -else - echo "Cloning Core Repository ..." - git clone --recursive https://github.com/espressif/arduino-esp32.git "$PLATFORMIO_ESP32_PATH" > /dev/null 2>&1 -fi - -echo "PlatformIO for ESP32 has been installed" -echo "" - -function build_pio_sketch(){ # build_pio_sketch - if [ "$#" -lt 3 ]; then - echo "ERROR: Illegal number of parameters" - echo "USAGE: build_pio_sketch " - return 1 - fi - - local board="$1" - local options="$2" - local sketch="$3" - local sketch_dir=$(dirname "$sketch") - echo "" - echo "Compiling '"$(basename "$sketch")"' ..." - python -m platformio ci --board "$board" "$sketch_dir" --project-option="$options" -} - -function count_sketches(){ # count_sketches - local examples="$1" - rm -rf sketches.txt - if [ ! -d "$examples" ]; then - touch sketches.txt - return 0 - fi - local sketches=$(find $examples -name *.ino) - local sketchnum=0 - for sketch in $sketches; do - local sketchdir=$(dirname $sketch) - local sketchdirname=$(basename $sketchdir) - local sketchname=$(basename $sketch) - if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then - continue - fi - is_target=$(jq -r --arg target $target '.targets[$target]' $sketchdir/ci.json) - # If the target is listed as false, skip the sketch. Otherwise, include it. - if [[ "$is_target" == "false" ]]; then - continue - fi - echo $sketch >> sketches.txt - sketchnum=$(($sketchnum + 1)) - done - return $sketchnum -} - -function build_pio_sketches(){ # build_pio_sketches - if [ "$#" -lt 3 ]; then - echo "ERROR: Illegal number of parameters" - echo "USAGE: build_pio_sketches [ ]" - return 1 - fi - - local board=$1 - local options="$2" - local examples=$3 - local chunk_idex=$4 - local chunks_num=$5 - - if [ "$#" -lt 5 ]; then - chunk_idex="0" - chunks_num="1" - fi - - if [ "$chunks_num" -le 0 ]; then - echo "ERROR: Chunks count must be positive number" - return 1 - fi - if [ "$chunk_idex" -ge "$chunks_num" ]; then - echo "ERROR: Chunk index must be less than chunks count" - return 1 - fi - - set +e - count_sketches "$examples" - local sketchcount=$? - set -e - local sketches=$(cat sketches.txt) - rm -rf sketches.txt - - local chunk_size=$(( $sketchcount / $chunks_num )) - local all_chunks=$(( $chunks_num * $chunk_size )) - if [ "$all_chunks" -lt "$sketchcount" ]; then - chunk_size=$(( $chunk_size + 1 )) - fi - - local start_index=$(( $chunk_idex * $chunk_size )) - if [ "$sketchcount" -le "$start_index" ]; then - echo "Skipping job" - return 0 - fi - - local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size )) - if [ "$end_index" -gt "$sketchcount" ]; then - end_index=$sketchcount - fi - - local start_num=$(( $start_index + 1 )) - echo "Found $sketchcount Sketches"; - echo "Chunk Count : $chunks_num" - echo "Chunk Size : $chunk_size" - echo "Start Sketch: $start_num" - echo "End Sketch : $end_index" - - local sketchnum=0 - for sketch in $sketches; do - local sketchdir=$(dirname $sketch) - local sketchdirname=$(basename $sketchdir) - local sketchname=$(basename $sketch) - is_target=$(jq -r --arg target $target '.targets[$target]' $sketchdir/ci.json) - # If the target is listed as false, skip the sketch. Otherwise, include it. - if [ "${sketchdirname}.ino" != "$sketchname" ] \ - || [[ "$is_target" == "false" ]]; then - continue - fi - sketchnum=$(($sketchnum + 1)) - if [ "$sketchnum" -le "$start_index" ] \ - || [ "$sketchnum" -gt "$end_index" ]; then - continue - fi - build_pio_sketch "$board" "$options" "$sketch" - local result=$? - if [ $result -ne 0 ]; then - return $result - fi - done - return 0 -} diff --git a/.github/scripts/merge_packages.py b/.github/scripts/merge_packages.py index 96999c17fd7..7e4f47ca8b3 100755 --- a/.github/scripts/merge_packages.py +++ b/.github/scripts/merge_packages.py @@ -1,50 +1,58 @@ #!/usr/bin/env python + # This script merges two Arduino Board Manager package json files. # Usage: # python merge_packages.py package_esp8266com_index.json version/new/package_esp8266com_index.json # Written by Ivan Grokhotkov, 2015 # + from __future__ import print_function -#from distutils.version import LooseVersion + +# from distutils.version import LooseVersion from packaging.version import Version import re import json import sys + def load_package(filename): - pkg = json.load(open(filename))['packages'][0] - print("Loaded package {0} from {1}".format(pkg['name'], filename), file=sys.stderr) - print("{0} platform(s), {1} tools".format(len(pkg['platforms']), len(pkg['tools'])), file=sys.stderr) + pkg = json.load(open(filename))["packages"][0] + print("Loaded package {0} from {1}".format(pkg["name"], filename), file=sys.stderr) + print("{0} platform(s), {1} tools".format(len(pkg["platforms"]), len(pkg["tools"])), file=sys.stderr) return pkg + def merge_objects(versions, obj): for o in obj: - name = o['name'].encode('ascii') - ver = o['version'].encode('ascii') - if not name in versions: + name = o["name"].encode("ascii") + ver = o["version"].encode("ascii") + if name not in versions: print("found new object, {0}".format(name), file=sys.stderr) versions[name] = {} - if not ver in versions[name]: + if ver not in versions[name]: print("found new version {0} for object {1}".format(ver, name), file=sys.stderr) versions[name][ver] = o return versions -# Normalize ESP release version string (x.x.x) by adding '-rc' (x.x.x-rc9223372036854775807) to ensure having REL above any RC -# Dummy approach, functional anyway for current ESP package versioning (unlike NormalizedVersion/LooseVersion/StrictVersion & similar crap) + +# Normalize ESP release version string (x.x.x) by adding '-rc' (x.x.x-rc9223372036854775807) +# to ensure having REL above any RC +# Dummy approach, functional anyway for current ESP package versioning +# (unlike NormalizedVersion/LooseVersion/StrictVersion & similar crap) def pkgVersionNormalized(versionString): verStr = str(versionString) - verParts = re.split('\.|-rc|-alpha', verStr, flags=re.IGNORECASE) - + verParts = re.split(r"\.|-rc|-alpha", verStr, flags=re.IGNORECASE) + if len(verParts) == 3: - if (sys.version_info > (3, 0)): # Python 3 - verStr = str(versionString) + '-rc' + str(sys.maxsize) - else: # Python 2 - verStr = str(versionString) + '-rc' + str(sys.maxint) - + if sys.version_info > (3, 0): # Python 3 + verStr = str(versionString) + "-rc" + str(sys.maxsize) + else: # Python 2 + verStr = str(versionString) + "-rc" + str(sys.maxint) + elif len(verParts) != 4: print("pkgVersionNormalized WARNING: unexpected version format: {0})".format(verStr), file=sys.stderr) - + return verStr @@ -54,31 +62,37 @@ def main(args): return 1 tools = {} - platforms = {} + platforms = {} pkg1 = load_package(args[1]) - tools = merge_objects(tools, pkg1['tools']); - platforms = merge_objects(platforms, pkg1['platforms']); + tools = merge_objects(tools, pkg1["tools"]) + platforms = merge_objects(platforms, pkg1["platforms"]) pkg2 = load_package(args[2]) - tools = merge_objects(tools, pkg2['tools']); - platforms = merge_objects(platforms, pkg2['platforms']); + tools = merge_objects(tools, pkg2["tools"]) + platforms = merge_objects(platforms, pkg2["platforms"]) - pkg1['tools'] = [] - pkg1['platforms'] = [] + pkg1["tools"] = [] + pkg1["platforms"] = [] for name in tools: for version in tools[name]: print("Adding tool {0}-{1}".format(name, version), file=sys.stderr) - pkg1['tools'].append(tools[name][version]) + pkg1["tools"].append(tools[name][version]) for name in platforms: for version in platforms[name]: print("Adding platform {0}-{1}".format(name, version), file=sys.stderr) - pkg1['platforms'].append(platforms[name][version]) - - #pkg1['platforms'] = sorted(pkg1['platforms'], key=lambda k: LooseVersion(pkgVersionNormalized(k['version'])), reverse=True) - pkg1['platforms'] = sorted(pkg1['platforms'], key=lambda k: Version(pkgVersionNormalized(k['version'])), reverse=True) + pkg1["platforms"].append(platforms[name][version]) + + # pkg1["platforms"] = sorted( + # pkg1["platforms"], key=lambda k: LooseVersion(pkgVersionNormalized(k["version"])), reverse=True + # ) + + pkg1["platforms"] = sorted( + pkg1["platforms"], key=lambda k: Version(pkgVersionNormalized(k["version"])), reverse=True + ) + + json.dump({"packages": [pkg1]}, sys.stdout, indent=2) - json.dump({'packages':[pkg1]}, sys.stdout, indent=2) -if __name__ == '__main__': +if __name__ == "__main__": sys.exit(main(sys.argv)) diff --git a/.github/scripts/on-pages.sh b/.github/scripts/on-pages.sh index 124518469d2..877d036106b 100755 --- a/.github/scripts/on-pages.sh +++ b/.github/scripts/on-pages.sh @@ -1,12 +1,13 @@ -#/bin/bash +#!/bin/bash + set -e -function get_file_size(){ +function get_file_size { local file="$1" if [[ "$OSTYPE" == "darwin"* ]]; then - eval `stat -s "$file"` + eval "$(stat -s "$file")" local res="$?" - echo "$st_size" + echo "${st_size:?}" return $res else stat --printf="%s" "$file" @@ -15,25 +16,32 @@ function get_file_size(){ } #git_remove_from_pages -function git_remove_from_pages(){ +function git_remove_from_pages { local path=$1 - local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"` - local type=`echo "$info" | jq -r '.type'` - if [ ! $type == "file" ]; then - if [ ! $type == "null" ]; then + local info + local type + local sha + local message + + info=$(curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages") + type=$(echo "$info" | jq -r '.type') + + if [ ! "$type" == "file" ]; then + if [ ! "$type" == "null" ]; then echo "Wrong type '$type'" else echo "File is not on Pages" fi return 0 fi - local sha=`echo "$info" | jq -r '.sha'` - local message="Deleting "$(basename $path) + + sha=$(echo "$info" | jq -r '.sha') + message="Deleting "$(basename "$path") local json="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"sha\":\"$sha\"}" echo "$json" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X DELETE --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path" } -function git_upload_to_pages(){ +function git_upload_to_pages { local path=$1 local src=$2 @@ -42,41 +50,50 @@ function git_upload_to_pages(){ return 1 fi - local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"` - local type=`echo "$info" | jq -r '.type'` - local message=$(basename $path) + local info + local type + local message local sha="" local content="" - if [ $type == "file" ]; then - sha=`echo "$info" | jq -r '.sha'` + info=$(curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages") + type=$(echo "$info" | jq -r '.type') + message=$(basename "$path") + + if [ "$type" == "file" ]; then + sha=$(echo "$info" | jq -r '.sha') sha=",\"sha\":\"$sha\"" message="Updating $message" - elif [ ! $type == "null" ]; then + elif [ ! "$type" == "null" ]; then >&2 echo "Wrong type '$type'" return 1 else message="Creating $message" fi - content=`base64 -i "$src"` + content=$(base64 -i "$src") data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}" echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path" } -function git_safe_upload_to_pages(){ +function git_safe_upload_to_pages { local path=$1 local file="$2" - local name=$(basename "$file") - local size=`get_file_size "$file"` - local upload_res=`git_upload_to_pages "$path" "$file"` - if [ $? -ne 0 ]; then + local name + local size + local upload_res + + name=$(basename "$file") + size=$(get_file_size "$file") + + if ! upload_res=$(git_upload_to_pages "$path" "$file"); then >&2 echo "ERROR: Failed to upload '$name' ($?)" return 1 fi - up_size=`echo "$upload_res" | jq -r '.content.size'` - if [ $up_size -ne $size ]; then + + up_size=$(echo "$upload_res" | jq -r '.content.size') + if [ "$up_size" -ne "$size" ]; then >&2 echo "ERROR: Uploaded size does not match! $up_size != $size" #git_delete_asset return 1 diff --git a/.github/scripts/on-push-idf.sh b/.github/scripts/on-push-idf.sh new file mode 100644 index 00000000000..72e7c7f574e --- /dev/null +++ b/.github/scripts/on-push-idf.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +CHECK_REQUIREMENTS="./components/arduino-esp32/.github/scripts/sketch_utils.sh check_requirements" + +# Export IDF environment +. ${IDF_PATH}/export.sh + +# Find all examples in ./components/arduino-esp32/idf_component_examples +idf_component_examples=$(find ./components/arduino-esp32/idf_component_examples -mindepth 1 -maxdepth 1 -type d) + +for example in $idf_component_examples; do + if [ -f "$example"/ci.json ]; then + # If the target is listed as false, skip the sketch. Otherwise, include it. + is_target=$(jq -r --arg target "$IDF_TARGET" '.targets[$target]' "$example"/ci.json) + if [[ "$is_target" == "false" ]]; then + printf "\n\033[93mSkipping %s for target %s\033[0m\n\n" "$example" "$IDF_TARGET" + continue + fi + fi + + idf.py -C "$example" set-target "$IDF_TARGET" + + has_requirements=$(${CHECK_REQUIREMENTS} "$example" "$example/sdkconfig") + if [ "$has_requirements" -eq 0 ]; then + printf "\n\033[93m%s does not meet the requirements for %s. Skipping...\033[0m\n\n" "$example" "$IDF_TARGET" + continue + fi + + printf "\n\033[95mBuilding %s\033[0m\n\n" "$example" + idf.py -C "$example" -DEXTRA_COMPONENT_DIRS="$PWD/components" build +done diff --git a/.github/scripts/on-push.sh b/.github/scripts/on-push.sh index f925390da13..6095f88e727 100755 --- a/.github/scripts/on-push.sh +++ b/.github/scripts/on-push.sh @@ -4,44 +4,45 @@ set -e export ARDUINO_BUILD_DIR="$HOME/.arduino/build.tmp" -function build(){ +function build { local target=$1 - local fqbn=$2 - local chunk_index=$3 - local chunks_cnt=$4 - local build_log=$5 + local chunk_index=$2 + local chunks_cnt=$3 + local build_log=$4 + local log_level=${5:-none} local sketches_file=$6 - shift; shift; shift; shift; shift; shift; - local sketches=$* + shift 6 + local sketches=("$@") local BUILD_SKETCH="${SCRIPTS_DIR}/sketch_utils.sh build" local BUILD_SKETCHES="${SCRIPTS_DIR}/sketch_utils.sh chunk_build" - local args="-ai $ARDUINO_IDE_PATH -au $ARDUINO_USR_PATH" - - args+=" -t $target -fqbn $fqbn" + local args=("-ai" "$ARDUINO_IDE_PATH" "-au" "$ARDUINO_USR_PATH" "-t" "$target") if [ "$OS_IS_LINUX" == "1" ]; then - args+=" -p $ARDUINO_ESP32_PATH/libraries" - args+=" -i $chunk_index -m $chunks_cnt" + args+=("-p" "$ARDUINO_ESP32_PATH/libraries" "-i" "$chunk_index" "-m" "$chunks_cnt" "-d" "$log_level") if [ -n "$sketches_file" ]; then - args+=" -f $sketches_file" + args+=("-f" "$sketches_file") fi - if [ $build_log -eq 1 ]; then - args+=" -l $build_log" + if [ "$build_log" -eq 1 ]; then + args+=("-l" "$build_log") fi - ${BUILD_SKETCHES} ${args} + ${BUILD_SKETCHES} "${args[@]}" else - for sketch in ${sketches}; do - local sargs="$args -s $(dirname $sketch)" + for sketch in "${sketches[@]}"; do + local sargs=("${args[@]}") + local ctags_version + local preprocessor_version + sargs+=("-s" "$(dirname "$sketch")") if [ "$OS_IS_WINDOWS" == "1" ] && [ -d "$ARDUINO_IDE_PATH/tools-builder" ]; then - local ctags_version=`ls "$ARDUINO_IDE_PATH/tools-builder/ctags/"` - local preprocessor_version=`ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/"` - win_opts="-prefs=runtime.tools.ctags.path=$ARDUINO_IDE_PATH/tools-builder/ctags/$ctags_version - -prefs=runtime.tools.arduino-preprocessor.path=$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/$preprocessor_version" - sargs+=" ${win_opts}" + ctags_version=$(ls "$ARDUINO_IDE_PATH/tools-builder/ctags/") + preprocessor_version=$(ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/") + sargs+=( + "-prefs=runtime.tools.ctags.path=$ARDUINO_IDE_PATH/tools-builder/ctags/$ctags_version" + "-prefs=runtime.tools.arduino-preprocessor.path=$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/$preprocessor_version" + ) fi - ${BUILD_SKETCH} ${sargs} + ${BUILD_SKETCH} "${sargs[@]}" done fi } @@ -54,15 +55,13 @@ fi CHUNK_INDEX=$1 CHUNKS_CNT=$2 BUILD_LOG=$3 -SKETCHES_FILE=$4 -BUILD_PIO=0 +LOG_LEVEL=$4 +SKETCHES_FILE=$5 if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then CHUNK_INDEX=0 CHUNKS_CNT=1 elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ] && [ "$CHUNKS_CNT" -ge 2 ]; then CHUNK_INDEX=$CHUNKS_CNT -elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then - BUILD_PIO=1 fi if [ -z "$BUILD_LOG" ] || [ "$BUILD_LOG" -le 0 ]; then @@ -73,61 +72,35 @@ fi #git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1 SCRIPTS_DIR="./.github/scripts" -if [ "$BUILD_PIO" -eq 0 ]; then - source ${SCRIPTS_DIR}/install-arduino-cli.sh - source ${SCRIPTS_DIR}/install-arduino-core-esp32.sh - - FQBN_ESP32="espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app" - FQBN_ESP32S2="espressif:esp32:esp32s2:PSRAM=enabled,PartitionScheme=huge_app" - FQBN_ESP32S3="espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=huge_app" - FQBN_ESP32C3="espressif:esp32:esp32c3:PartitionScheme=huge_app" - FQBN_ESP32C6="espressif:esp32:esp32c6:PartitionScheme=huge_app" - FQBN_ESP32H2="espressif:esp32:esp32h2:PartitionScheme=huge_app" - - SKETCHES_ESP32="\ - $ARDUINO_ESP32_PATH/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino\ - $ARDUINO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino\ - $ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino\ - $ARDUINO_ESP32_PATH/libraries/Insights/examples/MinimalDiagnostics/MinimalDiagnostics.ino\ - " - #create sizes_file - sizes_file="$GITHUB_WORKSPACE/cli_compile_$CHUNK_INDEX.json" - - if [ "$BUILD_LOG" -eq 1 ]; then - #create sizes_file and echo start of JSON array with "boards" key - echo "{\"boards\": [" > $sizes_file - fi - - #build sketches for different targets - build "esp32s3" $FQBN_ESP32S3 "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32" - build "esp32s2" $FQBN_ESP32S2 "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32" - build "esp32c3" $FQBN_ESP32C3 "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32" - build "esp32c6" $FQBN_ESP32C6 "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32" - build "esp32h2" $FQBN_ESP32H2 "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32" - build "esp32" $FQBN_ESP32 "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32" - - if [ "$BUILD_LOG" -eq 1 ]; then - #remove last comma from the last JSON object - sed -i '$ s/,$//' "$sizes_file" - #echo end of JSON array - echo "]}" >> $sizes_file - fi -else - source ${SCRIPTS_DIR}/install-platformio-esp32.sh - # PlatformIO ESP32 Test - BOARD="esp32dev" - OPTIONS="board_build.partitions = huge_app.csv" - build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \ - build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \ - build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \ - build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino" && \ - build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino" - - # Basic sanity testing for other series - for board in "esp32-c3-devkitm-1" "esp32-s2-saola-1" "esp32-s3-devkitc-1" - do - python -m platformio ci --board "$board" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient" --project-option="board_build.partitions = huge_app.csv" - done +source "${SCRIPTS_DIR}/install-arduino-cli.sh" +source "${SCRIPTS_DIR}/install-arduino-core-esp32.sh" + +SKETCHES_ESP32=( + "$ARDUINO_ESP32_PATH/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" + "$ARDUINO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino" + "$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino" + "$ARDUINO_ESP32_PATH/libraries/Insights/examples/MinimalDiagnostics/MinimalDiagnostics.ino" +) +#create sizes_file +sizes_file="$GITHUB_WORKSPACE/cli_compile_$CHUNK_INDEX.json" + +if [ "$BUILD_LOG" -eq 1 ]; then + #create sizes_file and echo start of JSON array with "boards" key + echo "{\"boards\": [" > "$sizes_file" +fi - #build_pio_sketches "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries" +#build sketches for different targets +build "esp32p4" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32s3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32s2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32c3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32c6" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32h2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" + +if [ "$BUILD_LOG" -eq 1 ]; then + #remove last comma from the last JSON object + sed -i '$ s/,$//' "$sizes_file" + #echo end of JSON array + echo "]}" >> "$sizes_file" fi diff --git a/.github/scripts/on-release.sh b/.github/scripts/on-release.sh index 445b0e0223f..dafbf3d6a1c 100755 --- a/.github/scripts/on-release.sh +++ b/.github/scripts/on-release.sh @@ -1,52 +1,65 @@ #!/bin/bash +# Disable shellcheck warning about using 'cat' to read a file. +# Disable shellcheck warning about using individual redirections for each command. +# Disable shellcheck warning about $? uses. +# shellcheck disable=SC2002,SC2129,SC2181,SC2319 -if [ ! $GITHUB_EVENT_NAME == "release" ]; then +if [ ! "$GITHUB_EVENT_NAME" == "release" ]; then echo "Wrong event '$GITHUB_EVENT_NAME'!" exit 1 fi -EVENT_JSON=`cat $GITHUB_EVENT_PATH` +EVENT_JSON=$(cat "$GITHUB_EVENT_PATH") -action=`echo $EVENT_JSON | jq -r '.action'` -if [ ! $action == "published" ]; then +action=$(echo "$EVENT_JSON" | jq -r '.action') +if [ ! "$action" == "published" ]; then echo "Wrong action '$action'. Exiting now..." exit 0 fi -draft=`echo $EVENT_JSON | jq -r '.release.draft'` -if [ $draft == "true" ]; then +draft=$(echo "$EVENT_JSON" | jq -r '.release.draft') +if [ "$draft" == "true" ]; then echo "It's a draft release. Exiting now..." exit 0 fi -RELEASE_PRE=`echo $EVENT_JSON | jq -r '.release.prerelease'` -RELEASE_TAG=`echo $EVENT_JSON | jq -r '.release.tag_name'` -RELEASE_BRANCH=`echo $EVENT_JSON | jq -r '.release.target_commitish'` -RELEASE_ID=`echo $EVENT_JSON | jq -r '.release.id'` +RELEASE_PRE=$(echo "$EVENT_JSON" | jq -r '.release.prerelease') +RELEASE_TAG=$(echo "$EVENT_JSON" | jq -r '.release.tag_name') +RELEASE_BRANCH=$(echo "$EVENT_JSON" | jq -r '.release.target_commitish') +RELEASE_ID=$(echo "$EVENT_JSON" | jq -r '.release.id') +SCRIPTS_DIR="./.github/scripts" OUTPUT_DIR="$GITHUB_WORKSPACE/build" PACKAGE_NAME="esp32-$RELEASE_TAG" PACKAGE_JSON_MERGE="$GITHUB_WORKSPACE/.github/scripts/merge_packages.py" PACKAGE_JSON_TEMPLATE="$GITHUB_WORKSPACE/package/package_esp32_index.template.json" PACKAGE_JSON_DEV="package_esp32_dev_index.json" PACKAGE_JSON_REL="package_esp32_index.json" +PACKAGE_JSON_DEV_CN="package_esp32_dev_index_cn.json" +PACKAGE_JSON_REL_CN="package_esp32_index_cn.json" echo "Event: $GITHUB_EVENT_NAME, Repo: $GITHUB_REPOSITORY, Path: $GITHUB_WORKSPACE, Ref: $GITHUB_REF" echo "Action: $action, Branch: $RELEASE_BRANCH, ID: $RELEASE_ID" echo "Tag: $RELEASE_TAG, Draft: $draft, Pre-Release: $RELEASE_PRE" # Try extracting something like a JSON with a "boards" array/element and "vendor" fields -BOARDS=`echo $RELEASE_BODY | grep -Pzo '(?s){.*}' | jq -r '.boards[]? // .boards? // empty' | xargs echo -n 2>/dev/null` -VENDOR=`echo $RELEASE_BODY | grep -Pzo '(?s){.*}' | jq -r '.vendor? // empty' | xargs echo -n 2>/dev/null` -if ! [ -z "${BOARDS}" ]; then echo "Releasing board(s): $BOARDS" ; fi -if ! [ -z "${VENDOR}" ]; then echo "Setting packager: $VENDOR" ; fi +BOARDS=$(echo "$RELEASE_BODY" | grep -Pzo '(?s){.*}' | jq -r '.boards[]? // .boards? // empty' | xargs echo -n 2>/dev/null) +VENDOR=$(echo "$RELEASE_BODY" | grep -Pzo '(?s){.*}' | jq -r '.vendor? // empty' | xargs echo -n 2>/dev/null) -function get_file_size(){ +if [ -n "${BOARDS}" ]; then + echo "Releasing board(s): $BOARDS" +fi + +if [ -n "${VENDOR}" ]; then + echo "Setting packager: $VENDOR" +fi + +function get_file_size { local file="$1" if [[ "$OSTYPE" == "darwin"* ]]; then - eval `stat -s "$file"` + eval "$(stat -s "$file")" local res="$?" - echo "$st_size" + echo "${st_size:?}" return $res else stat --printf="%s" "$file" @@ -54,23 +67,29 @@ function get_file_size(){ fi } -function git_upload_asset(){ - local name=$(basename "$1") +function git_upload_asset { + local name + name=$(basename "$1") # local mime=$(file -b --mime-type "$1") curl -k -X POST -sH "Authorization: token $GITHUB_TOKEN" -H "Content-Type: application/octet-stream" --data-binary @"$1" "https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID/assets?name=$name" } -function git_safe_upload_asset(){ +function git_safe_upload_asset { local file="$1" - local name=$(basename "$file") - local size=`get_file_size "$file"` - local upload_res=`git_upload_asset "$file"` - if [ $? -ne 0 ]; then + local name + local size + local upload_res + + name=$(basename "$file") + size=$(get_file_size "$file") + + if ! upload_res=$(git_upload_asset "$file"); then >&2 echo "ERROR: Failed to upload '$name' ($?)" return 1 fi - up_size=`echo "$upload_res" | jq -r '.size'` - if [ $up_size -ne $size ]; then + + up_size=$(echo "$upload_res" | jq -r '.size') + if [ "$up_size" -ne "$size" ]; then >&2 echo "ERROR: Uploaded size does not match! $up_size != $size" #git_delete_asset return 1 @@ -79,7 +98,7 @@ function git_safe_upload_asset(){ return $? } -function git_upload_to_pages(){ +function git_upload_to_pages { local path=$1 local src=$2 @@ -88,41 +107,50 @@ function git_upload_to_pages(){ return 1 fi - local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"` - local type=`echo "$info" | jq -r '.type'` - local message=$(basename $path) + local info + local type + local message local sha="" local content="" - if [ $type == "file" ]; then - sha=`echo "$info" | jq -r '.sha'` + info=$(curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages") + type=$(echo "$info" | jq -r '.type') + message=$(basename "$path") + + if [ "$type" == "file" ]; then + sha=$(echo "$info" | jq -r '.sha') sha=",\"sha\":\"$sha\"" message="Updating $message" - elif [ ! $type == "null" ]; then + elif [ ! "$type" == "null" ]; then >&2 echo "Wrong type '$type'" return 1 else message="Creating $message" fi - content=`base64 -i "$src"` + content=$(base64 -i "$src") data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}" echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path" } -function git_safe_upload_to_pages(){ +function git_safe_upload_to_pages { local path=$1 local file="$2" - local name=$(basename "$file") - local size=`get_file_size "$file"` - local upload_res=`git_upload_to_pages "$path" "$file"` - if [ $? -ne 0 ]; then + local name + local size + local upload_res + + name=$(basename "$file") + size=$(get_file_size "$file") + + if ! upload_res=$(git_upload_to_pages "$path" "$file"); then >&2 echo "ERROR: Failed to upload '$name' ($?)" return 1 fi - up_size=`echo "$upload_res" | jq -r '.content.size'` - if [ $up_size -ne $size ]; then + + up_size=$(echo "$upload_res" | jq -r '.content.size') + if [ "$up_size" -ne "$size" ]; then >&2 echo "ERROR: Uploaded size does not match! $up_size != $size" #git_delete_asset return 1 @@ -131,15 +159,20 @@ function git_safe_upload_to_pages(){ return $? } -function merge_package_json(){ +function merge_package_json { local jsonLink=$1 local jsonOut=$2 local old_json=$OUTPUT_DIR/oldJson.json local merged_json=$OUTPUT_DIR/mergedJson.json + local error_code=0 echo "Downloading previous JSON $jsonLink ..." curl -L -o "$old_json" "https://github.com/$GITHUB_REPOSITORY/releases/download/$jsonLink?access_token=$GITHUB_TOKEN" 2>/dev/null - if [ $? -ne 0 ]; then echo "ERROR: Download Failed! $?"; exit 1; fi + error_code=$? + if [ $error_code -ne 0 ]; then + echo "ERROR: Download Failed! $error_code" + exit 1 + fi echo "Creating new JSON ..." set +e @@ -147,7 +180,7 @@ function merge_package_json(){ set -e set -v - if [ ! -s $merged_json ]; then + if [ ! -s "$merged_json" ]; then rm -f "$merged_json" echo "Nothing to merge" else @@ -188,10 +221,14 @@ else done # Copy only relevant variant files mkdir "$PKG_DIR/variants/" - for variant in `cat ${PKG_DIR}/boards.txt | grep "\.variant=" | cut -d= -f2` ; do + board_list=$(cat "${PKG_DIR}"/boards.txt | grep "\.variant=" | cut -d= -f2) + while IFS= read -r variant; do cp -Rf "$GITHUB_WORKSPACE/variants/${variant}" "$PKG_DIR/variants/" - done + done <<< "$board_list" fi +cp -f "$GITHUB_WORKSPACE/CMakeLists.txt" "$PKG_DIR/" +cp -f "$GITHUB_WORKSPACE/idf_component.yml" "$PKG_DIR/" +cp -f "$GITHUB_WORKSPACE/Kconfig.projbuild" "$PKG_DIR/" cp -f "$GITHUB_WORKSPACE/package.json" "$PKG_DIR/" cp -f "$GITHUB_WORKSPACE/programmers.txt" "$PKG_DIR/" cp -Rf "$GITHUB_WORKSPACE/cores" "$PKG_DIR/" @@ -204,7 +241,7 @@ cp -f "$GITHUB_WORKSPACE/tools/gen_insights_package.py" "$PKG_DIR/tools/" cp -f "$GITHUB_WORKSPACE/tools/gen_insights_package.exe" "$PKG_DIR/tools/" cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/" cp -Rf "$GITHUB_WORKSPACE/tools/ide-debug" "$PKG_DIR/tools/" -cp -f "$GITHUB_WORKSPACE/tools/platformio-build.py" "$PKG_DIR/tools/" +cp -f "$GITHUB_WORKSPACE/tools/pioarduino-build.py" "$PKG_DIR/tools/" # Remove unnecessary files in the package folder echo "Cleaning up folders ..." @@ -216,12 +253,8 @@ find "$PKG_DIR" -name '*.git*' -type f -delete ## RVTC_NAME="riscv32-esp-elf-gcc" RVTC_NEW_NAME="esp-rv32" -X32TC_NAME="xtensa-esp32-elf-gcc" +X32TC_NAME="xtensa-esp-elf-gcc" X32TC_NEW_NAME="esp-x32" -XS2TC_NAME="xtensa-esp32s2-elf-gcc" -XS2TC_NEW_NAME="esp-xs2" -XS3TC_NAME="xtensa-esp32s3-elf-gcc" -XS3TC_NEW_NAME="esp-xs3" # Replace tools locations in platform.txt echo "Generating platform.txt..." @@ -230,40 +263,40 @@ sed "s/version=.*/version=$RELEASE_TAG/g" | \ sed 's/tools\.esp32-arduino-libs\.path\.windows=.*//g' | \ sed 's/{runtime\.platform\.path}.tools.esp32-arduino-libs/\{runtime.tools.esp32-arduino-libs.path\}/g' | \ sed 's/{runtime\.platform\.path}.tools.xtensa-esp-elf-gdb/\{runtime.tools.xtensa-esp-elf-gdb.path\}/g' | \ -sed "s/{runtime\.platform\.path}.tools.xtensa-esp32-elf/\\{runtime.tools.$X32TC_NEW_NAME.path\\}/g" | \ -sed "s/{runtime\.platform\.path}.tools.xtensa-esp32s2-elf/\\{runtime.tools.$XS2TC_NEW_NAME.path\\}/g" | \ -sed "s/{runtime\.platform\.path}.tools.xtensa-esp32s3-elf/\\{runtime.tools.$XS3TC_NEW_NAME.path\\}/g" | \ +sed "s/{runtime\.platform\.path}.tools.xtensa-esp-elf/\\{runtime.tools.$X32TC_NEW_NAME.path\\}/g" | \ sed 's/{runtime\.platform\.path}.tools.riscv32-esp-elf-gdb/\{runtime.tools.riscv32-esp-elf-gdb.path\}/g' | \ sed "s/{runtime\.platform\.path}.tools.riscv32-esp-elf/\\{runtime.tools.$RVTC_NEW_NAME.path\\}/g" | \ sed 's/{runtime\.platform\.path}.tools.esptool/\{runtime.tools.esptool_py.path\}/g' | \ -sed 's/{runtime\.platform\.path}.tools.openocd-esp32/\{runtime.tools.openocd-esp32.path\}/g' \ - > "$PKG_DIR/platform.txt" +sed 's/{runtime\.platform\.path}.tools.openocd-esp32/\{runtime.tools.openocd-esp32.path\}/g' > "$PKG_DIR/platform.txt" -if ! [ -z ${VENDOR} ]; then +if [ -n "${VENDOR}" ]; then # Append vendor name to platform.txt to create a separate section sed -i "/^name=.*/s/$/ ($VENDOR)/" "$PKG_DIR/platform.txt" fi # Add header with version information echo "Generating core_version.h ..." -ver_define=`echo $RELEASE_TAG | tr "[:lower:].\055" "[:upper:]_"` -ver_hex=`git -C "$GITHUB_WORKSPACE" rev-parse --short=8 HEAD 2>/dev/null` -echo \#define ARDUINO_ESP32_GIT_VER 0x$ver_hex > "$PKG_DIR/cores/esp32/core_version.h" -echo \#define ARDUINO_ESP32_GIT_DESC `git -C "$GITHUB_WORKSPACE" describe --tags 2>/dev/null` >> "$PKG_DIR/cores/esp32/core_version.h" -echo \#define ARDUINO_ESP32_RELEASE_$ver_define >> "$PKG_DIR/cores/esp32/core_version.h" -echo \#define ARDUINO_ESP32_RELEASE \"$ver_define\" >> "$PKG_DIR/cores/esp32/core_version.h" +ver_define=$(echo "$RELEASE_TAG" | tr "[:lower:].\055" "[:upper:]_") +ver_hex=$(git -C "$GITHUB_WORKSPACE" rev-parse --short=8 HEAD 2>/dev/null) +echo \#define ARDUINO_ESP32_GIT_VER 0x"$ver_hex" > "$PKG_DIR/cores/esp32/core_version.h" +echo \#define ARDUINO_ESP32_GIT_DESC "$(git -C "$GITHUB_WORKSPACE" describe --tags 2>/dev/null)" >> "$PKG_DIR/cores/esp32/core_version.h" +echo \#define ARDUINO_ESP32_RELEASE_"$ver_define" >> "$PKG_DIR/cores/esp32/core_version.h" +echo \#define ARDUINO_ESP32_RELEASE \""$ver_define"\" >> "$PKG_DIR/cores/esp32/core_version.h" # Compress package folder echo "Creating ZIP ..." pushd "$OUTPUT_DIR" >/dev/null zip -qr "$PACKAGE_ZIP" "$PACKAGE_NAME" -if [ $? -ne 0 ]; then echo "ERROR: Failed to create $PACKAGE_ZIP ($?)"; exit 1; fi +if [ $? -ne 0 ]; then + echo "ERROR: Failed to create $PACKAGE_ZIP ($?)" + exit 1 +fi # Calculate SHA-256 echo "Calculating SHA sum ..." PACKAGE_PATH="$OUTPUT_DIR/$PACKAGE_ZIP" -PACKAGE_SHA=`shasum -a 256 "$PACKAGE_ZIP" | cut -f 1 -d ' '` -PACKAGE_SIZE=`get_file_size "$PACKAGE_ZIP"` +PACKAGE_SHA=$(shasum -a 256 "$PACKAGE_ZIP" | cut -f 1 -d ' ') +PACKAGE_SIZE=$(get_file_size "$PACKAGE_ZIP") popd >/dev/null rm -rf "$PKG_DIR" echo "'$PACKAGE_ZIP' Created! Size: $PACKAGE_SIZE, SHA-256: $PACKAGE_SHA" @@ -271,79 +304,17 @@ echo # Upload package to release page echo "Uploading package to release page ..." -PACKAGE_URL=`git_safe_upload_asset "$PACKAGE_PATH"` +PACKAGE_URL=$(git_safe_upload_asset "$PACKAGE_PATH") echo "Package Uploaded" echo "Download URL: $PACKAGE_URL" echo -## -## LIBS PACKAGE ZIP -## - -LIBS_PROJ_NAME="esp32-arduino-libs" -LIBS_PKG_DIR="$OUTPUT_DIR/$LIBS_PROJ_NAME" -LIBS_PACKAGE_ZIP="$LIBS_PROJ_NAME-$RELEASE_TAG.zip" - -# Get the libs package URL from the template -LIBS_PACKAGE_SRC_ZIP="$OUTPUT_DIR/src-$LIBS_PROJ_NAME.zip" -LIBS_PACKAGE_SRC_URL=`cat $PACKAGE_JSON_TEMPLATE | jq -r ".packages[0].tools[] | select(.name==\"$LIBS_PROJ_NAME\") | .systems[0].url"` - -# Download the libs package -echo "Downloading the libs archive ..." -curl -o "$LIBS_PACKAGE_SRC_ZIP" -LJO --url "$LIBS_PACKAGE_SRC_URL" || exit 1 - -# Extract the libs package -echo "Extracting the archive ..." -unzip -q -d "$OUTPUT_DIR" "$LIBS_PACKAGE_SRC_ZIP" || exit 1 -EXTRACTED_DIR=`ls "$OUTPUT_DIR" | grep "^$LIBS_PROJ_NAME"` -mv "$OUTPUT_DIR/$EXTRACTED_DIR" "$LIBS_PKG_DIR" || exit 1 - -# Remove unnecessary files in the package folder -echo "Cleaning up folders ..." -find "$LIBS_PKG_DIR" -name '*.DS_Store' -exec rm -f {} \; -find "$LIBS_PKG_DIR" -name '*.git*' -type f -delete - -# Compress package folder -echo "Creating ZIP ..." -pushd "$OUTPUT_DIR" >/dev/null -zip -qr "$LIBS_PACKAGE_ZIP" "$LIBS_PROJ_NAME" -if [ $? -ne 0 ]; then echo "ERROR: Failed to create $LIBS_PACKAGE_ZIP ($?)"; exit 1; fi - -# Calculate SHA-256 -echo "Calculating SHA sum ..." -LIBS_PACKAGE_PATH="$OUTPUT_DIR/$LIBS_PACKAGE_ZIP" -LIBS_PACKAGE_SHA=`shasum -a 256 "$LIBS_PACKAGE_ZIP" | cut -f 1 -d ' '` -LIBS_PACKAGE_SIZE=`get_file_size "$LIBS_PACKAGE_ZIP"` -popd >/dev/null -rm -rf "$LIBS_PKG_DIR" -echo "'$LIBS_PACKAGE_ZIP' Created! Size: $LIBS_PACKAGE_SIZE, SHA-256: $LIBS_PACKAGE_SHA" -echo - -# Upload package to release page -echo "Uploading libs package to release page ..." -LIBS_PACKAGE_URL=`git_safe_upload_asset "$LIBS_PACKAGE_PATH"` -echo "Libs Package Uploaded" -echo "Libs Download URL: $LIBS_PACKAGE_URL" -echo - -# Construct JQ argument with libs package data -libs_jq_arg="\ - (.packages[0].tools[] | select(.name==\"$LIBS_PROJ_NAME\")).systems[].url = \"$LIBS_PACKAGE_URL\" |\ - (.packages[0].tools[] | select(.name==\"$LIBS_PROJ_NAME\")).systems[].archiveFileName = \"$LIBS_PACKAGE_ZIP\" |\ - (.packages[0].tools[] | select(.name==\"$LIBS_PROJ_NAME\")).systems[].size = \"$LIBS_PACKAGE_SIZE\" |\ - (.packages[0].tools[] | select(.name==\"$LIBS_PROJ_NAME\")).systems[].checksum = \"SHA-256:$LIBS_PACKAGE_SHA\"" - -# Update template values for the libs package and store it in the build folder -cat "$PACKAGE_JSON_TEMPLATE" | jq "$libs_jq_arg" > "$OUTPUT_DIR/package-$LIBS_PROJ_NAME.json" -# Overwrite the template location with the newly edited one -PACKAGE_JSON_TEMPLATE="$OUTPUT_DIR/package-$LIBS_PROJ_NAME.json" - ## ## TEMP WORKAROUND FOR RV32 LONG PATH ON WINDOWS ## -RVTC_VERSION=`cat $PACKAGE_JSON_TEMPLATE | jq -r ".packages[0].platforms[0].toolsDependencies[] | select(.name == \"$RVTC_NAME\") | .version" | cut -d '_' -f 2` +RVTC_VERSION=$(cat "$PACKAGE_JSON_TEMPLATE" | jq -r ".packages[0].platforms[0].toolsDependencies[] | select(.name == \"$RVTC_NAME\") | .version" | cut -d '_' -f 2) # RVTC_VERSION=`date -j -f '%Y%m%d' "$RVTC_VERSION" '+%y%m'` # MacOS -RVTC_VERSION=`date -d "$RVTC_VERSION" '+%y%m'` +RVTC_VERSION=$(date -d "$RVTC_VERSION" '+%y%m') rvtc_jq_arg="\ (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$RVTC_NAME\")).version = \"$RVTC_VERSION\" |\ (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$RVTC_NAME\")).name = \"$RVTC_NEW_NAME\" |\ @@ -352,17 +323,9 @@ rvtc_jq_arg="\ (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$X32TC_NAME\")).version = \"$RVTC_VERSION\" |\ (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$X32TC_NAME\")).name = \"$X32TC_NEW_NAME\" |\ (.packages[0].tools[] | select(.name==\"$X32TC_NAME\")).version = \"$RVTC_VERSION\" |\ - (.packages[0].tools[] | select(.name==\"$X32TC_NAME\")).name = \"$X32TC_NEW_NAME\" |\ - (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$XS2TC_NAME\")).version = \"$RVTC_VERSION\" |\ - (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$XS2TC_NAME\")).name = \"$XS2TC_NEW_NAME\" |\ - (.packages[0].tools[] | select(.name==\"$XS2TC_NAME\")).version = \"$RVTC_VERSION\" |\ - (.packages[0].tools[] | select(.name==\"$XS2TC_NAME\")).name = \"$XS2TC_NEW_NAME\" |\ - (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$XS3TC_NAME\")).version = \"$RVTC_VERSION\" |\ - (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$XS3TC_NAME\")).name = \"$XS3TC_NEW_NAME\" |\ - (.packages[0].tools[] | select(.name==\"$XS3TC_NAME\")).version = \"$RVTC_VERSION\" |\ - (.packages[0].tools[] | select(.name==\"$XS3TC_NAME\")).name = \"$XS3TC_NEW_NAME\"" -cat "$PACKAGE_JSON_TEMPLATE" | jq "$rvtc_jq_arg" > "$OUTPUT_DIR/package-$LIBS_PROJ_NAME-rvfix.json" -PACKAGE_JSON_TEMPLATE="$OUTPUT_DIR/package-$LIBS_PROJ_NAME-rvfix.json" + (.packages[0].tools[] | select(.name==\"$X32TC_NAME\")).name = \"$X32TC_NEW_NAME\"" +cat "$PACKAGE_JSON_TEMPLATE" | jq "$rvtc_jq_arg" > "$OUTPUT_DIR/package-rvfix.json" +PACKAGE_JSON_TEMPLATE="$OUTPUT_DIR/package-rvfix.json" ## ## PACKAGE JSON @@ -376,17 +339,24 @@ jq_arg=".packages[0].platforms[0].version = \"$RELEASE_TAG\" | \ .packages[0].platforms[0].checksum = \"SHA-256:$PACKAGE_SHA\"" # Generate package JSONs -echo "Genarating $PACKAGE_JSON_DEV ..." +echo "Generating $PACKAGE_JSON_DEV ..." cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_DEV" +# On MacOS the sed command won't skip the first match. Use gsed instead. +sed '0,/github\.com\/espressif\//!s|github\.com/espressif/|dl.espressif.cn/github_assets/espressif/|g' "$OUTPUT_DIR/$PACKAGE_JSON_DEV" > "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN" if [ "$RELEASE_PRE" == "false" ]; then - echo "Genarating $PACKAGE_JSON_REL ..." + echo "Generating $PACKAGE_JSON_REL ..." cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_REL" + # On MacOS the sed command won't skip the first match. Use gsed instead. + sed '0,/github\.com\/espressif\//!s|github\.com/espressif/|dl.espressif.cn/github_assets/espressif/|g' "$OUTPUT_DIR/$PACKAGE_JSON_REL" > "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN" fi # Figure out the last release or pre-release echo "Getting previous releases ..." -releasesJson=`curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases" 2>/dev/null` -if [ $? -ne 0 ]; then echo "ERROR: Get Releases Failed! ($?)"; exit 1; fi +releasesJson=$(curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases" 2>/dev/null) +if [ $? -ne 0 ]; then + echo "ERROR: Get Releases Failed! ($?)" + exit 1 +fi set +e prev_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false)) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name") @@ -406,27 +376,94 @@ echo "Previous (any)release: $prev_any_release" echo # Merge package JSONs with previous releases -if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then +if [ -n "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then echo "Merging with JSON from $prev_any_release ..." merge_package_json "$prev_any_release/$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV" + merge_package_json "$prev_any_release/$PACKAGE_JSON_DEV_CN" "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN" fi if [ "$RELEASE_PRE" == "false" ]; then - if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then + if [ -n "$prev_release" ] && [ "$prev_release" != "null" ]; then echo "Merging with JSON from $prev_release ..." merge_package_json "$prev_release/$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL" + merge_package_json "$prev_release/$PACKAGE_JSON_REL_CN" "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN" fi fi -# Upload package JSONs (temporary halted to fix json generation) +# Test the package JSONs + +echo "Installing arduino-cli ..." +export PATH="/home/runner/bin:$PATH" +source "${SCRIPTS_DIR}/install-arduino-cli.sh" + +# For the Chinese mirror, we can't test the package JSONs as the Chinese mirror might not be updated yet. + +echo "Testing $PACKAGE_JSON_DEV install ..." + +echo "Installing esp32 ..." +arduino-cli core install esp32:esp32 --additional-urls "file://$OUTPUT_DIR/$PACKAGE_JSON_DEV" +if [ $? -ne 0 ]; then + echo "ERROR: Failed to install esp32 ($?)" + exit 1 +fi + +echo "Compiling example ..." +arduino-cli compile --fqbn esp32:esp32:esp32 "$GITHUB_WORKSPACE"/libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino +if [ $? -ne 0 ]; then + echo "ERROR: Failed to compile example ($?)" + exit 1 +fi + +echo "Uninstalling esp32 ..." +arduino-cli core uninstall esp32:esp32 +if [ $? -ne 0 ]; then + echo "ERROR: Failed to uninstall esp32 ($?)" + exit 1 +fi + +echo "Test successful!" + +if [ "$RELEASE_PRE" == "false" ]; then + echo "Testing $PACKAGE_JSON_REL install ..." + + echo "Installing esp32 ..." + arduino-cli core install esp32:esp32 --additional-urls "file://$OUTPUT_DIR/$PACKAGE_JSON_REL" + if [ $? -ne 0 ]; then + echo "ERROR: Failed to install esp32 ($?)" + exit 1 + fi + + echo "Compiling example ..." + arduino-cli compile --fqbn esp32:esp32:esp32 "$GITHUB_WORKSPACE"/libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino + if [ $? -ne 0 ]; then + echo "ERROR: Failed to compile example ($?)" + exit 1 + fi + + echo "Uninstalling esp32 ..." + arduino-cli core uninstall esp32:esp32 + if [ $? -ne 0 ]; then + echo "ERROR: Failed to uninstall esp32 ($?)" + exit 1 + fi + + echo "Test successful!" +fi + +# Upload package JSONs + echo "Uploading $PACKAGE_JSON_DEV ..." -echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV"` -# echo "Pages URL: "`git_safe_upload_to_pages "$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV"` +echo "Download URL: $(git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV")" +echo "Pages URL: $(git_safe_upload_to_pages "$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV")" +echo "Download CN URL: $(git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN")" +echo "Pages CN URL: $(git_safe_upload_to_pages "$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN")" echo if [ "$RELEASE_PRE" == "false" ]; then echo "Uploading $PACKAGE_JSON_REL ..." - echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_REL"` - # echo "Pages URL: "`git_safe_upload_to_pages "$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"` + echo "Download URL: $(git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_REL")" + echo "Pages URL: $(git_safe_upload_to_pages "$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL")" + echo "Download CN URL: $(git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN")" + echo "Pages CN URL: $(git_safe_upload_to_pages "$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN")" echo fi diff --git a/.github/scripts/set_push_chunks.sh b/.github/scripts/set_push_chunks.sh index 472205f0c38..ff0af7da6e8 100644 --- a/.github/scripts/set_push_chunks.sh +++ b/.github/scripts/set_push_chunks.sh @@ -4,80 +4,81 @@ build_all=false chunks_count=0 if [[ $CORE_CHANGED == 'true' ]] || [[ $IS_PR != 'true' ]]; then - echo "Core files changed or not a PR. Building all." - build_all=true - chunks_count=$MAX_CHUNKS + echo "Core files changed or not a PR. Building all." + build_all=true + chunks_count=$MAX_CHUNKS elif [[ $LIB_CHANGED == 'true' ]]; then - echo "Libraries changed. Building only affected sketches." - if [[ $NETWORKING_CHANGED == 'true' ]]; then - echo "Networking libraries changed. Building networking related sketches." - networking_sketches="$(find libraries/WiFi -name *.ino) " - networking_sketches+="$(find libraries/Ethernet -name *.ino) " - networking_sketches+="$(find libraries/PPP -name *.ino) " - networking_sketches+="$(find libraries/NetworkClientSecure -name *.ino) " - networking_sketches+="$(find libraries/WebServer -name *.ino) " - fi - if [[ $FS_CHANGED == 'true' ]]; then - echo "FS libraries changed. Building FS related sketches." - fs_sketches="$(find libraries/SD -name *.ino) " - fs_sketches+="$(find libraries/SD_MMC -name *.ino) " - fs_sketches+="$(find libraries/SPIFFS -name *.ino) " - fs_sketches+="$(find libraries/LittleFS -name *.ino) " - fs_sketches+="$(find libraries/FFat -name *.ino) " - fi - sketches="$networking_sketches $fs_sketches" - for file in $LIB_FILES; do - if [[ $file == *.ino ]]; then - # If file ends with .ino, add it to the list of sketches - echo "Sketch found: $file" - sketches+="$file " - elif [[ $(basename $(dirname $file)) == "src" ]]; then - # If file is in a src directory, find all sketches in the parent/examples directory - echo "Library src file found: $file" - lib=$(dirname $(dirname $file)) - if [[ -d $lib/examples ]]; then - lib_sketches=$(find $lib/examples -name *.ino) - sketches+="$lib_sketches " - echo "Library sketches: $lib_sketches" - fi - else - # If file is in a example folder but it is not a sketch, find all sketches in the current directory - echo "File in example folder found: $file" - sketch=$(find $(dirname $file) -name *.ino) - sketches+="$sketch " - echo "Sketch in example folder: $sketch" - fi - echo "" - done + echo "Libraries changed. Building only affected sketches." + if [[ $NETWORKING_CHANGED == 'true' ]]; then + echo "Networking libraries changed. Building networking related sketches." + networking_sketches="$(find libraries/WiFi -name '*.ino') " + networking_sketches+="$(find libraries/Ethernet -name '*.ino') " + networking_sketches+="$(find libraries/PPP -name '*.ino') " + networking_sketches+="$(find libraries/NetworkClientSecure -name '*.ino') " + networking_sketches+="$(find libraries/WebServer -name '*.ino') " + fi + if [[ $FS_CHANGED == 'true' ]]; then + echo "FS libraries changed. Building FS related sketches." + fs_sketches="$(find libraries/SD -name '*.ino') " + fs_sketches+="$(find libraries/SD_MMC -name '*.ino') " + fs_sketches+="$(find libraries/SPIFFS -name '*.ino') " + fs_sketches+="$(find libraries/LittleFS -name '*.ino') " + fs_sketches+="$(find libraries/FFat -name '*.ino') " + fi + sketches="$networking_sketches $fs_sketches" + for file in $LIB_FILES; do + lib=$(echo "$file" | awk -F "/" '{print $1"/"$2}') + if [[ "$file" == *.ino ]]; then + # If file ends with .ino, add it to the list of sketches + echo "Sketch found: $file" + sketches+="$file " + elif [[ "$file" == "$lib/src/"* ]]; then + # If file is inside the src directory, find all sketches in the lib/examples directory + echo "Library src file found: $file" + if [[ -d $lib/examples ]]; then + lib_sketches=$(find "$lib"/examples -name '*.ino') + sketches+="$lib_sketches " + echo "Library sketches: $lib_sketches" + fi + else + # If file is in a example folder but it is not a sketch, find all sketches in the current directory + echo "File in example folder found: $file" + sketch=$(find "$(dirname "$file")" -name '*.ino') + sketches+="$sketch " + echo "Sketch in example folder: $sketch" + fi + echo "" + done fi if [[ -n $sketches ]]; then - # Remove duplicates - sketches=$(echo $sketches | tr ' ' '\n' | sort | uniq) - for sketch in $sketches; do - echo $sketch >> sketches_found.txt - chunks_count=$((chunks_count+1)) - done - echo "Number of sketches found: $chunks_count" - echo "Sketches:" - echo "$sketches" + # Remove duplicates + sketches=$(echo "$sketches" | tr ' ' '\n' | sort | uniq) + for sketch in $sketches; do + echo "$sketch" >> sketches_found.txt + chunks_count=$((chunks_count+1)) + done + echo "Number of sketches found: $chunks_count" + echo "Sketches:" + echo "$sketches" - if [[ $chunks_count -gt $MAX_CHUNKS ]]; then - echo "More sketches than the allowed number of chunks found. Limiting to $MAX_CHUNKS chunks." - chunks_count=$MAX_CHUNKS - fi + if [[ $chunks_count -gt $MAX_CHUNKS ]]; then + echo "More sketches than the allowed number of chunks found. Limiting to $MAX_CHUNKS chunks." + chunks_count=$MAX_CHUNKS + fi fi chunks='["0"' -for i in $(seq 1 $(( $chunks_count - 1 )) ); do - chunks+=",\"$i\"" +for i in $(seq 1 $(( chunks_count - 1 )) ); do + chunks+=",\"$i\"" done chunks+="]" -echo "build_all=$build_all" >> $GITHUB_OUTPUT -echo "build_libraries=$BUILD_LIBRARIES" >> $GITHUB_OUTPUT -echo "build_static_sketches=$BUILD_STATIC_SKETCHES" >> $GITHUB_OUTPUT -echo "build_idf=$BUILD_IDF" >> $GITHUB_OUTPUT -echo "build_platformio=$BUILD_PLATFORMIO" >> $GITHUB_OUTPUT -echo "chunk_count=$chunks_count" >> $GITHUB_OUTPUT -echo "chunks=$chunks" >> $GITHUB_OUTPUT +{ + echo "build_all=$build_all" + echo "build_libraries=$BUILD_LIBRARIES" + echo "build_static_sketches=$BUILD_STATIC_SKETCHES" + echo "build_idf=$BUILD_IDF" + echo "chunk_count=$chunks_count" + echo "chunks=$chunks" +} >> "$GITHUB_OUTPUT" diff --git a/.github/scripts/sketch_utils.sh b/.github/scripts/sketch_utils.sh index cdf334a4fc6..befea255e0b 100755 --- a/.github/scripts/sketch_utils.sh +++ b/.github/scripts/sketch_utils.sh @@ -1,7 +1,60 @@ #!/bin/bash -function build_sketch(){ # build_sketch [extra-options] - while [ ! -z "$1" ]; do +if [ -d "$ARDUINO_ESP32_PATH/tools/esp32-arduino-libs" ]; then + SDKCONFIG_DIR="$ARDUINO_ESP32_PATH/tools/esp32-arduino-libs" +elif [ -d "$GITHUB_WORKSPACE/tools/esp32-arduino-libs" ]; then + SDKCONFIG_DIR="$GITHUB_WORKSPACE/tools/esp32-arduino-libs" +else + SDKCONFIG_DIR="tools/esp32-arduino-libs" +fi + +function check_requirements { # check_requirements + local sketchdir=$1 + local sdkconfig_path=$2 + local has_requirements=1 + local requirements + local requirements_or + + if [ ! -f "$sdkconfig_path" ] || [ ! -f "$sketchdir/ci.json" ]; then + echo "WARNING: sdkconfig or ci.json not found. Assuming requirements are met." 1>&2 + # Return 1 on error to force the sketch to be built and fail. This way the + # CI will fail and the user will know that the sketch has a problem. + else + # Check if the sketch requires any configuration options (AND) + requirements=$(jq -r '.requires[]? // empty' "$sketchdir/ci.json") + if [[ "$requirements" != "null" && "$requirements" != "" ]]; then + for requirement in $requirements; do + requirement=$(echo "$requirement" | xargs) + found_line=$(grep -E "^$requirement" "$sdkconfig_path") + if [[ "$found_line" == "" ]]; then + has_requirements=0 + fi + done + fi + + # Check if the sketch requires any configuration options (OR) + requirements_or=$(jq -r '.requires_any[]? // empty' "$sketchdir/ci.json") + if [[ "$requirements_or" != "null" && "$requirements_or" != "" ]]; then + local found=false + for requirement in $requirements_or; do + requirement=$(echo "$requirement" | xargs) + found_line=$(grep -E "^$requirement" "$sdkconfig_path") + if [[ "$found_line" != "" ]]; then + found=true + break + fi + done + if [[ "$found" == "false" ]]; then + has_requirements=0 + fi + fi + fi + + echo $has_requirements +} + +function build_sketch { # build_sketch [extra-options] + while [ -n "$1" ]; do case "$1" in -ai ) shift @@ -35,6 +88,10 @@ function build_sketch(){ # build_sketch [ex shift log_compilation=$1 ;; + -d ) + shift + debug_level="DebugLevel=$1" + ;; * ) break ;; @@ -42,10 +99,10 @@ function build_sketch(){ # build_sketch [ex shift done - xtra_opts=$* + xtra_opts=("$@") len=0 - if [ -z $sketchdir ]; then + if [ -z "$sketchdir" ]; then echo "ERROR: Sketch directory not provided" echo "$USAGE" exit 1 @@ -53,8 +110,8 @@ function build_sketch(){ # build_sketch [ex # No FQBN was passed, try to get it from other options - if [ -z $fqbn ]; then - if [ -z $target ]; then + if [ -z "$fqbn" ]; then + if [ -z "$target" ]; then echo "ERROR: Unspecified chip" echo "$USAGE" exit 1 @@ -65,52 +122,78 @@ function build_sketch(){ # build_sketch [ex # precedence. Note that the following logic also falls to the default # parameters if no arguments were passed and no file was found. - if [ -z $options ] && [ -f $sketchdir/ci.json ]; then + if [ -z "$options" ] && [ -f "$sketchdir"/ci.json ]; then # The config file could contain multiple FQBNs for one chip. If # that's the case we build one time for every FQBN. - len=`jq -r --arg target $target '.fqbn[$target] | length' $sketchdir/ci.json` - if [ $len -gt 0 ]; then - fqbn=`jq -r --arg target $target '.fqbn[$target] | sort' $sketchdir/ci.json` + len=$(jq -r --arg target "$target" '.fqbn[$target] | length' "$sketchdir"/ci.json) + if [ "$len" -gt 0 ]; then + fqbn=$(jq -r --arg target "$target" '.fqbn[$target] | sort' "$sketchdir"/ci.json) fi fi - if [ ! -z $options ] || [ $len -eq 0 ]; then + if [ -n "$options" ] || [ "$len" -eq 0 ]; then # Since we are passing options, we will end up with only one FQBN to # build. len=1 + if [ -f "$sketchdir"/ci.json ]; then + fqbn_append=$(jq -r '.fqbn_append' "$sketchdir"/ci.json) + if [ "$fqbn_append" == "null" ]; then + fqbn_append="" + fi + fi + # Default FQBN options if none were passed in the command line. + # Replace any double commas with a single one and strip leading and + # trailing commas. - esp32_opts="PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio" - esp32s2_opts="PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio" - esp32s3_opts="PSRAM=opi,USBMode=default,PartitionScheme=huge_app,FlashMode=dio" - esp32c3_opts="PartitionScheme=huge_app,FlashMode=dio" - esp32c6_opts="PartitionScheme=huge_app,FlashMode=dio" - esp32h2_opts="PartitionScheme=huge_app,FlashMode=dio" + esp32_opts=$(echo "PSRAM=enabled,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') + esp32s2_opts=$(echo "PSRAM=enabled,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') + esp32s3_opts=$(echo "PSRAM=opi,USBMode=default,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') + esp32c3_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') + esp32c6_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') + esp32h2_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') + esp32p4_opts=$(echo "PSRAM=enabled,USBMode=default,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') # Select the common part of the FQBN based on the target. The rest will be # appended depending on the passed options. + opt="" + case "$target" in "esp32") - fqbn="espressif:esp32:esp32:${options:-$esp32_opts}" + [ -n "${options:-$esp32_opts}" ] && opt=":${options:-$esp32_opts}" + fqbn="espressif:esp32:esp32$opt" ;; "esp32s2") - fqbn="espressif:esp32:esp32s2:${options:-$esp32s2_opts}" + [ -n "${options:-$esp32s2_opts}" ] && opt=":${options:-$esp32s2_opts}" + fqbn="espressif:esp32:esp32s2$opt" ;; "esp32c3") - fqbn="espressif:esp32:esp32c3:${options:-$esp32c3_opts}" + [ -n "${options:-$esp32c3_opts}" ] && opt=":${options:-$esp32c3_opts}" + fqbn="espressif:esp32:esp32c3$opt" ;; "esp32s3") - fqbn="espressif:esp32:esp32s3:${options:-$esp32s3_opts}" + [ -n "${options:-$esp32s3_opts}" ] && opt=":${options:-$esp32s3_opts}" + fqbn="espressif:esp32:esp32s3$opt" ;; "esp32c6") - fqbn="espressif:esp32:esp32c6:${options:-$esp32c6_opts}" + [ -n "${options:-$esp32c6_opts}" ] && opt=":${options:-$esp32c6_opts}" + fqbn="espressif:esp32:esp32c6$opt" ;; "esp32h2") - fqbn="espressif:esp32:esp32h2:${options:-$esp32h2_opts}" + [ -n "${options:-$esp32h2_opts}" ] && opt=":${options:-$esp32h2_opts}" + fqbn="espressif:esp32:esp32h2$opt" + ;; + "esp32p4") + [ -n "${options:-$esp32p4_opts}" ] && opt=":${options:-$esp32p4_opts}" + fqbn="espressif:esp32:esp32p4$opt" + ;; + *) + echo "ERROR: Invalid chip: $target" + exit 1 ;; esac @@ -130,7 +213,7 @@ function build_sketch(){ # build_sketch [ex exit 1 fi - # The directory that will hold all the artifcats (the build directory) is + # The directory that will hold all the artifacts (the build directory) is # provided through: # 1. An env variable called ARDUINO_BUILD_DIR. # 2. Created at the sketch level as "build" in the case of a single @@ -138,77 +221,79 @@ function build_sketch(){ # build_sketch [ex # 3. Created at the sketch level as "buildX" where X is the number # of configuration built in case of a multiconfiguration test. - sketchname=$(basename $sketchdir) + sketchname=$(basename "$sketchdir") + local has_requirements - # If the target is listed as false, skip the sketch. Otherwise, include it. - if [ -f $sketchdir/ci.json ]; then - is_target=$(jq -r --arg target $target '.targets[$target]' $sketchdir/ci.json) - else - is_target="true" - fi + if [ -f "$sketchdir"/ci.json ]; then + # If the target is listed as false, skip the sketch. Otherwise, include it. + is_target=$(jq -r --arg target "$target" '.targets[$target]' "$sketchdir"/ci.json) + if [[ "$is_target" == "false" ]]; then + echo "Skipping $sketchname for target $target" + exit 0 + fi - if [[ "$is_target" == "false" ]]; then - echo "Skipping $sketchname for target $target" - exit 0 + has_requirements=$(check_requirements "$sketchdir" "$SDKCONFIG_DIR/$target/sdkconfig") + if [ "$has_requirements" == "0" ]; then + echo "Target $target does not meet the requirements for $sketchname. Skipping." + exit 0 + fi fi ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp" if [ -n "$ARDUINO_BUILD_DIR" ]; then build_dir="$ARDUINO_BUILD_DIR" - elif [ $len -eq 1 ]; then + elif [ "$len" -eq 1 ]; then # build_dir="$sketchdir/build" - build_dir="$HOME/.arduino/tests/$sketchname/build.tmp" + build_dir="$HOME/.arduino/tests/$target/$sketchname/build.tmp" fi output_file="$HOME/.arduino/cli_compile_output.txt" sizes_file="$GITHUB_WORKSPACE/cli_compile_$chunk_index.json" mkdir -p "$ARDUINO_CACHE_DIR" - for i in `seq 0 $(($len - 1))` - do - if [ $len -ne 1 ]; then - # build_dir="$sketchdir/build$i" - build_dir="$HOME/.arduino/tests/$sketchname/build$i.tmp" + for i in $(seq 0 $((len - 1))); do + if [ "$len" -ne 1 ]; then + # build_dir="$sketchdir/build$i" + build_dir="$HOME/.arduino/tests/$target/$sketchname/build$i.tmp" fi - rm -rf $build_dir - mkdir -p $build_dir + rm -rf "$build_dir" + mkdir -p "$build_dir" - currfqbn=`echo $fqbn | jq -r --argjson i $i '.[$i]'` + currfqbn=$(echo "$fqbn" | jq -r --argjson i "$i" '.[$i]') if [ -f "$ide_path/arduino-cli" ]; then echo "Building $sketchname with arduino-cli and FQBN=$currfqbn" - curroptions=`echo "$currfqbn" | cut -d':' -f4` - currfqbn=`echo "$currfqbn" | cut -d':' -f1-3` - $ide_path/arduino-cli compile \ + curroptions=$(echo "$currfqbn" | cut -d':' -f4) + currfqbn=$(echo "$currfqbn" | cut -d':' -f1-3) + "$ide_path"/arduino-cli compile \ --fqbn "$currfqbn" \ --board-options "$curroptions" \ --warnings "all" \ --build-property "compiler.warning_flags.all=-Wall -Werror=all -Wextra" \ - --build-cache-path "$ARDUINO_CACHE_DIR" \ --build-path "$build_dir" \ - $xtra_opts "${sketchdir}" \ - > $output_file + "${xtra_opts[@]}" "${sketchdir}" \ + 2>&1 | tee "$output_file" - exit_status=$? - if [ $exit_status -ne 0 ]; then + exit_status=${PIPESTATUS[0]} + if [ "$exit_status" -ne 0 ]; then echo "ERROR: Compilation failed with error code $exit_status" - exit $exit_status + exit "$exit_status" fi - if [ $log_compilation ]; then + if [ -n "$log_compilation" ]; then #Extract the program storage space and dynamic memory usage in bytes and percentage in separate variables from the output, just the value without the string - flash_bytes=$(grep -oE 'Sketch uses ([0-9]+) bytes' $output_file | awk '{print $3}') - flash_percentage=$(grep -oE 'Sketch uses ([0-9]+) bytes \(([0-9]+)%\)' $output_file | awk '{print $5}' | tr -d '(%)') - ram_bytes=$(grep -oE 'Global variables use ([0-9]+) bytes' $output_file | awk '{print $4}') - ram_percentage=$(grep -oE 'Global variables use ([0-9]+) bytes \(([0-9]+)%\)' $output_file | awk '{print $6}' | tr -d '(%)') + flash_bytes=$(grep -oE 'Sketch uses ([0-9]+) bytes' "$output_file" | awk '{print $3}') + flash_percentage=$(grep -oE 'Sketch uses ([0-9]+) bytes \(([0-9]+)%\)' "$output_file" | awk '{print $5}' | tr -d '(%)') + ram_bytes=$(grep -oE 'Global variables use ([0-9]+) bytes' "$output_file" | awk '{print $4}') + ram_percentage=$(grep -oE 'Global variables use ([0-9]+) bytes \(([0-9]+)%\)' "$output_file" | awk '{print $6}' | tr -d '(%)') # Extract the directory path excluding the filename directory_path=$(dirname "$sketch") # Define the constant part constant_part="/home/runner/Arduino/hardware/espressif/esp32/libraries/" - # Extract the desired substring using sed - lib_sketch_name=$(echo "$directory_path" | sed "s|$constant_part||") + # Extract the desired substring + lib_sketch_name="${directory_path#"$constant_part"}" #append json file where key is fqbn, sketch name, sizes -> extracted values echo "{\"name\": \"$lib_sketch_name\", \"sizes\": [{ @@ -224,15 +309,15 @@ function build_sketch(){ # build_sketch [ex echo "Building $sketchname with arduino-builder and FQBN=$currfqbn" echo "Build path = $build_dir" - $ide_path/arduino-builder -compile -logger=human -core-api-version=10810 \ - -fqbn=\"$currfqbn\" \ + "$ide_path"/arduino-builder -compile -logger=human -core-api-version=10810 \ + -fqbn=\""$currfqbn"\" \ -warnings="all" \ -tools "$ide_path/tools-builder" \ -hardware "$user_path/hardware" \ -libraries "$user_path/libraries" \ -build-cache "$ARDUINO_CACHE_DIR" \ -build-path "$build_dir" \ - $xtra_opts "${sketchdir}/${sketchname}.ino" + "${xtra_opts[@]}" "${sketchdir}/${sketchname}.ino" exit_status=$? if [ $exit_status -ne 0 ]; then @@ -259,14 +344,16 @@ function build_sketch(){ # build_sketch [ex unset options } -function count_sketches(){ # count_sketches [target] [file] +function count_sketches { # count_sketches [target] [file] [ignore-requirements] local path=$1 local target=$2 - local file=$3 + local ignore_requirements=$3 + local file=$4 + local sketches if [ $# -lt 1 ]; then - echo "ERROR: Illegal number of parameters" - echo "USAGE: ${0} count [target]" + echo "ERROR: Illegal number of parameters" + echo "USAGE: ${0} count [target]" fi rm -rf sketches.txt @@ -275,40 +362,48 @@ function count_sketches(){ # count_sketches [target] [file] return 0 fi - if [ -n "$file" ]; then - local sketches=$(cat $file) + if [ -f "$file" ]; then + sketches=$(cat "$file") else - local sketches=$(find $path -name *.ino | sort) + sketches=$(find "$path" -name '*.ino' | sort) fi local sketchnum=0 for sketch in $sketches; do - local sketchdir=$(dirname $sketch) - local sketchdirname=$(basename $sketchdir) - local sketchname=$(basename $sketch) + local sketchdir + local sketchdirname + local sketchname + local has_requirements + + sketchdir=$(dirname "$sketch") + sketchdirname=$(basename "$sketchdir") + sketchname=$(basename "$sketch") + if [[ "$sketchdirname.ino" != "$sketchname" ]]; then continue - elif [[ -n $target ]]; then + elif [[ -n $target ]] && [[ -f $sketchdir/ci.json ]]; then # If the target is listed as false, skip the sketch. Otherwise, include it. - if [ -f $sketchdir/ci.json ]; then - is_target=$(jq -r --arg target $target '.targets[$target]' $sketchdir/ci.json) - else - is_target="true" - fi + is_target=$(jq -r --arg target "$target" '.targets[$target]' "$sketchdir"/ci.json) if [[ "$is_target" == "false" ]]; then continue fi + + if [ "$ignore_requirements" != "1" ]; then + has_requirements=$(check_requirements "$sketchdir" "$SDKCONFIG_DIR/$target/sdkconfig") + if [ "$has_requirements" == "0" ]; then + continue + fi + fi fi - echo $sketch >> sketches.txt - sketchnum=$(($sketchnum + 1)) + echo "$sketch" >> sketches.txt + sketchnum=$((sketchnum + 1)) done return $sketchnum } -function build_sketches(){ # build_sketches [extra-options] - - local args="" - while [ ! -z "$1" ]; do +function build_sketches { # build_sketches [extra-options] + local args=() + while [ -n "$1" ]; do case $1 in -ai ) shift @@ -321,12 +416,12 @@ function build_sketches(){ # build_sketches > "$sizes_file" fi local sketchnum=0 - args+=" -ai $ide_path -au $user_path -i $chunk_index" - if [ $log_compilation ]; then - args+=" -l $log_compilation" + args+=("-ai" "$ide_path" "-au" "$user_path" "-i" "$chunk_index") + if [ -n "$log_compilation" ]; then + args+=("-l" "$log_compilation") fi for sketch in $sketches; do - local sketchdir=$(dirname $sketch) - local sketchdirname=$(basename $sketchdir) - sketchnum=$(($sketchnum + 1)) + local sketchdir + local sketchdirname + + sketchdir=$(dirname "$sketch") + sketchdirname=$(basename "$sketchdir") + sketchnum=$((sketchnum + 1)) + if [ "$sketchnum" -le "$start_index" ] \ || [ "$sketchnum" -gt "$end_index" ]; then continue fi echo "" echo "Building Sketch Index $sketchnum - $sketchdirname" - build_sketch $args -s $sketchdir $xtra_opts + build_sketch "${args[@]}" -s "$sketchdir" "${xtra_opts[@]}" local result=$? if [ $result -ne 0 ]; then return $result fi done - if [ $log_compilation ]; then + if [ -n "$log_compilation" ]; then #remove last comma from json - if [ $i -eq $(($len - 1)) ]; then + if [ "$i" -eq $((len - 1)) ]; then sed -i '$ s/.$//' "$sizes_file" fi #echo end of sketches sizes_file json @@ -463,25 +578,28 @@ function build_sketches(){ # build_sketches info/wokwi_types.txt +echo "[$targets]" > info/targets.txt + +{ + echo "build-types=[$build_types]" + echo "hw-types=[$hw_types]" + echo "wokwi-types=[$wokwi_types]" + echo "qemu-types=[$qemu_types]" + echo "targets=[$targets]" +} >> "$GITHUB_OUTPUT" diff --git a/.github/scripts/tests_run.sh b/.github/scripts/tests_run.sh index d5c6f1f35c3..1c4bee79742 100755 --- a/.github/scripts/tests_run.sh +++ b/.github/scripts/tests_run.sh @@ -1,103 +1,132 @@ #!/bin/bash -function run_test() { +function run_test { local target=$1 local sketch=$2 local options=$3 local erase_flash=$4 - local sketchdir=$(dirname $sketch) - local sketchname=$(basename $sketchdir) + local sketchdir + local sketchname local result=0 local error=0 + local sdkconfig_path + local extra_args + local test_type - # If the target or platform is listed as false, skip the sketch. Otherwise, include it. - if [ -f $sketchdir/ci.json ]; then - is_target=$(jq -r --arg target $target '.targets[$target]' $sketchdir/ci.json) - selected_platform=$(jq -r --arg platform $platform '.platforms[$platform]' $sketchdir/ci.json) + sketchdir=$(dirname "$sketch") + sketchname=$(basename "$sketchdir") + test_type=$(basename "$(dirname "$sketchdir")") + + if [ "$options" -eq 0 ] && [ -f "$sketchdir"/ci.json ]; then + len=$(jq -r --arg target "$target" '.fqbn[$target] | length' "$sketchdir"/ci.json) + if [ "$len" -eq 0 ]; then + len=1 + fi else - is_target="true" - selected_platform="true" + len=1 fi - if [[ $is_target == "false" ]] || [[ $selected_platform == "false" ]]; then - printf "\033[93mSkipping $sketchname test for $target, platform: $platform\033[0m\n" - printf "\n\n\n" - return 0 + if [ "$len" -eq 1 ]; then + sdkconfig_path="$HOME/.arduino/tests/$target/$sketchname/build.tmp/sdkconfig" + else + sdkconfig_path="$HOME/.arduino/tests/$target/$sketchname/build0.tmp/sdkconfig" fi - if [ $options -eq 0 ] && [ -f $sketchdir/ci.json ]; then - len=`jq -r --arg target $target '.fqbn[$target] | length' $sketchdir/ci.json` - if [ $len -eq 0 ]; then - len=1 + if [ -f "$sketchdir"/ci.json ]; then + # If the target or platform is listed as false, skip the sketch. Otherwise, include it. + is_target=$(jq -r --arg target "$target" '.targets[$target]' "$sketchdir"/ci.json) + selected_platform=$(jq -r --arg platform "$platform" '.platforms[$platform]' "$sketchdir"/ci.json) + + if [[ $is_target == "false" ]] || [[ $selected_platform == "false" ]]; then + printf "\033[93mSkipping %s test for %s, platform: %s\033[0m\n" "$sketchname" "$target" "$platform" + printf "\n\n\n" + return 0 fi - else - len=1 fi - if [ $len -eq 1 ]; then - # build_dir="$sketchdir/build" - build_dir="$HOME/.arduino/tests/$sketchname/build.tmp" - report_file="$sketchdir/$target/$sketchname.xml" + if [ ! -f "$sdkconfig_path" ]; then + printf "\033[93mSketch %s build not found in %s\nMight be due to missing target requirements or build failure\033[0m\n" "$(dirname "$sdkconfig_path")" "$sketchname" + printf "\n\n\n" + return 0 + fi + + local compiled_target + compiled_target=$(grep -E "CONFIG_IDF_TARGET=" "$sdkconfig_path" | cut -d'"' -f2) + if [ "$compiled_target" != "$target" ]; then + printf "\033[91mError: Sketch %s compiled for %s, expected %s\033[0m\n" "$sketchname" "$compiled_target" "$target" + printf "\n\n\n" + return 1 fi - for i in `seq 0 $(($len - 1))` - do + if [ "$len" -eq 1 ]; then + # build_dir="$sketchdir/build" + build_dir="$HOME/.arduino/tests/$target/$sketchname/build.tmp" + report_file="$sketchdir/$target/$sketchname.xml" + fi + + for i in $(seq 0 $((len - 1))); do fqbn="Default" - if [ $len -ne 1 ]; then - fqbn=`jq -r --arg target $target --argjson i $i '.fqbn[$target] | sort | .[$i]' $sketchdir/ci.json` - elif [ -f $sketchdir/ci.json ]; then - has_fqbn=`jq -r --arg target $target '.fqbn[$target]' $sketchdir/ci.json` + if [ "$len" -ne 1 ]; then + fqbn=$(jq -r --arg target "$target" --argjson i "$i" '.fqbn[$target] | sort | .[$i]' "$sketchdir"/ci.json) + elif [ -f "$sketchdir"/ci.json ]; then + has_fqbn=$(jq -r --arg target "$target" '.fqbn[$target]' "$sketchdir"/ci.json) if [ "$has_fqbn" != "null" ]; then - fqbn=`jq -r --arg target $target '.fqbn[$target] | .[0]' $sketchdir/ci.json` + fqbn=$(jq -r --arg target "$target" '.fqbn[$target] | .[0]' "$sketchdir"/ci.json) fi fi - printf "\033[95mRunning test: $sketchname -- Config: $fqbn\033[0m\n" - if [ $erase_flash -eq 1 ]; then - esptool.py -c $target erase_flash + printf "\033[95mRunning test: %s -- Config: %s\033[0m\n" "$sketchname" "$fqbn" + if [ "$erase_flash" -eq 1 ]; then + esptool.py -c "$target" erase_flash fi - if [ $len -ne 1 ]; then + if [ "$len" -ne 1 ]; then # build_dir="$sketchdir/build$i" - build_dir="$HOME/.arduino/tests/$sketchname/build$i.tmp" + build_dir="$HOME/.arduino/tests/$target/$sketchname/build$i.tmp" report_file="$sketchdir/$target/$sketchname$i.xml" fi if [ $platform == "wokwi" ]; then - extra_args="--target $target --embedded-services arduino,wokwi --wokwi-timeout=$wokwi_timeout" + extra_args=("--target" "$target" "--embedded-services" "arduino,wokwi" "--wokwi-timeout=$wokwi_timeout") if [[ -f "$sketchdir/scenario.yaml" ]]; then - extra_args+=" --wokwi-scenario $sketchdir/scenario.yaml" + extra_args+=("--wokwi-scenario" "$sketchdir/scenario.yaml") + fi + if [[ -f "$sketchdir/diagram.$target.json" ]]; then + extra_args+=("--wokwi-diagram" "$sketchdir/diagram.$target.json") fi + elif [ $platform == "qemu" ]; then PATH=$HOME/qemu/bin:$PATH - extra_args="--embedded-services qemu --qemu-image-path $build_dir/$sketchname.ino.merged.bin" + extra_args=("--embedded-services" "qemu" "--qemu-image-path" "$build_dir/$sketchname.ino.merged.bin") - if [ $target == "esp32" ] || [ $target == "esp32s3" ]; then - extra_args+=" --qemu-prog-path qemu-system-xtensa --qemu-cli-args=\"-machine $target -m 4M -nographic\"" - elif [ $target == "esp32c3" ]; then - extra_args+=" --qemu-prog-path qemu-system-riscv32 --qemu-cli-args=\"-machine $target -icount 3 -nographic\"" + if [ "$target" == "esp32" ] || [ "$target" == "esp32s3" ]; then + extra_args+=("--qemu-prog-path" "qemu-system-xtensa" "--qemu-cli-args=\"-machine $target -m 4M -nographic\"") + elif [ "$target" == "esp32c3" ]; then + extra_args+=("--qemu-prog-path" "qemu-system-riscv32" "--qemu-cli-args=\"-machine $target -icount 3 -nographic\"") else - printf "\033[91mUnsupported QEMU target: $target\033[0m\n" + printf "\033[91mUnsupported QEMU target: %s\033[0m\n" "$target" exit 1 fi else - extra_args="--embedded-services esp,arduino" + extra_args=("--embedded-services" "esp,arduino") fi + rm "$sketchdir"/diagram.json 2>/dev/null || true + result=0 - printf "\033[95mpytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args\033[0m\n" - bash -c "set +e; pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args; exit \$?" || result=$? + printf "\033[95mpytest \"%s/test_%s.py\" --build-dir \"%s\" --junit-xml=\"%s\" -o junit_suite_name=%s_%s_%s_%s%s %s\033[0m\n" "$sketchdir" "$sketchname" "$build_dir" "$report_file" "$test_type" "$platform" "$target" "$sketchname" "$i" "${extra_args[*]@Q}" + bash -c "set +e; pytest \"$sketchdir/test_$sketchname.py\" --build-dir \"$build_dir\" --junit-xml=\"$report_file\" -o junit_suite_name=${test_type}_${platform}_${target}_${sketchname}${i} ${extra_args[*]@Q}; exit \$?" || result=$? printf "\n" if [ $result -ne 0 ]; then result=0 - printf "\033[95mRetrying test: $sketchname -- Config: $i\033[0m\n" - printf "\033[95mpytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args\033[0m\n" - bash -c "set +e; pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args; exit \$?" || result=$? + printf "\033[95mRetrying test: %s -- Config: %s\033[0m\n" "$sketchname" "$i" + printf "\033[95mpytest \"%s/test_%s.py\" --build-dir \"%s\" --junit-xml=\"%s\" -o junit_suite_name=%s_%s_%s_%s%s %s\033[0m\n" "$sketchdir" "$sketchname" "$build_dir" "$report_file" "$test_type" "$platform" "$target" "$sketchname" "$i" "${extra_args[*]@Q}" + bash -c "set +e; pytest \"$sketchdir/test_$sketchname.py\" --build-dir \"$build_dir\" --junit-xml=\"$report_file\" -o junit_suite_name=${test_type}_${platform}_${target}_${sketchname}${i} ${extra_args[*]@Q}; exit \$?" || result=$? printf "\n" if [ $result -ne 0 ]; then - printf "\033[91mFailed test: $sketchname -- Config: $i\033[0m\n\n" - error=$result + printf "\033[91mFailed test: %s -- Config: %s\033[0m\n\n" "$sketchname" "$i" + error=$result fi fi done @@ -113,13 +142,13 @@ chunk_run=0 options=0 erase=0 -while [ ! -z "$1" ]; do +while [ -n "$1" ]; do case $1 in -c ) chunk_run=1 ;; -Q ) - if [ ! -d $QEMU_PATH ]; then + if [ ! -d "$QEMU_PATH" ]; then echo "QEMU path $QEMU_PATH does not exist" exit 1 fi @@ -128,6 +157,10 @@ while [ ! -z "$1" ]; do -W ) shift wokwi_timeout=$1 + if [[ -z $WOKWI_CLI_TOKEN ]]; then + echo "Wokwi CLI token is not set" + exit 1 + fi platform="wokwi" ;; -o ) @@ -161,97 +194,97 @@ while [ ! -z "$1" ]; do test_type=$1 ;; * ) - break - ;; + break + ;; esac shift done if [ ! $platform == "qemu" ]; then - source ${SCRIPTS_DIR}/install-arduino-ide.sh + source "${SCRIPTS_DIR}/install-arduino-ide.sh" fi # If sketch is provided and test type is not, test type is inferred from the sketch path if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then if [ -n "$sketch" ]; then - tmp_sketch_path=$(find tests -name $sketch.ino) - test_type=$(basename $(dirname $(dirname "$tmp_sketch_path"))) + tmp_sketch_path=$(find tests -name "$sketch".ino) + test_type=$(basename "$(dirname "$(dirname "$tmp_sketch_path")")") echo "Sketch $sketch test type: $test_type" test_folder="$PWD/tests/$test_type" else - test_folder="$PWD/tests" + test_folder="$PWD/tests" fi else test_folder="$PWD/tests/$test_type" fi if [ $chunk_run -eq 0 ]; then - if [ -z $sketch ]; then + if [ -z "$sketch" ]; then echo "ERROR: Sketch name is required for single test run" exit 1 fi - run_test $target $test_folder/$sketch/$sketch.ino $options $erase + run_test "$target" "$test_folder"/"$sketch"/"$sketch".ino $options $erase exit $? else - if [ "$chunk_max" -le 0 ]; then - echo "ERROR: Chunks count must be positive number" - exit 1 - fi - - if [ "$chunk_index" -ge "$chunk_max" ] && [ "$chunk_max" -ge 2 ]; then - echo "ERROR: Chunk index must be less than chunks count" - exit 1 - fi - - set +e - ${COUNT_SKETCHES} $test_folder $target - sketchcount=$? - set -e - sketches=$(cat sketches.txt) - rm -rf sketches.txt - - chunk_size=$(( $sketchcount / $chunk_max )) - all_chunks=$(( $chunk_max * $chunk_size )) - if [ "$all_chunks" -lt "$sketchcount" ]; then - chunk_size=$(( $chunk_size + 1 )) - fi - - start_index=0 - end_index=0 - if [ "$chunk_index" -ge "$chunk_max" ]; then - start_index=$chunk_index - end_index=$sketchcount - else - start_index=$(( $chunk_index * $chunk_size )) - if [ "$sketchcount" -le "$start_index" ]; then - exit 0 - fi - - end_index=$(( $(( $chunk_index + 1 )) * $chunk_size )) - if [ "$end_index" -gt "$sketchcount" ]; then - end_index=$sketchcount - fi - fi - - start_num=$(( $start_index + 1 )) - sketchnum=0 - error=0 - - for sketch in $sketches; do - - sketchnum=$(($sketchnum + 1)) - if [ "$sketchnum" -le "$start_index" ] \ - || [ "$sketchnum" -gt "$end_index" ]; then - continue - fi - - printf "\033[95mSketch Index $(($sketchnum - 1))\033[0m\n" - - exit_code=0 - run_test $target $sketch $options $erase || exit_code=$? - if [ $exit_code -ne 0 ]; then - error=$exit_code - fi - done - exit $error + if [ "$chunk_max" -le 0 ]; then + echo "ERROR: Chunks count must be positive number" + exit 1 + fi + + if [ "$chunk_index" -ge "$chunk_max" ] && [ "$chunk_max" -ge 2 ]; then + echo "ERROR: Chunk index must be less than chunks count" + exit 1 + fi + + set +e + # Ignore requirements as we don't have the libs. The requirements will be checked in the run_test function + ${COUNT_SKETCHES} "$test_folder" "$target" "1" + sketchcount=$? + set -e + sketches=$(cat sketches.txt) + rm -rf sketches.txt + + chunk_size=$(( sketchcount / chunk_max )) + all_chunks=$(( chunk_max * chunk_size )) + if [ "$all_chunks" -lt "$sketchcount" ]; then + chunk_size=$(( chunk_size + 1 )) + fi + + start_index=0 + end_index=0 + if [ "$chunk_index" -ge "$chunk_max" ]; then + start_index=$chunk_index + end_index=$sketchcount + else + start_index=$(( chunk_index * chunk_size )) + if [ "$sketchcount" -le "$start_index" ]; then + exit 0 + fi + + end_index=$(( $(( chunk_index + 1 )) * chunk_size )) + if [ "$end_index" -gt "$sketchcount" ]; then + end_index=$sketchcount + fi + fi + + sketchnum=0 + error=0 + + for sketch in $sketches; do + + sketchnum=$((sketchnum + 1)) + if [ "$sketchnum" -le "$start_index" ] \ + || [ "$sketchnum" -gt "$end_index" ]; then + continue + fi + + printf "\033[95mSketch Index %s\033[0m\n" "$((sketchnum - 1))" + + exit_code=0 + run_test "$target" "$sketch" $options $erase || exit_code=$? + if [ $exit_code -ne 0 ]; then + error=$exit_code + fi + done + exit $error fi diff --git a/.github/scripts/update-version.sh b/.github/scripts/update-version.sh index 150d8594812..9a38b27a57a 100755 --- a/.github/scripts/update-version.sh +++ b/.github/scripts/update-version.sh @@ -1,20 +1,21 @@ #!/bin/bash +# shellcheck disable=SC2002 # For reference: add tools for all boards by replacing one line in each board # "[board].upload.tool=esptool_py" to "[board].upload.tool=esptool_py\n[board].upload.tool.default=esptool_py\n[board].upload.tool.network=esp_ota" #cat boards.txt | sed "s/\([a-zA-Z0-9_\-]*\)\.upload\.tool\=esptool_py/\1\.upload\.tool\=esptool_py\\n\1\.upload\.tool\.default\=esptool_py\\n\1\.upload\.tool\.network\=esp_ota/" if [ ! $# -eq 3 ]; then - echo "Bad number of arguments: $#" >&2 - echo "usage: $0 " >&2 - exit 1 + echo "Bad number of arguments: $#" >&2 + echo "usage: $0 " >&2 + exit 1 fi re='^[0-9]+$' if [[ ! $1 =~ $re ]] || [[ ! $2 =~ $re ]] || [[ ! $3 =~ $re ]] ; then - echo "error: Not a valid version: $1.$2.$3" >&2 - echo "usage: $0 " >&2 - exit 1 + echo "error: Not a valid version: $1.$2.$3" >&2 + echo "usage: $0 " >&2 + exit 1 fi ESP_ARDUINO_VERSION_MAJOR="$1" @@ -36,4 +37,12 @@ sed "s/#define ESP_ARDUINO_VERSION_MAJOR.*/#define ESP_ARDUINO_VERSION_MAJOR $ES sed "s/#define ESP_ARDUINO_VERSION_MINOR.*/#define ESP_ARDUINO_VERSION_MINOR $ESP_ARDUINO_VERSION_MINOR/g" | \ sed "s/#define ESP_ARDUINO_VERSION_PATCH.*/#define ESP_ARDUINO_VERSION_PATCH $ESP_ARDUINO_VERSION_PATCH/g" > __esp_arduino_version.h && mv __esp_arduino_version.h cores/esp32/esp_arduino_version.h +libraries=$(find libraries -maxdepth 1 -mindepth 1 -type d -exec basename {} \;) +for lib in $libraries; do + if [ -f "libraries/$lib/library.properties" ]; then + echo "Updating Library $lib..." + cat "libraries/$lib/library.properties" | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > "libraries/$lib/__library.properties" && mv "libraries/$lib/__library.properties" "libraries/$lib/library.properties" + fi +done + exit 0 diff --git a/.github/scripts/upload_py_tools.sh b/.github/scripts/upload_py_tools.sh index 0544bccd710..abe18a50c6e 100755 --- a/.github/scripts/upload_py_tools.sh +++ b/.github/scripts/upload_py_tools.sh @@ -1,11 +1,12 @@ #!/bin/bash + CHANGED_FILES=$1 echo "Pushing '$CHANGED_FILES' as github-actions[bot]" git config --global github.user "github-actions[bot]" git config --global user.name "github-actions[bot]" git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" for tool in $CHANGED_FILES; do - git add tools/$tool.exe + git add tools/"$tool".exe done git commit -m "change(tools): Push generated binaries to PR" git push diff --git a/.github/workflows/allboards.yml b/.github/workflows/allboards.yml index 4a2d4349ac3..6910ad05d3f 100644 --- a/.github/workflows/allboards.yml +++ b/.github/workflows/allboards.yml @@ -1,6 +1,6 @@ name: Boards Test - Remote trigger -# The workflow will run on remote dispath with event-type set to "test-boards" +# The workflow will run on remote dispatch with event-type set to "test-boards" on: repository_dispatch: types: [test-boards] @@ -15,13 +15,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.client_payload.branch }} - name: Get boards fqbns - run: - bash .github/scripts/find_all_boards.sh + run: bash .github/scripts/find_all_boards.sh setup-chunks: needs: find-boards @@ -33,18 +32,17 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.client_payload.branch }} - run: npm install - name: Setup jq - uses: dcarbone/install-jq-action@v1.0.1 + uses: dcarbone/install-jq-action@e397bd87438d72198f81efd21f876461183d383a # v3.0.1 - id: set-test-chunks name: Set Chunks - run: - echo "test-chunks<> $GITHUB_OUTPUT + run: echo "test-chunks<> $GITHUB_OUTPUT echo "$( jq -nc '${{ needs.find-boards.outputs.fqbns }} | [_nwise( ${{ needs.find-boards.outputs.board-count }}/15 | ceil)]')" >> $GITHUB_OUTPUT @@ -61,23 +59,22 @@ jobs: strategy: fail-fast: false - matrix: + matrix: chunk: ${{ fromJSON(needs.setup-chunks.outputs['test-chunks']) }} steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.client_payload.branch }} - name: Echo FQBNS to file - run: - echo "$FQBN" > fqbns.json - env: + run: echo "$FQBN" > fqbns.json + env: FQBN: ${{ toJSON(matrix.chunk) }} - name: Compile sketch - uses: P-R-O-C-H-Y/compile-sketches@main + uses: P-R-O-C-H-Y/compile-sketches@a62f069b92dc8f5053da4ac439ea6d1950cf6379 # main with: platforms: | ${{ env.REPOSITORY }} @@ -88,5 +85,4 @@ jobs: enable-warnings-report: false cli-compile-flags: | - --warnings="all" - sketch-paths: - "- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino" + sketch-paths: "- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino" diff --git a/.github/workflows/boards.yml b/.github/workflows/boards.yml index 30175c3e8d2..287e97219c4 100644 --- a/.github/workflows/boards.yml +++ b/.github/workflows/boards.yml @@ -4,9 +4,9 @@ name: Boards Test on: pull_request: paths: - - 'boards.txt' - - 'libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino' - - '.github/workflows/boards.yml' + - "boards.txt" + - "libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino" + - ".github/workflows/boards.yml" env: # It's convenient to set variables for values used multiple times in the workflow @@ -22,14 +22,13 @@ jobs: steps: # This step makes the contents of the repository available to the workflow - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup jq - uses: dcarbone/install-jq-action@v1.0.1 + uses: dcarbone/install-jq-action@e397bd87438d72198f81efd21f876461183d383a # v3.0.1 - name: Get board name - run: - bash .github/scripts/find_new_boards.sh ${{ github.repository }} ${{github.event.number}} + run: bash .github/scripts/find_new_boards.sh ${{ github.repository }} ${{github.base_ref}} test-boards: needs: find-boards @@ -42,12 +41,13 @@ jobs: name: "espressif:esp32" strategy: + fail-fast: false matrix: ${{ fromJson(needs.find-boards.outputs.fqbns) }} steps: # This step makes the contents of the repository available to the workflow - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Check if build.board is uppercase run: | @@ -59,8 +59,21 @@ jobs: exit 1; fi + - name: Get libs cache + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }} + path: | + ./tools/dist + ./tools/esp32-arduino-libs + ./tools/esptool + ./tools/mk* + ./tools/openocd-esp32 + ./tools/riscv32-* + ./tools/xtensa-* + - name: Compile sketch - uses: P-R-O-C-H-Y/compile-sketches@main + uses: P-R-O-C-H-Y/compile-sketches@a62f069b92dc8f5053da4ac439ea6d1950cf6379 # main with: platforms: | ${{ env.REPOSITORY }} @@ -71,5 +84,5 @@ jobs: cli-compile-flags: | - --warnings="all" exit-on-fail: true - sketch-paths: - "- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino" + sketch-paths: "- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino" + verbose: true diff --git a/.github/workflows/build_py_tools.yml b/.github/workflows/build_py_tools.yml index d08f1781311..bbb36589c84 100644 --- a/.github/workflows/build_py_tools.yml +++ b/.github/workflows/build_py_tools.yml @@ -3,35 +3,44 @@ name: Build Python Tools on: pull_request: paths: - - 'tools/get.py' - - 'tools/espota.py' - - 'tools/gen_esp32part.py' - - 'tools/gen_insights_package.py' + - ".github/workflows/build_py_tools.yml" + - "tools/get.py" + - "tools/espota.py" + - "tools/gen_esp32part.py" + - "tools/gen_insights_package.py" jobs: find-changed-tools: name: Check if tools have been changed - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest outputs: any_changed: ${{ steps.verify-changed-files.outputs.any_changed }} all_changed_files: ${{ steps.verify-changed-files.outputs.all_changed_files }} steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 ref: ${{ github.event.pull_request.head.ref }} + + - name: Check if checkout failed + if: failure() + run: | + echo "Checkout failed." + echo "Make sure you are using a branch inside the repository and not a fork." + - name: Verify Python Tools Changed - uses: tj-actions/changed-files@v41 + uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1 id: verify-changed-files with: - fetch_depth: '2' - since_last_remote_commit: 'true' + fetch_depth: "2" + since_last_remote_commit: "true" files: | tools/get.py tools/espota.py tools/gen_esp32part.py tools/gen_insights_package.py + - name: List all changed files shell: bash run: | @@ -47,27 +56,21 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-latest, macos-latest, ubuntu-20.04, ARM, ARM64] + os: [windows-latest, macos-latest, ubuntu-latest, ubuntu-24.04-arm] include: - - os: windows-latest - TARGET: win64 - EXTEN: .exe - SEPARATOR: ';' - - os: macos-latest - TARGET: macos - SEPARATOR: ':' - - os: ubuntu-20.04 - TARGET: linux-amd64 - SEPARATOR: ':' - - os: ARM - CONTAINER: python:3.8-bullseye - TARGET: arm - SEPARATOR: ':' - - os: ARM64 - CONTAINER: python:3.8-bullseye - TARGET: arm64 - SEPARATOR: ':' - container: ${{ matrix.CONTAINER }} # use python container on ARM + - os: windows-latest + TARGET: win64 + EXTEN: .exe + SEPARATOR: ";" + - os: macos-latest + TARGET: macos + SEPARATOR: ":" + - os: ubuntu-latest + TARGET: linux-amd64 + SEPARATOR: ":" + - os: ubuntu-24.04-arm + TARGET: arm + SEPARATOR: ":" env: DISTPATH: pytools-${{ matrix.TARGET }} PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi" @@ -86,29 +89,32 @@ jobs: for tool in ${{ env.CHANGED_TOOLS }}; do echo "tool $tool was changed" done + - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: token: ${{ secrets.TOOLS_UPLOAD_PAT }} ref: ${{ github.event.pull_request.head.ref }} + - name: Set up Python 3.8 - # Skip setting python on ARM because of missing compatibility: https://github.com/actions/setup-python/issues/108 - if: matrix.os != 'ARM' && matrix.os != 'ARM64' - uses: actions/setup-python@master + uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 with: python-version: 3.8 + - name: Install dependencies run: | python -m pip install --upgrade pip pip install pyinstaller requests + - name: Build with PyInstaller shell: bash run: | for tool in ${{ env.CHANGED_TOOLS }}; do pyinstaller --distpath ./${{ env.DISTPATH }} -F --icon=.github/pytools/espressif.ico tools/$tool.py done + - name: Sign binaries - if: matrix.os == 'windows-latest' && env.CERTIFICATE != '' && env.CERTIFICATE_PASSWORD != '' + if: matrix.os == 'windows-latest' env: CERTIFICATE: ${{ secrets.CERTIFICATE }} CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }} @@ -119,12 +125,14 @@ jobs: { ./.github/pytools/Sign-File.ps1 -Path ./${{ env.DISTPATH }}/$node.exe } + - name: Test binaries shell: bash run: | for tool in ${{ env.CHANGED_TOOLS }}; do ./${{ env.DISTPATH }}/$tool${{ matrix.EXTEN }} -h done + - name: Push binary to tools if: matrix.os == 'windows-latest' env: @@ -135,8 +143,9 @@ jobs: cp -f ./${{ env.DISTPATH }}/$tool.exe tools/$tool.exe done bash .github/scripts/upload_py_tools.sh "${{ env.CHANGED_TOOLS }}" + - name: Archive artifact - uses: actions/upload-artifact@master + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: ${{ env.DISTPATH }} path: ${{ env.DISTPATH }} diff --git a/.github/workflows/dangerjs.yml b/.github/workflows/dangerjs.yml index 9f7360bc34f..13bc907566b 100644 --- a/.github/workflows/dangerjs.yml +++ b/.github/workflows/dangerjs.yml @@ -11,12 +11,17 @@ jobs: pull-request-style-linter: runs-on: ubuntu-latest steps: - - name: Check out PR head - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} + - name: Check out PR head + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha }} - - name: DangerJS pull request linter - uses: espressif/shared-github-dangerjs@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + - name: DangerJS pull request linter + uses: espressif/shared-github-dangerjs@fb17367fd3e8ff7412603b8e946d9b19ffdb2d7f # v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + instructions-cla-link: "https://cla-assistant.io/espressif/arduino-esp32" + instructions-contributions-file: "docs/en/contributing.rst" + rule-max-commits: "false" + commit-messages-min-summary-length: "10" diff --git a/.github/workflows/docs_build.yml b/.github/workflows/docs_build.yml index 568813729d4..d9b9f160228 100644 --- a/.github/workflows/docs_build.yml +++ b/.github/workflows/docs_build.yml @@ -3,18 +3,17 @@ name: Documentation Build and Deploy CI on: push: branches: - - master - - release/* + - master + - release/v2.x paths: - - 'docs/**' - - '.github/workflows/docs_build.yml' + - "docs/**" + - ".github/workflows/docs_build.yml" pull_request: paths: - - 'docs/**' - - '.github/workflows/docs_build.yml' + - "docs/**" + - ".github/workflows/docs_build.yml" jobs: - build-docs: name: Build ESP-Docs runs-on: ubuntu-22.04 @@ -22,25 +21,28 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4 - with: - submodules: true - - uses: actions/setup-python@v5 - with: - cache-dependency-path: docs/requirements.txt - cache: 'pip' - python-version: '3.10' - - name: Build - run: | - sudo apt update - sudo apt install python3-pip python3-setuptools - # GitHub CI installs pip3 and setuptools outside the path. - # Update the path to include them and run. - cd ./docs - PATH=/home/runner/.local/bin:$PATH pip3 install -r requirements.txt --prefer-binary - PATH=/home/runner/.local/bin:$PATH SPHINXOPTS="-W" build-docs -l en - - name: Archive Docs - uses: actions/upload-artifact@v4 - with: - name: docs - path: docs + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + submodules: true + + - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 + with: + cache-dependency-path: docs/requirements.txt + cache: "pip" + python-version: "3.10" + + - name: Build + run: | + sudo apt update + sudo apt install python3-pip python3-setuptools + # GitHub CI installs pip3 and setuptools outside the path. + # Update the path to include them and run. + cd ./docs + PATH=/home/runner/.local/bin:$PATH pip3 install -r requirements.txt --prefer-binary + PATH=/home/runner/.local/bin:$PATH SPHINXOPTS="-W" build-docs -l en + + - name: Archive Docs + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: docs + path: docs diff --git a/.github/workflows/docs_deploy.yml b/.github/workflows/docs_deploy.yml index 89c7eb9f516..9f45e35aef8 100644 --- a/.github/workflows/docs_deploy.yml +++ b/.github/workflows/docs_deploy.yml @@ -1,18 +1,19 @@ name: Documentation Build and Production Deploy CI on: - release: - types: [published] + workflow_run: + workflows: ["ESP32 Arduino Release"] + types: + - completed push: branches: - - release/* - - master + - release/v2.x + - master paths: - - 'docs/**' - - '.github/workflows/docs_deploy.yml' + - "docs/**" + - ".github/workflows/docs_deploy.yml" jobs: - deploy-prod-docs: name: Deploy Documentation on Production runs-on: ubuntu-22.04 @@ -20,34 +21,42 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4 - with: - submodules: true - - uses: actions/setup-python@v5 - with: - cache-dependency-path: docs/requirements.txt - cache: 'pip' - python-version: '3.10' - - name: Deploy Documentation - env: - # Deploy to production server - # DOCS_BUILD_DIR: "./docs/_build/" - DOCS_DEPLOY_PRIVATEKEY: ${{ secrets.DOCS_KEY }} - DOCS_DEPLOY_PATH: ${{ secrets.DOCS_PATH }} - DOCS_DEPLOY_SERVER: ${{ secrets.DOCS_SERVER }} - DOCS_DEPLOY_SERVER_USER: ${{ secrets.DOCS_USER }} - DOCS_DEPLOY_URL_BASE: ${{ secrets.DOCS_URL }} - run: | - sudo apt update - sudo apt install python3-pip python3-setuptools - source ./docs/utils.sh - add_doc_server_ssh_keys $DOCS_DEPLOY_PRIVATEKEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER - export GIT_VER=$(git describe --always) - echo "PIP install requirements..." - pip3 install --user -r ./docs/requirements.txt - echo "Building the Docs..." - cd ./docs && build-docs -l en - echo "Deploy the Docs..." - export DOCS_BUILD_DIR=$GITHUB_WORKSPACE/docs/ - cd $GITHUB_WORKSPACE/docs - deploy-docs + - name: Check if release workflow is successful + if: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.conclusion != 'success' }} + run: | + echo "Release workflow failed. Exiting..." + exit 1 + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + submodules: true + + - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 + with: + cache-dependency-path: docs/requirements.txt + cache: "pip" + python-version: "3.10" + + - name: Deploy Documentation + env: + # Deploy to production server + # DOCS_BUILD_DIR: "./docs/_build/" + DOCS_DEPLOY_PRIVATEKEY: ${{ secrets.DOCS_KEY }} + DOCS_DEPLOY_PATH: ${{ secrets.DOCS_PATH }} + DOCS_DEPLOY_SERVER: ${{ secrets.DOCS_SERVER }} + DOCS_DEPLOY_SERVER_USER: ${{ secrets.DOCS_USER }} + DOCS_DEPLOY_URL_BASE: ${{ secrets.DOCS_URL }} + run: | + sudo apt update + sudo apt install python3-pip python3-setuptools + source ./docs/utils.sh + add_doc_server_ssh_keys $DOCS_DEPLOY_PRIVATEKEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER + export GIT_VER=$(git describe --always) + echo "PIP install requirements..." + pip3 install --user -r ./docs/requirements.txt + echo "Building the Docs..." + cd ./docs && build-docs -l en + echo "Deploy the Docs..." + export DOCS_BUILD_DIR=$GITHUB_WORKSPACE/docs/ + cd $GITHUB_WORKSPACE/docs + deploy-docs diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 5d8e1794a8a..60795229eff 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -3,21 +3,22 @@ name: GitHub Pages CI on: push: branches: - - master - - pages + - master + - pages paths: - - 'README.md' - - '.github/scripts/on-pages.sh' - - '.github/workflows/gh-pages.yml' + - "README.md" + - ".github/scripts/on-pages.sh" + - ".github/workflows/gh-pages.yml" jobs: - build-pages: name: Build GitHub Pages runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Copy Files - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: bash ./.github/scripts/on-pages.sh + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Copy Files + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash ./.github/scripts/on-pages.sh diff --git a/.github/workflows/lib.json b/.github/workflows/lib.json index 9b528e4cc43..5b93d6689ef 100644 --- a/.github/workflows/lib.json +++ b/.github/workflows/lib.json @@ -23,16 +23,44 @@ ] }, { - "source-url": "https://github.com/me-no-dev/ESPAsyncWebServer.git", + "source-url": "https://github.com/ESP32Async/ESPAsyncWebServer.git", "required-libs": [ - {"source-url": "https://github.com/me-no-dev/AsyncTCP.git"} + {"source-url": "https://github.com/ESP32Async/AsyncTCP.git"} ], "exclude_targets": [], "sketch_path": [ + "~/Arduino/libraries/ESPAsyncWebServer/examples/Auth/Auth.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/CORS/CORS.ino", "~/Arduino/libraries/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino", - "~/Arduino/libraries/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino", - "~/Arduino/libraries/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino", - "~/Arduino/libraries/ESPAsyncWebServer/examples/simple_server/simple_server.ino" + "~/Arduino/libraries/ESPAsyncWebServer/examples/CatchAllHandler/CatchAllHandler.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/ChunkResponse/ChunkResponse.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/ChunkRetryResponse/ChunkRetryResponse.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/EndBegin/EndBegin.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/Filters/Filters.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/FlashResponse/FlashResponse.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/HeaderManipulation/HeaderManipulation.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/Headers/Headers.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/Json/Json.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/Logging/Logging.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/MessagePack/MessagePack.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/Middleware/Middleware.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/Params/Params.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/PartitionDownloader/PartitionDownloader.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/PerfTests/PerfTests.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/RateLimit/RateLimit.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/Redirect/Redirect.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/RequestContinuation/RequestContinuation.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/RequestContinuationComplete/RequestContinuationComplete.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/ResumableDownload/ResumableDownload.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/Rewrite/Rewrite.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/ServerSentEvents/ServerSentEvents.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/ServerState/ServerState.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/SkipServerMiddleware/SkipServerMiddleware.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/SlowChunkResponse/SlowChunkResponse.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/StaticFile/StaticFile.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/Templates/Templates.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/Upload/Upload.ino", + "~/Arduino/libraries/ESPAsyncWebServer/examples/WebSocket/WebSocket.ino" ] }, { diff --git a/.github/workflows/lib.yml b/.github/workflows/lib.yml index 894df61f4fd..0cb50842e5d 100644 --- a/.github/workflows/lib.yml +++ b/.github/workflows/lib.yml @@ -7,7 +7,7 @@ on: # Schedule weekly builds on every Sunday at 4 am schedule: - - cron: '0 4 * * SUN' + - cron: "0 4 * * SUN" concurrency: group: libs-${{ github.event.pull_request.number || github.ref }} @@ -27,7 +27,6 @@ jobs: contains(github.event.pull_request.labels.*.name, 'lib_test') || (github.event_name == 'schedule' && github.repository == 'espressif/arduino-esp32') runs-on: ubuntu-latest - env: REPOSITORY: | - source-path: '.' @@ -42,6 +41,7 @@ jobs: - esp32s3 - esp32c6 - esp32h2 + - esp32p4 include: - target: esp32 @@ -56,15 +56,16 @@ jobs: fqbn: espressif:esp32:esp32c6 - target: esp32h2 fqbn: espressif:esp32:esp32h2 - + - target: esp32p4 + fqbn: espressif:esp32:esp32p4 steps: # This step makes the contents of the repository available to the workflow - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Compile sketch - uses: P-R-O-C-H-Y/compile-sketches@main + uses: P-R-O-C-H-Y/compile-sketches@a62f069b92dc8f5053da4ac439ea6d1950cf6379 # main with: platforms: | ${{ env.REPOSITORY }} @@ -79,44 +80,42 @@ jobs: - --warnings="all" - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}-${{ matrix.target }} path: ${{ env.SKETCHES_REPORTS_PATH }} report-to-file: - needs: compile-sketch # Wait for the compile job to finish to get the data for the report + needs: compile-sketch # Wait for the compile job to finish to get the data for the report if: github.event_name == 'schedule' # Only run the job when the workflow is triggered by a schedule runs-on: ubuntu-latest steps: # Check out repository - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: token: ${{ env.GITHUB_TOKEN }} - fetch-depth: '0' + fetch-depth: "0" - name: Switch branch - run: - git checkout remotes/origin/gh-pages + run: git checkout remotes/origin/gh-pages # This step is needed to get the size data produced by the compile jobs - name: Download sketches reports artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: pattern: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}-* merge-multiple: true path: ${{ env.SKETCHES_REPORTS_PATH }} - name: Report results - uses: P-R-O-C-H-Y/report-size-deltas@main + uses: P-R-O-C-H-Y/report-size-deltas@4a79caa6dcc3579024293638b97156106edc588e # main with: sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }} destination-file: ${{ env.RESULT_LIBRARY_TEST_FILE }} - name: Append file with action URL - run: - echo "/ [GitHub Action Link](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}})" >> ${{ env.RESULT_LIBRARY_TEST_FILE }} + run: echo "/ [GitHub Action Link](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}})" >> ${{ env.RESULT_LIBRARY_TEST_FILE }} - name: Push to github repo run: | @@ -137,8 +136,9 @@ jobs: env: PR_NUM: ${{ github.event.number }} run: echo $PR_NUM > pr_num.txt + - name: Upload PR number - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: pr_number path: ./pr_num.txt diff --git a/.github/workflows/pre-commit-status.yml b/.github/workflows/pre-commit-status.yml index d0060668476..c7be9f8d352 100644 --- a/.github/workflows/pre-commit-status.yml +++ b/.github/workflows/pre-commit-status.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Report success - uses: actions/github-script@v7 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | const owner = '${{ github.repository_owner }}'; @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Report pending - uses: actions/github-script@v7 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | const owner = '${{ github.repository_owner }}'; diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index c4ae017c229..a3b858dd0fb 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -6,7 +6,7 @@ on: branches: - master pull_request: - types: [opened, reopened, synchronize, labeled, unlabeled] + types: [opened, reopened, synchronize, labeled] concurrency: group: pre-commit-${{github.event.pull_request.number || github.ref}} @@ -15,21 +15,29 @@ concurrency: jobs: lint: if: | + github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'Status: Pending Merge') || - github.event_name != 'pull_request' + contains(github.event.pull_request.labels.*.name, 'Re-trigger Pre-commit Hooks') + name: Check if fixes are needed runs-on: ubuntu-latest steps: - name: Checkout latest commit - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 + - name: Remove Label + if: contains(github.event.pull_request.labels.*.name, 'Re-trigger Pre-commit Hooks') + run: gh pr edit ${{ github.event.number }} --remove-label 'Re-trigger Pre-commit Hooks' + env: + GH_TOKEN: ${{ github.token }} + - name: Set up Python 3 - uses: actions/setup-python@v5 + uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 with: cache-dependency-path: tools/pre-commit/requirements.txt - cache: 'pip' + cache: "pip" python-version: "3.x" - name: Get Python version hash @@ -38,7 +46,7 @@ jobs: echo "PY_HASH=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV - name: Restore pre-commit cache - uses: actions/cache/restore@v4 + uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 id: restore-cache with: path: | @@ -50,13 +58,13 @@ jobs: - name: Get changed files id: changed-files - uses: tj-actions/changed-files@v42.0.2 + uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1 - name: Run pre-commit hooks in changed files run: pre-commit run --color=always --show-diff-on-failure --files ${{ steps.changed-files.outputs.all_changed_files }} - name: Save pre-commit cache - uses: actions/cache/save@v4 + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 if: ${{ always() && steps.restore-cache.outputs.cache-hit != 'true' }} continue-on-error: true with: @@ -65,7 +73,7 @@ jobs: key: ${{ steps.restore-cache.outputs.cache-primary-key }} - name: Push changes using pre-commit-ci-lite - uses: pre-commit-ci/lite-action@v1.0.2 + uses: pre-commit-ci/lite-action@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 # v1.1.0 # Only push changes in PRs if: ${{ always() && github.event_name == 'pull_request' }} with: diff --git a/.github/workflows/publishlib.yml b/.github/workflows/publishlib.yml index 7fd932f5309..0e1c3f64afd 100644 --- a/.github/workflows/publishlib.yml +++ b/.github/workflows/publishlib.yml @@ -44,12 +44,12 @@ jobs: - name: Read the pr_num file id: pr_num_reader - uses: juliangruber/read-file-action@v1 + uses: juliangruber/read-file-action@b549046febe0fe86f8cb4f93c24e284433f9ab58 # v1.1.7 with: path: ./artifacts/workflows/pr_num.txt - + - name: Report results - uses: P-R-O-C-H-Y/report-size-deltas@libs + uses: P-R-O-C-H-Y/report-size-deltas@256d1f13e4195cd7fd436d2f959e6dc4d5e4b406 # libs with: sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }} github-token: ${{ env.GITHUB_TOKEN }} diff --git a/.github/workflows/publishsizes-2.x.yml b/.github/workflows/publishsizes-2.x.yml index bdd2fc311e4..738e215bc3f 100644 --- a/.github/workflows/publishsizes-2.x.yml +++ b/.github/workflows/publishsizes-2.x.yml @@ -11,11 +11,11 @@ env: jobs: sizes-test-results: - name: Sizes Comparsion Results + name: Sizes Comparison Results runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@v4 # This step checks out the repository's code at gh-pages branch + - name: Checkout gh-pages branch + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: gh-pages @@ -34,15 +34,14 @@ jobs: mv v2.x_cli_compile/*.json artifacts/sizes-report/master/ - name: Report results - uses: P-R-O-C-H-Y/report-size-deltas@sizes_v2 + uses: P-R-O-C-H-Y/report-size-deltas@2043188c68f483a7b50527c4eacf609d05bb67a5 # sizes_v2 with: sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }} github-token: ${{ env.GITHUB_TOKEN }} destination-file: ${{ env.RESULT_SIZES_TEST_FILE }} - name: Append file with action URL - run: - echo "/ [GitHub Action Link](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}})" >> ${{ env.RESULT_SIZES_TEST_FILE }} + run: echo "/ [GitHub Action Link](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}})" >> ${{ env.RESULT_SIZES_TEST_FILE }} - name: Push to github repo run: | diff --git a/.github/workflows/publishsizes.yml b/.github/workflows/publishsizes.yml index ce4e94cd5e5..69c18cf1835 100644 --- a/.github/workflows/publishsizes.yml +++ b/.github/workflows/publishsizes.yml @@ -14,15 +14,15 @@ env: jobs: sizes-test-results: - name: Sizes Comparsion Results + name: Sizes Comparison Results runs-on: ubuntu-latest if: | github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' steps: - - name: Checkout code - uses: actions/checkout@v4 # This step checks out the repository's code at gh-pages branch + - name: Checkout gh-pages branch + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: gh-pages @@ -60,12 +60,12 @@ jobs: - name: Read the pr_num file id: pr_num_reader - uses: juliangruber/read-file-action@v1 + uses: juliangruber/read-file-action@b549046febe0fe86f8cb4f93c24e284433f9ab58 # v1.1.7 with: path: ./artifacts/sizes-report/pr_num.txt - name: Report results - uses: P-R-O-C-H-Y/report-size-deltas@sizes_v2 + uses: P-R-O-C-H-Y/report-size-deltas@2043188c68f483a7b50527c4eacf609d05bb67a5 # sizes_v2 with: sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }} github-token: ${{ env.GITHUB_TOKEN }} diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 2f14a6fb62f..c8b8ddc2127 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -2,31 +2,56 @@ name: Compilation Tests on: workflow_dispatch: + inputs: + log_level: + description: "Log level" + default: "none" + type: "choice" + required: true + options: + - "none" + - "error" + - "warn" + - "info" + - "debug" + - "verbose" + schedule: + # Every Sunday at 2:00 UTC run a build with verbose log level + - cron: "0 2 * * SUN" push: branches: - - master - - release/* + - master + - release/* pull_request: paths: - - 'cores/**' - - 'libraries/**' - - '!libraries/**.md' - - '!libraries/**.txt' - - '!libraries/**.properties' - - '!libraries/**.py' - - 'package/**' - - 'tools/**.py' - - 'platform.txt' - - 'programmers.txt' - - 'idf_component.yml' - - 'Kconfig.projbuild' - - 'package.json' - - '.github/workflows/push.yml' - - '.github/scripts/**' - - '!.github/scripts/find_*' - - '!.github/scripts/on-release.sh' - - '!.github/scripts/tests_*' - - '!.github/scripts/upload_*' + - "cores/**" + - "libraries/**" + - "!libraries/**.md" + - "!libraries/**.txt" + - "!libraries/**.properties" + - "!libraries/**.py" + - "package/**" + - "idf_component_examples/**" + - "tools/**.py" + - "platform.txt" + - "programmers.txt" + - "idf_component.yml" + - "Kconfig.projbuild" + - "package.json" + - "CMakeLists.txt" + - ".github/workflows/push.yml" + - ".github/scripts/**" + - "!.github/scripts/find_*" + - "!.github/scripts/on-release.sh" + - "!.github/scripts/tests_*" + - "!.github/scripts/upload_*" + - "variants/esp32/**/*" + - "variants/esp32c3/**/*" + - "variants/esp32c6/**/*" + - "variants/esp32h2/**/*" + - "variants/esp32p4/**/*" + - "variants/esp32s2/**/*" + - "variants/esp32s3/**/*" concurrency: group: build-${{github.event.pull_request.number || github.ref}} @@ -39,41 +64,47 @@ jobs: cmake-check: name: Check cmake file runs-on: ubuntu-latest + if: ${{ !(github.event_name == 'pull_request' && startsWith(github.head_ref, 'release/')) }} steps: - - uses: actions/checkout@v4 - - run: bash ./.github/scripts/check-cmakelists.sh + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - run: bash ./.github/scripts/check-cmakelists.sh gen-chunks: name: Generate chunks runs-on: ubuntu-latest + if: ${{ !(github.event_name == 'pull_request' && startsWith(github.head_ref, 'release/')) }} outputs: build_all: ${{ steps.set-chunks.outputs.build_all }} build_libraries: ${{ steps.set-chunks.outputs.build_libraries }} build_static_sketches: ${{ steps.set-chunks.outputs.build_static_sketches }} build_idf: ${{ steps.set-chunks.outputs.build_idf }} - build_platformio: ${{ steps.set-chunks.outputs.build_platformio }} chunk_count: ${{ steps.set-chunks.outputs.chunk_count }} chunks: ${{ steps.set-chunks.outputs.chunks }} steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 2 + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 2 - - name: Get changed files - id: changed-files - uses: tj-actions/changed-files@v44 - with: - files_yaml: | + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1 + with: + files_yaml: | core: - '.github/**' - - '!.github/scripts/install-platformio-esp32.sh' - 'cores/**' - 'package/**' - 'tools/**' - - '!tools/platformio-build.py' - 'platform.txt' - 'programmers.txt' + - "variants/esp32/**/*" + - "variants/esp32c3/**/*" + - "variants/esp32c6/**/*" + - "variants/esp32h2/**/*" + - "variants/esp32p4/**/*" + - "variants/esp32s2/**/*" + - "variants/esp32s3/**/*" libraries: - 'libraries/**/examples/**' - 'libraries/**/src/**' @@ -92,36 +123,33 @@ jobs: idf: - 'idf_component.yml' - 'Kconfig.projbuild' - platformio: - - 'package.json' - - '.github/scripts/install-platformio-esp32.sh' - - 'tools/platformio-build.py' + - 'CMakeLists.txt' + - "idf_component_examples/**" - - name: Set chunks - id: set-chunks - env: - LIB_FILES: ${{ steps.changed-files.outputs.libraries_all_changed_files }} - IS_PR: ${{ github.event_name == 'pull_request' }} - MAX_CHUNKS: ${{ env.MAX_CHUNKS }} - BUILD_PLATFORMIO: ${{ steps.changed-files.outputs.platformio_any_changed == 'true' }} - BUILD_IDF: ${{ steps.changed-files.outputs.idf_any_changed == 'true' }} - BUILD_LIBRARIES: ${{ steps.changed-files.outputs.libraries_any_changed == 'true' }} - BUILD_STATIC_SKETCHES: ${{ steps.changed-files.outputs.static_sketeches_any_changed == 'true' }} - FS_CHANGED: ${{ steps.changed-files.outputs.fs_any_changed == 'true' }} - NETWORKING_CHANGED: ${{ steps.changed-files.outputs.networking_any_changed == 'true' }} - CORE_CHANGED: ${{ steps.changed-files.outputs.core_any_changed == 'true' }} - LIB_CHANGED: ${{ steps.changed-files.outputs.libraries_any_changed == 'true' }} - run: | - bash ./.github/scripts/set_push_chunks.sh + - name: Set chunks + id: set-chunks + env: + LIB_FILES: ${{ steps.changed-files.outputs.libraries_all_changed_files }} + IS_PR: ${{ github.event_name == 'pull_request' }} + MAX_CHUNKS: ${{ env.MAX_CHUNKS }} + BUILD_IDF: ${{ steps.changed-files.outputs.idf_any_changed == 'true' }} + BUILD_LIBRARIES: ${{ steps.changed-files.outputs.libraries_any_changed == 'true' }} + BUILD_STATIC_SKETCHES: ${{ steps.changed-files.outputs.static_sketeches_any_changed == 'true' }} + FS_CHANGED: ${{ steps.changed-files.outputs.fs_any_changed == 'true' }} + NETWORKING_CHANGED: ${{ steps.changed-files.outputs.networking_any_changed == 'true' }} + CORE_CHANGED: ${{ steps.changed-files.outputs.core_any_changed == 'true' }} + LIB_CHANGED: ${{ steps.changed-files.outputs.libraries_any_changed == 'true' }} + run: | + bash ./.github/scripts/set_push_chunks.sh - - name: Upload sketches found - if: ${{ steps.set-chunks.outputs.build_all == 'false' && steps.set-chunks.outputs.build_libraries == 'true' }} - uses: actions/upload-artifact@v4 - with: - name: sketches_found - path: sketches_found.txt - overwrite: true - if-no-files-found: error + - name: Upload sketches found + if: ${{ steps.set-chunks.outputs.build_all == 'false' && steps.set-chunks.outputs.build_libraries == 'true' }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: sketches_found + path: sketches_found.txt + overwrite: true + if-no-files-found: error # Ubuntu build-arduino-linux: @@ -135,45 +163,55 @@ jobs: chunk: ${{ fromJson(needs.gen-chunks.outputs.chunks) }} steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.x' + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 + with: + python-version: "3.x" - - name: Get libs cache - uses: actions/cache@v4 - with: - key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }} - path: | - ./tools/dist - ./tools/esp32-arduino-libs - ./tools/esptool - ./tools/mk* - ./tools/openocd-esp32 - ./tools/riscv32-* - ./tools/xtensa-* + - name: Get libs cache + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }} + path: | + ./tools/dist + ./tools/esp32-arduino-libs + ./tools/esptool + ./tools/mk* + ./tools/openocd-esp32 + ./tools/riscv32-* + ./tools/xtensa-* + + - name: Set Log Level + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + echo "LOG_LEVEL=${{ github.event.inputs.log_level }}" >> $GITHUB_ENV + elif [ "${{ github.event_name }}" == "schedule" ]; then + echo "LOG_LEVEL=verbose" >> $GITHUB_ENV + else + echo "LOG_LEVEL=none" >> $GITHUB_ENV + fi - - name: Build all sketches - if: ${{ needs.gen-chunks.outputs.build_all == 'true' }} - run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ env.MAX_CHUNKS }} 1 + - name: Build all sketches + if: ${{ needs.gen-chunks.outputs.build_all == 'true' }} + run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ env.MAX_CHUNKS }} 1 ${{ env.LOG_LEVEL }} - - name: Download sketches found - if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }} - uses: actions/download-artifact@v4 - with: - name: sketches_found + - name: Download sketches found + if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }} + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + with: + name: sketches_found - - name: Build selected sketches - if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }} - run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ needs.gen-chunks.outputs.chunk_count }} 1 sketches_found.txt + - name: Build selected sketches + if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }} + run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ needs.gen-chunks.outputs.chunk_count }} 1 ${{ env.LOG_LEVEL }} sketches_found.txt - #Upload cli compile json as artifact - - name: Upload cli compile json - uses: actions/upload-artifact@v4 - with: - name: pr_cli_compile_${{ matrix.chunk }} - path: cli_compile_${{ matrix.chunk }}.json - overwrite: true + #Upload cli compile json as artifact + - name: Upload cli compile json + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: pr_cli_compile_${{ matrix.chunk }} + path: cli_compile_${{ matrix.chunk }}.json + overwrite: true # Windows and MacOS build-arduino-win-mac: @@ -187,34 +225,12 @@ jobs: os: [windows-latest, macOS-latest] steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: Build Sketches - run: bash ./.github/scripts/on-push.sh - - # PlatformIO on Windows, Ubuntu and Mac - build-platformio: - name: PlatformIO on ${{ matrix.os }} - needs: gen-chunks - if: | - needs.gen-chunks.outputs.build_all == 'true' || - needs.gen-chunks.outputs.build_static_sketches == 'true' || - needs.gen-chunks.outputs.build_platformio == 'true' - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] - - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: Build Sketches - run: bash ./.github/scripts/on-push.sh 1 1 #equal and non-zero to trigger PIO + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 + with: + python-version: "3.x" + - name: Build Sketches + run: bash ./.github/scripts/on-push.sh build-esp-idf-component: name: Build with ESP-IDF ${{ matrix.idf_ver }} for ${{ matrix.idf_target }} @@ -223,7 +239,7 @@ jobs: needs.gen-chunks.outputs.build_all == 'true' || needs.gen-chunks.outputs.build_libraries == 'true' || needs.gen-chunks.outputs.build_idf == 'true' - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: @@ -231,24 +247,43 @@ jobs: # See https://hub.docker.com/r/espressif/idf/tags and # https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-docker-image.html # for details. - idf_ver: ["release-v5.1"] - idf_target: ["esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2"] + idf_ver: ["release-v5.4"] + idf_target: + [ + "esp32", + "esp32s2", + "esp32s3", + "esp32c2", + "esp32c3", + "esp32c6", + "esp32h2", + "esp32p4" + ] container: espressif/idf:${{ matrix.idf_ver }} steps: - name: Check out arduino-esp32 as a component - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: submodules: recursive path: components/arduino-esp32 + + - name: Setup jq + uses: dcarbone/install-jq-action@e397bd87438d72198f81efd21f876461183d383a # v3.0.1 + - name: Build env: IDF_TARGET: ${{ matrix.idf_target }} shell: bash run: | - . ${IDF_PATH}/export.sh - idf.py create-project test - echo CONFIG_FREERTOS_HZ=1000 > test/sdkconfig.defaults - idf.py -C test -DEXTRA_COMPONENT_DIRS=$PWD/components build + chmod a+x ./components/arduino-esp32/.github/scripts/* + ./components/arduino-esp32/.github/scripts/on-push-idf.sh + + - name: Upload generated sdkconfig files for debugging + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + if: always() + with: + name: sdkconfig-${{ matrix.idf_target }} + path: ./components/arduino-esp32/idf_component_examples/**/sdkconfig # Save artifacts to gh-pages save-master-artifacts: @@ -257,19 +292,18 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/master' runs-on: ubuntu-latest steps: - # Check out repository + # Check out repository - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: token: ${{secrets.GITHUB_TOKEN}} - fetch-depth: '0' + fetch-depth: "0" - name: Switch branch - run: - git checkout remotes/origin/gh-pages + run: git checkout remotes/origin/gh-pages - name: Download sketches reports artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: pattern: pr_cli_compile_* merge-multiple: true @@ -291,7 +325,7 @@ jobs: #Upload PR number as artifact upload-pr-number: name: Upload PR number - if: github.event_name == 'pull_request' + if: ${{ github.event_name == 'pull_request' && !startsWith(github.head_ref, 'release/') }} runs-on: ubuntu-latest steps: - name: Save the PR number in an artifact @@ -299,8 +333,9 @@ jobs: env: PR_NUM: ${{ github.event.number }} run: echo $PR_NUM > pr_num.txt + - name: Upload PR number - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: pr_number path: ./pr_num.txt diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1610be3f901..7b23c80c49a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,14 +10,23 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - run: pip install packaging - - name: Build Release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: bash ./.github/scripts/on-release.sh + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 + with: + python-version: "3.x" + + - name: Install packaging + run: pip install packaging + + - name: Install pyserial + run: pip install pyserial + + - name: Build Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash ./.github/scripts/on-release.sh diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d5a8e267c5f..ddc9b64aace 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,104 +1,106 @@ +# This file is used to run the runtime tests for the Arduino core for ESP32. +# The tests are run on the hardware, Wokwi and QEMU emulators. +# The QEMU tests are disabled for now as they are redundant with most of the Wokwi tests. +# As the Wokwi tests require access to secrets, they are run in a separate workflow. +# We need to ensure that the artifacts from previous tests in the chain are propagated for publishing the results. +# This is the current trigger sequence for the tests: +# tests.yml -> tests_wokwi.yml -> tests_results.yml +# ⌙> tests_build.yml +# ⌙> tests_hw.yml +# ⌙> tests_qemu.yml + name: Runtime Tests on: workflow_dispatch: - pull_request_target: + pull_request: types: [opened, reopened, closed, synchronize, labeled, unlabeled] paths: - - 'tests/**' - - 'cores/**' - - 'libraries/**' - - '!libraries/**.md' - - '!libraries/**.txt' - - '!libraries/**.properties' - - 'package/**' + - ".github/workflows/tests*" + - ".github/scripts/*.sh" + - "!.github/scripts/check-cmakelists.sh" + - "!.github/scripts/find_*" + - "!.github/scripts/on-*.sh" + - "!.github/scripts/set_push_chunks.sh" + - "!.github/scripts/update-version.sh" + - "!.github/scripts/upload_py_tools.sh" + - "tests/**" + - "cores/**" + - "libraries/*/src/**.cpp" + - "libraries/*/src/**.h" + - "libraries/*/src/**.c" + - "package/**" schedule: - - cron: '0 2 * * *' + - cron: "0 2 * * *" concurrency: group: tests-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true -# To avoid giving elevated permissions to the entire workflow, specify default permissions at the top level -# and then override them for specific jobs. -permissions: { contents: read } - jobs: + push-event-file: + name: Push event file + runs-on: ubuntu-latest + steps: + - name: Upload + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: event_file + path: ${{ github.event_path }} + gen-matrix: name: Generate matrix - if: github.event.action != 'closed' runs-on: ubuntu-latest outputs: build-types: ${{ steps.set-matrix.outputs.build-types }} hw-types: ${{ steps.set-matrix.outputs.hw-types }} wokwi-types: ${{ steps.set-matrix.outputs.wokwi-types }} qemu-types: ${{ steps.set-matrix.outputs.qemu-types }} + targets: ${{ steps.set-matrix.outputs.targets }} + env: + IS_PR: ${{ github.event.pull_request.number != null }} + PERFORMANCE_ENABLED: ${{ contains(github.event.pull_request.labels.*.name, 'perf_test') }} steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + sparse-checkout: .github/scripts/tests_matrix.sh + - name: Set matrix id: set-matrix - run: | - build_types='["validation"' - hw_types='["validation"' - wokwi_types='["validation"' - qemu_types='["validation"' - - is_pr=${{ github.event.pull_request.number != null }} - is_performance_enabled=${{ contains(github.event.pull_request.labels.*.name, 'perf_test') }} + run: bash .github/scripts/tests_matrix.sh - if [[ $is_pr != 'true' ]] || [[ $is_performance_enabled == 'true' ]]; then - build_types+=',"performance"' - hw_types+=',"performance"' - #wokwi_types+=',"performance"' - #qemu_types+=',"performance"' - fi - - echo "build-types=$build_types]" >> $GITHUB_OUTPUT - echo "hw-types=$hw_types]" >> $GITHUB_OUTPUT - echo "wokwi-types=$wokwi_types]" >> $GITHUB_OUTPUT - echo "qemu-types=$qemu_types]" >> $GITHUB_OUTPUT + - name: Upload + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: matrix_info + path: info/* call-build-tests: name: Build - uses: espressif/arduino-esp32/.github/workflows/build_tests.yml@master + uses: ./.github/workflows/tests_build.yml needs: gen-matrix - if: github.event.action != 'closed' strategy: matrix: type: ${{ fromJson(needs.gen-matrix.outputs.build-types) }} - chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'] + chip: ${{ fromJson(needs.gen-matrix.outputs.targets) }} with: type: ${{ matrix.type }} chip: ${{ matrix.chip }} call-hardware-tests: name: Hardware - uses: espressif/arduino-esp32/.github/workflows/hw.yml@master + uses: ./.github/workflows/tests_hw.yml needs: [gen-matrix, call-build-tests] if: | github.repository == 'espressif/arduino-esp32' && - (github.event_name != 'pull_request_target' || + (github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'hil_test')) strategy: fail-fast: false matrix: type: ${{ fromJson(needs.gen-matrix.outputs.hw-types) }} - chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'] - with: - type: ${{ matrix.type }} - chip: ${{ matrix.chip }} - - call-wokwi-tests: - name: Wokwi - uses: espressif/arduino-esp32/.github/workflows/wokwi.yml@master - needs: [gen-matrix, call-build-tests] - if: github.event.action != 'closed' - strategy: - fail-fast: false - matrix: - type: ${{ fromJson(needs.gen-matrix.outputs.wokwi-types) }} - chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'] - secrets: - WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }} + chip: ${{ fromJson(needs.gen-matrix.outputs.targets) }} with: type: ${{ matrix.type }} chip: ${{ matrix.chip }} @@ -106,90 +108,16 @@ jobs: # This job is disabled for now call-qemu-tests: name: QEMU - uses: espressif/arduino-esp32/.github/workflows/qemu.yml@master + uses: ./.github/workflows/tests_qemu.yml needs: [gen-matrix, call-build-tests] if: false strategy: fail-fast: false matrix: type: ${{ fromJson(needs.gen-matrix.outputs.qemu-types) }} - chip: ['esp32', 'esp32c3'] + chip: ["esp32", "esp32c3"] with: type: ${{ matrix.type }} chip: ${{ matrix.chip }} - unit-test-results: - name: Unit Test Results - needs: [call-hardware-tests, call-wokwi-tests, call-qemu-tests] - if: always() && github.event_name == 'pull_request_target' - runs-on: ubuntu-latest - permissions: - checks: write - pull-requests: write - steps: - - name: Download and Extract HW Artifacts - uses: actions/download-artifact@v4 - continue-on-error: true - with: - merge-multiple: true - pattern: tests-results-hw-* - path: ./results/hw - - - name: Download and Extract Wokwi Artifacts - uses: actions/download-artifact@v4 - continue-on-error: true - with: - merge-multiple: true - pattern: tests-results-wokwi-* - path: ./results/wokwi - - - name: Download and Extract QEMU Artifacts - uses: actions/download-artifact@v4 - continue-on-error: true - with: - merge-multiple: true - pattern: tests-results-qemu-* - path: ./results/qemu - - - name: Publish Unit Test Results - uses: EnricoMi/publish-unit-test-result-action@v2 - with: - commit: ${{ github.event.pull_request.head.sha || github.sha }} - files: ./results/**/*.xml - clean: - name: Clean objects - needs: unit-test-results - if: always() - permissions: - actions: write - runs-on: ubuntu-latest - steps: - - name: Clean up caches - uses: actions/github-script@v7 - with: - script: | - const ref = '${{ github.event.pull_request.number || github.ref }}'; - const key_prefix = 'tests-' + ref + '-'; - - if ('${{ github.event_name }}' == 'pull_request_target' && '${{ github.event.action }}' != 'closed') { - console.log('Skipping cache cleanup for open PR'); - return; - } - - await github.paginate(github.rest.actions.getActionsCacheList, { - owner: context.repo.owner, - repo: context.repo.repo, - per_page: 100, - key: key_prefix - }).then(caches => { - if (caches) { - for (const cache of caches) { - console.log(`Deleting cache: ${cache.key}`); - github.rest.actions.deleteActionsCacheById({ - owner: context.repo.owner, - repo: context.repo.repo, - cache_id: cache.id - }); - } - } - }); + # Wokwi tests are run after this workflow as it needs access to secrets diff --git a/.github/workflows/build_tests.yml b/.github/workflows/tests_build.yml similarity index 58% rename from .github/workflows/build_tests.yml rename to .github/workflows/tests_build.yml index b7c4ec40f1a..ac1f40644ed 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/tests_build.yml @@ -5,11 +5,11 @@ on: inputs: type: type: string - description: 'Type of tests to build' + description: "Type of tests to build" required: true chip: type: string - description: 'Chip to build tests for' + description: "Chip to build tests for" required: true jobs: @@ -20,15 +20,16 @@ jobs: id: ${{ github.event.pull_request.number || github.ref }}-${{ github.event.pull_request.head.sha || github.sha }}-${{ inputs.chip }}-${{ inputs.type }} steps: - name: Check if already built - if: ${{ github.event.pull_request.number != null }} id: cache-build-binaries - uses: actions/cache/restore@v4 + if: github.event.pull_request.number != null + uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: key: tests-${{ env.id }}-bin path: | - ~/.arduino/tests/**/build*.tmp/*.bin - ~/.arduino/tests/**/build*.tmp/*.elf - ~/.arduino/tests/**/build*.tmp/*.json + ~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.bin + ~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.elf + ~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.json + ~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/sdkconfig - name: Evaluate if tests should be built id: check-build @@ -45,25 +46,10 @@ jobs: - name: Checkout user repository if: ${{ steps.check-build.outputs.enabled == 'true' }} - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - persist-credentials: false - sparse-checkout-cone-mode: false - sparse-checkout: | - /* - !.github - - # To avoid giving unknown scripts elevated permissions, download them from the master branch - - name: Get CI scripts from master - if: ${{ steps.check-build.outputs.enabled == 'true' }} - run: | - mkdir -p .github - cd .github - curl https://codeload.github.com/${{ github.repository }}/tar.gz/master | tar -xz --strip=2 arduino-esp32-master/.github + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Get libs cache - uses: actions/cache@v4 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 if: ${{ steps.check-build.outputs.enabled == 'true' }} with: key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }} @@ -82,21 +68,23 @@ jobs: bash .github/scripts/tests_build.sh -c -type ${{ inputs.type }} -t ${{ inputs.chip }} - name: Upload ${{ inputs.chip }} ${{ inputs.type }} binaries as cache - uses: actions/cache/save@v4 - if: ${{ steps.check-build.outputs.enabled == 'true' }} + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + if: steps.check-build.outputs.enabled == 'true' && github.event.pull_request.number != null with: key: tests-${{ env.id }}-bin path: | - ~/.arduino/tests/**/build*.tmp/*.bin - ~/.arduino/tests/**/build*.tmp/*.elf - ~/.arduino/tests/**/build*.tmp/*.json + ~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.bin + ~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.elf + ~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.json + ~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/sdkconfig - name: Upload ${{ inputs.chip }} ${{ inputs.type }} binaries as artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: tests-bin-${{ inputs.chip }}-${{ inputs.type }} overwrite: true path: | - ~/.arduino/tests/**/build*.tmp/*.bin - ~/.arduino/tests/**/build*.tmp/*.elf - ~/.arduino/tests/**/build*.tmp/*.json + ~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.bin + ~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.elf + ~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.json + ~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/sdkconfig diff --git a/.github/workflows/hw.yml b/.github/workflows/tests_hw.yml similarity index 68% rename from .github/workflows/hw.yml rename to .github/workflows/tests_hw.yml index b401f0f3f07..6f5fc67f7b9 100644 --- a/.github/workflows/hw.yml +++ b/.github/workflows/tests_hw.yml @@ -5,27 +5,39 @@ on: inputs: type: type: string - description: 'Type of tests to run' + description: "Type of tests to run" required: true chip: type: string - description: 'Chip to run tests for' + description: "Chip to run tests for" required: true +env: + DEBIAN_FRONTEND: noninteractive + +defaults: + run: + shell: bash + jobs: hardware-test: name: Hardware ${{ inputs.chip }} ${{ inputs.type }} tests - runs-on: [arduino, "${{ inputs.chip }}"] + runs-on: ["arduino", "${{ inputs.chip }}"] env: id: ${{ github.event.pull_request.number || github.ref }}-${{ github.event.pull_request.head.sha || github.sha }}-${{ inputs.chip }}-${{ inputs.type }} container: image: python:3.10.1-bullseye - options: --privileged + options: --privileged --device-cgroup-rule="c 188:* rmw" --device-cgroup-rule="c 166:* rmw" steps: - - name: Check if already built - if: ${{ github.event.pull_request.number != null }} + - name: Clean workspace + run: | + rm -rf ./* + rm -rf ~/.arduino/tests + + - name: Check if already passed id: cache-results - uses: actions/cache/restore@v4 + if: github.event.pull_request.number != null + uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: key: tests-${{ env.id }}-results-hw path: | @@ -47,25 +59,13 @@ jobs: - name: Checkout user repository if: ${{ steps.check-tests.outputs.enabled == 'true' }} - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - persist-credentials: false - sparse-checkout-cone-mode: false sparse-checkout: | - /* - !.github - - # To avoid giving unknown scripts elevated permissions, download them from the master branch - - name: Get CI scripts from master - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - run: | - mkdir -p .github - cd .github - curl https://codeload.github.com/${{ github.repository }}/tar.gz/master | tar -xz --strip=2 arduino-esp32-master/.github + * # setup-python currently only works on ubuntu images - # - uses: actions/setup-python@v5 + # - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 # if: ${{ steps.check-tests.outputs.enabled == 'true' }} # with: # cache-dependency-path: tests/requirements.txt @@ -82,11 +82,16 @@ jobs: - name: Get binaries if: ${{ steps.check-tests.outputs.enabled == 'true' }} - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: name: tests-bin-${{ inputs.chip }}-${{ inputs.type }} path: | - ~/.arduino/tests + ~/.arduino/tests/${{ inputs.chip }} + + - name: List binaries + if: ${{ steps.check-tests.outputs.enabled == 'true' }} + run: | + ls -laR ~/.arduino/tests - name: Run Tests if: ${{ steps.check-tests.outputs.enabled == 'true' }} @@ -94,8 +99,8 @@ jobs: bash .github/scripts/tests_run.sh -c -type ${{ inputs.type }} -t ${{ inputs.chip }} -i 0 -m 1 -e - name: Upload ${{ inputs.chip }} ${{ inputs.type }} hardware results as cache - uses: actions/cache/save@v4 - if: ${{ always() && steps.check-tests.outputs.enabled == 'true' }} + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + if: steps.check-tests.outputs.enabled == 'true' && github.event.pull_request.number != null with: key: tests-${{ env.id }}-results-hw path: | @@ -103,7 +108,7 @@ jobs: tests/**/result_*.json - name: Upload ${{ inputs.chip }} ${{ inputs.type }} hardware results as artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: always() with: name: tests-results-hw-${{ inputs.chip }}-${{ inputs.type }} diff --git a/.github/workflows/qemu.yml b/.github/workflows/tests_qemu.yml similarity index 80% rename from .github/workflows/qemu.yml rename to .github/workflows/tests_qemu.yml index da31054aeef..fa3f874cbbb 100644 --- a/.github/workflows/qemu.yml +++ b/.github/workflows/tests_qemu.yml @@ -18,10 +18,10 @@ jobs: QEMU_INSTALL_PATH: "$HOME" runs-on: ubuntu-latest steps: - - name: Check if already run - if: ${{ github.event.pull_request.number != null }} + - name: Check if already passed id: get-cache-results - uses: actions/cache/restore@v4 + if: github.event.pull_request.number != null + uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: key: tests-${{ env.id }}-results-qemu path: | @@ -43,7 +43,7 @@ jobs: - name: Checkout user repository if: ${{ steps.check-tests.outputs.enabled == 'true' }} - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} persist-credentials: false @@ -60,12 +60,12 @@ jobs: cd .github curl https://codeload.github.com/${{ github.repository }}/tar.gz/master | tar -xz --strip=2 arduino-esp32-master/.github - - uses: actions/setup-python@v5 + - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 if: ${{ steps.check-tests.outputs.enabled == 'true' }} with: cache-dependency-path: tests/requirements.txt - cache: 'pip' - python-version: '3.x' + cache: "pip" + python-version: "3.x" - name: Install Python dependencies if: ${{ steps.check-tests.outputs.enabled == 'true' }} @@ -74,14 +74,14 @@ jobs: pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi - name: Install APT dependencies - uses: awalsh128/cache-apt-pkgs-action@v1.4.2 + uses: awalsh128/cache-apt-pkgs-action@5902b33ae29014e6ca012c5d8025d4346556bd40 # v1.4.3 if: ${{ steps.check-tests.outputs.enabled == 'true' }} with: packages: libpixman-1-0 libnuma1 libglib2.0-0 libslirp0 libsdl2-2.0-0 version: 1.0 - name: Get QEMU version - uses: pozetroninc/github-action-get-latest-release@v0.7.0 + uses: pozetroninc/github-action-get-latest-release@2a61c339ea7ef0a336d1daa35ef0cb1418e7676c # v0.8.0 if: ${{ steps.check-tests.outputs.enabled == 'true' }} id: get-qemu-version with: @@ -92,12 +92,12 @@ jobs: - name: Cache QEMU id: cache-qemu - uses: actions/cache@v4 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 if: ${{ steps.check-tests.outputs.enabled == 'true' }} with: path: | ~/qemu - key: qemu-${{ steps.get-qemu-version.outputs.release }}-${{ hashFiles('.github/workflows/qemu.yml') }} + key: qemu-${{ steps.get-qemu-version.outputs.release }}-${{ hashFiles('.github/workflows/tests_qemu.yml') }} - name: Download QEMU if: ${{ steps.cache-qemu.outputs.cache-hit != 'true' && steps.check-tests.outputs.enabled == 'true' }} @@ -113,19 +113,19 @@ jobs: - name: Get binaries if: ${{ steps.check-tests.outputs.enabled == 'true' }} - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: name: tests-bin-${{ inputs.chip }}-${{ inputs.type }} path: | - ~/.arduino/tests + ~/.arduino/tests/${{ inputs.chip }} - name: Run Tests if: ${{ steps.check-tests.outputs.enabled == 'true' }} run: QEMU_PATH="${{ env.QEMU_INSTALL_PATH }}" bash .github/scripts/tests_run.sh -c -type ${{inputs.type}} -t ${{inputs.chip}} -i 0 -m 1 -Q - name: Upload ${{ inputs.chip }} ${{ inputs.type }} QEMU results as cache - uses: actions/cache/save@v4 - if: ${{ always() && steps.check-tests.outputs.enabled == 'true' }} + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + if: steps.check-tests.outputs.enabled == 'true' && github.event.pull_request.number != null with: key: tests-${{ env.id }}-results-qemu path: | @@ -133,7 +133,7 @@ jobs: tests/**/result_*.json - name: Upload ${{ inputs.chip }} ${{ inputs.type }} QEMU results as artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: always() with: name: tests-results-qemu-${{ inputs.chip }}-${{ inputs.type }} diff --git a/.github/workflows/tests_results.yml b/.github/workflows/tests_results.yml new file mode 100644 index 00000000000..ebba2a3aa08 --- /dev/null +++ b/.github/workflows/tests_results.yml @@ -0,0 +1,195 @@ +name: Publish and clean test results + +on: + workflow_run: + workflows: ["Wokwi tests"] + types: + - completed + +# No permissions by default +permissions: { contents: read } + +jobs: + unit-test-results: + name: Unit Test Results + if: | + github.event.workflow_run.conclusion == 'success' || + github.event.workflow_run.conclusion == 'failure' || + github.event.workflow_run.conclusion == 'timed_out' + runs-on: ubuntu-latest + permissions: + actions: write + statuses: write + checks: write + pull-requests: write + contents: write + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: gh-pages + + - name: Download and Extract Artifacts + uses: dawidd6/action-download-artifact@07ab29fd4a977ae4d2b275087cf67563dfdf0295 # v9 + with: + run_id: ${{ github.event.workflow_run.id }} + path: ./artifacts + + - name: Get original info + run: | + original_event=$(cat ./artifacts/parent-artifacts/event.txt) + original_action=$(cat ./artifacts/parent-artifacts/action.txt) + original_sha=$(cat ./artifacts/parent-artifacts/sha.txt) + original_ref=$(cat ./artifacts/parent-artifacts/ref.txt) + original_conclusion=$(cat ./artifacts/parent-artifacts/conclusion.txt) + original_run_id=$(cat ./artifacts/parent-artifacts/run_id.txt) + + # Sanitize the values to avoid security issues + + # Event: Allow alphabetical characters and underscores + original_event=$(echo "$original_event" | tr -cd '[:alpha:]_') + + # Action: Allow alphabetical characters and underscores + original_action=$(echo "$original_action" | tr -cd '[:alpha:]_') + + # SHA: Allow alphanumeric characters + original_sha=$(echo "$original_sha" | tr -cd '[:alnum:]') + + # Ref: Allow alphanumeric characters, slashes, underscores, dots, and dashes + original_ref=$(echo "$original_ref" | tr -cd '[:alnum:]/_.-') + + # Conclusion: Allow alphabetical characters and underscores + original_conclusion=$(echo "$original_conclusion" | tr -cd '[:alpha:]_') + + # Run ID: Allow numeric characters + original_run_id=$(echo "$original_run_id" | tr -cd '[:digit:]') + + echo "original_event=$original_event" >> $GITHUB_ENV + echo "original_action=$original_action" >> $GITHUB_ENV + echo "original_sha=$original_sha" >> $GITHUB_ENV + echo "original_ref=$original_ref" >> $GITHUB_ENV + echo "original_conclusion=$original_conclusion" >> $GITHUB_ENV + echo "original_run_id=$original_run_id" >> $GITHUB_ENV + + echo "original_event = $original_event" + echo "original_action = $original_action" + echo "original_sha = $original_sha" + echo "original_ref = $original_ref" + echo "original_conclusion = $original_conclusion" + echo "original_run_id = $original_run_id" + + - name: Print links to other runs + run: | + echo "Build, Hardware and QEMU tests: https://github.com/${{ github.repository }}/actions/runs/${{ env.original_run_id }}" + echo "Wokwi tests: https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}" + + - name: Publish Unit Test Results + uses: EnricoMi/publish-unit-test-result-action@170bf24d20d201b842d7a52403b73ed297e6645b # v2.18.0 + with: + commit: ${{ env.original_sha }} + event_file: ./artifacts/parent-artifacts/event_file/event.json + event_name: ${{ env.original_event }} + files: ./artifacts/**/*.xml + action_fail: true + compare_to_earlier_commit: false + json_file: ./unity_results.json + json_suite_details: true + + - name: Upload JSON + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + if: ${{ always() }} + with: + name: unity_results + overwrite: true + path: | + ./unity_results.json + + - name: Fail if tests failed + if: ${{ env.original_conclusion == 'failure' || env.original_conclusion == 'timed_out' || github.event.workflow_run.conclusion == 'failure' || github.event.workflow_run.conclusion == 'timed_out' }} + run: exit 1 + + - name: Clean up caches + if: always() + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const ref = process.env.original_ref; + const key_prefix = 'tests-' + ref + '-'; + + if (process.env.original_event == 'pull_request' && process.env.original_action != 'closed') { + console.log('Skipping cache cleanup for open PR'); + return; + } + + await github.paginate(github.rest.actions.getActionsCacheList, { + owner: context.repo.owner, + repo: context.repo.repo, + per_page: 100, + key: key_prefix + }).then(caches => { + if (caches) { + for (const cache of caches) { + console.log(`Deleting cache: ${cache.key}`); + github.rest.actions.deleteActionsCacheById({ + owner: context.repo.owner, + repo: context.repo.repo, + cache_id: cache.id + }); + } + } + }); + + - name: Report conclusion + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + if: always() + with: + script: | + const owner = '${{ github.repository_owner }}'; + const repo = '${{ github.repository }}'.split('/')[1]; + const sha = process.env.original_sha; + core.debug(`owner: ${owner}`); + core.debug(`repo: ${repo}`); + core.debug(`sha: ${sha}`); + const { context: name, state } = (await github.rest.repos.createCommitStatus({ + context: `Runtime Tests / Report results (${process.env.original_event} -> workflow_run -> workflow_run)`, + owner: owner, + repo: repo, + sha: sha, + state: '${{ job.status }}', + description: '${{ job.status }}' == 'success' ? 'Runtime tests successful' : 'Runtime tests failed', + target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' + })).data; + core.info(`${name} is ${state}`); + + - name: Generate report + if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled + env: + REPORT_FILE: ./runtime-tests-results/RUNTIME_TESTS_REPORT.md + WOKWI_RUN_ID: ${{ github.event.workflow_run.id }} + BUILD_RUN_ID: ${{ env.original_run_id }} + IS_FAILING: ${{ env.original_conclusion == 'failure' || env.original_conclusion == 'timed_out' || github.event.workflow_run.conclusion == 'failure' || github.event.workflow_run.conclusion == 'timed_out' || job.status == 'failure' }} + run: | + rm -rf artifacts $REPORT_FILE + mv -f ./unity_results.json ./runtime-tests-results/unity_results.json + touch $REPORT_FILE + python3 ./runtime-tests-results/table_generator.py ./runtime-tests-results/unity_results.json >> $REPORT_FILE + + - name: Generate badge + if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled + uses: jaywcjlove/generated-badges@0e078ae4d4bab3777ea4f137de496ab44688f5ad # v1.0.13 + with: + label: Runtime Tests + status: ${{ job.status == 'success' && 'passing' || 'failing' }} + output: runtime-tests-results/badge.svg + color: ${{ job.status == 'success' && 'green' || 'red' }} + style: flat + + - name: Push badge + if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + if [[ `git status --porcelain` ]]; then + git add --all + git commit -m "Updated runtime tests report" + git push origin HEAD:gh-pages + fi diff --git a/.github/workflows/tests_wokwi.yml b/.github/workflows/tests_wokwi.yml new file mode 100644 index 00000000000..03dd64fc0fb --- /dev/null +++ b/.github/workflows/tests_wokwi.yml @@ -0,0 +1,326 @@ +name: Wokwi tests + +on: + workflow_run: + workflows: ["Runtime Tests"] + types: + - completed + +# No permissions by default +permissions: { contents: read } + +env: + WOKWI_TIMEOUT: 600000 # Milliseconds + +jobs: + get-artifacts: + name: Get required artifacts + runs-on: ubuntu-latest + permissions: + actions: read + statuses: write + outputs: + pr_num: ${{ steps.set-ref.outputs.pr_num }} + ref: ${{ steps.set-ref.outputs.ref }} + base: ${{ steps.set-ref.outputs.base }} + targets: ${{ steps.set-ref.outputs.targets }} + types: ${{ steps.set-ref.outputs.types }} + steps: + - name: Report pending + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const owner = '${{ github.repository_owner }}'; + const repo = '${{ github.repository }}'.split('/')[1]; + const sha = '${{ github.event.workflow_run.head_sha }}'; + core.debug(`owner: ${owner}`); + core.debug(`repo: ${repo}`); + core.debug(`sha: ${sha}`); + const { context: name, state } = (await github.rest.repos.createCommitStatus({ + context: 'Runtime Tests / Wokwi (Get artifacts) (${{ github.event.workflow_run.event }} -> workflow_run)', + owner: owner, + repo: repo, + sha: sha, + state: 'pending', + target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' + })).data; + core.info(`${name} is ${state}`); + + - name: Download and extract event file + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + name: event_file + path: artifacts/event_file + + - name: Download and extract matrix info + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + name: matrix_info + path: artifacts/matrix_info + + - name: Try to read PR number + id: set-ref + run: | + pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json | tr -cd "[:digit:]") + if [ -z "$pr_num" ] || [ "$pr_num" == "null" ]; then + pr_num="" + fi + + ref=$pr_num + if [ -z "$ref" ] || [ "$ref" == "null" ]; then + ref=${{ github.ref }} + fi + + action=$(jq -r '.action' artifacts/event_file/event.json | tr -cd "[:alpha:]_") + if [ "$action" == "null" ]; then + action="" + fi + + base=$(jq -r '.pull_request.base.ref' artifacts/event_file/event.json | tr -cd "[:alnum:]/_.-") + if [ -z "$base" ] || [ "$base" == "null" ]; then + base=${{ github.ref }} + fi + + types=$(cat artifacts/matrix_info/wokwi_types.txt | tr -cd "[:alpha:],[]'") + targets=$(cat artifacts/matrix_info/targets.txt | tr -cd "[:alnum:],[]'") + + echo "base = $base" + echo "targets = $targets" + echo "types = $types" + echo "pr_num = $pr_num" + + printf "$ref" >> artifacts/ref.txt + printf "Ref = " + cat artifacts/ref.txt + + printf "${{ github.event.workflow_run.event }}" >> artifacts/event.txt + printf "\nEvent name = " + cat artifacts/event.txt + + printf "${{ github.event.workflow_run.head_sha || github.sha }}" >> artifacts/sha.txt + printf "\nHead SHA = " + cat artifacts/sha.txt + + printf "$action" >> artifacts/action.txt + printf "\nAction = " + cat artifacts/action.txt + + printf "${{ github.event.workflow_run.id }}" >> artifacts/run_id.txt + printf "\nRun ID = " + cat artifacts/run_id.txt + + if [ -z "$ref" ] || [ "$ref" == "null" ]; then + echo "Failed to get PR number or ref" + exit 1 + fi + + conclusion="${{ github.event.workflow_run.conclusion }}" + printf "$conclusion" >> artifacts/conclusion.txt + printf "\nConclusion = " + cat artifacts/conclusion.txt + + echo "pr_num=$pr_num" >> $GITHUB_OUTPUT + echo "base=$base" >> $GITHUB_OUTPUT + echo "targets=$targets" >> $GITHUB_OUTPUT + echo "types=$types" >> $GITHUB_OUTPUT + echo "ref=$ref" >> $GITHUB_OUTPUT + + - name: Download and extract parent hardware results + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + continue-on-error: true + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + pattern: tests-results-hw-* + merge-multiple: true + path: artifacts/results/hw + + - name: Download and extract parent QEMU results + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + continue-on-error: true + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + pattern: tests-results-qemu-* + merge-multiple: true + path: artifacts/results/qemu + + - name: Upload parent artifacts + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: parent-artifacts + path: artifacts + if-no-files-found: error + + - name: Report conclusion + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + if: always() + with: + script: | + const owner = '${{ github.repository_owner }}'; + const repo = '${{ github.repository }}'.split('/')[1]; + const sha = '${{ github.event.workflow_run.head_sha }}'; + core.debug(`owner: ${owner}`); + core.debug(`repo: ${repo}`); + core.debug(`sha: ${sha}`); + const { context: name, state } = (await github.rest.repos.createCommitStatus({ + context: 'Runtime Tests / Wokwi (Get artifacts) (${{ github.event.workflow_run.event }} -> workflow_run)', + owner: owner, + repo: repo, + sha: sha, + state: '${{ job.status }}', + target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' + })).data; + core.info(`${name} is ${state}`); + + wokwi-test: + name: Wokwi ${{ matrix.chip }} ${{ matrix.type }} tests + if: | + github.event.workflow_run.conclusion == 'success' || + github.event.workflow_run.conclusion == 'failure' || + github.event.workflow_run.conclusion == 'timed_out' + runs-on: ubuntu-latest + needs: get-artifacts + env: + id: ${{ needs.get-artifacts.outputs.ref }}-${{ github.event.workflow_run.head_sha || github.sha }}-${{ matrix.chip }}-${{ matrix.type }} + permissions: + actions: read + statuses: write + strategy: + fail-fast: false + matrix: + type: ${{ fromJson(needs.get-artifacts.outputs.types) }} + chip: ${{ fromJson(needs.get-artifacts.outputs.targets) }} + steps: + - name: Report pending + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const owner = '${{ github.repository_owner }}'; + const repo = '${{ github.repository }}'.split('/')[1]; + const sha = '${{ github.event.workflow_run.head_sha }}'; + core.debug(`owner: ${owner}`); + core.debug(`repo: ${repo}`); + core.debug(`sha: ${sha}`); + const { context: name, state } = (await github.rest.repos.createCommitStatus({ + context: 'Runtime Tests / Wokwi (${{ matrix.type }}, ${{ matrix.chip }}) / Wokwi ${{ matrix.chip }} ${{ matrix.type }} tests (${{ github.event.workflow_run.event }} -> workflow_run)', + owner: owner, + repo: repo, + sha: sha, + state: 'pending', + target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' + })).data; + core.info(`${name} is ${state}`); + + - name: Check if already passed + id: get-cache-results + if: needs.get-artifacts.outputs.pr_num + uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + key: tests-${{ env.id }}-results-wokwi + path: | + tests/**/*.xml + tests/**/result_*.json + + - name: Evaluate if tests should be run + id: check-tests + run: | + cache_exists=${{ steps.get-cache-results.outputs.cache-hit == 'true' }} + enabled=true + + if [[ $cache_exists == 'true' ]]; then + echo "Already ran, skipping" + enabled=false + fi + + echo "enabled=$enabled" >> $GITHUB_OUTPUT + + # Note that changes to the workflows and tests will only be picked up after the PR is merged + # DO NOT CHECKOUT THE USER'S REPOSITORY IN THIS WORKFLOW. IT HAS HIGH SECURITY RISKS. + - name: Checkout repository + if: ${{ steps.check-tests.outputs.enabled == 'true' }} + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ needs.get-artifacts.outputs.base || github.ref }} + + - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 + if: ${{ steps.check-tests.outputs.enabled == 'true' }} + with: + cache-dependency-path: tests/requirements.txt + cache: "pip" + python-version: "3.x" + + - name: Install dependencies + if: ${{ steps.check-tests.outputs.enabled == 'true' }} + run: | + pip install -U pip + pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi + + - name: Install Wokwi CLI + if: ${{ steps.check-tests.outputs.enabled == 'true' }} + run: curl -L https://wokwi.com/ci/install.sh | sh + + - name: Wokwi CI Server + if: ${{ steps.check-tests.outputs.enabled == 'true' }} + uses: wokwi/wokwi-ci-server-action@a6fabb5a49e080158c7a1d121ea5b789536a82c3 # v1 + + - name: Get binaries + if: ${{ steps.check-tests.outputs.enabled == 'true' }} + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + name: tests-bin-${{ matrix.chip }}-${{ matrix.type }} + path: | + ~/.arduino/tests/${{ matrix.chip }} + + - name: Run Tests + if: ${{ steps.check-tests.outputs.enabled == 'true' }} + env: + WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }} + run: | + bash .github/scripts/tests_run.sh -c -type ${{ matrix.type }} -t ${{ matrix.chip }} -i 0 -m 1 -W ${{ env.WOKWI_TIMEOUT }} + + - name: Upload ${{ matrix.chip }} ${{ matrix.type }} Wokwi results as cache + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + if: steps.check-tests.outputs.enabled == 'true' && needs.get-artifacts.outputs.pr_num + with: + key: tests-${{ env.id }}-results-wokwi + path: | + tests/**/*.xml + tests/**/result_*.json + + - name: Upload ${{ matrix.chip }} ${{ matrix.type }} Wokwi results as artifacts + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + if: always() + with: + name: tests-results-wokwi-${{ matrix.chip }}-${{ matrix.type }} + overwrite: true + path: | + tests/**/*.xml + tests/**/result_*.json + + - name: Report conclusion + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + if: always() + with: + script: | + const owner = '${{ github.repository_owner }}'; + const repo = '${{ github.repository }}'.split('/')[1]; + const sha = '${{ github.event.workflow_run.head_sha }}'; + core.debug(`owner: ${owner}`); + core.debug(`repo: ${repo}`); + core.debug(`sha: ${sha}`); + const { context: name, state } = (await github.rest.repos.createCommitStatus({ + context: 'Runtime Tests / Wokwi (${{ matrix.type }}, ${{ matrix.chip }}) / Wokwi ${{ matrix.chip }} ${{ matrix.type }} tests (${{ github.event.workflow_run.event }} -> workflow_run)', + owner: owner, + repo: repo, + sha: sha, + state: '${{ job.status }}', + target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' + })).data; + core.info(`${name} is ${state}`); diff --git a/.github/workflows/upload-idf-component.yml b/.github/workflows/upload-idf-component.yml index ca21361689f..687e721fbc2 100644 --- a/.github/workflows/upload-idf-component.yml +++ b/.github/workflows/upload-idf-component.yml @@ -1,20 +1,59 @@ name: Push components to https://components.espressif.com + on: - push: - tags: - - '*' + workflow_dispatch: + inputs: + tag: + description: 'Version to push to the component registry' + required: true + git_ref: + description: 'Git ref with the source to push to the component registry' + required: true + workflow_run: + workflows: ["ESP32 Arduino Release"] + types: + - completed + +permissions: + contents: read + jobs: upload_components: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - name: Get the release tag + env: + head_branch: ${{ inputs.tag || github.event.workflow_run.head_branch }} + run: | + if [ "${{ github.event.workflow_run.conclusion }}" != "success" ] && [ "${{ github.event_name }}" == "workflow_run" ]; then + echo "Release workflow failed. Exiting..." + exit 1 + fi + + # Read and sanitize the branch/tag name + branch=$(echo "$head_branch" | tr -cd '[:alnum:]/_.-') + + if [[ $branch == refs/tags/* ]]; then + tag="${branch#refs/tags/}" + elif [[ $branch =~ ^[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then + tag=$branch + else + echo "Tag not found in $branch. Exiting..." + exit 1 + fi + + echo "Tag: $tag" + echo "RELEASE_TAG=$tag" >> $GITHUB_ENV + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: + ref: ${{ inputs.git_ref || env.RELEASE_TAG }} submodules: "recursive" - name: Upload components to the component registry - uses: espressif/upload-components-ci-action@v1 + uses: espressif/upload-components-ci-action@b78a19fa5424714997596d3ecffa634aef8ae20b # v1.0.5 with: name: arduino-esp32 - version: ${{ github.ref_name }} + version: ${{ env.RELEASE_TAG }} namespace: espressif api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} diff --git a/.github/workflows/wokwi.yml b/.github/workflows/wokwi.yml deleted file mode 100644 index f9eee85f95f..00000000000 --- a/.github/workflows/wokwi.yml +++ /dev/null @@ -1,124 +0,0 @@ -name: Wokwi tests - -on: - workflow_call: - inputs: - chip: - type: string - description: 'Chip to run tests for' - required: true - type: - type: string - description: 'Type of tests to run' - required: true - secrets: - WOKWI_CLI_TOKEN: - description: 'Wokwi CLI API token' - required: true - -env: - WOKWI_TIMEOUT: 600000 # Milliseconds - -jobs: - wokwi-test: - name: Wokwi ${{ inputs.chip }} ${{ inputs.type }} tests - env: - id: ${{ github.event.pull_request.number || github.ref }}-${{ github.event.pull_request.head.sha || github.sha }}-${{ inputs.chip }}-${{ inputs.type }} - runs-on: ubuntu-latest - steps: - - name: Check if already run - if: ${{ github.event.pull_request.number != null }} - id: get-cache-results - uses: actions/cache/restore@v4 - with: - key: tests-${{ env.id }}-results-wokwi - path: | - tests/**/*.xml - tests/**/result_*.json - - - name: Evaluate if tests should be run - id: check-tests - run: | - cache_exists=${{ steps.get-cache-results.outputs.cache-hit == 'true' }} - enabled=true - - if [[ $cache_exists == 'true' ]]; then - echo "Already ran, skipping" - enabled=false - fi - - echo "enabled=$enabled" >> $GITHUB_OUTPUT - - - name: Checkout user repository - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - persist-credentials: false - sparse-checkout-cone-mode: false - sparse-checkout: | - /* - !.github - - # To avoid giving unknown scripts elevated permissions, download them from the master branch - - name: Get CI scripts from master - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - run: | - mkdir -p .github - cd .github - curl https://codeload.github.com/${{ github.repository }}/tar.gz/master | tar -xz --strip=2 arduino-esp32-master/.github - - - uses: actions/setup-python@v5 - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - with: - cache-dependency-path: tests/requirements.txt - cache: 'pip' - python-version: '3.x' - - - name: Install dependencies - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - run: | - pip install -U pip - pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi - - - name: Install Wokwi CLI - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - run: curl -L https://wokwi.com/ci/install.sh | sh - - - name: Wokwi CI Server - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - uses: wokwi/wokwi-ci-server-action@v1 - - - name: Get binaries - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - uses: actions/download-artifact@v4 - with: - name: tests-bin-${{ inputs.chip }}-${{ inputs.type }} - path: | - ~/.arduino/tests - - - name: Run Tests - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - env: - WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }} - run: | - bash .github/scripts/tests_run.sh -c -type ${{ inputs.type }} -t ${{inputs.chip}} -i 0 -m 1 -W ${{env.WOKWI_TIMEOUT}} - - - name: Upload ${{ inputs.chip }} ${{ inputs.type }} Wokwi results as cache - uses: actions/cache/save@v4 - if: ${{ always() && steps.check-tests.outputs.enabled == 'true' }} - with: - key: tests-${{ env.id }}-results-wokwi - path: | - tests/**/*.xml - tests/**/result_*.json - - - name: Upload ${{ inputs.chip }} ${{ inputs.type }} Wokwi results as artifacts - uses: actions/upload-artifact@v4 - if: always() - with: - name: tests-results-wokwi-${{ inputs.chip }}-${{ inputs.type }} - overwrite: true - path: | - tests/**/*.xml - tests/**/result_*.json diff --git a/.gitignore b/.gitignore index 1519de52764..d254d439834 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ tools/esp32-arduino-libs +tools/xtensa-esp-elf tools/xtensa-esp32-elf tools/xtensa-esp32s2-elf tools/xtensa-esp32s3-elf diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b06629896ed..0d425c46eae 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,9 @@ exclude: | (?x)( ^\.github\/| - ^tests\/performance\/coremark\/.*\.[ch]$ + ^tests\/performance\/coremark\/.*\.[ch]$| + ^tests\/performance\/superpi\/.*\.(cpp|h)$| + LICENSE\.md$ ) default_language_version: @@ -10,8 +12,9 @@ default_language_version: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: "v4.5.0" + rev: "cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b" # v5.0.0 hooks: + # Generic checks - id: check-case-conflict - id: check-symlinks - id: debug-statements @@ -23,48 +26,85 @@ repos: args: [--fix=lf] - id: trailing-whitespace args: [--markdown-linebreak-ext=md] - - repo: https://github.com/codespell-project/codespell - rev: "v2.2.4" - hooks: - - id: codespell - exclude: ^.*\.(svd|SVD)$ + + # JSON formatting + - id: pretty-format-json stages: [manual] + args: [--autofix] + types_or: [json] + exclude: | + (?x)( + diagram\..*\.json$| + package\.json$| + ^package\/.*$ + ) + - repo: https://github.com/pre-commit/mirrors-clang-format - rev: "v18.1.3" + rev: "f6446549e5e97ec9665b9b03e75b87b445857f9a" # v18.1.3 hooks: + # C/C++ formatting - id: clang-format types_or: [c, c++] + exclude: ^.*\/build_opt\.h$ + - repo: https://github.com/psf/black-pre-commit-mirror - rev: "22.10.0" + rev: "a4920527036bb9a3f3e6055d595849d67d0da066" # 25.1.0 hooks: + # Python formatting - id: black types_or: [python] args: [--line-length=120] #From the arduino code style. Add as argument rather than creating a new config file. + - repo: https://github.com/PyCQA/flake8 - rev: "7.0.0" + rev: "16f5f28a384f0781bebb37a08aa45e65b9526c50" # 7.2.0 hooks: + # Python linting - id: flake8 types_or: [python] additional_dependencies: - flake8-bugbear - flake8-comprehensions - flake8-simplify + - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v3.1.0" + rev: "ffb6a759a979008c0e6dff86e39f4745a2d9eac4" # v3.1.0 hooks: + # YAML formatting - id: prettier types_or: [yaml] + + - repo: https://github.com/codespell-project/codespell + rev: "63c8f8312b7559622c0d82815639671ae42132ac" # v2.4.1 + hooks: + # Spell checking + - id: codespell + exclude: ^.*\.(svd|SVD)$ + + - repo: https://github.com/shellcheck-py/shellcheck-py + rev: "a23f6b85d0fdd5bb9d564e2579e678033debbdff" # v0.10.0.1 + hooks: + # Bash linting + - id: shellcheck + types: [shell] + + - repo: https://github.com/openstack/bashate + rev: "fbd7c2534c2701351c603ff700ddf08202430a31" # 2.1.1 + hooks: + # Bash formatting + - id: bashate + types: [shell] + args: ["-i", "E006"] # Ignore E006: Line too long + - repo: https://github.com/errata-ai/vale - rev: "v3.0.7" + rev: "dc4c47923788a413fb5677de6e3370d514aecb78" # v3.11.2 hooks: + # Sync vale styles and lint markdown and reStructuredText - id: vale name: vale-sync - language_version: "1.21.6" + language_version: "1.23.2" pass_filenames: false args: [sync] types_or: [markdown, rst] - stages: [manual] - id: vale - language_version: "1.21.6" + language_version: "1.23.2" types_or: [markdown, rst] - stages: [manual] diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 00000000000..a7612e611a2 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,11 @@ +# Shellcheck configuration file for ESP32 Arduino core + +# Optional checks. https://github.com/koalaman/shellcheck/wiki/optional +enable=add-default-case,deprecate-which,avoid-nullary-conditions + +# Enable search for external sources +external-sources=true + +# Search folder for sourced files. +# Set to the folder where the original script is located. +source-path=SCRIPTDIR diff --git a/.vale.ini b/.vale.ini index d51d3016a57..f04df30f840 100644 --- a/.vale.ini +++ b/.vale.ini @@ -23,7 +23,7 @@ StylesPath = .vale/styles # Specify the minimum alert severity that Vale will report. -MinAlertLevel = suggestion # "suggestion", "warning", or "error" +MinAlertLevel = error # "suggestion", "warning", or "error" # Specify vocabulary for special treatment. diff --git a/CMakeLists.txt b/CMakeLists.txt index ba19b8cf035..14fcb19b6da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ # export ARDUINO_SKIP_IDF_VERSION_CHECK=1 # idf.py build -set(min_supported_idf_version "5.1.0") -set(max_supported_idf_version "5.1.99") +set(min_supported_idf_version "5.3.0") +set(max_supported_idf_version "5.4.99") set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}.${IDF_VERSION_PATCH}") if ("${idf_version}" AND NOT "$ENV{ARDUINO_SKIP_IDF_VERSION_CHECK}") @@ -25,6 +25,7 @@ endif() set(CORE_SRCS cores/esp32/base64.cpp cores/esp32/cbuf.cpp + cores/esp32/ColorFormat.c cores/esp32/chip-debug-report.cpp cores/esp32/esp32-hal-adc.c cores/esp32/esp32-hal-bt.c @@ -32,6 +33,7 @@ set(CORE_SRCS cores/esp32/esp32-hal-dac.c cores/esp32/esp32-hal-gpio.c cores/esp32/esp32-hal-i2c.c + cores/esp32/esp32-hal-i2c-ng.c cores/esp32/esp32-hal-i2c-slave.c cores/esp32/esp32-hal-ledc.c cores/esp32/esp32-hal-matrix.c @@ -45,9 +47,11 @@ set(CORE_SRCS cores/esp32/esp32-hal-timer.c cores/esp32/esp32-hal-tinyusb.c cores/esp32/esp32-hal-touch.c + cores/esp32/esp32-hal-touch-ng.c cores/esp32/esp32-hal-uart.c cores/esp32/esp32-hal-rmt.c cores/esp32/Esp.cpp + cores/esp32/freertos_stats.cpp cores/esp32/FunctionalInterrupt.cpp cores/esp32/HardwareSerial.cpp cores/esp32/HEXBuilder.cpp @@ -93,8 +97,10 @@ set(ARDUINO_ALL_LIBRARIES HTTPUpdate Insights LittleFS + Matter NetBIOS Network + OpenThread PPP Preferences RainMaker @@ -111,10 +117,10 @@ set(ARDUINO_ALL_LIBRARIES WiFi WiFiProv Wire + Zigbee ) set(ARDUINO_LIBRARY_ArduinoOTA_SRCS libraries/ArduinoOTA/src/ArduinoOTA.cpp) -set(ARDUINO_LIBRARY_ArduinoOTA_REQUIRES esp_https_ota) set(ARDUINO_LIBRARY_AsyncUDP_SRCS libraries/AsyncUDP/src/AsyncUDP.cpp) @@ -158,6 +164,27 @@ set(ARDUINO_LIBRARY_LittleFS_SRCS libraries/LittleFS/src/LittleFS.cpp) set(ARDUINO_LIBRARY_NetBIOS_SRCS libraries/NetBIOS/src/NetBIOS.cpp) +set(ARDUINO_LIBRARY_OpenThread_SRCS + libraries/OpenThread/src/OThreadCLI.cpp + libraries/OpenThread/src/OThreadCLI_Util.cpp) + +set(ARDUINO_LIBRARY_Matter_SRCS + libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.cpp + libraries/Matter/src/MatterEndpoints/MatterOnOffLight.cpp + libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp + libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp + libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp + libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp + libraries/Matter/src/MatterEndpoints/MatterFan.cpp + libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp + libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp + libraries/Matter/src/MatterEndpoints/MatterContactSensor.cpp + libraries/Matter/src/MatterEndpoints/MatterPressureSensor.cpp + libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.cpp + libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.cpp + libraries/Matter/src/MatterEndpoints/MatterThermostat.cpp + libraries/Matter/src/Matter.cpp) + set(ARDUINO_LIBRARY_PPP_SRCS libraries/PPP/src/PPP.cpp libraries/PPP/src/ppp.c) @@ -198,6 +225,16 @@ set(ARDUINO_LIBRARY_USB_SRCS libraries/USB/src/USBMIDI.cpp libraries/USB/src/USBHIDMouse.cpp libraries/USB/src/USBHIDKeyboard.cpp + libraries/USB/src/keyboardLayout/KeyboardLayout_da_DK.cpp + libraries/USB/src/keyboardLayout/KeyboardLayout_de_DE.cpp + libraries/USB/src/keyboardLayout/KeyboardLayout_en_US.cpp + libraries/USB/src/keyboardLayout/KeyboardLayout_es_ES.cpp + libraries/USB/src/keyboardLayout/KeyboardLayout_fr_FR.cpp + libraries/USB/src/keyboardLayout/KeyboardLayout_hu_HU.cpp + libraries/USB/src/keyboardLayout/KeyboardLayout_it_IT.cpp + libraries/USB/src/keyboardLayout/KeyboardLayout_pt_BR.cpp + libraries/USB/src/keyboardLayout/KeyboardLayout_pt_PT.cpp + libraries/USB/src/keyboardLayout/KeyboardLayout_sv_SE.cpp libraries/USB/src/USBHIDGamepad.cpp libraries/USB/src/USBHIDConsumerControl.cpp libraries/USB/src/USBHIDSystemControl.cpp @@ -207,7 +244,11 @@ set(ARDUINO_LIBRARY_USB_SRCS set(ARDUINO_LIBRARY_WebServer_SRCS libraries/WebServer/src/WebServer.cpp libraries/WebServer/src/Parsing.cpp - libraries/WebServer/src/detail/mimetable.cpp) + libraries/WebServer/src/detail/mimetable.cpp + libraries/WebServer/src/middleware/MiddlewareChain.cpp + libraries/WebServer/src/middleware/AuthenticationMiddleware.cpp + libraries/WebServer/src/middleware/CorsMiddleware.cpp + libraries/WebServer/src/middleware/LoggingMiddleware.cpp) set(ARDUINO_LIBRARY_NetworkClientSecure_SRCS libraries/NetworkClientSecure/src/ssl_client.cpp @@ -235,7 +276,35 @@ set(ARDUINO_LIBRARY_WiFiProv_SRCS libraries/WiFiProv/src/WiFiProv.cpp) set(ARDUINO_LIBRARY_Wire_SRCS libraries/Wire/src/Wire.cpp) +set(ARDUINO_LIBRARY_Zigbee_SRCS + libraries/Zigbee/src/ZigbeeCore.cpp + libraries/Zigbee/src/ZigbeeEP.cpp + libraries/Zigbee/src/ZigbeeHandlers.cpp + libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp + libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp + libraries/Zigbee/src/ep/ZigbeeDimmableLight.cpp + libraries/Zigbee/src/ep/ZigbeeLight.cpp + libraries/Zigbee/src/ep/ZigbeeSwitch.cpp + libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp + libraries/Zigbee/src/ep/ZigbeeThermostat.cpp + libraries/Zigbee/src/ep/ZigbeeFlowSensor.cpp + libraries/Zigbee/src/ep/ZigbeePressureSensor.cpp + libraries/Zigbee/src/ep/ZigbeeOccupancySensor.cpp + libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.cpp + libraries/Zigbee/src/ep/ZigbeeContactSwitch.cpp + libraries/Zigbee/src/ep/ZigbeeDoorWindowHandle.cpp + libraries/Zigbee/src/ep/ZigbeeWindowCovering.cpp + libraries/Zigbee/src/ep/ZigbeeVibrationSensor.cpp + libraries/Zigbee/src/ep/ZigbeeAnalog.cpp + libraries/Zigbee/src/ep/ZigbeeRangeExtender.cpp + libraries/Zigbee/src/ep/ZigbeeGateway.cpp + libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.cpp + libraries/Zigbee/src/ep/ZigbeeIlluminanceSensor.cpp + libraries/Zigbee/src/ep/ZigbeePM25Sensor.cpp + ) + set(ARDUINO_LIBRARY_BLE_SRCS + libraries/BLE/src/BLE2901.cpp libraries/BLE/src/BLE2902.cpp libraries/BLE/src/BLE2904.cpp libraries/BLE/src/BLEAddress.cpp @@ -287,9 +356,21 @@ endforeach() set(includedirs variants/${CONFIG_ARDUINO_VARIANT}/ cores/esp32/ ${ARDUINO_LIBRARIES_INCLUDEDIRS}) set(srcs ${CORE_SRCS} ${ARDUINO_LIBRARIES_SRCS}) set(priv_includes cores/esp32/libb64) -set(requires spi_flash esp_partition mbedtls wifi_provisioning wpa_supplicant esp_adc esp_eth http_parser) +set(requires spi_flash esp_partition mbedtls wpa_supplicant esp_adc esp_eth http_parser esp_ringbuf esp_driver_gptimer esp_driver_usb_serial_jtag driver) set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support bt esp_hid usb esp_psram ${ARDUINO_LIBRARIES_REQUIRES}) +if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_OpenThread) + #if(CONFIG_SOC_IEEE802154_SUPPORTED) # Does not work! + #if(CONFIG_OPENTHREAD_ENABLED) # Does not work! + if(IDF_TARGET STREQUAL "esp32c6" OR IDF_TARGET STREQUAL "esp32h2") # Sadly only this works + list(APPEND requires openthread) + endif() +endif() + +if(IDF_TARGET STREQUAL "esp32p4") + list(APPEND requires esp_driver_touch_sens) +endif() + idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires}) if(NOT CONFIG_FREERTOS_HZ EQUAL 1000 AND NOT "$ENV{ARDUINO_SKIP_TICK_CHECK}") @@ -306,7 +387,7 @@ target_compile_options(${COMPONENT_TARGET} PUBLIC -DARDUINO_ARCH_ESP32 -DARDUINO_BOARD="${idf_target_caps}_DEV" -DARDUINO_VARIANT="${CONFIG_ARDUINO_VARIANT}" - -DESP32) + -DESP32=ESP32) if(CONFIG_AUTOSTART_ARDUINO) # in autostart mode, arduino-esp32 contains app_main() function and needs to @@ -329,9 +410,21 @@ function(maybe_add_component component_name) endif() endfunction() -if(IDF_TARGET MATCHES "esp32s2|esp32s3" AND CONFIG_TINYUSB_ENABLED) +if(IDF_TARGET MATCHES "esp32s2|esp32s3|esp32p4" AND CONFIG_TINYUSB_ENABLED) maybe_add_component(arduino_tinyusb) endif() if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ArduinoOTA) maybe_add_component(esp_https_ota) endif() +if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ESP_SR) + maybe_add_component(espressif__esp_sr) +endif() +if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_Matter) + maybe_add_component(espressif__esp_matter) +endif() +if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_LittleFS) + maybe_add_component(joltwallet__littlefs) +endif() +if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_WiFiProv) + maybe_add_component(espressif__network_provisioning) +endif() diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index ab0dbd360b3..0c90775c760 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -5,7 +5,7 @@ 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, +identity and expression, level of experience, education, socioeconomic status, nationality, personal appearance, race, religion, or sexual identity and orientation. diff --git a/Kconfig.projbuild b/Kconfig.projbuild index c1a9f4cb7bd..9966463f8c1 100644 --- a/Kconfig.projbuild +++ b/Kconfig.projbuild @@ -266,6 +266,11 @@ config ARDUINO_SELECTIVE_Wire depends on ARDUINO_SELECTIVE_COMPILATION default y +config ARDUINO_SELECTIVE_ESP_SR + bool "Enable ESP-SR" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + config ARDUINO_SELECTIVE_EEPROM bool "Enable EEPROM" depends on ARDUINO_SELECTIVE_COMPILATION @@ -286,6 +291,11 @@ config ARDUINO_SELECTIVE_Update depends on ARDUINO_SELECTIVE_COMPILATION default y +config ARDUINO_SELECTIVE_Zigbee + bool "Enable Zigbee" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + config ARDUINO_SELECTIVE_FS bool "Enable FS" depends on ARDUINO_SELECTIVE_COMPILATION @@ -355,7 +365,12 @@ config ARDUINO_SELECTIVE_ESPmDNS config ARDUINO_SELECTIVE_HTTPClient bool "Enable HTTPClient" depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network - select ARDUINO_SELECTIVE_WiFiClientSecure + select ARDUINO_SELECTIVE_NetworkClientSecure + default y + +config ARDUINO_SELECTIVE_Matter + bool "Enable Matter" + depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network default y config ARDUINO_SELECTIVE_NetBIOS @@ -375,7 +390,7 @@ config ARDUINO_SELECTIVE_WiFi default y config ARDUINO_SELECTIVE_NetworkClientSecure - bool "Enable WiFiClientSecure" + bool "Enable NetworkClientSecure" depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network default y @@ -399,4 +414,19 @@ config ARDUINO_SELECTIVE_SimpleBLE depends on ARDUINO_SELECTIVE_COMPILATION default y +config ARDUINO_SELECTIVE_RainMaker + bool "Enable RainMaker" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + +config ARDUINO_SELECTIVE_OpenThread + bool "Enable OpenThread" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + +config ARDUINO_SELECTIVE_Insights + bool "Enable Insights" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + endmenu diff --git a/README.md b/README.md index 52d13707db6..f40315c03cc 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,13 @@ -# Arduino core for the ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6 and ESP32-H2 +# Arduino core for the ESP32, ESP32-C3, ESP32-C6, ESP32-H2, ESP32-P4, ESP32-S2 and ESP32-S3. -![Build Status](https://github.com/espressif/arduino-esp32/workflows/ESP32%20Arduino%20CI/badge.svg) [![External Libraries Test](https://github.com/espressif/arduino-esp32/actions/workflows/lib.yml/badge.svg?branch=master&event=schedule)](https://github.com/espressif/arduino-esp32/blob/gh-pages/LIBRARIES_TEST.md) [![Hardware Tests](https://github.com/espressif/arduino-esp32/actions/workflows/tests.yml/badge.svg?branch=master&event=schedule)](https://github.com/espressif/arduino-esp32/actions/workflows/tests.yml?query=event%3Aschedule) +[![Build Status](https://img.shields.io/github/actions/workflow/status/espressif/arduino-esp32/push.yml?branch=master&event=push&label=Compilation%20Tests)](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml?query=branch%3Amaster+event%3Apush) +[![Verbose Build Status](https://img.shields.io/github/actions/workflow/status/espressif/arduino-esp32/push.yml?branch=master&event=schedule&label=Compilation%20Tests%20(Verbose))](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml?query=branch%3Amaster+event%3Aschedule) +[![External Libraries Test](https://img.shields.io/github/actions/workflow/status/espressif/arduino-esp32/lib.yml?branch=master&event=schedule&label=External%20Libraries%20Test)](https://github.com/espressif/arduino-esp32/blob/gh-pages/LIBRARIES_TEST.md) +[![Runtime Tests](https://github.com/espressif/arduino-esp32/blob/gh-pages/runtime-tests-results/badge.svg)](https://github.com/espressif/arduino-esp32/blob/gh-pages/runtime-tests-results/RUNTIME_TESTS_REPORT.md) -### Need help or have a question? Join the chat at [Gitter](https://gitter.im/espressif/arduino-esp32) or [open a new Discussion](https://github.com/espressif/arduino-esp32/discussions) +### Need help or have a question? Join the chat at [Discord](https://discord.gg/8xY6e9crwv) or [open a new Discussion](https://github.com/espressif/arduino-esp32/discussions) + +[![Discord invite](https://img.shields.io/discord/1327272229427216425?logo=discord&logoColor=white&logoSize=auto&label=Discord)](https://discord.gg/8xY6e9crwv) ## Contents @@ -16,9 +21,17 @@ ### Development Status -Latest Stable Release [![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) [![Release Date](https://img.shields.io/github/release-date/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) [![Downloads](https://img.shields.io/github/downloads/espressif/arduino-esp32/latest/total.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) +#### Latest Stable Release + +[![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32.svg)](https://github.com/espressif/arduino-esp32/releases/latest/) +[![Release Date](https://img.shields.io/github/release-date/espressif/arduino-esp32.svg)](https://github.com/espressif/arduino-esp32/releases/latest/) +[![Downloads](https://img.shields.io/github/downloads/espressif/arduino-esp32/latest/total.svg)](https://github.com/espressif/arduino-esp32/releases/latest/) -Latest Development Release [![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32/all.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/) [![Release Date](https://img.shields.io/github/release-date-pre/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/) [![Downloads](https://img.shields.io/github/downloads-pre/espressif/arduino-esp32/latest/total.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/) +#### Latest Development Release + +[![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32/all.svg)](https://github.com/espressif/arduino-esp32/releases/) +[![Release Date](https://img.shields.io/github/release-date-pre/espressif/arduino-esp32.svg)](https://github.com/espressif/arduino-esp32/releases/) +[![Downloads](https://img.shields.io/github/downloads-pre/espressif/arduino-esp32/latest/total.svg)](https://github.com/espressif/arduino-esp32/releases/) ### Development Planning @@ -54,15 +67,17 @@ Here are the ESP32 series supported by the Arduino-ESP32 project: | **SoC** | **Stable** | **Development** | **Datasheet** | |----------|:----------:|:---------------:|:-------------------------------------------------------------------------------------------------:| | ESP32 | Yes | Yes | [ESP32](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) | -| ESP32-S2 | Yes | Yes | [ESP32-S2](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) | | ESP32-C3 | Yes | Yes | [ESP32-C3](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) | -| ESP32-S3 | Yes | Yes | [ESP32-S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) | | ESP32-C6 | Yes | Yes | [ESP32-C6](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) | | ESP32-H2 | Yes | Yes | [ESP32-H2](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) | +| ESP32-P4 | Yes | Yes | [ESP32-P4](https://www.espressif.com/sites/default/files/documentation/esp32-p4_datasheet_en.pdf) | +| ESP32-S2 | Yes | Yes | [ESP32-S2](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) | +| ESP32-S3 | Yes | Yes | [ESP32-S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) | > [!NOTE] -> ESP32-C2 is also supported by Arduino-ESP32 but requires rebuilding the static libraries. This is not trivial and requires a good understanding of the ESP-IDF -> build system. For more information, see the [Lib Builder documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/lib_builder.html). +> ESP32-C2 is also supported by Arduino-ESP32 but requires using Arduino as an ESP-IDF component or rebuilding the static libraries. +> For more information, see the [Arduino as an ESP-IDF component documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/esp-idf_component.html) or the +> [Lib Builder documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/lib_builder.html), respectively. For more details visit the [supported chips](https://docs.espressif.com/projects/arduino-esp32/en/latest/getting_started.html#supported-soc-s) documentation page. diff --git a/boards.txt b/boards.txt index 5163a2d84c9..7113bf4c248 100644 --- a/boards.txt +++ b/boards.txt @@ -123,7 +123,6 @@ esp32c2.menu.FlashFreq.30.build.flash_freq=30m esp32c2.menu.FlashSize.2M=2MB (16Mb) esp32c2.menu.FlashSize.2M.build.flash_size=2MB -esp32c2.menu.FlashSize.2M.build.partitions=minimal esp32c2.menu.FlashSize.4M=4MB (32Mb) esp32c2.menu.FlashSize.4M.build.flash_size=4MB @@ -162,6 +161,195 @@ esp32c2.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +esp32p4.name=ESP32P4 Dev Module + +esp32p4.bootloader.tool=esptool_py +esp32p4.bootloader.tool.default=esptool_py + +esp32p4.upload.tool=esptool_py +esp32p4.upload.tool.default=esptool_py +esp32p4.upload.tool.network=esp_ota + +esp32p4.upload.maximum_size=1310720 +esp32p4.upload.maximum_data_size=327680 +esp32p4.upload.flags= +esp32p4.upload.extra_flags= +esp32p4.upload.use_1200bps_touch=false +esp32p4.upload.wait_for_upload_port=false + +esp32p4.serial.disableDTR=false +esp32p4.serial.disableRTS=false + +esp32p4.build.tarch=riscv32 +esp32p4.build.target=esp +esp32p4.build.mcu=esp32p4 +esp32p4.build.core=esp32 +esp32p4.build.variant=esp32p4 +esp32p4.build.board=ESP32P4_DEV +esp32p4.build.bootloader_addr=0x2000 + +esp32p4.build.usb_mode=0 +esp32p4.build.cdc_on_boot=0 +esp32p4.build.msc_on_boot=0 +esp32p4.build.dfu_on_boot=0 +esp32p4.build.f_cpu=360000000L +esp32p4.build.flash_size=4MB +esp32p4.build.flash_freq=80m +esp32p4.build.img_freq=80m +esp32p4.build.flash_mode=qio +esp32p4.build.boot=qio +esp32p4.build.partitions=default +esp32p4.build.defines= + +## IDE 2.0 Seems to not update the value +esp32p4.menu.JTAGAdapter.default=Disabled +esp32p4.menu.JTAGAdapter.default.build.copy_jtag_files=0 +esp32p4.menu.JTAGAdapter.builtin=Integrated USB JTAG +esp32p4.menu.JTAGAdapter.builtin.build.openocdscript=esp32p4-builtin.cfg +esp32p4.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +esp32p4.menu.JTAGAdapter.external=FTDI Adapter +esp32p4.menu.JTAGAdapter.external.build.openocdscript=esp32p4-ftdi.cfg +esp32p4.menu.JTAGAdapter.external.build.copy_jtag_files=1 +esp32p4.menu.JTAGAdapter.bridge=ESP USB Bridge +esp32p4.menu.JTAGAdapter.bridge.build.openocdscript=esp32p4-bridge.cfg +esp32p4.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +esp32p4.menu.PSRAM.disabled=Disabled +esp32p4.menu.PSRAM.disabled.build.defines= +esp32p4.menu.PSRAM.enabled=Enabled +esp32p4.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM + +esp32p4.menu.USBMode.default=USB-OTG (TinyUSB) +esp32p4.menu.USBMode.default.build.usb_mode=0 +esp32p4.menu.USBMode.hwcdc=Hardware CDC and JTAG +esp32p4.menu.USBMode.hwcdc.build.usb_mode=1 + +esp32p4.menu.CDCOnBoot.default=Disabled +esp32p4.menu.CDCOnBoot.default.build.cdc_on_boot=0 +esp32p4.menu.CDCOnBoot.cdc=Enabled +esp32p4.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +esp32p4.menu.MSCOnBoot.default=Disabled +esp32p4.menu.MSCOnBoot.default.build.msc_on_boot=0 +esp32p4.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +esp32p4.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +esp32p4.menu.DFUOnBoot.default=Disabled +esp32p4.menu.DFUOnBoot.default.build.dfu_on_boot=0 +esp32p4.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +esp32p4.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +esp32p4.menu.UploadMode.default=UART0 / Hardware CDC +esp32p4.menu.UploadMode.default.upload.use_1200bps_touch=false +esp32p4.menu.UploadMode.default.upload.wait_for_upload_port=false +esp32p4.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +esp32p4.menu.UploadMode.cdc.upload.use_1200bps_touch=true +esp32p4.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +esp32p4.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +esp32p4.menu.PartitionScheme.default.build.partitions=default +esp32p4.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +esp32p4.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +esp32p4.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +esp32p4.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +esp32p4.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +esp32p4.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +esp32p4.menu.PartitionScheme.minimal.build.partitions=minimal +esp32p4.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +esp32p4.menu.PartitionScheme.no_fs.build.partitions=no_fs +esp32p4.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +esp32p4.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +esp32p4.menu.PartitionScheme.no_ota.build.partitions=no_ota +esp32p4.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +esp32p4.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +esp32p4.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +esp32p4.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +esp32p4.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +esp32p4.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +esp32p4.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +esp32p4.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +esp32p4.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +esp32p4.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +esp32p4.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +esp32p4.menu.PartitionScheme.huge_app.build.partitions=huge_app +esp32p4.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +esp32p4.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +esp32p4.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +esp32p4.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +esp32p4.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +esp32p4.menu.PartitionScheme.fatflash.build.partitions=ffat +esp32p4.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +esp32p4.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +esp32p4.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +esp32p4.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +esp32p4.menu.PartitionScheme.custom=Custom +esp32p4.menu.PartitionScheme.custom.build.partitions= +esp32p4.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +## From https://docs.espressif.com/projects/esp-idf/en/latest/esp32p4/api-reference/kconfig.html#config-esp-default-cpu-freq-mhz +esp32p4.menu.CPUFreq.360=360MHz +esp32p4.menu.CPUFreq.360.build.f_cpu=360000000L +esp32p4.menu.CPUFreq.40=40MHz +esp32p4.menu.CPUFreq.40.build.f_cpu=40000000L + +esp32p4.menu.FlashMode.qio=QIO +esp32p4.menu.FlashMode.qio.build.flash_mode=dio +esp32p4.menu.FlashMode.qio.build.boot=qio +esp32p4.menu.FlashMode.dio=DIO +esp32p4.menu.FlashMode.dio.build.flash_mode=dio +esp32p4.menu.FlashMode.dio.build.boot=dio + +esp32p4.menu.FlashFreq.80=80MHz +esp32p4.menu.FlashFreq.80.build.flash_freq=80m +esp32p4.menu.FlashFreq.40=40MHz +esp32p4.menu.FlashFreq.40.build.flash_freq=40m + +esp32p4.menu.FlashSize.4M=4MB (32Mb) +esp32p4.menu.FlashSize.4M.build.flash_size=4MB +esp32p4.menu.FlashSize.8M=8MB (64Mb) +esp32p4.menu.FlashSize.8M.build.flash_size=8MB +esp32p4.menu.FlashSize.8M.build.partitions=default_8MB +esp32p4.menu.FlashSize.2M=2MB (16Mb) +esp32p4.menu.FlashSize.2M.build.flash_size=2MB +esp32p4.menu.FlashSize.2M.build.partitions=minimal +esp32p4.menu.FlashSize.16M=16MB (128Mb) +esp32p4.menu.FlashSize.16M.build.flash_size=16MB + +esp32p4.menu.UploadSpeed.921600=921600 +esp32p4.menu.UploadSpeed.921600.upload.speed=921600 +esp32p4.menu.UploadSpeed.115200=115200 +esp32p4.menu.UploadSpeed.115200.upload.speed=115200 +esp32p4.menu.UploadSpeed.256000.windows=256000 +esp32p4.menu.UploadSpeed.256000.upload.speed=256000 +esp32p4.menu.UploadSpeed.230400.windows.upload.speed=256000 +esp32p4.menu.UploadSpeed.230400=230400 +esp32p4.menu.UploadSpeed.230400.upload.speed=230400 +esp32p4.menu.UploadSpeed.460800.linux=460800 +esp32p4.menu.UploadSpeed.460800.macosx=460800 +esp32p4.menu.UploadSpeed.460800.upload.speed=460800 +esp32p4.menu.UploadSpeed.512000.windows=512000 +esp32p4.menu.UploadSpeed.512000.upload.speed=512000 + +esp32p4.menu.DebugLevel.none=None +esp32p4.menu.DebugLevel.none.build.code_debug=0 +esp32p4.menu.DebugLevel.error=Error +esp32p4.menu.DebugLevel.error.build.code_debug=1 +esp32p4.menu.DebugLevel.warn=Warn +esp32p4.menu.DebugLevel.warn.build.code_debug=2 +esp32p4.menu.DebugLevel.info=Info +esp32p4.menu.DebugLevel.info.build.code_debug=3 +esp32p4.menu.DebugLevel.debug=Debug +esp32p4.menu.DebugLevel.debug.build.code_debug=4 +esp32p4.menu.DebugLevel.verbose=Verbose +esp32p4.menu.DebugLevel.verbose.build.code_debug=5 + +esp32p4.menu.EraseFlash.none=Disabled +esp32p4.menu.EraseFlash.none.upload.erase_cmd= +esp32p4.menu.EraseFlash.all=Enabled +esp32p4.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + esp32h2.name=ESP32H2 Dev Module esp32h2.bootloader.tool=esptool_py @@ -253,15 +441,33 @@ esp32h2.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32h2.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32h2.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32h2.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32h2.menu.PartitionScheme.rainmaker=RainMaker -esp32h2.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32h2.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +#esp32h2.menu.PartitionScheme.rainmaker=RainMaker 4MB +#esp32h2.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +#esp32h2.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +#esp32h2.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +#esp32h2.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +#esp32h2.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +#esp32h2.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +#esp32h2.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +#esp32h2.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +esp32h2.menu.PartitionScheme.zigbee_2MB=Zigbee 2MB with spiffs +esp32h2.menu.PartitionScheme.zigbee_2MB.build.partitions=zigbee_2MB +esp32h2.menu.PartitionScheme.zigbee_2MB.upload.maximum_size=1310720 esp32h2.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs esp32h2.menu.PartitionScheme.zigbee.build.partitions=zigbee esp32h2.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 +esp32h2.menu.PartitionScheme.zigbee_8MB=Zigbee 8MB with spiffs +esp32h2.menu.PartitionScheme.zigbee_8MB.build.partitions=zigbee_8MB +esp32h2.menu.PartitionScheme.zigbee_8MB.upload.maximum_size=3407872 +esp32h2.menu.PartitionScheme.zigbee_zczr_2MB=Zigbee ZCZR 2MB with spiffs +esp32h2.menu.PartitionScheme.zigbee_zczr_2MB.build.partitions=zigbee_zczr_2MB +esp32h2.menu.PartitionScheme.zigbee_zczr_2MB.upload.maximum_size=1310720 esp32h2.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs esp32h2.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr esp32h2.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +esp32h2.menu.PartitionScheme.zigbee_zczr_8MB=Zigbee ZCZR 8MB with spiffs +esp32h2.menu.PartitionScheme.zigbee_zczr_8MB.build.partitions=zigbee_zczr_8MB +esp32h2.menu.PartitionScheme.zigbee_zczr_8MB.upload.maximum_size=3407872 esp32h2.menu.PartitionScheme.custom=Custom esp32h2.menu.PartitionScheme.custom.build.partitions= esp32h2.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -287,10 +493,8 @@ esp32h2.menu.FlashSize.4M=4MB (32Mb) esp32h2.menu.FlashSize.4M.build.flash_size=4MB esp32h2.menu.FlashSize.8M=8MB (64Mb) esp32h2.menu.FlashSize.8M.build.flash_size=8MB -esp32h2.menu.FlashSize.8M.build.partitions=default_8MB esp32h2.menu.FlashSize.2M=2MB (16Mb) esp32h2.menu.FlashSize.2M.build.flash_size=2MB -esp32h2.menu.FlashSize.2M.build.partitions=minimal esp32h2.menu.FlashSize.16M=16MB (128Mb) esp32h2.menu.FlashSize.16M.build.flash_size=16MB @@ -332,14 +536,16 @@ esp32h2.menu.ZigbeeMode.default.build.zigbee_mode= esp32h2.menu.ZigbeeMode.default.build.zigbee_libs= esp32h2.menu.ZigbeeMode.ed=Zigbee ED (end device) esp32h2.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED -esp32h2.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -esp32h2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32h2.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +esp32h2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32h2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -esp32h2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port -esp32h2.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) -esp32h2.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP -esp32h2.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port - +esp32h2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native +esp32h2.menu.ZigbeeMode.ed_debug=Zigbee ED (end device) - Debug +esp32h2.menu.ZigbeeMode.ed_debug.build.zigbee_mode=-DZIGBEE_MODE_ED +esp32h2.menu.ZigbeeMode.ed_debug.build.zigbee_libs=-lesp_zb_api.ed.debug -lzboss_stack.ed.debug -lzboss_port.native.debug +esp32h2.menu.ZigbeeMode.zczr_debug=Zigbee ZCZR (coordinator/router) - Debug +esp32h2.menu.ZigbeeMode.zczr_debug.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +esp32h2.menu.ZigbeeMode.zczr_debug.build.zigbee_libs=-lesp_zb_api.zczr.debug -lzboss_stack.zczr.debug -lzboss_port.native.debug ############################################################## @@ -433,15 +639,33 @@ esp32c6.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32c6.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32c6.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32c6.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32c6.menu.PartitionScheme.rainmaker=RainMaker +esp32c6.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32c6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32c6.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32c6.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32c6.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32c6.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32c6.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32c6.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +esp32c6.menu.PartitionScheme.zigbee_2MB=Zigbee 2MB with spiffs +esp32c6.menu.PartitionScheme.zigbee_2MB.build.partitions=zigbee_2MB +esp32c6.menu.PartitionScheme.zigbee_2MB.upload.maximum_size=1310720 esp32c6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs esp32c6.menu.PartitionScheme.zigbee.build.partitions=zigbee esp32c6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 +esp32c6.menu.PartitionScheme.zigbee_8MB=Zigbee 8MB with spiffs +esp32c6.menu.PartitionScheme.zigbee_8MB.build.partitions=zigbee_8MB +esp32c6.menu.PartitionScheme.zigbee_8MB.upload.maximum_size=3407872 +esp32c6.menu.PartitionScheme.zigbee_zczr_2MB=Zigbee ZCZR 2MB with spiffs +esp32c6.menu.PartitionScheme.zigbee_zczr_2MB.build.partitions=zigbee_zczr_2MB +esp32c6.menu.PartitionScheme.zigbee_zczr_2MB.upload.maximum_size=1310720 esp32c6.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs esp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr esp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +esp32c6.menu.PartitionScheme.zigbee_zczr_8MB=Zigbee ZCZR 8MB with spiffs +esp32c6.menu.PartitionScheme.zigbee_zczr_8MB.build.partitions=zigbee_zczr_8MB +esp32c6.menu.PartitionScheme.zigbee_zczr_8MB.upload.maximum_size=3407872 esp32c6.menu.PartitionScheme.custom=Custom esp32c6.menu.PartitionScheme.custom.build.partitions= esp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -475,10 +699,8 @@ esp32c6.menu.FlashSize.4M=4MB (32Mb) esp32c6.menu.FlashSize.4M.build.flash_size=4MB esp32c6.menu.FlashSize.8M=8MB (64Mb) esp32c6.menu.FlashSize.8M.build.flash_size=8MB -esp32c6.menu.FlashSize.8M.build.partitions=default_8MB esp32c6.menu.FlashSize.2M=2MB (16Mb) esp32c6.menu.FlashSize.2M.build.flash_size=2MB -esp32c6.menu.FlashSize.2M.build.partitions=minimal esp32c6.menu.FlashSize.16M=16MB (128Mb) esp32c6.menu.FlashSize.16M.build.flash_size=16MB @@ -520,13 +742,16 @@ esp32c6.menu.ZigbeeMode.default.build.zigbee_mode= esp32c6.menu.ZigbeeMode.default.build.zigbee_libs= esp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) esp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED -esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port -esp32c6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) -esp32c6.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP -esp32c6.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port +esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native +esp32c6.menu.ZigbeeMode.ed_debug=Zigbee ED (end device) - Debug +esp32c6.menu.ZigbeeMode.ed_debug.build.zigbee_mode=-DZIGBEE_MODE_ED +esp32c6.menu.ZigbeeMode.ed_debug.build.zigbee_libs=-lesp_zb_api.ed.debug -lzboss_stack.ed.debug -lzboss_port.native.debug +esp32c6.menu.ZigbeeMode.zczr_debug=Zigbee ZCZR (coordinator/router) - Debug +esp32c6.menu.ZigbeeMode.zczr_debug.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +esp32c6.menu.ZigbeeMode.zczr_debug.build.zigbee_libs=-lesp_zb_api.zczr.debug -lzboss_stack.zczr.debug -lzboss_port.native.debug ############################################################## @@ -622,12 +847,10 @@ esp32s3.menu.FlashSize.4M=4MB (32Mb) esp32s3.menu.FlashSize.4M.build.flash_size=4MB esp32s3.menu.FlashSize.8M=8MB (64Mb) esp32s3.menu.FlashSize.8M.build.flash_size=8MB -esp32s3.menu.FlashSize.8M.build.partitions=default_8MB esp32s3.menu.FlashSize.16M=16MB (128Mb) esp32s3.menu.FlashSize.16M.build.flash_size=16MB esp32s3.menu.FlashSize.32M=32MB (256Mb) esp32s3.menu.FlashSize.32M.build.flash_size=32MB -esp32s3.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB esp32s3.menu.LoopCore.1=Core 1 esp32s3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -702,15 +925,24 @@ esp32s3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32s3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32s3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32s3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32s3.menu.PartitionScheme.rainmaker=RainMaker +esp32s3.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32s3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32s3.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) esp32s3.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB esp32s3.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 esp32s3.menu.PartitionScheme.app5M_little24M_32MB=32M Flash (4.8MB APP/22MB LittleFS) esp32s3.menu.PartitionScheme.app5M_little24M_32MB.build.partitions=large_littlefs_32MB esp32s3.menu.PartitionScheme.app5M_little24M_32MB.upload.maximum_size=4718592 +esp32s3.menu.PartitionScheme.app13M_data7M_32MB=32M Flash (13MB APP/6.75MB SPIFFS) +esp32s3.menu.PartitionScheme.app13M_data7M_32MB.build.partitions=default_32MB +esp32s3.menu.PartitionScheme.app13M_data7M_32MB.upload.maximum_size=13107200 esp32s3.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) esp32s3.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 esp32s3.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin @@ -718,6 +950,9 @@ esp32s3.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 esp32s3.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs esp32s3.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr esp32s3.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +esp32s3.menu.PartitionScheme.zigbee_zczr_8MB=Zigbee ZCZR 8MB with spiffs +esp32s3.menu.PartitionScheme.zigbee_zczr_8MB.build.partitions=zigbee_zczr_8MB +esp32s3.menu.PartitionScheme.zigbee_zczr_8MB.upload.maximum_size=3407872 esp32s3.menu.PartitionScheme.custom=Custom esp32s3.menu.PartitionScheme.custom.build.partitions= esp32s3.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -771,9 +1006,9 @@ esp32s3.menu.EraseFlash.all.upload.erase_cmd=-e esp32s3.menu.ZigbeeMode.default=Disabled esp32s3.menu.ZigbeeMode.default.build.zigbee_mode= esp32s3.menu.ZigbeeMode.default.build.zigbee_libs= -esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32s3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## @@ -867,12 +1102,21 @@ esp32c3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32c3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32c3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32c3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32c3.menu.PartitionScheme.rainmaker=RainMaker +esp32c3.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32c3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32c3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32c3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32c3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32c3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32c3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32c3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32c3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32c3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32c3.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs esp32c3.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr esp32c3.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +esp32c3.menu.PartitionScheme.zigbee_zczr_8MB=Zigbee ZCZR 8MB with spiffs +esp32c3.menu.PartitionScheme.zigbee_zczr_8MB.build.partitions=zigbee_zczr_8MB +esp32c3.menu.PartitionScheme.zigbee_zczr_8MB.upload.maximum_size=3407872 esp32c3.menu.PartitionScheme.custom=Custom esp32c3.menu.PartitionScheme.custom.build.partitions= esp32c3.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -904,10 +1148,8 @@ esp32c3.menu.FlashSize.4M=4MB (32Mb) esp32c3.menu.FlashSize.4M.build.flash_size=4MB esp32c3.menu.FlashSize.8M=8MB (64Mb) esp32c3.menu.FlashSize.8M.build.flash_size=8MB -esp32c3.menu.FlashSize.8M.build.partitions=default_8MB esp32c3.menu.FlashSize.2M=2MB (16Mb) esp32c3.menu.FlashSize.2M.build.flash_size=2MB -esp32c3.menu.FlashSize.2M.build.partitions=minimal esp32c3.menu.FlashSize.16M=16MB (128Mb) esp32c3.menu.FlashSize.16M.build.flash_size=16MB @@ -947,9 +1189,9 @@ esp32c3.menu.EraseFlash.all.upload.erase_cmd=-e esp32c3.menu.ZigbeeMode.default=Disabled esp32c3.menu.ZigbeeMode.default.build.zigbee_mode= esp32c3.menu.ZigbeeMode.default.build.zigbee_libs= -esp32c3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32c3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32c3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -esp32c3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +esp32c3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## @@ -1068,12 +1310,21 @@ esp32s2.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32s2.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32s2.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32s2.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32s2.menu.PartitionScheme.rainmaker=RainMaker +esp32s2.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32s2.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32s2.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32s2.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32s2.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32s2.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32s2.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32s2.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32s2.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32s2.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32s2.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs esp32s2.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr esp32s2.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +esp32s2.menu.PartitionScheme.zigbee_zczr_8MB=Zigbee ZCZR 8MB with spiffs +esp32s2.menu.PartitionScheme.zigbee_zczr_8MB.build.partitions=zigbee_zczr_8MB +esp32s2.menu.PartitionScheme.zigbee_zczr_8MB.upload.maximum_size=3407872 esp32s2.menu.PartitionScheme.custom=Custom esp32s2.menu.PartitionScheme.custom.build.partitions= esp32s2.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -1107,10 +1358,8 @@ esp32s2.menu.FlashSize.4M=4MB (32Mb) esp32s2.menu.FlashSize.4M.build.flash_size=4MB esp32s2.menu.FlashSize.8M=8MB (64Mb) esp32s2.menu.FlashSize.8M.build.flash_size=8MB -esp32s2.menu.FlashSize.8M.build.partitions=default_8MB esp32s2.menu.FlashSize.2M=2MB (16Mb) esp32s2.menu.FlashSize.2M.build.flash_size=2MB -esp32s2.menu.FlashSize.2M.build.partitions=minimal esp32s2.menu.FlashSize.16M=16MB (128Mb) esp32s2.menu.FlashSize.16M.build.flash_size=16MB @@ -1150,9 +1399,9 @@ esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e esp32s2.menu.ZigbeeMode.default=Disabled esp32s2.menu.ZigbeeMode.default.build.zigbee_mode= esp32s2.menu.ZigbeeMode.default.build.zigbee_libs= -esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32s2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## @@ -1244,12 +1493,21 @@ esp32.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32.menu.PartitionScheme.rainmaker=RainMaker +esp32.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs esp32.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr esp32.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +esp32.menu.PartitionScheme.zigbee_zczr_8MB=Zigbee ZCZR 8MB with spiffs +esp32.menu.PartitionScheme.zigbee_zczr_8MB.build.partitions=zigbee_zczr_8MB +esp32.menu.PartitionScheme.zigbee_zczr_8MB.upload.maximum_size=3407872 esp32.menu.PartitionScheme.custom=Custom esp32.menu.PartitionScheme.custom.build.partitions= esp32.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -1287,10 +1545,8 @@ esp32.menu.FlashSize.4M=4MB (32Mb) esp32.menu.FlashSize.4M.build.flash_size=4MB esp32.menu.FlashSize.8M=8MB (64Mb) esp32.menu.FlashSize.8M.build.flash_size=8MB -esp32.menu.FlashSize.8M.build.partitions=default_8MB esp32.menu.FlashSize.2M=2MB (16Mb) esp32.menu.FlashSize.2M.build.flash_size=2MB -esp32.menu.FlashSize.2M.build.partitions=minimal esp32.menu.FlashSize.16M=16MB (128Mb) esp32.menu.FlashSize.16M.build.flash_size=16MB @@ -1340,9 +1596,9 @@ esp32.menu.EraseFlash.all.upload.erase_cmd=-e esp32.menu.ZigbeeMode.default=Disabled esp32.menu.ZigbeeMode.default.build.zigbee_mode= esp32.menu.ZigbeeMode.default.build.zigbee_libs= -esp32.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -esp32.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +esp32.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## @@ -1417,9 +1673,15 @@ esp32da.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32da.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32da.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32da.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32da.menu.PartitionScheme.rainmaker=RainMaker +esp32da.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32da.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32da.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32da.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32da.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32da.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32da.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32da.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32da.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32da.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32da.menu.PartitionScheme.custom=Custom esp32da.menu.PartitionScheme.custom.build.partitions= esp32da.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -1457,7 +1719,6 @@ esp32da.menu.FlashSize.4M=4MB (32Mb) esp32da.menu.FlashSize.4M.build.flash_size=4MB esp32da.menu.FlashSize.8M=8MB (64Mb) esp32da.menu.FlashSize.8M.build.flash_size=8MB -esp32da.menu.FlashSize.8M.build.partitions=default_8MB esp32da.menu.FlashSize.16M=16MB (128Mb) esp32da.menu.FlashSize.16M.build.flash_size=16MB @@ -1570,9 +1831,12 @@ esp32wrover.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 esp32wrover.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) esp32wrover.menu.PartitionScheme.fatflash.build.partitions=ffat esp32wrover.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -esp32wrover.menu.PartitionScheme.rainmaker=RainMaker +esp32wrover.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32wrover.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32wrover.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32wrover.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32wrover.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32wrover.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32wrover.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 esp32wrover.menu.PartitionScheme.custom=Custom esp32wrover.menu.PartitionScheme.custom.build.partitions= esp32wrover.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -1796,12 +2060,10 @@ esp32s3-octal.menu.FlashSize.4M=4MB (32Mb) esp32s3-octal.menu.FlashSize.4M.build.flash_size=4MB esp32s3-octal.menu.FlashSize.8M=8MB (64Mb) esp32s3-octal.menu.FlashSize.8M.build.flash_size=8MB -esp32s3-octal.menu.FlashSize.8M.build.partitions=default_8MB esp32s3-octal.menu.FlashSize.16M=16MB (128Mb) esp32s3-octal.menu.FlashSize.16M.build.flash_size=16MB esp32s3-octal.menu.FlashSize.32M=32MB (256Mb) esp32s3-octal.menu.FlashSize.32M.build.flash_size=32MB -esp32s3-octal.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB esp32s3-octal.menu.LoopCore.1=Core 1 esp32s3-octal.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -1874,15 +2136,24 @@ esp32s3-octal.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32s3-octal.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32s3-octal.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32s3-octal.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32s3-octal.menu.PartitionScheme.rainmaker=RainMaker +esp32s3-octal.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32s3-octal.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32s3-octal.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32s3-octal.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32s3-octal.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32s3-octal.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32s3-octal.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32s3-octal.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32s3-octal.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32s3-octal.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32s3-octal.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) esp32s3-octal.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB esp32s3-octal.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 esp32s3-octal.menu.PartitionScheme.app5M_little24M_32MB=32M Flash (4.8MB APP/22MB LittleFS) esp32s3-octal.menu.PartitionScheme.app5M_little24M_32MB.build.partitions=large_littlefs_32MB esp32s3-octal.menu.PartitionScheme.app5M_little24M_32MB.upload.maximum_size=4718592 +esp32s3-octal.menu.PartitionScheme.app13M_data7M_32MB=32M Flash (13MB APP/6.75MB SPIFFS) +esp32s3-octal.menu.PartitionScheme.app13M_data7M_32MB.build.partitions=default_32MB +esp32s3-octal.menu.PartitionScheme.app13M_data7M_32MB.upload.maximum_size=13107200 esp32s3-octal.menu.CPUFreq.240=240MHz (WiFi) esp32s3-octal.menu.CPUFreq.240.build.f_cpu=240000000L @@ -1997,9 +2268,12 @@ esp32s3box.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 esp32s3box.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32s3box.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32s3box.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32s3box.menu.PartitionScheme.rainmaker=RainMaker +esp32s3box.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32s3box.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32s3box.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32s3box.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32s3box.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32s3box.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32s3box.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 esp32s3box.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) esp32s3box.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 esp32s3box.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin @@ -2313,7 +2587,6 @@ esp32s2usb.menu.FlashSize.4M=4MB (32Mb) esp32s2usb.menu.FlashSize.4M.build.flash_size=4MB esp32s2usb.menu.FlashSize.8M=8MB (64Mb) esp32s2usb.menu.FlashSize.8M.build.flash_size=8MB -esp32s2usb.menu.FlashSize.8M.build.partitions=default_8MB esp32s2usb.menu.FlashSize.16M=16MB (128Mb) esp32s2usb.menu.FlashSize.16M.build.flash_size=16MB @@ -2407,10 +2680,8 @@ esp32wroverkit.menu.FlashSize.4M=4MB (32Mb) esp32wroverkit.menu.FlashSize.4M.build.flash_size=4MB esp32wroverkit.menu.FlashSize.8M=8MB (64Mb) esp32wroverkit.menu.FlashSize.8M.build.flash_size=8MB -esp32wroverkit.menu.FlashSize.8M.build.partitions=default_8MB esp32wroverkit.menu.FlashSize.2M=2MB (16Mb) esp32wroverkit.menu.FlashSize.2M.build.flash_size=2MB -esp32wroverkit.menu.FlashSize.2M.build.partitions=minimal esp32wroverkit.menu.FlashSize.16M=16MB (128Mb) esp32wroverkit.menu.FlashSize.16M.build.flash_size=16MB @@ -2426,6 +2697,9 @@ esp32wroverkit.menu.PartitionScheme.defaultffat.build.partitions=default_ffat esp32wroverkit.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) esp32wroverkit.menu.PartitionScheme.default_8MB.build.partitions=default_8MB esp32wroverkit.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +esp32wroverkit.menu.PartitionScheme.default_16MB=16M with spiffs (6.25MB APP/3.43MB SPIFFS) +esp32wroverkit.menu.PartitionScheme.default_16MB.build.partitions=default_16MB +esp32wroverkit.menu.PartitionScheme.default_16MB.upload.maximum_size=6553600 esp32wroverkit.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) esp32wroverkit.menu.PartitionScheme.minimal.build.partitions=minimal esp32wroverkit.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -2449,9 +2723,15 @@ esp32wroverkit.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 esp32wroverkit.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) esp32wroverkit.menu.PartitionScheme.fatflash.build.partitions=ffat esp32wroverkit.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -esp32wroverkit.menu.PartitionScheme.rainmaker=RainMaker +esp32wroverkit.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32wroverkit.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32wroverkit.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32wroverkit.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32wroverkit.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32wroverkit.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32wroverkit.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32wroverkit.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32wroverkit.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32wroverkit.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32wroverkit.menu.CPUFreq.240=240MHz (WiFi/BT) esp32wroverkit.menu.CPUFreq.240.build.f_cpu=240000000L @@ -2678,9 +2958,15 @@ aventen_s3_sync.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 aventen_s3_sync.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) aventen_s3_sync.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB aventen_s3_sync.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -aventen_s3_sync.menu.PartitionScheme.rainmaker=RainMaker +aventen_s3_sync.menu.PartitionScheme.rainmaker=RainMaker 4MB aventen_s3_sync.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -aventen_s3_sync.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +aventen_s3_sync.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +aventen_s3_sync.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +aventen_s3_sync.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +aventen_s3_sync.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +aventen_s3_sync.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +aventen_s3_sync.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +aventen_s3_sync.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 aventen_s3_sync.menu.CPUFreq.240=240MHz (WiFi) aventen_s3_sync.menu.CPUFreq.240.build.f_cpu=240000000L @@ -2730,6 +3016,479 @@ aventen_s3_sync.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +BharatPi-Node-Wifi.name=BharatPi Node Wifi Module + +BharatPi-Node-Wifi.bootloader.tool=esptool_py +BharatPi-Node-Wifi.bootloader.tool.default=esptool_py + +BharatPi-Node-Wifi.upload.tool=esptool_py +BharatPi-Node-Wifi.upload.tool.default=esptool_py +BharatPi-Node-Wifi.upload.tool.network=esp_ota + +BharatPi-Node-Wifi.upload.maximum_size=1310720 +BharatPi-Node-Wifi.upload.maximum_data_size=327680 +BharatPi-Node-Wifi.upload.flags= +BharatPi-Node-Wifi.upload.extra_flags= + +BharatPi-Node-Wifi.serial.disableDTR=true +BharatPi-Node-Wifi.serial.disableRTS=true + +BharatPi-Node-Wifi.build.tarch=xtensa +BharatPi-Node-Wifi.build.bootloader_addr=0x1000 +BharatPi-Node-Wifi.build.target=esp32 +BharatPi-Node-Wifi.build.mcu=esp32 +BharatPi-Node-Wifi.build.core=esp32 +BharatPi-Node-Wifi.build.variant=BharatPi-Node-Wifi +BharatPi-Node-Wifi.build.board=BHARATPI_NODE_WIFI + +BharatPi-Node-Wifi.build.f_cpu=240000000L +BharatPi-Node-Wifi.build.flash_size=4MB +BharatPi-Node-Wifi.build.flash_freq=40m +BharatPi-Node-Wifi.build.flash_mode=dio +BharatPi-Node-Wifi.build.boot=dio +BharatPi-Node-Wifi.build.partitions=default +BharatPi-Node-Wifi.build.defines= +BharatPi-Node-Wifi.build.loop_core= +BharatPi-Node-Wifi.build.event_core= + +BharatPi-Node-Wifi.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.default.build.partitions=default +BharatPi-Node-Wifi.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +BharatPi-Node-Wifi.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +BharatPi-Node-Wifi.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +BharatPi-Node-Wifi.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +BharatPi-Node-Wifi.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.minimal.build.partitions=minimal +BharatPi-Node-Wifi.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.no_ota.build.partitions=no_ota +BharatPi-Node-Wifi.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +BharatPi-Node-Wifi.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +BharatPi-Node-Wifi.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +BharatPi-Node-Wifi.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +BharatPi-Node-Wifi.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +BharatPi-Node-Wifi.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +BharatPi-Node-Wifi.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +BharatPi-Node-Wifi.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +BharatPi-Node-Wifi.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +BharatPi-Node-Wifi.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.huge_app.build.partitions=huge_app +BharatPi-Node-Wifi.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +BharatPi-Node-Wifi.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +BharatPi-Node-Wifi.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +BharatPi-Node-Wifi.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +BharatPi-Node-Wifi.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +BharatPi-Node-Wifi.menu.PartitionScheme.fatflash.build.partitions=ffat +BharatPi-Node-Wifi.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +BharatPi-Node-Wifi.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +BharatPi-Node-Wifi.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +BharatPi-Node-Wifi.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +BharatPi-Node-Wifi.menu.PartitionScheme.rainmaker=RainMaker +BharatPi-Node-Wifi.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +BharatPi-Node-Wifi.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +BharatPi-Node-Wifi.menu.PartitionScheme.custom=Custom +BharatPi-Node-Wifi.menu.PartitionScheme.custom.build.partitions= +BharatPi-Node-Wifi.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +BharatPi-Node-Wifi.menu.CPUFreq.240=240MHz (WiFi/BT) +BharatPi-Node-Wifi.menu.CPUFreq.240.build.f_cpu=240000000L +BharatPi-Node-Wifi.menu.CPUFreq.160=160MHz (WiFi/BT) +BharatPi-Node-Wifi.menu.CPUFreq.160.build.f_cpu=160000000L +BharatPi-Node-Wifi.menu.CPUFreq.80=80MHz (WiFi/BT) +BharatPi-Node-Wifi.menu.CPUFreq.80.build.f_cpu=80000000L +BharatPi-Node-Wifi.menu.CPUFreq.40=40MHz (40MHz XTAL) +BharatPi-Node-Wifi.menu.CPUFreq.40.build.f_cpu=40000000L +BharatPi-Node-Wifi.menu.CPUFreq.26=26MHz (26MHz XTAL) +BharatPi-Node-Wifi.menu.CPUFreq.26.build.f_cpu=26000000L +BharatPi-Node-Wifi.menu.CPUFreq.20=20MHz (40MHz XTAL) +BharatPi-Node-Wifi.menu.CPUFreq.20.build.f_cpu=20000000L +BharatPi-Node-Wifi.menu.CPUFreq.13=13MHz (26MHz XTAL) +BharatPi-Node-Wifi.menu.CPUFreq.13.build.f_cpu=13000000L +BharatPi-Node-Wifi.menu.CPUFreq.10=10MHz (40MHz XTAL) +BharatPi-Node-Wifi.menu.CPUFreq.10.build.f_cpu=10000000L + +BharatPi-Node-Wifi.menu.FlashMode.qio=QIO +BharatPi-Node-Wifi.menu.FlashMode.qio.build.flash_mode=dio +BharatPi-Node-Wifi.menu.FlashMode.qio.build.boot=qio +BharatPi-Node-Wifi.menu.FlashMode.dio=DIO +BharatPi-Node-Wifi.menu.FlashMode.dio.build.flash_mode=dio +BharatPi-Node-Wifi.menu.FlashMode.dio.build.boot=dio + +BharatPi-Node-Wifi.menu.FlashFreq.80=80MHz +BharatPi-Node-Wifi.menu.FlashFreq.80.build.flash_freq=80m +BharatPi-Node-Wifi.menu.FlashFreq.40=40MHz +BharatPi-Node-Wifi.menu.FlashFreq.40.build.flash_freq=40m + +BharatPi-Node-Wifi.menu.FlashSize.4M=4MB (32Mb) +BharatPi-Node-Wifi.menu.FlashSize.4M.build.flash_size=4MB +BharatPi-Node-Wifi.menu.FlashSize.8M=8MB (64Mb) +BharatPi-Node-Wifi.menu.FlashSize.8M.build.flash_size=8MB +BharatPi-Node-Wifi.menu.FlashSize.8M.build.partitions=default_8MB +BharatPi-Node-Wifi.menu.FlashSize.16M=16MB (128Mb) +BharatPi-Node-Wifi.menu.FlashSize.16M.build.flash_size=16MB + +BharatPi-Node-Wifi.menu.UploadSpeed.921600=921600 +BharatPi-Node-Wifi.menu.UploadSpeed.921600.upload.speed=921600 +BharatPi-Node-Wifi.menu.UploadSpeed.115200=115200 +BharatPi-Node-Wifi.menu.UploadSpeed.115200.upload.speed=115200 +BharatPi-Node-Wifi.menu.UploadSpeed.256000.windows=256000 +BharatPi-Node-Wifi.menu.UploadSpeed.256000.upload.speed=256000 +BharatPi-Node-Wifi.menu.UploadSpeed.230400.windows.upload.speed=256000 +BharatPi-Node-Wifi.menu.UploadSpeed.230400=230400 +BharatPi-Node-Wifi.menu.UploadSpeed.230400.upload.speed=230400 +BharatPi-Node-Wifi.menu.UploadSpeed.460800.linux=460800 +BharatPi-Node-Wifi.menu.UploadSpeed.460800.macosx=460800 +BharatPi-Node-Wifi.menu.UploadSpeed.460800.upload.speed=460800 +BharatPi-Node-Wifi.menu.UploadSpeed.512000.windows=512000 +BharatPi-Node-Wifi.menu.UploadSpeed.512000.upload.speed=512000 + +BharatPi-Node-Wifi.menu.LoopCore.1=Core 1 +BharatPi-Node-Wifi.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +BharatPi-Node-Wifi.menu.LoopCore.0=Core 0 +BharatPi-Node-Wifi.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +BharatPi-Node-Wifi.menu.EventsCore.1=Core 1 +BharatPi-Node-Wifi.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +BharatPi-Node-Wifi.menu.EventsCore.0=Core 0 +BharatPi-Node-Wifi.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +BharatPi-Node-Wifi.menu.DebugLevel.none=None +BharatPi-Node-Wifi.menu.DebugLevel.none.build.code_debug=0 +BharatPi-Node-Wifi.menu.DebugLevel.error=Error +BharatPi-Node-Wifi.menu.DebugLevel.error.build.code_debug=1 +BharatPi-Node-Wifi.menu.DebugLevel.warn=Warn +BharatPi-Node-Wifi.menu.DebugLevel.warn.build.code_debug=2 +BharatPi-Node-Wifi.menu.DebugLevel.info=Info +BharatPi-Node-Wifi.menu.DebugLevel.info.build.code_debug=3 +BharatPi-Node-Wifi.menu.DebugLevel.debug=Debug +BharatPi-Node-Wifi.menu.DebugLevel.debug.build.code_debug=4 +BharatPi-Node-Wifi.menu.DebugLevel.verbose=Verbose +BharatPi-Node-Wifi.menu.DebugLevel.verbose.build.code_debug=5 + +BharatPi-Node-Wifi.menu.EraseFlash.none=Disabled +BharatPi-Node-Wifi.menu.EraseFlash.none.upload.erase_cmd= +BharatPi-Node-Wifi.menu.EraseFlash.all=Enabled +BharatPi-Node-Wifi.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + + +BharatPi-A7672S-4G.name=BharatPi A7672S 4G Module + +BharatPi-A7672S-4G.bootloader.tool=esptool_py +BharatPi-A7672S-4G.bootloader.tool.default=esptool_py + +BharatPi-A7672S-4G.upload.tool=esptool_py +BharatPi-A7672S-4G.upload.tool.default=esptool_py +BharatPi-A7672S-4G.upload.tool.network=esp_ota + +BharatPi-A7672S-4G.upload.maximum_size=1310720 +BharatPi-A7672S-4G.upload.maximum_data_size=327680 +BharatPi-A7672S-4G.upload.flags= +BharatPi-A7672S-4G.upload.extra_flags= + +BharatPi-A7672S-4G.serial.disableDTR=true +BharatPi-A7672S-4G.serial.disableRTS=true + +BharatPi-A7672S-4G.build.tarch=xtensa +BharatPi-A7672S-4G.build.bootloader_addr=0x1000 +BharatPi-A7672S-4G.build.target=esp32 +BharatPi-A7672S-4G.build.mcu=esp32 +BharatPi-A7672S-4G.build.core=esp32 +BharatPi-A7672S-4G.build.variant=BharatPi-A7672S-4G +BharatPi-A7672S-4G.build.board=BHARATPI_A7672S_4G + +BharatPi-A7672S-4G.build.f_cpu=240000000L +BharatPi-A7672S-4G.build.flash_size=4MB +BharatPi-A7672S-4G.build.flash_freq=40m +BharatPi-A7672S-4G.build.flash_mode=dio +BharatPi-A7672S-4G.build.boot=dio +BharatPi-A7672S-4G.build.partitions=default +BharatPi-A7672S-4G.build.defines= +BharatPi-A7672S-4G.build.loop_core= +BharatPi-A7672S-4G.build.event_core= + +BharatPi-A7672S-4G.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.default.build.partitions=default +BharatPi-A7672S-4G.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +BharatPi-A7672S-4G.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +BharatPi-A7672S-4G.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +BharatPi-A7672S-4G.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +BharatPi-A7672S-4G.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.minimal.build.partitions=minimal +BharatPi-A7672S-4G.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.no_ota.build.partitions=no_ota +BharatPi-A7672S-4G.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +BharatPi-A7672S-4G.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +BharatPi-A7672S-4G.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +BharatPi-A7672S-4G.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +BharatPi-A7672S-4G.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +BharatPi-A7672S-4G.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +BharatPi-A7672S-4G.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +BharatPi-A7672S-4G.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +BharatPi-A7672S-4G.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +BharatPi-A7672S-4G.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.huge_app.build.partitions=huge_app +BharatPi-A7672S-4G.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +BharatPi-A7672S-4G.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +BharatPi-A7672S-4G.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +BharatPi-A7672S-4G.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +BharatPi-A7672S-4G.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +BharatPi-A7672S-4G.menu.PartitionScheme.fatflash.build.partitions=ffat +BharatPi-A7672S-4G.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +BharatPi-A7672S-4G.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +BharatPi-A7672S-4G.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +BharatPi-A7672S-4G.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +BharatPi-A7672S-4G.menu.PartitionScheme.rainmaker=RainMaker +BharatPi-A7672S-4G.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +BharatPi-A7672S-4G.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +BharatPi-A7672S-4G.menu.PartitionScheme.custom=Custom +BharatPi-A7672S-4G.menu.PartitionScheme.custom.build.partitions= +BharatPi-A7672S-4G.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +BharatPi-A7672S-4G.menu.CPUFreq.240=240MHz (WiFi/BT) +BharatPi-A7672S-4G.menu.CPUFreq.240.build.f_cpu=240000000L +BharatPi-A7672S-4G.menu.CPUFreq.160=160MHz (WiFi/BT) +BharatPi-A7672S-4G.menu.CPUFreq.160.build.f_cpu=160000000L +BharatPi-A7672S-4G.menu.CPUFreq.80=80MHz (WiFi/BT) +BharatPi-A7672S-4G.menu.CPUFreq.80.build.f_cpu=80000000L +BharatPi-A7672S-4G.menu.CPUFreq.40=40MHz (40MHz XTAL) +BharatPi-A7672S-4G.menu.CPUFreq.40.build.f_cpu=40000000L +BharatPi-A7672S-4G.menu.CPUFreq.26=26MHz (26MHz XTAL) +BharatPi-A7672S-4G.menu.CPUFreq.26.build.f_cpu=26000000L +BharatPi-A7672S-4G.menu.CPUFreq.20=20MHz (40MHz XTAL) +BharatPi-A7672S-4G.menu.CPUFreq.20.build.f_cpu=20000000L +BharatPi-A7672S-4G.menu.CPUFreq.13=13MHz (26MHz XTAL) +BharatPi-A7672S-4G.menu.CPUFreq.13.build.f_cpu=13000000L +BharatPi-A7672S-4G.menu.CPUFreq.10=10MHz (40MHz XTAL) +BharatPi-A7672S-4G.menu.CPUFreq.10.build.f_cpu=10000000L + +BharatPi-A7672S-4G.menu.FlashMode.qio=QIO +BharatPi-A7672S-4G.menu.FlashMode.qio.build.flash_mode=dio +BharatPi-A7672S-4G.menu.FlashMode.qio.build.boot=qio +BharatPi-A7672S-4G.menu.FlashMode.dio=DIO +BharatPi-A7672S-4G.menu.FlashMode.dio.build.flash_mode=dio +BharatPi-A7672S-4G.menu.FlashMode.dio.build.boot=dio + +BharatPi-A7672S-4G.menu.FlashFreq.80=80MHz +BharatPi-A7672S-4G.menu.FlashFreq.80.build.flash_freq=80m +BharatPi-A7672S-4G.menu.FlashFreq.40=40MHz +BharatPi-A7672S-4G.menu.FlashFreq.40.build.flash_freq=40m + +BharatPi-A7672S-4G.menu.FlashSize.4M=4MB (32Mb) +BharatPi-A7672S-4G.menu.FlashSize.4M.build.flash_size=4MB +BharatPi-A7672S-4G.menu.FlashSize.8M=8MB (64Mb) +BharatPi-A7672S-4G.menu.FlashSize.8M.build.flash_size=8MB +BharatPi-A7672S-4G.menu.FlashSize.8M.build.partitions=default_8MB +BharatPi-A7672S-4G.menu.FlashSize.16M=16MB (128Mb) +BharatPi-A7672S-4G.menu.FlashSize.16M.build.flash_size=16MB + +BharatPi-A7672S-4G.menu.UploadSpeed.921600=921600 +BharatPi-A7672S-4G.menu.UploadSpeed.921600.upload.speed=921600 +BharatPi-A7672S-4G.menu.UploadSpeed.115200=115200 +BharatPi-A7672S-4G.menu.UploadSpeed.115200.upload.speed=115200 +BharatPi-A7672S-4G.menu.UploadSpeed.256000.windows=256000 +BharatPi-A7672S-4G.menu.UploadSpeed.256000.upload.speed=256000 +BharatPi-A7672S-4G.menu.UploadSpeed.230400.windows.upload.speed=256000 +BharatPi-A7672S-4G.menu.UploadSpeed.230400=230400 +BharatPi-A7672S-4G.menu.UploadSpeed.230400.upload.speed=230400 +BharatPi-A7672S-4G.menu.UploadSpeed.460800.linux=460800 +BharatPi-A7672S-4G.menu.UploadSpeed.460800.macosx=460800 +BharatPi-A7672S-4G.menu.UploadSpeed.460800.upload.speed=460800 +BharatPi-A7672S-4G.menu.UploadSpeed.512000.windows=512000 +BharatPi-A7672S-4G.menu.UploadSpeed.512000.upload.speed=512000 + +BharatPi-A7672S-4G.menu.LoopCore.1=Core 1 +BharatPi-A7672S-4G.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +BharatPi-A7672S-4G.menu.LoopCore.0=Core 0 +BharatPi-A7672S-4G.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +BharatPi-A7672S-4G.menu.EventsCore.1=Core 1 +BharatPi-A7672S-4G.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +BharatPi-A7672S-4G.menu.EventsCore.0=Core 0 +BharatPi-A7672S-4G.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +BharatPi-A7672S-4G.menu.DebugLevel.none=None +BharatPi-A7672S-4G.menu.DebugLevel.none.build.code_debug=0 +BharatPi-A7672S-4G.menu.DebugLevel.error=Error +BharatPi-A7672S-4G.menu.DebugLevel.error.build.code_debug=1 +BharatPi-A7672S-4G.menu.DebugLevel.warn=Warn +BharatPi-A7672S-4G.menu.DebugLevel.warn.build.code_debug=2 +BharatPi-A7672S-4G.menu.DebugLevel.info=Info +BharatPi-A7672S-4G.menu.DebugLevel.info.build.code_debug=3 +BharatPi-A7672S-4G.menu.DebugLevel.debug=Debug +BharatPi-A7672S-4G.menu.DebugLevel.debug.build.code_debug=4 +BharatPi-A7672S-4G.menu.DebugLevel.verbose=Verbose +BharatPi-A7672S-4G.menu.DebugLevel.verbose.build.code_debug=5 + +BharatPi-A7672S-4G.menu.EraseFlash.none=Disabled +BharatPi-A7672S-4G.menu.EraseFlash.none.upload.erase_cmd= +BharatPi-A7672S-4G.menu.EraseFlash.all=Enabled +BharatPi-A7672S-4G.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + + +BharatPi-LoRa.name=BharatPi LoRa Module + +BharatPi-LoRa.bootloader.tool=esptool_py +BharatPi-LoRa.bootloader.tool.default=esptool_py + +BharatPi-LoRa.upload.tool=esptool_py +BharatPi-LoRa.upload.tool.default=esptool_py +BharatPi-LoRa.upload.tool.network=esp_ota + +BharatPi-LoRa.upload.maximum_size=1310720 +BharatPi-LoRa.upload.maximum_data_size=327680 +BharatPi-LoRa.upload.flags= +BharatPi-LoRa.upload.extra_flags= + +BharatPi-LoRa.serial.disableDTR=true +BharatPi-LoRa.serial.disableRTS=true + +BharatPi-LoRa.build.tarch=xtensa +BharatPi-LoRa.build.bootloader_addr=0x1000 +BharatPi-LoRa.build.target=esp32 +BharatPi-LoRa.build.mcu=esp32 +BharatPi-LoRa.build.core=esp32 +BharatPi-LoRa.build.variant=BharatPi-LoRa +BharatPi-LoRa.build.board=BHARATPI_LORA + +BharatPi-LoRa.build.f_cpu=240000000L +BharatPi-LoRa.build.flash_size=4MB +BharatPi-LoRa.build.flash_freq=40m +BharatPi-LoRa.build.flash_mode=dio +BharatPi-LoRa.build.boot=dio +BharatPi-LoRa.build.partitions=default +BharatPi-LoRa.build.defines= +BharatPi-LoRa.build.loop_core= +BharatPi-LoRa.build.event_core= + +BharatPi-LoRa.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.default.build.partitions=default +BharatPi-LoRa.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +BharatPi-LoRa.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +BharatPi-LoRa.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +BharatPi-LoRa.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +BharatPi-LoRa.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.minimal.build.partitions=minimal +BharatPi-LoRa.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.no_ota.build.partitions=no_ota +BharatPi-LoRa.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +BharatPi-LoRa.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +BharatPi-LoRa.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +BharatPi-LoRa.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +BharatPi-LoRa.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +BharatPi-LoRa.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +BharatPi-LoRa.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +BharatPi-LoRa.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +BharatPi-LoRa.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +BharatPi-LoRa.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.huge_app.build.partitions=huge_app +BharatPi-LoRa.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +BharatPi-LoRa.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +BharatPi-LoRa.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +BharatPi-LoRa.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +BharatPi-LoRa.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +BharatPi-LoRa.menu.PartitionScheme.fatflash.build.partitions=ffat +BharatPi-LoRa.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +BharatPi-LoRa.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +BharatPi-LoRa.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +BharatPi-LoRa.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +BharatPi-LoRa.menu.PartitionScheme.rainmaker=RainMaker +BharatPi-LoRa.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +BharatPi-LoRa.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +BharatPi-LoRa.menu.PartitionScheme.custom=Custom +BharatPi-LoRa.menu.PartitionScheme.custom.build.partitions= +BharatPi-LoRa.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +BharatPi-LoRa.menu.CPUFreq.240=240MHz (WiFi/BT) +BharatPi-LoRa.menu.CPUFreq.240.build.f_cpu=240000000L +BharatPi-LoRa.menu.CPUFreq.160=160MHz (WiFi/BT) +BharatPi-LoRa.menu.CPUFreq.160.build.f_cpu=160000000L +BharatPi-LoRa.menu.CPUFreq.80=80MHz (WiFi/BT) +BharatPi-LoRa.menu.CPUFreq.80.build.f_cpu=80000000L +BharatPi-LoRa.menu.CPUFreq.40=40MHz (40MHz XTAL) +BharatPi-LoRa.menu.CPUFreq.40.build.f_cpu=40000000L +BharatPi-LoRa.menu.CPUFreq.26=26MHz (26MHz XTAL) +BharatPi-LoRa.menu.CPUFreq.26.build.f_cpu=26000000L +BharatPi-LoRa.menu.CPUFreq.20=20MHz (40MHz XTAL) +BharatPi-LoRa.menu.CPUFreq.20.build.f_cpu=20000000L +BharatPi-LoRa.menu.CPUFreq.13=13MHz (26MHz XTAL) +BharatPi-LoRa.menu.CPUFreq.13.build.f_cpu=13000000L +BharatPi-LoRa.menu.CPUFreq.10=10MHz (40MHz XTAL) +BharatPi-LoRa.menu.CPUFreq.10.build.f_cpu=10000000L + +BharatPi-LoRa.menu.FlashMode.qio=QIO +BharatPi-LoRa.menu.FlashMode.qio.build.flash_mode=dio +BharatPi-LoRa.menu.FlashMode.qio.build.boot=qio +BharatPi-LoRa.menu.FlashMode.dio=DIO +BharatPi-LoRa.menu.FlashMode.dio.build.flash_mode=dio +BharatPi-LoRa.menu.FlashMode.dio.build.boot=dio + +BharatPi-LoRa.menu.FlashFreq.80=80MHz +BharatPi-LoRa.menu.FlashFreq.80.build.flash_freq=80m +BharatPi-LoRa.menu.FlashFreq.40=40MHz +BharatPi-LoRa.menu.FlashFreq.40.build.flash_freq=40m + +BharatPi-LoRa.menu.FlashSize.4M=4MB (32Mb) +BharatPi-LoRa.menu.FlashSize.4M.build.flash_size=4MB +BharatPi-LoRa.menu.FlashSize.8M=8MB (64Mb) +BharatPi-LoRa.menu.FlashSize.8M.build.flash_size=8MB +BharatPi-LoRa.menu.FlashSize.8M.build.partitions=default_8MB +BharatPi-LoRa.menu.FlashSize.16M=16MB (128Mb) +BharatPi-LoRa.menu.FlashSize.16M.build.flash_size=16MB + +BharatPi-LoRa.menu.UploadSpeed.921600=921600 +BharatPi-LoRa.menu.UploadSpeed.921600.upload.speed=921600 +BharatPi-LoRa.menu.UploadSpeed.115200=115200 +BharatPi-LoRa.menu.UploadSpeed.115200.upload.speed=115200 +BharatPi-LoRa.menu.UploadSpeed.256000.windows=256000 +BharatPi-LoRa.menu.UploadSpeed.256000.upload.speed=256000 +BharatPi-LoRa.menu.UploadSpeed.230400.windows.upload.speed=256000 +BharatPi-LoRa.menu.UploadSpeed.230400=230400 +BharatPi-LoRa.menu.UploadSpeed.230400.upload.speed=230400 +BharatPi-LoRa.menu.UploadSpeed.460800.linux=460800 +BharatPi-LoRa.menu.UploadSpeed.460800.macosx=460800 +BharatPi-LoRa.menu.UploadSpeed.460800.upload.speed=460800 +BharatPi-LoRa.menu.UploadSpeed.512000.windows=512000 +BharatPi-LoRa.menu.UploadSpeed.512000.upload.speed=512000 + +BharatPi-LoRa.menu.LoopCore.1=Core 1 +BharatPi-LoRa.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +BharatPi-LoRa.menu.LoopCore.0=Core 0 +BharatPi-LoRa.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +BharatPi-LoRa.menu.EventsCore.1=Core 1 +BharatPi-LoRa.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +BharatPi-LoRa.menu.EventsCore.0=Core 0 +BharatPi-LoRa.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +BharatPi-LoRa.menu.DebugLevel.none=None +BharatPi-LoRa.menu.DebugLevel.none.build.code_debug=0 +BharatPi-LoRa.menu.DebugLevel.error=Error +BharatPi-LoRa.menu.DebugLevel.error.build.code_debug=1 +BharatPi-LoRa.menu.DebugLevel.warn=Warn +BharatPi-LoRa.menu.DebugLevel.warn.build.code_debug=2 +BharatPi-LoRa.menu.DebugLevel.info=Info +BharatPi-LoRa.menu.DebugLevel.info.build.code_debug=3 +BharatPi-LoRa.menu.DebugLevel.debug=Debug +BharatPi-LoRa.menu.DebugLevel.debug.build.code_debug=4 +BharatPi-LoRa.menu.DebugLevel.verbose=Verbose +BharatPi-LoRa.menu.DebugLevel.verbose.build.code_debug=5 + +BharatPi-LoRa.menu.EraseFlash.none=Disabled +BharatPi-LoRa.menu.EraseFlash.none.upload.erase_cmd= +BharatPi-LoRa.menu.EraseFlash.all=Enabled +BharatPi-LoRa.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + um_bling.name=UM BLING um_bling.vid.0=0x303a um_bling.pid.0=0x817F @@ -2999,10 +3758,8 @@ um_feathers2.menu.FlashSize.4M=4MB (32Mb) um_feathers2.menu.FlashSize.4M.build.flash_size=4MB um_feathers2.menu.FlashSize.8M=8MB (64Mb) um_feathers2.menu.FlashSize.8M.build.flash_size=8MB -um_feathers2.menu.FlashSize.8M.build.partitions=default_8MB um_feathers2.menu.FlashSize.2M=2MB (16Mb) um_feathers2.menu.FlashSize.2M.build.flash_size=2MB -um_feathers2.menu.FlashSize.2M.build.partitions=minimal um_feathers2.menu.UploadSpeed.921600=921600 um_feathers2.menu.UploadSpeed.921600.upload.speed=921600 @@ -3141,7 +3898,6 @@ um_feathers2neo.menu.FlashSize.4M=4MB (32Mb) um_feathers2neo.menu.FlashSize.4M.build.flash_size=4MB um_feathers2neo.menu.FlashSize.2M=2MB (16Mb) um_feathers2neo.menu.FlashSize.2M.build.flash_size=2MB -um_feathers2neo.menu.FlashSize.2M.build.partitions=minimal um_feathers2neo.menu.UploadSpeed.921600=921600 um_feathers2neo.menu.UploadSpeed.921600.upload.speed=921600 @@ -3375,7 +4131,7 @@ um_feathers3neo.build.cdc_on_boot=1 um_feathers3neo.build.msc_on_boot=0 um_feathers3neo.build.dfu_on_boot=0 um_feathers3neo.build.f_cpu=240000000L -um_feathers3neo.build.flash_size=16MB +um_feathers3neo.build.flash_size=8MB um_feathers3neo.build.flash_freq=80m um_feathers3neo.build.flash_mode=dio um_feathers3neo.build.boot=qio @@ -3662,6 +4418,160 @@ um_nanos3.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +um_omgs3.name=UM OMGS3 +um_omgs3.vid.0=0x303a +um_omgs3.pid.0=0x8224 +um_omgs3.upload_port.0.vid=0x303a +um_omgs3.upload_port.0.pid=0x8224 + +um_omgs3.bootloader.tool=esptool_py +um_omgs3.bootloader.tool.default=esptool_py + +um_omgs3.upload.tool=esptool_py +um_omgs3.upload.tool.default=esptool_py +um_omgs3.upload.tool.network=esp_ota + +um_omgs3.upload.maximum_size=1310720 +um_omgs3.upload.maximum_data_size=327680 +um_omgs3.upload.flags= +um_omgs3.upload.extra_flags= +um_omgs3.upload.use_1200bps_touch=false +um_omgs3.upload.wait_for_upload_port=false + +um_omgs3.serial.disableDTR=false +um_omgs3.serial.disableRTS=false + +um_omgs3.build.tarch=xtensa +um_omgs3.build.bootloader_addr=0x0 +um_omgs3.build.target=esp32s3 +um_omgs3.build.mcu=esp32s3 +um_omgs3.build.core=esp32 +um_omgs3.build.variant=um_omgs3 +um_omgs3.build.board=OMGS3 + +um_omgs3.build.usb_mode=1 +um_omgs3.build.cdc_on_boot=1 +um_omgs3.build.msc_on_boot=0 +um_omgs3.build.dfu_on_boot=0 +um_omgs3.build.f_cpu=240000000L +um_omgs3.build.flash_size=8MB +um_omgs3.build.flash_freq=80m +um_omgs3.build.flash_mode=dio +um_omgs3.build.boot=qio +um_omgs3.build.partitions=default +um_omgs3.build.defines= +um_omgs3.build.loop_core= +um_omgs3.build.event_core= +um_omgs3.build.flash_type=qio +um_omgs3.build.psram_type=qspi +um_omgs3.build.memory_type=qio_qspi + +um_omgs3.menu.LoopCore.1=Core 1 +um_omgs3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +um_omgs3.menu.LoopCore.0=Core 0 +um_omgs3.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +um_omgs3.menu.EventsCore.1=Core 1 +um_omgs3.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +um_omgs3.menu.EventsCore.0=Core 0 +um_omgs3.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +um_omgs3.menu.USBMode.hwcdc=Hardware CDC and JTAG +um_omgs3.menu.USBMode.hwcdc.build.usb_mode=1 +um_omgs3.menu.USBMode.default=USB-OTG (TinyUSB) +um_omgs3.menu.USBMode.default.build.usb_mode=0 + +um_omgs3.menu.CDCOnBoot.cdc=Enabled +um_omgs3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 +um_omgs3.menu.CDCOnBoot.default=Disabled +um_omgs3.menu.CDCOnBoot.default.build.cdc_on_boot=0 + +um_omgs3.menu.MSCOnBoot.default=Disabled +um_omgs3.menu.MSCOnBoot.default.build.msc_on_boot=0 +um_omgs3.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +um_omgs3.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +um_omgs3.menu.DFUOnBoot.default=Disabled +um_omgs3.menu.DFUOnBoot.default.build.dfu_on_boot=0 +um_omgs3.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +um_omgs3.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +um_omgs3.menu.UploadMode.cdc.upload.wait_for_upload_port=true +um_omgs3.menu.UploadMode.default=UART0 / Hardware CDC +um_omgs3.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +um_omgs3.menu.UploadMode.cdc.upload.use_1200bps_touch=true +um_omgs3.menu.UploadMode.default.upload.use_1200bps_touch=false +um_omgs3.menu.UploadMode.default.upload.wait_for_upload_port=false + +um_omgs3.menu.PSRAM.enabled=Enabled +um_omgs3.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +um_omgs3.menu.PSRAM.disabled=Disabled +um_omgs3.menu.PSRAM.disabled.build.defines= + +um_omgs3.menu.PartitionScheme.default_8MB=Default (3MB APP/1.5MB SPIFFS) +um_omgs3.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +um_omgs3.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +um_omgs3.menu.PartitionScheme.tinyuf2=TinyUF2 Compatibility (2MB APP/3.7MB FFAT) +um_omgs3.menu.PartitionScheme.tinyuf2.build.custom_bootloader=bootloader_tinyuf2 +um_omgs3.menu.PartitionScheme.tinyuf2.build.custom_partitions=partitions_tinyuf2 +um_omgs3.menu.PartitionScheme.tinyuf2.upload.extra_flags=0x410000 "{runtime.platform.path}/variants/{build.variant}/tinyuf2.bin" +um_omgs3.menu.PartitionScheme.tinyuf2.upload.maximum_size=2097152 + +um_omgs3.menu.CPUFreq.240=240MHz (WiFi) +um_omgs3.menu.CPUFreq.240.build.f_cpu=240000000L +um_omgs3.menu.CPUFreq.160=160MHz (WiFi) +um_omgs3.menu.CPUFreq.160.build.f_cpu=160000000L +um_omgs3.menu.CPUFreq.80=80MHz (WiFi) +um_omgs3.menu.CPUFreq.80.build.f_cpu=80000000L +um_omgs3.menu.CPUFreq.40=40MHz +um_omgs3.menu.CPUFreq.40.build.f_cpu=40000000L +um_omgs3.menu.CPUFreq.20=20MHz +um_omgs3.menu.CPUFreq.20.build.f_cpu=20000000L +um_omgs3.menu.CPUFreq.10=10MHz +um_omgs3.menu.CPUFreq.10.build.f_cpu=10000000L + +um_omgs3.menu.FlashMode.qio=QIO +um_omgs3.menu.FlashMode.qio.build.flash_mode=dio +um_omgs3.menu.FlashMode.qio.build.boot=qio +um_omgs3.menu.FlashMode.dio=DIO +um_omgs3.menu.FlashMode.dio.build.flash_mode=dio +um_omgs3.menu.FlashMode.dio.build.boot=dio + +um_omgs3.menu.UploadSpeed.921600=921600 +um_omgs3.menu.UploadSpeed.921600.upload.speed=921600 +um_omgs3.menu.UploadSpeed.115200=115200 +um_omgs3.menu.UploadSpeed.115200.upload.speed=115200 +um_omgs3.menu.UploadSpeed.256000.windows=256000 +um_omgs3.menu.UploadSpeed.256000.upload.speed=256000 +um_omgs3.menu.UploadSpeed.230400.windows.upload.speed=256000 +um_omgs3.menu.UploadSpeed.230400=230400 +um_omgs3.menu.UploadSpeed.230400.upload.speed=230400 +um_omgs3.menu.UploadSpeed.460800.linux=460800 +um_omgs3.menu.UploadSpeed.460800.macosx=460800 +um_omgs3.menu.UploadSpeed.460800.upload.speed=460800 +um_omgs3.menu.UploadSpeed.512000.windows=512000 +um_omgs3.menu.UploadSpeed.512000.upload.speed=512000 + +um_omgs3.menu.DebugLevel.none=None +um_omgs3.menu.DebugLevel.none.build.code_debug=0 +um_omgs3.menu.DebugLevel.error=Error +um_omgs3.menu.DebugLevel.error.build.code_debug=1 +um_omgs3.menu.DebugLevel.warn=Warn +um_omgs3.menu.DebugLevel.warn.build.code_debug=2 +um_omgs3.menu.DebugLevel.info=Info +um_omgs3.menu.DebugLevel.info.build.code_debug=3 +um_omgs3.menu.DebugLevel.debug=Debug +um_omgs3.menu.DebugLevel.debug.build.code_debug=4 +um_omgs3.menu.DebugLevel.verbose=Verbose +um_omgs3.menu.DebugLevel.verbose.build.code_debug=5 + +um_omgs3.menu.EraseFlash.none=Disabled +um_omgs3.menu.EraseFlash.none.upload.erase_cmd= +um_omgs3.menu.EraseFlash.all=Enabled +um_omgs3.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + um_pros3.name=UM PROS3 um_pros3.vid.0=0x303a um_pros3.pid.0=0x80D3 @@ -3978,9 +4888,15 @@ um_tinyc6.menu.CDCOnBoot.default.build.cdc_on_boot=0 um_tinyc6.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) um_tinyc6.menu.PartitionScheme.default_8MB.build.partitions=default_8MB um_tinyc6.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 -um_tinyc6.menu.PartitionScheme.rainmaker=RainMaker +um_tinyc6.menu.PartitionScheme.rainmaker=RainMaker 4MB um_tinyc6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -um_tinyc6.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +um_tinyc6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +um_tinyc6.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +um_tinyc6.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +um_tinyc6.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +um_tinyc6.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +um_tinyc6.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +um_tinyc6.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 um_tinyc6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs um_tinyc6.menu.PartitionScheme.zigbee.build.partitions=zigbee um_tinyc6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 @@ -4016,7 +4932,6 @@ um_tinyc6.menu.FlashFreq.40.build.flash_freq=40m um_tinyc6.menu.FlashSize.8M=8MB (64Mb) um_tinyc6.menu.FlashSize.8M.build.flash_size=8MB -um_tinyc6.menu.FlashSize.8M.build.partitions=default_8MB um_tinyc6.menu.UploadSpeed.921600=921600 um_tinyc6.menu.UploadSpeed.921600.upload.speed=921600 @@ -4056,13 +4971,10 @@ um_tinyc6.menu.ZigbeeMode.default.build.zigbee_mode= um_tinyc6.menu.ZigbeeMode.default.build.zigbee_libs= um_tinyc6.menu.ZigbeeMode.ed=Zigbee ED (end device) um_tinyc6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED -um_tinyc6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -um_tinyc6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +um_tinyc6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +um_tinyc6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) um_tinyc6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -um_tinyc6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port -um_tinyc6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) -um_tinyc6.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP -um_tinyc6.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port +um_tinyc6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native ############################################################## @@ -4170,7 +5082,6 @@ um_tinys2.menu.FlashSize.4M=4MB (32Mb) um_tinys2.menu.FlashSize.4M.build.flash_size=4MB um_tinys2.menu.FlashSize.2M=2MB (16Mb) um_tinys2.menu.FlashSize.2M.build.flash_size=2MB -um_tinys2.menu.FlashSize.2M.build.partitions=minimal um_tinys2.menu.UploadSpeed.921600=921600 um_tinys2.menu.UploadSpeed.921600.upload.speed=921600 @@ -4431,8 +5342,6 @@ S_ODI_Ultra.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## lilygo_t_display.name=LilyGo T-Display -lilygo_t_display.vid.0=0x1a86 -lilygo_t_display.pid.0=0x55d4 lilygo_t_display.upload.tool=esptool_py lilygo_t_display.upload.tool.default=esptool_py @@ -4673,9 +5582,15 @@ lilygo_t_display_s3.menu.UploadMode.cdc.upload.wait_for_upload_port=true lilygo_t_display_s3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) lilygo_t_display_s3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB lilygo_t_display_s3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -lilygo_t_display_s3.menu.PartitionScheme.rainmaker=RainMaker +lilygo_t_display_s3.menu.PartitionScheme.rainmaker=RainMaker 4MB lilygo_t_display_s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -lilygo_t_display_s3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +lilygo_t_display_s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +lilygo_t_display_s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +lilygo_t_display_s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +lilygo_t_display_s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +lilygo_t_display_s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +lilygo_t_display_s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +lilygo_t_display_s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 lilygo_t_display_s3.menu.DebugLevel.none=None lilygo_t_display_s3.menu.DebugLevel.none.build.code_debug=0 @@ -4697,6 +5612,807 @@ lilygo_t_display_s3.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +lilygo_t_eth_lite.name=LilyGo T-ETH-Lite + +lilygo_t_eth_lite.bootloader.tool=esptool_py +lilygo_t_eth_lite.bootloader.tool.default=esptool_py + +lilygo_t_eth_lite.upload.tool=esptool_py +lilygo_t_eth_lite.upload.tool.default=esptool_py +lilygo_t_eth_lite.upload.tool.network=esp_ota + +lilygo_t_eth_lite.upload.maximum_size=3145728 +lilygo_t_eth_lite.upload.maximum_data_size=327680 +lilygo_t_eth_lite.upload.speed=921600 +lilygo_t_eth_lite.upload.flags= +lilygo_t_eth_lite.upload.extra_flags= +lilygo_t_eth_lite.upload.use_1200bps_touch=false +lilygo_t_eth_lite.upload.wait_for_upload_port=false + +lilygo_t_eth_lite.serial.disableDTR=false +lilygo_t_eth_lite.serial.disableRTS=false + +lilygo_t_eth_lite.build.tarch=xtensa +lilygo_t_eth_lite.build.bootloader_addr=0x0 +lilygo_t_eth_lite.build.target=esp32s3 +lilygo_t_eth_lite.build.mcu=esp32s3 +lilygo_t_eth_lite.build.core=esp32 +lilygo_t_eth_lite.build.variant=lilygo_t_eth_lite +lilygo_t_eth_lite.build.board=LILYGO_T_ETH_LITE + +lilygo_t_eth_lite.build.usb_mode=1 +lilygo_t_eth_lite.build.cdc_on_boot=0 +lilygo_t_eth_lite.build.msc_on_boot=0 +lilygo_t_eth_lite.build.dfu_on_boot=0 +lilygo_t_eth_lite.build.f_cpu=240000000L +lilygo_t_eth_lite.build.flash_size=16MB +lilygo_t_eth_lite.build.flash_freq=80m +lilygo_t_eth_lite.build.flash_mode=dio +lilygo_t_eth_lite.build.boot=qio +lilygo_t_eth_lite.build.boot_freq=80m +lilygo_t_eth_lite.build.partitions=app3M_fat9M_16MB +lilygo_t_eth_lite.build.defines= +lilygo_t_eth_lite.build.loop_core= +lilygo_t_eth_lite.build.event_core= +lilygo_t_eth_lite.build.psram_type=opi +lilygo_t_eth_lite.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +lilygo_t_eth_lite.menu.JTAGAdapter.default=Disabled +lilygo_t_eth_lite.menu.JTAGAdapter.default.build.copy_jtag_files=0 +lilygo_t_eth_lite.menu.JTAGAdapter.builtin=Integrated USB JTAG +lilygo_t_eth_lite.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +lilygo_t_eth_lite.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 + +lilygo_t_eth_lite.menu.LoopCore.1=Core 1 +lilygo_t_eth_lite.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +lilygo_t_eth_lite.menu.LoopCore.0=Core 0 +lilygo_t_eth_lite.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +lilygo_t_eth_lite.menu.EventsCore.1=Core 1 +lilygo_t_eth_lite.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +lilygo_t_eth_lite.menu.EventsCore.0=Core 0 +lilygo_t_eth_lite.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +lilygo_t_eth_lite.menu.USBMode.hwcdc=Hardware CDC and JTAG +lilygo_t_eth_lite.menu.USBMode.hwcdc.build.usb_mode=1 +lilygo_t_eth_lite.menu.USBMode.default=USB-OTG (TinyUSB) +lilygo_t_eth_lite.menu.USBMode.default.build.usb_mode=0 + +lilygo_t_eth_lite.menu.CDCOnBoot.default=Disabled +lilygo_t_eth_lite.menu.CDCOnBoot.default.build.cdc_on_boot=0 +lilygo_t_eth_lite.menu.CDCOnBoot.cdc=Enabled +lilygo_t_eth_lite.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +lilygo_t_eth_lite.menu.MSCOnBoot.default=Disabled +lilygo_t_eth_lite.menu.MSCOnBoot.default.build.msc_on_boot=0 +lilygo_t_eth_lite.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +lilygo_t_eth_lite.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +lilygo_t_eth_lite.menu.DFUOnBoot.default=Disabled +lilygo_t_eth_lite.menu.DFUOnBoot.default.build.dfu_on_boot=0 +lilygo_t_eth_lite.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +lilygo_t_eth_lite.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +lilygo_t_eth_lite.menu.UploadMode.default=UART0 / Hardware CDC +lilygo_t_eth_lite.menu.UploadMode.default.upload.use_1200bps_touch=false +lilygo_t_eth_lite.menu.UploadMode.default.upload.wait_for_upload_port=false +lilygo_t_eth_lite.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +lilygo_t_eth_lite.menu.UploadMode.cdc.upload.use_1200bps_touch=true +lilygo_t_eth_lite.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +lilygo_t_eth_lite.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +lilygo_t_eth_lite.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +lilygo_t_eth_lite.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +lilygo_t_eth_lite.menu.PartitionScheme.rainmaker=RainMaker 4MB +lilygo_t_eth_lite.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +lilygo_t_eth_lite.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +lilygo_t_eth_lite.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +lilygo_t_eth_lite.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +lilygo_t_eth_lite.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +lilygo_t_eth_lite.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +lilygo_t_eth_lite.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +lilygo_t_eth_lite.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 + +lilygo_t_eth_lite.menu.DebugLevel.none=None +lilygo_t_eth_lite.menu.DebugLevel.none.build.code_debug=0 +lilygo_t_eth_lite.menu.DebugLevel.error=Error +lilygo_t_eth_lite.menu.DebugLevel.error.build.code_debug=1 +lilygo_t_eth_lite.menu.DebugLevel.warn=Warn +lilygo_t_eth_lite.menu.DebugLevel.warn.build.code_debug=2 +lilygo_t_eth_lite.menu.DebugLevel.info=Info +lilygo_t_eth_lite.menu.DebugLevel.info.build.code_debug=3 +lilygo_t_eth_lite.menu.DebugLevel.debug=Debug +lilygo_t_eth_lite.menu.DebugLevel.debug.build.code_debug=4 +lilygo_t_eth_lite.menu.DebugLevel.verbose=Verbose +lilygo_t_eth_lite.menu.DebugLevel.verbose.build.code_debug=5 + +lilygo_t_eth_lite.menu.EraseFlash.none=Disabled +lilygo_t_eth_lite.menu.EraseFlash.none.upload.erase_cmd= +lilygo_t_eth_lite.menu.EraseFlash.all=Enabled +lilygo_t_eth_lite.menu.EraseFlash.all.upload.erase_cmd=-e + + +############################################################## + +lilygo_t3s3.name=LilyGo T3-S3 + +lilygo_t3s3.upload.tool=esptool_py +lilygo_t3s3.upload.tool.default=esptool_py +lilygo_t3s3.upload.tool.network=esp_ota +lilygo_t3s3.upload.maximum_size=1310720 +lilygo_t3s3.upload.maximum_data_size=327680 +lilygo_t3s3.upload.wait_for_upload_port=false +lilygo_t3s3.upload.speed=460800 +lilygo_t3s3.upload.flags= +lilygo_t3s3.upload.extra_flags= + +lilygo_t3s3.bootloader.tool=esptool_py +lilygo_t3s3.bootloader.tool.default=esptool_py + +lilygo_t3s3.serial.disableDTR=true +lilygo_t3s3.serial.disableRTS=true + +lilygo_t3s3.build.tarch=xtensa +lilygo_t3s3.build.bootloader_addr=0x0 +lilygo_t3s3.build.mcu=esp32s3 +lilygo_t3s3.build.core=esp32 +lilygo_t3s3.build.target=esp32s3 +lilygo_t3s3.build.board=LILYGO_T3_S3 + +lilygo_t3s3.build.usb_mode=1 +lilygo_t3s3.build.cdc_on_boot=1 +lilygo_t3s3.build.msc_on_boot=0 +lilygo_t3s3.build.dfu_on_boot=0 + +lilygo_t3s3.build.f_cpu=240000000L +lilygo_t3s3.build.flash_size=4MB +lilygo_t3s3.build.flash_freq=80m +lilygo_t3s3.build.flash_mode=dio +lilygo_t3s3.build.boot=dio +lilygo_t3s3.build.partitions=default +lilygo_t3s3.build.defines= + +lilygo_t3s3.menu.PSRAM.disabled=Disabled +lilygo_t3s3.menu.PSRAM.disabled.build.defines= +lilygo_t3s3.menu.PSRAM.enabled=Enabled +lilygo_t3s3.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +lilygo_t3s3.menu.PSRAM.enabled.build.psram_type=qspi + +lilygo_t3s3.menu.LoopCore.1=Core 1 +lilygo_t3s3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +lilygo_t3s3.menu.LoopCore.0=Core 0 +lilygo_t3s3.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +lilygo_t3s3.menu.EventsCore.1=Core 1 +lilygo_t3s3.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +lilygo_t3s3.menu.EventsCore.0=Core 0 +lilygo_t3s3.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +lilygo_t3s3.menu.USBMode.hwcdc=Hardware CDC and JTAG +lilygo_t3s3.menu.USBMode.hwcdc.build.usb_mode=1 +lilygo_t3s3.menu.USBMode.default=USB-OTG (TinyUSB) +lilygo_t3s3.menu.USBMode.default.build.usb_mode=0 + +lilygo_t3s3.menu.CDCOnBoot.default=Disabled +lilygo_t3s3.menu.CDCOnBoot.default.build.cdc_on_boot=0 +lilygo_t3s3.menu.CDCOnBoot.cdc=Enabled +lilygo_t3s3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +lilygo_t3s3.menu.MSCOnBoot.default=Disabled +lilygo_t3s3.menu.MSCOnBoot.default.build.msc_on_boot=0 +lilygo_t3s3.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +lilygo_t3s3.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +lilygo_t3s3.menu.DFUOnBoot.default=Disabled +lilygo_t3s3.menu.DFUOnBoot.default.build.dfu_on_boot=0 +lilygo_t3s3.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +lilygo_t3s3.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +lilygo_t3s3.menu.UploadMode.default=UART0 / Hardware CDC +lilygo_t3s3.menu.UploadMode.default.upload.use_1200bps_touch=false +lilygo_t3s3.menu.UploadMode.default.upload.wait_for_upload_port=false +lilygo_t3s3.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +lilygo_t3s3.menu.UploadMode.cdc.upload.use_1200bps_touch=true +lilygo_t3s3.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +lilygo_t3s3.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +lilygo_t3s3.menu.PartitionScheme.default.build.partitions=default +lilygo_t3s3.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +lilygo_t3s3.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +lilygo_t3s3.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +lilygo_t3s3.menu.PartitionScheme.minimal.build.partitions=minimal +lilygo_t3s3.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +lilygo_t3s3.menu.PartitionScheme.no_ota.build.partitions=no_ota +lilygo_t3s3.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +lilygo_t3s3.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +lilygo_t3s3.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +lilygo_t3s3.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +lilygo_t3s3.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +lilygo_t3s3.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +lilygo_t3s3.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +lilygo_t3s3.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +lilygo_t3s3.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +lilygo_t3s3.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +lilygo_t3s3.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +lilygo_t3s3.menu.PartitionScheme.huge_app.build.partitions=huge_app +lilygo_t3s3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +lilygo_t3s3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +lilygo_t3s3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +lilygo_t3s3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 + +lilygo_t3s3.menu.CPUFreq.240=240MHz (WiFi/BT) +lilygo_t3s3.menu.CPUFreq.240.build.f_cpu=240000000L +lilygo_t3s3.menu.CPUFreq.160=160MHz (WiFi/BT) +lilygo_t3s3.menu.CPUFreq.160.build.f_cpu=160000000L +lilygo_t3s3.menu.CPUFreq.80=80MHz (WiFi/BT) +lilygo_t3s3.menu.CPUFreq.80.build.f_cpu=80000000L + +lilygo_t3s3.menu.FlashMode.qio=QIO +lilygo_t3s3.menu.FlashMode.qio.build.flash_mode=dio +lilygo_t3s3.menu.FlashMode.qio.build.boot=qio +lilygo_t3s3.menu.FlashMode.dio=DIO +lilygo_t3s3.menu.FlashMode.dio.build.flash_mode=dio +lilygo_t3s3.menu.FlashMode.dio.build.boot=dio + +lilygo_t3s3.menu.FlashFreq.80=80MHz +lilygo_t3s3.menu.FlashFreq.80.build.flash_freq=80m +lilygo_t3s3.menu.FlashFreq.40=40MHz +lilygo_t3s3.menu.FlashFreq.40.build.flash_freq=40m + +lilygo_t3s3.menu.UploadSpeed.921600=921600 +lilygo_t3s3.menu.UploadSpeed.921600.upload.speed=921600 +lilygo_t3s3.menu.UploadSpeed.115200=115200 +lilygo_t3s3.menu.UploadSpeed.115200.upload.speed=115200 +lilygo_t3s3.menu.UploadSpeed.256000.windows=256000 +lilygo_t3s3.menu.UploadSpeed.256000.upload.speed=256000 +lilygo_t3s3.menu.UploadSpeed.230400.windows.upload.speed=256000 +lilygo_t3s3.menu.UploadSpeed.230400=230400 +lilygo_t3s3.menu.UploadSpeed.230400.upload.speed=230400 +lilygo_t3s3.menu.UploadSpeed.460800.linux=460800 +lilygo_t3s3.menu.UploadSpeed.460800.macosx=460800 +lilygo_t3s3.menu.UploadSpeed.460800.upload.speed=460800 +lilygo_t3s3.menu.UploadSpeed.512000.windows=512000 +lilygo_t3s3.menu.UploadSpeed.512000.upload.speed=512000 + +lilygo_t3s3.menu.DebugLevel.none=None +lilygo_t3s3.menu.DebugLevel.none.build.code_debug=0 +lilygo_t3s3.menu.DebugLevel.error=Error +lilygo_t3s3.menu.DebugLevel.error.build.code_debug=1 +lilygo_t3s3.menu.DebugLevel.warn=Warn +lilygo_t3s3.menu.DebugLevel.warn.build.code_debug=2 +lilygo_t3s3.menu.DebugLevel.info=Info +lilygo_t3s3.menu.DebugLevel.info.build.code_debug=3 +lilygo_t3s3.menu.DebugLevel.debug=Debug +lilygo_t3s3.menu.DebugLevel.debug.build.code_debug=4 +lilygo_t3s3.menu.DebugLevel.verbose=Verbose +lilygo_t3s3.menu.DebugLevel.verbose.build.code_debug=5 + +lilygo_t3s3.menu.EraseFlash.none=Disabled +lilygo_t3s3.menu.EraseFlash.none.upload.erase_cmd= +lilygo_t3s3.menu.EraseFlash.all=Enabled +lilygo_t3s3.menu.EraseFlash.all.upload.erase_cmd=-e + +lilygo_t3s3.menu.Revision.Radio_SX1262=Radio-SX1262 +lilygo_t3s3.menu.Revision.Radio_SX1262.build.board=LILYGO_T3S3_SX1262 +lilygo_t3s3.menu.Revision.Radio_SX1262.build.variant=lilygo_t3_s3_sx1262 + +lilygo_t3s3.menu.Revision.Radio_SX1276=Radio-SX1276 +lilygo_t3s3.menu.Revision.Radio_SX1276.build.board=LILYGO_T3S3_SX1276 +lilygo_t3s3.menu.Revision.Radio_SX1276.build.variant=lilygo_t3_s3_sx127x + +lilygo_t3s3.menu.Revision.Radio_SX1278=Radio-SX1278 +lilygo_t3s3.menu.Revision.Radio_SX1278.build.board=LILYGO_T3S3_SX1278 +lilygo_t3s3.menu.Revision.Radio_SX1278.build.variant=lilygo_t3_s3_sx127x + +lilygo_t3s3.menu.Revision.Radio_SX1280=Radio-SX1280 +lilygo_t3s3.menu.Revision.Radio_SX1280.build.board=LILYGO_T3S3_SX1280 +lilygo_t3s3.menu.Revision.Radio_SX1280.build.variant=lilygo_t3_s3_sx1280 + +lilygo_t3s3.menu.Revision.Radio_SX1280PA=Radio-SX1280PA +lilygo_t3s3.menu.Revision.Radio_SX1280PA.build.board=LILYGO_T3S3_SX1280PA +lilygo_t3s3.menu.Revision.Radio_SX1280PA.build.variant=lilygo_t3_s3_sx1280pa + +lilygo_t3s3.menu.Revision.Radio_LR1121=Radio-LR1121 +lilygo_t3s3.menu.Revision.Radio_LR1121.build.board=LILYGO_T3S3_LR1121 +lilygo_t3s3.menu.Revision.Radio_LR1121.build.variant=lilygo_t3_s3_lr1121 + +############################################################## + +twatchs3.name=LilyGo T-Watch-S3 + +twatchs3.bootloader.tool=esptool_py +twatchs3.bootloader.tool.default=esptool_py + +twatchs3.upload.tool=esptool_py +twatchs3.upload.tool.default=esptool_py +twatchs3.upload.tool.network=esp_ota + +twatchs3.upload.maximum_size=1310720 +twatchs3.upload.maximum_data_size=327680 +twatchs3.upload.flags= +twatchs3.upload.extra_flags= +twatchs3.upload.use_1200bps_touch=false +twatchs3.upload.wait_for_upload_port=false + +twatchs3.serial.disableDTR=false +twatchs3.serial.disableRTS=false + +twatchs3.build.tarch=xtensa +twatchs3.build.bootloader_addr=0x0 +twatchs3.build.target=esp32s3 +twatchs3.build.mcu=esp32s3 +twatchs3.build.core=esp32 +twatchs3.build.variant=lilygo_twatch_s3 +twatchs3.build.board=T_WATCH_S3 + +twatchs3.build.usb_mode=1 +twatchs3.build.cdc_on_boot=0 +twatchs3.build.msc_on_boot=0 +twatchs3.build.dfu_on_boot=0 +twatchs3.build.f_cpu=240000000L +twatchs3.build.flash_size=16MB +twatchs3.build.flash_freq=80m +twatchs3.build.flash_mode=dio +twatchs3.build.boot=qio +twatchs3.build.boot_freq=80m +twatchs3.build.partitions=app3M_fat9M_16MB +twatchs3.build.defines=-DBOARD_HAS_PSRAM -DARDUINO_T_WATCH_S3 +twatchs3.build.loop_core= +twatchs3.build.event_core= +twatchs3.build.psram_type=opi +twatchs3.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +twatchs3.menu.JTAGAdapter.default=Disabled +twatchs3.menu.JTAGAdapter.default.build.copy_jtag_files=0 +twatchs3.menu.JTAGAdapter.builtin=Integrated USB JTAG +twatchs3.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +twatchs3.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 + +twatchs3.menu.LoopCore.1=Core 1 +twatchs3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +twatchs3.menu.LoopCore.0=Core 0 +twatchs3.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +twatchs3.menu.EventsCore.1=Core 1 +twatchs3.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +twatchs3.menu.EventsCore.0=Core 0 +twatchs3.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +twatchs3.menu.USBMode.hwcdc=Hardware CDC and JTAG +twatchs3.menu.USBMode.hwcdc.build.usb_mode=1 +twatchs3.menu.USBMode.default=USB-OTG (TinyUSB) +twatchs3.menu.USBMode.default.build.usb_mode=0 + +twatchs3.menu.CDCOnBoot.default=Enabled +twatchs3.menu.CDCOnBoot.default.build.cdc_on_boot=1 +twatchs3.menu.CDCOnBoot.cdc=Disabled +twatchs3.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +twatchs3.menu.MSCOnBoot.default=Disabled +twatchs3.menu.MSCOnBoot.default.build.msc_on_boot=0 +twatchs3.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +twatchs3.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +twatchs3.menu.DFUOnBoot.default=Disabled +twatchs3.menu.DFUOnBoot.default.build.dfu_on_boot=0 +twatchs3.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +twatchs3.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +twatchs3.menu.UploadMode.default=UART0 / Hardware CDC +twatchs3.menu.UploadMode.default.upload.use_1200bps_touch=false +twatchs3.menu.UploadMode.default.upload.wait_for_upload_port=false +twatchs3.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +twatchs3.menu.UploadMode.cdc.upload.use_1200bps_touch=true +twatchs3.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +twatchs3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +twatchs3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +twatchs3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +twatchs3.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +twatchs3.menu.PartitionScheme.fatflash.build.partitions=ffat +twatchs3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +twatchs3.menu.PartitionScheme.rainmaker=RainMaker +twatchs3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +twatchs3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +twatchs3.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +twatchs3.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +twatchs3.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +twatchs3.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +twatchs3.menu.PartitionScheme.custom=Custom +twatchs3.menu.PartitionScheme.custom.build.partitions= +twatchs3.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +twatchs3.menu.CPUFreq.240=240MHz (WiFi) +twatchs3.menu.CPUFreq.240.build.f_cpu=240000000L +twatchs3.menu.CPUFreq.160=160MHz (WiFi) +twatchs3.menu.CPUFreq.160.build.f_cpu=160000000L +twatchs3.menu.CPUFreq.80=80MHz (WiFi) +twatchs3.menu.CPUFreq.80.build.f_cpu=80000000L +twatchs3.menu.CPUFreq.40=40MHz +twatchs3.menu.CPUFreq.40.build.f_cpu=40000000L +twatchs3.menu.CPUFreq.20=20MHz +twatchs3.menu.CPUFreq.20.build.f_cpu=20000000L +twatchs3.menu.CPUFreq.10=10MHz +twatchs3.menu.CPUFreq.10.build.f_cpu=10000000L + +twatchs3.menu.UploadSpeed.921600=921600 +twatchs3.menu.UploadSpeed.921600.upload.speed=921600 +twatchs3.menu.UploadSpeed.115200=115200 +twatchs3.menu.UploadSpeed.115200.upload.speed=115200 +twatchs3.menu.UploadSpeed.256000.windows=256000 +twatchs3.menu.UploadSpeed.256000.upload.speed=256000 +twatchs3.menu.UploadSpeed.230400.windows.upload.speed=256000 +twatchs3.menu.UploadSpeed.230400=230400 +twatchs3.menu.UploadSpeed.230400.upload.speed=230400 +twatchs3.menu.UploadSpeed.460800.linux=460800 +twatchs3.menu.UploadSpeed.460800.macosx=460800 +twatchs3.menu.UploadSpeed.460800.upload.speed=460800 +twatchs3.menu.UploadSpeed.512000.windows=512000 +twatchs3.menu.UploadSpeed.512000.upload.speed=512000 + +twatchs3.menu.DebugLevel.none=None +twatchs3.menu.DebugLevel.none.build.code_debug=0 +twatchs3.menu.DebugLevel.error=Error +twatchs3.menu.DebugLevel.error.build.code_debug=1 +twatchs3.menu.DebugLevel.warn=Warn +twatchs3.menu.DebugLevel.warn.build.code_debug=2 +twatchs3.menu.DebugLevel.info=Info +twatchs3.menu.DebugLevel.info.build.code_debug=3 +twatchs3.menu.DebugLevel.debug=Debug +twatchs3.menu.DebugLevel.debug.build.code_debug=4 +twatchs3.menu.DebugLevel.verbose=Verbose +twatchs3.menu.DebugLevel.verbose.build.code_debug=5 + +twatchs3.menu.EraseFlash.none=Disabled +twatchs3.menu.EraseFlash.none.upload.erase_cmd= +twatchs3.menu.EraseFlash.all=Enabled +twatchs3.menu.EraseFlash.all.upload.erase_cmd=-e + +twatchs3.menu.Revision.Radio_SX1262=Radio-SX1262 +twatchs3.menu.Revision.Radio_SX1262.build.board=LILYGO_LORA_SX1262 +twatchs3.menu.Revision.Radio_SX1280=Radio-SX1280 +twatchs3.menu.Revision.Radio_SX1280.build.board=LILYGO_LORA_SX1280 +twatchs3.menu.Revision.Radio_CC1101=Radio-CC1101 +twatchs3.menu.Revision.Radio_CC1101.build.board=LILYGO_LORA_CC1101 +twatchs3.menu.Revision.Radio_LR1121=Radio-LR1121 +twatchs3.menu.Revision.Radio_LR1121.build.board=LILYGO_LORA_LR1121 +twatchs3.menu.Revision.Radio_SI4432=Radio-SI4432 +twatchs3.menu.Revision.Radio_SI4432.build.board=LILYGO_LORA_SI4432 + +############################################################## + + +twatch_ultra.name=LilyGo T-Watch-Ultra + +twatch_ultra.bootloader.tool=esptool_py +twatch_ultra.bootloader.tool.default=esptool_py + +twatch_ultra.upload.tool=esptool_py +twatch_ultra.upload.tool.default=esptool_py +twatch_ultra.upload.tool.network=esp_ota + +twatch_ultra.upload.maximum_size=1310720 +twatch_ultra.upload.maximum_data_size=327680 +twatch_ultra.upload.flags= +twatch_ultra.upload.extra_flags= +twatch_ultra.upload.use_1200bps_touch=false +twatch_ultra.upload.wait_for_upload_port=false + +twatch_ultra.serial.disableDTR=false +twatch_ultra.serial.disableRTS=false + +twatch_ultra.build.tarch=xtensa +twatch_ultra.build.bootloader_addr=0x0 +twatch_ultra.build.target=esp32s3 +twatch_ultra.build.mcu=esp32s3 +twatch_ultra.build.core=esp32 +twatch_ultra.build.variant=lilygo_twatch_ultra +twatch_ultra.build.board=T_WATCH_S3_ULTRA + +twatch_ultra.build.usb_mode=1 +twatch_ultra.build.cdc_on_boot=1 +twatch_ultra.build.msc_on_boot=0 +twatch_ultra.build.dfu_on_boot=0 +twatch_ultra.build.f_cpu=240000000L +twatch_ultra.build.flash_size=16MB +twatch_ultra.build.flash_freq=80m +twatch_ultra.build.flash_mode=dio +twatch_ultra.build.boot=qio +twatch_ultra.build.boot_freq=80m +twatch_ultra.build.partitions=app3M_fat9M_16MB +twatch_ultra.build.defines=-DBOARD_HAS_PSRAM -DARDUINO_T_WATCH_S3_ULTRA +twatch_ultra.build.loop_core= +twatch_ultra.build.event_core= +twatch_ultra.build.psram_type=qspi +twatch_ultra.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +twatch_ultra.menu.JTAGAdapter.default=Disabled +twatch_ultra.menu.JTAGAdapter.default.build.copy_jtag_files=0 +twatch_ultra.menu.JTAGAdapter.builtin=Integrated USB JTAG +twatch_ultra.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +twatch_ultra.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 + +twatch_ultra.menu.LoopCore.1=Core 1 +twatch_ultra.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +twatch_ultra.menu.LoopCore.0=Core 0 +twatch_ultra.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +twatch_ultra.menu.EventsCore.1=Core 1 +twatch_ultra.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +twatch_ultra.menu.EventsCore.0=Core 0 +twatch_ultra.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +twatch_ultra.menu.USBMode.hwcdc=Hardware CDC and JTAG +twatch_ultra.menu.USBMode.hwcdc.build.usb_mode=1 +twatch_ultra.menu.USBMode.default=USB-OTG (TinyUSB) +twatch_ultra.menu.USBMode.default.build.usb_mode=0 + +twatch_ultra.menu.CDCOnBoot.default=Enabled +twatch_ultra.menu.CDCOnBoot.default.build.cdc_on_boot=1 +twatch_ultra.menu.CDCOnBoot.cdc=Disabled +twatch_ultra.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +twatch_ultra.menu.MSCOnBoot.default=Disabled +twatch_ultra.menu.MSCOnBoot.default.build.msc_on_boot=0 +twatch_ultra.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +twatch_ultra.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +twatch_ultra.menu.DFUOnBoot.default=Disabled +twatch_ultra.menu.DFUOnBoot.default.build.dfu_on_boot=0 +twatch_ultra.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +twatch_ultra.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +twatch_ultra.menu.UploadMode.default=UART0 / Hardware CDC +twatch_ultra.menu.UploadMode.default.upload.use_1200bps_touch=false +twatch_ultra.menu.UploadMode.default.upload.wait_for_upload_port=false +twatch_ultra.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +twatch_ultra.menu.UploadMode.cdc.upload.use_1200bps_touch=true +twatch_ultra.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +twatch_ultra.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +twatch_ultra.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +twatch_ultra.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +twatch_ultra.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +twatch_ultra.menu.PartitionScheme.fatflash.build.partitions=ffat +twatch_ultra.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +twatch_ultra.menu.PartitionScheme.rainmaker=RainMaker +twatch_ultra.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +twatch_ultra.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +twatch_ultra.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +twatch_ultra.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +twatch_ultra.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +twatch_ultra.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +twatch_ultra.menu.PartitionScheme.custom=Custom +twatch_ultra.menu.PartitionScheme.custom.build.partitions= +twatch_ultra.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +twatch_ultra.menu.CPUFreq.240=240MHz (WiFi) +twatch_ultra.menu.CPUFreq.240.build.f_cpu=240000000L +twatch_ultra.menu.CPUFreq.160=160MHz (WiFi) +twatch_ultra.menu.CPUFreq.160.build.f_cpu=160000000L +twatch_ultra.menu.CPUFreq.80=80MHz (WiFi) +twatch_ultra.menu.CPUFreq.80.build.f_cpu=80000000L +twatch_ultra.menu.CPUFreq.40=40MHz +twatch_ultra.menu.CPUFreq.40.build.f_cpu=40000000L +twatch_ultra.menu.CPUFreq.20=20MHz +twatch_ultra.menu.CPUFreq.20.build.f_cpu=20000000L +twatch_ultra.menu.CPUFreq.10=10MHz +twatch_ultra.menu.CPUFreq.10.build.f_cpu=10000000L + +twatch_ultra.menu.UploadSpeed.921600=921600 +twatch_ultra.menu.UploadSpeed.921600.upload.speed=921600 +twatch_ultra.menu.UploadSpeed.115200=115200 +twatch_ultra.menu.UploadSpeed.115200.upload.speed=115200 +twatch_ultra.menu.UploadSpeed.256000.windows=256000 +twatch_ultra.menu.UploadSpeed.256000.upload.speed=256000 +twatch_ultra.menu.UploadSpeed.230400.windows.upload.speed=256000 +twatch_ultra.menu.UploadSpeed.230400=230400 +twatch_ultra.menu.UploadSpeed.230400.upload.speed=230400 +twatch_ultra.menu.UploadSpeed.460800.linux=460800 +twatch_ultra.menu.UploadSpeed.460800.macosx=460800 +twatch_ultra.menu.UploadSpeed.460800.upload.speed=460800 +twatch_ultra.menu.UploadSpeed.512000.windows=512000 +twatch_ultra.menu.UploadSpeed.512000.upload.speed=512000 + +twatch_ultra.menu.DebugLevel.none=None +twatch_ultra.menu.DebugLevel.none.build.code_debug=0 +twatch_ultra.menu.DebugLevel.error=Error +twatch_ultra.menu.DebugLevel.error.build.code_debug=1 +twatch_ultra.menu.DebugLevel.warn=Warn +twatch_ultra.menu.DebugLevel.warn.build.code_debug=2 +twatch_ultra.menu.DebugLevel.info=Info +twatch_ultra.menu.DebugLevel.info.build.code_debug=3 +twatch_ultra.menu.DebugLevel.debug=Debug +twatch_ultra.menu.DebugLevel.debug.build.code_debug=4 +twatch_ultra.menu.DebugLevel.verbose=Verbose +twatch_ultra.menu.DebugLevel.verbose.build.code_debug=5 + +twatch_ultra.menu.EraseFlash.none=Disabled +twatch_ultra.menu.EraseFlash.none.upload.erase_cmd= +twatch_ultra.menu.EraseFlash.all=Enabled +twatch_ultra.menu.EraseFlash.all.upload.erase_cmd=-e + +twatch_ultra.menu.Revision.Radio_SX1262=Radio-SX1262 +twatch_ultra.menu.Revision.Radio_SX1262.build.board=LILYGO_LORA_SX1262 +twatch_ultra.menu.Revision.Radio_SX1280=Radio-SX1280 +twatch_ultra.menu.Revision.Radio_SX1280.build.board=LILYGO_LORA_SX1280 +twatch_ultra.menu.Revision.Radio_CC1101=Radio-CC1101 +twatch_ultra.menu.Revision.Radio_CC1101.build.board=LILYGO_LORA_CC1101 +twatch_ultra.menu.Revision.Radio_LR1121=Radio-LR1121 +twatch_ultra.menu.Revision.Radio_LR1121.build.board=LILYGO_LORA_LR1121 +twatch_ultra.menu.Revision.Radio_SI4432=Radio-SI4432 +twatch_ultra.menu.Revision.Radio_SI4432.build.board=LILYGO_LORA_SI4432 + +############################################################## + +tlora_pager.name=LilyGo-T-LoRa-Pager + +tlora_pager.bootloader.tool=esptool_py +tlora_pager.bootloader.tool.default=esptool_py + +tlora_pager.upload.tool=esptool_py +tlora_pager.upload.tool.default=esptool_py +tlora_pager.upload.tool.network=esp_ota + +tlora_pager.upload.maximum_size=1310720 +tlora_pager.upload.maximum_data_size=327680 +tlora_pager.upload.flags= +tlora_pager.upload.extra_flags= +tlora_pager.upload.use_1200bps_touch=false +tlora_pager.upload.wait_for_upload_port=false + +tlora_pager.serial.disableDTR=false +tlora_pager.serial.disableRTS=false + +tlora_pager.build.tarch=xtensa +tlora_pager.build.bootloader_addr=0x0 +tlora_pager.build.target=esp32s3 +tlora_pager.build.mcu=esp32s3 +tlora_pager.build.core=esp32 +tlora_pager.build.variant=lilygo_tlora_pager +tlora_pager.build.board=T_LORA_PAGER + +tlora_pager.build.usb_mode=1 +tlora_pager.build.cdc_on_boot=1 +tlora_pager.build.msc_on_boot=0 +tlora_pager.build.dfu_on_boot=0 +tlora_pager.build.f_cpu=240000000L +tlora_pager.build.flash_size=16MB +tlora_pager.build.flash_freq=80m +tlora_pager.build.flash_mode=dio +tlora_pager.build.boot=qio +tlora_pager.build.boot_freq=80m +tlora_pager.build.partitions=app3M_fat9M_16MB +tlora_pager.build.defines=-DBOARD_HAS_PSRAM -DARDUINO_T_LORA_PAGER +tlora_pager.build.loop_core= +tlora_pager.build.event_core= +tlora_pager.build.psram_type=qspi +tlora_pager.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +tlora_pager.menu.JTAGAdapter.default=Disabled +tlora_pager.menu.JTAGAdapter.default.build.copy_jtag_files=0 +tlora_pager.menu.JTAGAdapter.builtin=Integrated USB JTAG +tlora_pager.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +tlora_pager.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 + +tlora_pager.menu.LoopCore.1=Core 1 +tlora_pager.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +tlora_pager.menu.LoopCore.0=Core 0 +tlora_pager.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +tlora_pager.menu.EventsCore.1=Core 1 +tlora_pager.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +tlora_pager.menu.EventsCore.0=Core 0 +tlora_pager.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +tlora_pager.menu.USBMode.hwcdc=Hardware CDC and JTAG +tlora_pager.menu.USBMode.hwcdc.build.usb_mode=1 +tlora_pager.menu.USBMode.default=USB-OTG (TinyUSB) +tlora_pager.menu.USBMode.default.build.usb_mode=0 + +tlora_pager.menu.CDCOnBoot.default=Enabled +tlora_pager.menu.CDCOnBoot.default.build.cdc_on_boot=1 +tlora_pager.menu.CDCOnBoot.cdc=Disabled +tlora_pager.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +tlora_pager.menu.MSCOnBoot.default=Disabled +tlora_pager.menu.MSCOnBoot.default.build.msc_on_boot=0 +tlora_pager.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +tlora_pager.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +tlora_pager.menu.DFUOnBoot.default=Disabled +tlora_pager.menu.DFUOnBoot.default.build.dfu_on_boot=0 +tlora_pager.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +tlora_pager.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +tlora_pager.menu.UploadMode.default=UART0 / Hardware CDC +tlora_pager.menu.UploadMode.default.upload.use_1200bps_touch=false +tlora_pager.menu.UploadMode.default.upload.wait_for_upload_port=false +tlora_pager.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +tlora_pager.menu.UploadMode.cdc.upload.use_1200bps_touch=true +tlora_pager.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +tlora_pager.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +tlora_pager.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +tlora_pager.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +tlora_pager.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +tlora_pager.menu.PartitionScheme.fatflash.build.partitions=ffat +tlora_pager.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +tlora_pager.menu.PartitionScheme.rainmaker=RainMaker +tlora_pager.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +tlora_pager.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +tlora_pager.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +tlora_pager.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +tlora_pager.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +tlora_pager.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +tlora_pager.menu.PartitionScheme.custom=Custom +tlora_pager.menu.PartitionScheme.custom.build.partitions= +tlora_pager.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +tlora_pager.menu.CPUFreq.240=240MHz (WiFi) +tlora_pager.menu.CPUFreq.240.build.f_cpu=240000000L +tlora_pager.menu.CPUFreq.160=160MHz (WiFi) +tlora_pager.menu.CPUFreq.160.build.f_cpu=160000000L +tlora_pager.menu.CPUFreq.80=80MHz (WiFi) +tlora_pager.menu.CPUFreq.80.build.f_cpu=80000000L +tlora_pager.menu.CPUFreq.40=40MHz +tlora_pager.menu.CPUFreq.40.build.f_cpu=40000000L +tlora_pager.menu.CPUFreq.20=20MHz +tlora_pager.menu.CPUFreq.20.build.f_cpu=20000000L +tlora_pager.menu.CPUFreq.10=10MHz +tlora_pager.menu.CPUFreq.10.build.f_cpu=10000000L + +tlora_pager.menu.UploadSpeed.921600=921600 +tlora_pager.menu.UploadSpeed.921600.upload.speed=921600 +tlora_pager.menu.UploadSpeed.115200=115200 +tlora_pager.menu.UploadSpeed.115200.upload.speed=115200 +tlora_pager.menu.UploadSpeed.256000.windows=256000 +tlora_pager.menu.UploadSpeed.256000.upload.speed=256000 +tlora_pager.menu.UploadSpeed.230400.windows.upload.speed=256000 +tlora_pager.menu.UploadSpeed.230400=230400 +tlora_pager.menu.UploadSpeed.230400.upload.speed=230400 +tlora_pager.menu.UploadSpeed.460800.linux=460800 +tlora_pager.menu.UploadSpeed.460800.macosx=460800 +tlora_pager.menu.UploadSpeed.460800.upload.speed=460800 +tlora_pager.menu.UploadSpeed.512000.windows=512000 +tlora_pager.menu.UploadSpeed.512000.upload.speed=512000 + +tlora_pager.menu.DebugLevel.none=None +tlora_pager.menu.DebugLevel.none.build.code_debug=0 +tlora_pager.menu.DebugLevel.error=Error +tlora_pager.menu.DebugLevel.error.build.code_debug=1 +tlora_pager.menu.DebugLevel.warn=Warn +tlora_pager.menu.DebugLevel.warn.build.code_debug=2 +tlora_pager.menu.DebugLevel.info=Info +tlora_pager.menu.DebugLevel.info.build.code_debug=3 +tlora_pager.menu.DebugLevel.debug=Debug +tlora_pager.menu.DebugLevel.debug.build.code_debug=4 +tlora_pager.menu.DebugLevel.verbose=Verbose +tlora_pager.menu.DebugLevel.verbose.build.code_debug=5 + +tlora_pager.menu.EraseFlash.none=Disabled +tlora_pager.menu.EraseFlash.none.upload.erase_cmd= +tlora_pager.menu.EraseFlash.all=Enabled +tlora_pager.menu.EraseFlash.all.upload.erase_cmd=-e + + +tlora_pager.menu.Revision.Radio_SX1262=Radio-SX1262 +tlora_pager.menu.Revision.Radio_SX1262.build.board=LILYGO_LORA_SX1262 +tlora_pager.menu.Revision.Radio_SX1280=Radio-SX1280 +tlora_pager.menu.Revision.Radio_SX1280.build.board=LILYGO_LORA_SX1280 +tlora_pager.menu.Revision.Radio_CC1101=Radio-CC1101 +tlora_pager.menu.Revision.Radio_CC1101.build.board=LILYGO_LORA_CC1101 +tlora_pager.menu.Revision.Radio_LR1121=Radio-LR1121 +tlora_pager.menu.Revision.Radio_LR1121.build.board=LILYGO_LORA_LR1121 +tlora_pager.menu.Revision.Radio_SI4432=Radio-SI4432 +tlora_pager.menu.Revision.Radio_SI4432.build.board=LILYGO_LORA_SI4432 + +############################################################## + micros2.name=microS2 micros2.vid.0=0x239A micros2.pid.0=0x80C5 @@ -4810,10 +6526,8 @@ micros2.menu.FlashSize.4M=4MB (32Mb) micros2.menu.FlashSize.4M.build.flash_size=4MB micros2.menu.FlashSize.8M=8MB (64Mb) micros2.menu.FlashSize.8M.build.flash_size=8MB -micros2.menu.FlashSize.8M.build.partitions=default_8MB micros2.menu.FlashSize.2M=2MB (16Mb) micros2.menu.FlashSize.2M.build.flash_size=2MB -micros2.menu.FlashSize.2M.build.partitions=minimal micros2.menu.UploadSpeed.921600=921600 micros2.menu.UploadSpeed.921600.upload.speed=921600 @@ -5144,10 +6858,8 @@ ttgo-t1.menu.FlashSize.4M=4MB (32Mb) ttgo-t1.menu.FlashSize.4M.build.flash_size=4MB ttgo-t1.menu.FlashSize.2M=2MB (16Mb) ttgo-t1.menu.FlashSize.2M.build.flash_size=2MB -ttgo-t1.menu.FlashSize.2M.build.partitions=minimal ttgo-t1.menu.FlashSize.16M=16MB (128Mb) ttgo-t1.menu.FlashSize.16M.build.flash_size=16MB -ttgo-t1.menu.FlashSize.16M.build.partitions=ffat ttgo-t1.menu.UploadSpeed.921600=921600 ttgo-t1.menu.UploadSpeed.921600.upload.speed=921600 @@ -5604,7 +7316,6 @@ cw02.menu.FlashSize.4M=4MB (32Mb) cw02.menu.FlashSize.4M.build.flash_size=4MB cw02.menu.FlashSize.2M=2MB (16Mb) cw02.menu.FlashSize.2M.build.flash_size=2MB -cw02.menu.FlashSize.2M.build.partitions=minimal cw02.menu.UploadSpeed.921600=921600 cw02.menu.UploadSpeed.921600.upload.speed=921600 @@ -6005,10 +7716,8 @@ sparkfun_esp32s2_thing_plus.menu.FlashSize.4M=4MB (32Mb) sparkfun_esp32s2_thing_plus.menu.FlashSize.4M.build.flash_size=4MB sparkfun_esp32s2_thing_plus.menu.FlashSize.8M=8MB (64Mb) sparkfun_esp32s2_thing_plus.menu.FlashSize.8M.build.flash_size=8MB -sparkfun_esp32s2_thing_plus.menu.FlashSize.8M.build.partitions=default_8MB sparkfun_esp32s2_thing_plus.menu.FlashSize.2M=2MB (16Mb) sparkfun_esp32s2_thing_plus.menu.FlashSize.2M.build.flash_size=2MB -sparkfun_esp32s2_thing_plus.menu.FlashSize.2M.build.partitions=minimal sparkfun_esp32s2_thing_plus.menu.FlashSize.16M=16MB (128Mb) sparkfun_esp32s2_thing_plus.menu.FlashSize.16M.build.flash_size=16MB @@ -6045,6 +7754,223 @@ sparkfun_esp32s2_thing_plus.menu.EraseFlash.none.upload.erase_cmd= sparkfun_esp32s2_thing_plus.menu.EraseFlash.all=Enabled sparkfun_esp32s2_thing_plus.menu.EraseFlash.all.upload.erase_cmd=-e +############################################################## +# Sparkfun ESP32S3 Thing Plus + +sparkfun_esp32s3_thing_plus.name=SparkFun ESP32-S3 Thing Plus +sparkfun_esp32s3_thing_plus.bootloader.tool=esptool_py +sparkfun_esp32s3_thing_plus.bootloader.tool.default=esptool_py + +sparkfun_esp32s3_thing_plus.upload.tool=esptool_py +sparkfun_esp32s3_thing_plus.upload.tool.default=esptool_py +sparkfun_esp32s3_thing_plus.upload.tool.network=esp_ota + +sparkfun_esp32s3_thing_plus.upload.maximum_size=1310720 +sparkfun_esp32s3_thing_plus.upload.maximum_data_size=327680 +sparkfun_esp32s3_thing_plus.upload.flags= +sparkfun_esp32s3_thing_plus.upload.extra_flags= +sparkfun_esp32s3_thing_plus.upload.use_1200bps_touch=false +sparkfun_esp32s3_thing_plus.upload.wait_for_upload_port=false + +sparkfun_esp32s3_thing_plus.serial.disableDTR=false +sparkfun_esp32s3_thing_plus.serial.disableRTS=false + +sparkfun_esp32s3_thing_plus.build.tarch=xtensa +sparkfun_esp32s3_thing_plus.build.bootloader_addr=0x0 +sparkfun_esp32s3_thing_plus.build.target=esp32s3 +sparkfun_esp32s3_thing_plus.build.mcu=esp32s3 +sparkfun_esp32s3_thing_plus.build.core=esp32 +sparkfun_esp32s3_thing_plus.build.variant=sparkfun_esp32s3_thing_plus +sparkfun_esp32s3_thing_plus.build.board=SPARKFUN_ESP32S3_THING_PLUS + +sparkfun_esp32s3_thing_plus.build.usb_mode=1 +sparkfun_esp32s3_thing_plus.build.cdc_on_boot=0 +sparkfun_esp32s3_thing_plus.build.msc_on_boot=0 +sparkfun_esp32s3_thing_plus.build.dfu_on_boot=0 +sparkfun_esp32s3_thing_plus.build.f_cpu=240000000L +sparkfun_esp32s3_thing_plus.build.flash_size=4MB +sparkfun_esp32s3_thing_plus.build.flash_freq=80m +sparkfun_esp32s3_thing_plus.build.flash_mode=dio +sparkfun_esp32s3_thing_plus.build.boot=qio +sparkfun_esp32s3_thing_plus.build.boot_freq=80m +sparkfun_esp32s3_thing_plus.build.partitions=default +sparkfun_esp32s3_thing_plus.build.defines= +sparkfun_esp32s3_thing_plus.build.loop_core= +sparkfun_esp32s3_thing_plus.build.event_core= +sparkfun_esp32s3_thing_plus.build.psram_type=qspi +sparkfun_esp32s3_thing_plus.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +sparkfun_esp32s3_thing_plus.menu.JTAGAdapter.default=Disabled +sparkfun_esp32s3_thing_plus.menu.JTAGAdapter.default.build.copy_jtag_files=0 +sparkfun_esp32s3_thing_plus.menu.JTAGAdapter.builtin=Integrated USB JTAG +sparkfun_esp32s3_thing_plus.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +sparkfun_esp32s3_thing_plus.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +sparkfun_esp32s3_thing_plus.menu.JTAGAdapter.external=FTDI Adapter +sparkfun_esp32s3_thing_plus.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +sparkfun_esp32s3_thing_plus.menu.JTAGAdapter.external.build.copy_jtag_files=1 +sparkfun_esp32s3_thing_plus.menu.JTAGAdapter.bridge=ESP USB Bridge +sparkfun_esp32s3_thing_plus.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +sparkfun_esp32s3_thing_plus.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +sparkfun_esp32s3_thing_plus.menu.PSRAM.enabled=QSPI PSRAM +sparkfun_esp32s3_thing_plus.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +sparkfun_esp32s3_thing_plus.menu.PSRAM.enabled.build.psram_type=qspi + +sparkfun_esp32s3_thing_plus.menu.PSRAM.disabled=Disabled +sparkfun_esp32s3_thing_plus.menu.PSRAM.disabled.build.defines= +sparkfun_esp32s3_thing_plus.menu.PSRAM.disabled.build.psram_type=qspi +sparkfun_esp32s3_thing_plus.menu.PSRAM.opi=OPI PSRAM +sparkfun_esp32s3_thing_plus.menu.PSRAM.opi.build.defines=-DBOARD_HAS_PSRAM +sparkfun_esp32s3_thing_plus.menu.PSRAM.opi.build.psram_type=opi + +sparkfun_esp32s3_thing_plus.menu.FlashMode.qio=QIO 80MHz +sparkfun_esp32s3_thing_plus.menu.FlashMode.qio.build.flash_mode=dio +sparkfun_esp32s3_thing_plus.menu.FlashMode.qio.build.boot=qio +sparkfun_esp32s3_thing_plus.menu.FlashMode.qio.build.boot_freq=80m +sparkfun_esp32s3_thing_plus.menu.FlashMode.qio.build.flash_freq=80m +sparkfun_esp32s3_thing_plus.menu.FlashMode.qio120=QIO 120MHz +sparkfun_esp32s3_thing_plus.menu.FlashMode.qio120.build.flash_mode=dio +sparkfun_esp32s3_thing_plus.menu.FlashMode.qio120.build.boot=qio +sparkfun_esp32s3_thing_plus.menu.FlashMode.qio120.build.boot_freq=120m +sparkfun_esp32s3_thing_plus.menu.FlashMode.qio120.build.flash_freq=80m +sparkfun_esp32s3_thing_plus.menu.FlashMode.dio=DIO 80MHz +sparkfun_esp32s3_thing_plus.menu.FlashMode.dio.build.flash_mode=dio +sparkfun_esp32s3_thing_plus.menu.FlashMode.dio.build.boot=dio +sparkfun_esp32s3_thing_plus.menu.FlashMode.dio.build.boot_freq=80m +sparkfun_esp32s3_thing_plus.menu.FlashMode.dio.build.flash_freq=80m + +sparkfun_esp32s3_thing_plus.menu.LoopCore.1=Core 1 +sparkfun_esp32s3_thing_plus.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +sparkfun_esp32s3_thing_plus.menu.LoopCore.0=Core 0 +sparkfun_esp32s3_thing_plus.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +sparkfun_esp32s3_thing_plus.menu.EventsCore.1=Core 1 +sparkfun_esp32s3_thing_plus.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +sparkfun_esp32s3_thing_plus.menu.EventsCore.0=Core 0 +sparkfun_esp32s3_thing_plus.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +sparkfun_esp32s3_thing_plus.menu.USBMode.default=Hardware CDC and JTAG +sparkfun_esp32s3_thing_plus.menu.USBMode.default.build.usb_mode=1 +sparkfun_esp32s3_thing_plus.menu.USBMode.hwcdc=USB-OTG (TinyUSB) +sparkfun_esp32s3_thing_plus.menu.USBMode.hwcdc.build.usb_mode=0 + +# sparkfun says to put that to Enabled but it fails +sparkfun_esp32s3_thing_plus.menu.CDCOnBoot.default=Disabled +sparkfun_esp32s3_thing_plus.menu.CDCOnBoot.default.build.cdc_on_boot=0 +sparkfun_esp32s3_thing_plus.menu.CDCOnBoot.cdc=Enabled +sparkfun_esp32s3_thing_plus.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +sparkfun_esp32s3_thing_plus.menu.MSCOnBoot.default=Disabled +sparkfun_esp32s3_thing_plus.menu.MSCOnBoot.default.build.msc_on_boot=0 +sparkfun_esp32s3_thing_plus.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +sparkfun_esp32s3_thing_plus.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +sparkfun_esp32s3_thing_plus.menu.DFUOnBoot.default=Disabled +sparkfun_esp32s3_thing_plus.menu.DFUOnBoot.default.build.dfu_on_boot=0 +sparkfun_esp32s3_thing_plus.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +sparkfun_esp32s3_thing_plus.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +sparkfun_esp32s3_thing_plus.menu.UploadMode.default=UART0 / Hardware CDC +sparkfun_esp32s3_thing_plus.menu.UploadMode.default.upload.use_1200bps_touch=false +sparkfun_esp32s3_thing_plus.menu.UploadMode.default.upload.wait_for_upload_port=false +sparkfun_esp32s3_thing_plus.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +sparkfun_esp32s3_thing_plus.menu.UploadMode.cdc.upload.use_1200bps_touch=true +sparkfun_esp32s3_thing_plus.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.default.build.partitions=default +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.minimal.build.partitions=minimal +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.no_fs.build.partitions=no_fs +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.no_ota.build.partitions=no_ota +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.huge_app.build.partitions=huge_app +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.rainmaker=RainMaker 4MB +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.custom=Custom +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.custom.build.partitions= +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +sparkfun_esp32s3_thing_plus.menu.CPUFreq.240=240MHz (WiFi) +sparkfun_esp32s3_thing_plus.menu.CPUFreq.240.build.f_cpu=240000000L +sparkfun_esp32s3_thing_plus.menu.CPUFreq.160=160MHz (WiFi) +sparkfun_esp32s3_thing_plus.menu.CPUFreq.160.build.f_cpu=160000000L +sparkfun_esp32s3_thing_plus.menu.CPUFreq.80=80MHz (WiFi) +sparkfun_esp32s3_thing_plus.menu.CPUFreq.80.build.f_cpu=80000000L +sparkfun_esp32s3_thing_plus.menu.CPUFreq.40=40MHz +sparkfun_esp32s3_thing_plus.menu.CPUFreq.40.build.f_cpu=40000000L +sparkfun_esp32s3_thing_plus.menu.CPUFreq.20=20MHz +sparkfun_esp32s3_thing_plus.menu.CPUFreq.20.build.f_cpu=20000000L +sparkfun_esp32s3_thing_plus.menu.CPUFreq.10=10MHz +sparkfun_esp32s3_thing_plus.menu.CPUFreq.10.build.f_cpu=10000000L + +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.921600=921600 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.921600.upload.speed=921600 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.115200=115200 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.115200.upload.speed=115200 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.256000.windows=256000 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.256000.upload.speed=256000 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.230400.windows.upload.speed=256000 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.230400=230400 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.230400.upload.speed=230400 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.460800.linux=460800 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.460800.macosx=460800 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.460800.upload.speed=460800 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.512000.windows=512000 +sparkfun_esp32s3_thing_plus.menu.UploadSpeed.512000.upload.speed=512000 + +sparkfun_esp32s3_thing_plus.menu.DebugLevel.none=None +sparkfun_esp32s3_thing_plus.menu.DebugLevel.none.build.code_debug=0 +sparkfun_esp32s3_thing_plus.menu.DebugLevel.error=Error +sparkfun_esp32s3_thing_plus.menu.DebugLevel.error.build.code_debug=1 +sparkfun_esp32s3_thing_plus.menu.DebugLevel.warn=Warn +sparkfun_esp32s3_thing_plus.menu.DebugLevel.warn.build.code_debug=2 +sparkfun_esp32s3_thing_plus.menu.DebugLevel.info=Info +sparkfun_esp32s3_thing_plus.menu.DebugLevel.info.build.code_debug=3 +sparkfun_esp32s3_thing_plus.menu.DebugLevel.debug=Debug +sparkfun_esp32s3_thing_plus.menu.DebugLevel.debug.build.code_debug=4 +sparkfun_esp32s3_thing_plus.menu.DebugLevel.verbose=Verbose +sparkfun_esp32s3_thing_plus.menu.DebugLevel.verbose.build.code_debug=5 + +sparkfun_esp32s3_thing_plus.menu.EraseFlash.none=Disabled +sparkfun_esp32s3_thing_plus.menu.EraseFlash.none.upload.erase_cmd= +sparkfun_esp32s3_thing_plus.menu.EraseFlash.all=Enabled +sparkfun_esp32s3_thing_plus.menu.EraseFlash.all.upload.erase_cmd=-e + +sparkfun_esp32s3_thing_plus.menu.ZigbeeMode.default=Disabled +sparkfun_esp32s3_thing_plus.menu.ZigbeeMode.default.build.zigbee_mode= +sparkfun_esp32s3_thing_plus.menu.ZigbeeMode.default.build.zigbee_libs= +sparkfun_esp32s3_thing_plus.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +sparkfun_esp32s3_thing_plus.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +sparkfun_esp32s3_thing_plus.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + ############################################################## sparkfun_esp32c6_thing_plus.name=SparkFun ESP32-C6 Thing Plus @@ -6134,9 +8060,15 @@ sparkfun_esp32c6_thing_plus.menu.PartitionScheme.fatflash.upload.maximum_size=20 sparkfun_esp32c6_thing_plus.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) sparkfun_esp32c6_thing_plus.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB sparkfun_esp32c6_thing_plus.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -sparkfun_esp32c6_thing_plus.menu.PartitionScheme.rainmaker=RainMaker +sparkfun_esp32c6_thing_plus.menu.PartitionScheme.rainmaker=RainMaker 4MB sparkfun_esp32c6_thing_plus.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -sparkfun_esp32c6_thing_plus.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +sparkfun_esp32c6_thing_plus.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +sparkfun_esp32c6_thing_plus.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +sparkfun_esp32c6_thing_plus.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +sparkfun_esp32c6_thing_plus.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +sparkfun_esp32c6_thing_plus.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +sparkfun_esp32c6_thing_plus.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +sparkfun_esp32c6_thing_plus.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 sparkfun_esp32c6_thing_plus.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs sparkfun_esp32c6_thing_plus.menu.PartitionScheme.zigbee.build.partitions=zigbee sparkfun_esp32c6_thing_plus.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 @@ -6174,10 +8106,8 @@ sparkfun_esp32c6_thing_plus.menu.FlashSize.4M=4MB (32Mb) sparkfun_esp32c6_thing_plus.menu.FlashSize.4M.build.flash_size=4MB sparkfun_esp32c6_thing_plus.menu.FlashSize.8M=8MB (64Mb) sparkfun_esp32c6_thing_plus.menu.FlashSize.8M.build.flash_size=8MB -sparkfun_esp32c6_thing_plus.menu.FlashSize.8M.build.partitions=default_8MB sparkfun_esp32c6_thing_plus.menu.FlashSize.2M=2MB (16Mb) sparkfun_esp32c6_thing_plus.menu.FlashSize.2M.build.flash_size=2MB -sparkfun_esp32c6_thing_plus.menu.FlashSize.2M.build.partitions=minimal sparkfun_esp32c6_thing_plus.menu.FlashSize.16M=16MB (128Mb) sparkfun_esp32c6_thing_plus.menu.FlashSize.16M.build.flash_size=16MB @@ -6219,13 +8149,10 @@ sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.default.build.zigbee_mode= sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.default.build.zigbee_libs= sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.ed=Zigbee ED (end device) sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED -sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port -sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) -sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP -sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port +sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native ############################################################## @@ -6335,10 +8262,8 @@ esp32micromod.menu.FlashSize.4M=4MB (32Mb) esp32micromod.menu.FlashSize.4M.build.flash_size=4MB esp32micromod.menu.FlashSize.8M=8MB (64Mb) esp32micromod.menu.FlashSize.8M.build.flash_size=8MB -esp32micromod.menu.FlashSize.8M.build.partitions=default_8MB esp32micromod.menu.FlashSize.2M=2MB (16Mb) esp32micromod.menu.FlashSize.2M.build.flash_size=2MB -esp32micromod.menu.FlashSize.2M.build.partitions=minimal esp32micromod.menu.FlashSize.16M=16MB (128Mb) esp32micromod.menu.FlashSize.16M.build.flash_size=16MB @@ -6545,9 +8470,15 @@ sparkfun_esp32_iot_redboard.menu.PartitionScheme.fatflash.upload.maximum_size=20 sparkfun_esp32_iot_redboard.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) sparkfun_esp32_iot_redboard.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB sparkfun_esp32_iot_redboard.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -sparkfun_esp32_iot_redboard.menu.PartitionScheme.rainmaker=RainMaker +sparkfun_esp32_iot_redboard.menu.PartitionScheme.rainmaker=RainMaker 4MB sparkfun_esp32_iot_redboard.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -sparkfun_esp32_iot_redboard.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +sparkfun_esp32_iot_redboard.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +sparkfun_esp32_iot_redboard.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +sparkfun_esp32_iot_redboard.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +sparkfun_esp32_iot_redboard.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +sparkfun_esp32_iot_redboard.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +sparkfun_esp32_iot_redboard.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +sparkfun_esp32_iot_redboard.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 sparkfun_esp32_iot_redboard.menu.CPUFreq.240=240MHz (WiFi/BT) sparkfun_esp32_iot_redboard.menu.CPUFreq.240.build.f_cpu=240000000L @@ -6582,10 +8513,8 @@ sparkfun_esp32_iot_redboard.menu.FlashSize.4M=4MB (32Mb) sparkfun_esp32_iot_redboard.menu.FlashSize.4M.build.flash_size=4MB sparkfun_esp32_iot_redboard.menu.FlashSize.8M=8MB (64Mb) sparkfun_esp32_iot_redboard.menu.FlashSize.8M.build.flash_size=8MB -sparkfun_esp32_iot_redboard.menu.FlashSize.8M.build.partitions=default_8MB sparkfun_esp32_iot_redboard.menu.FlashSize.2M=2MB (16Mb) sparkfun_esp32_iot_redboard.menu.FlashSize.2M.build.flash_size=2MB -sparkfun_esp32_iot_redboard.menu.FlashSize.2M.build.partitions=minimal sparkfun_esp32_iot_redboard.menu.FlashSize.16M=16MB (128Mb) sparkfun_esp32_iot_redboard.menu.FlashSize.16M.build.flash_size=16MB @@ -6721,9 +8650,15 @@ sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.fatflash.upload.maximum_size= sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.rainmaker=RainMaker +sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.rainmaker=RainMaker 4MB sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.zigbee.build.partitions=zigbee sparkfun_esp32c6_qwiic_pocket.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 @@ -6761,10 +8696,8 @@ sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.4M=4MB (32Mb) sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.4M.build.flash_size=4MB sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.8M=8MB (64Mb) sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.8M.build.flash_size=8MB -sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.8M.build.partitions=default_8MB sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.2M=2MB (16Mb) sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.2M.build.flash_size=2MB -sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.2M.build.partitions=minimal sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.16M=16MB (128Mb) sparkfun_esp32c6_qwiic_pocket.menu.FlashSize.16M.build.flash_size=16MB @@ -6806,13 +8739,10 @@ sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.default.build.zigbee_mode= sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.default.build.zigbee_libs= sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.ed=Zigbee ED (end device) sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED -sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port -sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) -sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP -sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port +sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native ############################################################## @@ -7017,13 +8947,10 @@ nina_w10.menu.UploadSpeed.512000.upload.speed=512000 nina_w10.menu.FlashSize.2M=2MB (16Mb, NINA-W101/W102) nina_w10.menu.FlashSize.2M.build.flash_size=2MB -nina_w10.menu.FlashSize.2M.build.partitions=minimal nina_w10.menu.FlashSize.4M=4MB (32Mb, NINA-W106-00B) nina_w10.menu.FlashSize.4M.build.flash_size=4MB -nina_w10.menu.FlashSize.4M.build.partitions=default nina_w10.menu.FlashSize.8M=8MB (64Mb, NINA-W106-10B) nina_w10.menu.FlashSize.8M.build.flash_size=8MB -nina_w10.menu.FlashSize.8M.build.partitions=default_8MB nina_w10.menu.FlashFreq.80=80MHz nina_w10.menu.FlashFreq.80.build.flash_freq=80m @@ -7057,9 +8984,15 @@ nina_w10.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 nina_w10.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) nina_w10.menu.PartitionScheme.huge_app.build.partitions=huge_app nina_w10.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 -nina_w10.menu.PartitionScheme.rainmaker=RainMaker +nina_w10.menu.PartitionScheme.rainmaker=RainMaker 4MB nina_w10.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -nina_w10.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +nina_w10.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +nina_w10.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +nina_w10.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +nina_w10.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +nina_w10.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +nina_w10.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +nina_w10.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 nina_w10.menu.CPUFreq.240=240MHz (WiFi/BT) nina_w10.menu.CPUFreq.240.build.f_cpu=240000000L @@ -7187,7 +9120,6 @@ nora_w10.menu.FlashSize.4M=4MB (32Mb) nora_w10.menu.FlashSize.4M.build.flash_size=4MB nora_w10.menu.FlashSize.8M=8MB (64Mb) nora_w10.menu.FlashSize.8M.build.flash_size=8MB -nora_w10.menu.FlashSize.8M.build.partitions=default_8MB #nora_w10.menu.FlashSize.16M=16MB (128Mb) #nora_w10.menu.FlashSize.16M.build.flash_size=16MB #nora_w10.menu.FlashSize.32M=32MB (256Mb) @@ -7263,9 +9195,15 @@ nora_w10.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 #nora_w10.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9MB FATFS) #nora_w10.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB #nora_w10.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -nora_w10.menu.PartitionScheme.rainmaker=RainMaker +nora_w10.menu.PartitionScheme.rainmaker=RainMaker 4MB nora_w10.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -nora_w10.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +nora_w10.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +nora_w10.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +nora_w10.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +nora_w10.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +nora_w10.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +nora_w10.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +nora_w10.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 nora_w10.menu.CPUFreq.240=240MHz (WiFi) nora_w10.menu.CPUFreq.240.build.f_cpu=240000000L @@ -8229,9 +10167,15 @@ lolin_s3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 lolin_s3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) lolin_s3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB lolin_s3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -lolin_s3.menu.PartitionScheme.rainmaker=RainMaker +lolin_s3.menu.PartitionScheme.rainmaker=RainMaker 4MB lolin_s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -lolin_s3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +lolin_s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +lolin_s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +lolin_s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +lolin_s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +lolin_s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +lolin_s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +lolin_s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 lolin_s3.menu.CPUFreq.240=240MHz (WiFi) lolin_s3.menu.CPUFreq.240.build.f_cpu=240000000L @@ -8397,9 +10341,12 @@ lolin_s3_mini.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 lolin_s3_mini.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) lolin_s3_mini.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs lolin_s3_mini.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -lolin_s3_mini.menu.PartitionScheme.rainmaker=RainMaker +lolin_s3_mini.menu.PartitionScheme.rainmaker=RainMaker 4MB lolin_s3_mini.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -lolin_s3_mini.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +lolin_s3_mini.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +lolin_s3_mini.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +lolin_s3_mini.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +lolin_s3_mini.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 lolin_s3_mini.menu.CPUFreq.240=240MHz (WiFi) lolin_s3_mini.menu.CPUFreq.240.build.f_cpu=240000000L @@ -8449,6 +10396,177 @@ lolin_s3_mini.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +lolin_s3_mini_pro.name=LOLIN S3 Mini Pro +lolin_s3_mini_pro.vid.0=0x303a +lolin_s3_mini_pro.pid.0=0x8216 + +lolin_s3_mini_pro.bootloader.tool=esptool_py +lolin_s3_mini_pro.bootloader.tool.default=esptool_py + +lolin_s3_mini_pro.upload.tool=esptool_py +lolin_s3_mini_pro.upload.tool.default=esptool_py +lolin_s3_mini_pro.upload.tool.network=esp_ota + +lolin_s3_mini_pro.upload.maximum_size=1310720 +lolin_s3_mini_pro.upload.maximum_data_size=327680 +lolin_s3_mini_pro.upload.flags= +lolin_s3_mini_pro.upload.extra_flags= +lolin_s3_mini_pro.upload.use_1200bps_touch=false +lolin_s3_mini_pro.upload.wait_for_upload_port=false + +lolin_s3_mini_pro.serial.disableDTR=false +lolin_s3_mini_pro.serial.disableRTS=false + +lolin_s3_mini_pro.build.tarch=xtensa +lolin_s3_mini_pro.build.bootloader_addr=0x0 +lolin_s3_mini_pro.build.target=esp32s3 +lolin_s3_mini_pro.build.mcu=esp32s3 +lolin_s3_mini_pro.build.core=esp32 +lolin_s3_mini_pro.build.variant=lolin_s3_mini_pro +lolin_s3_mini_pro.build.board=LOLIN_S3_MINI_PRO + +lolin_s3_mini_pro.build.usb_mode=1 +lolin_s3_mini_pro.build.cdc_on_boot=0 +lolin_s3_mini_pro.build.msc_on_boot=0 +lolin_s3_mini_pro.build.dfu_on_boot=0 +lolin_s3_mini_pro.build.f_cpu=240000000L +lolin_s3_mini_pro.build.flash_size=4MB +lolin_s3_mini_pro.build.flash_freq=80m +lolin_s3_mini_pro.build.flash_mode=dio +lolin_s3_mini_pro.build.boot=qio +lolin_s3_mini_pro.build.boot_freq=80m +lolin_s3_mini_pro.build.partitions=default +lolin_s3_mini_pro.build.defines=-DBOARD_HAS_PSRAM +lolin_s3_mini_pro.build.loop_core= +lolin_s3_mini_pro.build.event_core= +lolin_s3_mini_pro.build.psram_type=qspi +lolin_s3_mini_pro.build.memory_type={build.boot}_{build.psram_type} + +lolin_s3_mini_pro.menu.FlashMode.qio=QIO 80MHz +lolin_s3_mini_pro.menu.FlashMode.qio.build.flash_mode=dio +lolin_s3_mini_pro.menu.FlashMode.qio.build.boot=qio +lolin_s3_mini_pro.menu.FlashMode.qio.build.boot_freq=80m +lolin_s3_mini_pro.menu.FlashMode.qio.build.flash_freq=80m +lolin_s3_mini_pro.menu.FlashMode.qio120=QIO 120MHz +lolin_s3_mini_pro.menu.FlashMode.qio120.build.flash_mode=dio +lolin_s3_mini_pro.menu.FlashMode.qio120.build.boot=qio +lolin_s3_mini_pro.menu.FlashMode.qio120.build.boot_freq=120m +lolin_s3_mini_pro.menu.FlashMode.qio120.build.flash_freq=80m + +lolin_s3_mini_pro.menu.LoopCore.1=Core 1 +lolin_s3_mini_pro.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +lolin_s3_mini_pro.menu.LoopCore.0=Core 0 +lolin_s3_mini_pro.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +lolin_s3_mini_pro.menu.EventsCore.1=Core 1 +lolin_s3_mini_pro.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +lolin_s3_mini_pro.menu.EventsCore.0=Core 0 +lolin_s3_mini_pro.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +lolin_s3_mini_pro.menu.USBMode.hwcdc=Hardware CDC and JTAG +lolin_s3_mini_pro.menu.USBMode.hwcdc.build.usb_mode=1 +lolin_s3_mini_pro.menu.USBMode.default=USB-OTG (TinyUSB) +lolin_s3_mini_pro.menu.USBMode.default.build.usb_mode=0 + +lolin_s3_mini_pro.menu.CDCOnBoot.default=Disabled +lolin_s3_mini_pro.menu.CDCOnBoot.default.build.cdc_on_boot=0 +lolin_s3_mini_pro.menu.CDCOnBoot.cdc=Enabled +lolin_s3_mini_pro.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +lolin_s3_mini_pro.menu.MSCOnBoot.default=Disabled +lolin_s3_mini_pro.menu.MSCOnBoot.default.build.msc_on_boot=0 +lolin_s3_mini_pro.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +lolin_s3_mini_pro.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +lolin_s3_mini_pro.menu.DFUOnBoot.default=Disabled +lolin_s3_mini_pro.menu.DFUOnBoot.default.build.dfu_on_boot=0 +lolin_s3_mini_pro.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +lolin_s3_mini_pro.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +lolin_s3_mini_pro.menu.UploadMode.default=UART0 / Hardware CDC +lolin_s3_mini_pro.menu.UploadMode.default.upload.use_1200bps_touch=false +lolin_s3_mini_pro.menu.UploadMode.default.upload.wait_for_upload_port=false +lolin_s3_mini_pro.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +lolin_s3_mini_pro.menu.UploadMode.cdc.upload.use_1200bps_touch=true +lolin_s3_mini_pro.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +lolin_s3_mini_pro.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +lolin_s3_mini_pro.menu.PartitionScheme.default.build.partitions=default +lolin_s3_mini_pro.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +lolin_s3_mini_pro.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +lolin_s3_mini_pro.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +lolin_s3_mini_pro.menu.PartitionScheme.no_ota.build.partitions=no_ota +lolin_s3_mini_pro.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +lolin_s3_mini_pro.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +lolin_s3_mini_pro.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +lolin_s3_mini_pro.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +lolin_s3_mini_pro.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +lolin_s3_mini_pro.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +lolin_s3_mini_pro.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +lolin_s3_mini_pro.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +lolin_s3_mini_pro.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +lolin_s3_mini_pro.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +lolin_s3_mini_pro.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +lolin_s3_mini_pro.menu.PartitionScheme.huge_app.build.partitions=huge_app +lolin_s3_mini_pro.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +lolin_s3_mini_pro.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +lolin_s3_mini_pro.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +lolin_s3_mini_pro.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +lolin_s3_mini_pro.menu.PartitionScheme.rainmaker=RainMaker 4MB +lolin_s3_mini_pro.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +lolin_s3_mini_pro.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +lolin_s3_mini_pro.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +lolin_s3_mini_pro.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +lolin_s3_mini_pro.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 + +lolin_s3_mini_pro.menu.CPUFreq.240=240MHz (WiFi) +lolin_s3_mini_pro.menu.CPUFreq.240.build.f_cpu=240000000L +lolin_s3_mini_pro.menu.CPUFreq.160=160MHz (WiFi) +lolin_s3_mini_pro.menu.CPUFreq.160.build.f_cpu=160000000L +lolin_s3_mini_pro.menu.CPUFreq.80=80MHz (WiFi) +lolin_s3_mini_pro.menu.CPUFreq.80.build.f_cpu=80000000L +lolin_s3_mini_pro.menu.CPUFreq.40=40MHz +lolin_s3_mini_pro.menu.CPUFreq.40.build.f_cpu=40000000L +lolin_s3_mini_pro.menu.CPUFreq.20=20MHz +lolin_s3_mini_pro.menu.CPUFreq.20.build.f_cpu=20000000L +lolin_s3_mini_pro.menu.CPUFreq.10=10MHz +lolin_s3_mini_pro.menu.CPUFreq.10.build.f_cpu=10000000L + +lolin_s3_mini_pro.menu.UploadSpeed.921600=921600 +lolin_s3_mini_pro.menu.UploadSpeed.921600.upload.speed=921600 +lolin_s3_mini_pro.menu.UploadSpeed.115200=115200 +lolin_s3_mini_pro.menu.UploadSpeed.115200.upload.speed=115200 +lolin_s3_mini_pro.menu.UploadSpeed.256000.windows=256000 +lolin_s3_mini_pro.menu.UploadSpeed.256000.upload.speed=256000 +lolin_s3_mini_pro.menu.UploadSpeed.230400.windows.upload.speed=256000 +lolin_s3_mini_pro.menu.UploadSpeed.230400=230400 +lolin_s3_mini_pro.menu.UploadSpeed.230400.upload.speed=230400 +lolin_s3_mini_pro.menu.UploadSpeed.460800.linux=460800 +lolin_s3_mini_pro.menu.UploadSpeed.460800.macosx=460800 +lolin_s3_mini_pro.menu.UploadSpeed.460800.upload.speed=460800 +lolin_s3_mini_pro.menu.UploadSpeed.512000.windows=512000 +lolin_s3_mini_pro.menu.UploadSpeed.512000.upload.speed=512000 + +lolin_s3_mini_pro.menu.DebugLevel.none=None +lolin_s3_mini_pro.menu.DebugLevel.none.build.code_debug=0 +lolin_s3_mini_pro.menu.DebugLevel.error=Error +lolin_s3_mini_pro.menu.DebugLevel.error.build.code_debug=1 +lolin_s3_mini_pro.menu.DebugLevel.warn=Warn +lolin_s3_mini_pro.menu.DebugLevel.warn.build.code_debug=2 +lolin_s3_mini_pro.menu.DebugLevel.info=Info +lolin_s3_mini_pro.menu.DebugLevel.info.build.code_debug=3 +lolin_s3_mini_pro.menu.DebugLevel.debug=Debug +lolin_s3_mini_pro.menu.DebugLevel.debug.build.code_debug=4 +lolin_s3_mini_pro.menu.DebugLevel.verbose=Verbose +lolin_s3_mini_pro.menu.DebugLevel.verbose.build.code_debug=5 + +lolin_s3_mini_pro.menu.EraseFlash.none=Disabled +lolin_s3_mini_pro.menu.EraseFlash.none.upload.erase_cmd= +lolin_s3_mini_pro.menu.EraseFlash.all=Enabled +lolin_s3_mini_pro.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + lolin_s3_pro.name=LOLIN S3 Pro lolin_s3_pro.vid.0=0x303a lolin_s3_pro.pid.0=0x8161 @@ -8549,9 +10667,15 @@ lolin_s3_pro.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 lolin_s3_pro.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) lolin_s3_pro.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB lolin_s3_pro.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -lolin_s3_pro.menu.PartitionScheme.rainmaker=RainMaker +lolin_s3_pro.menu.PartitionScheme.rainmaker=RainMaker 4MB lolin_s3_pro.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -lolin_s3_pro.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +lolin_s3_pro.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +lolin_s3_pro.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +lolin_s3_pro.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +lolin_s3_pro.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +lolin_s3_pro.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +lolin_s3_pro.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +lolin_s3_pro.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 lolin_s3_pro.menu.CPUFreq.240=240MHz (WiFi) lolin_s3_pro.menu.CPUFreq.240.build.f_cpu=240000000L @@ -8699,6 +10823,202 @@ lolin32.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +viralink32g01.name=ViraLink Gate32-0.1 + +viralink32g01.bootloader.tool=esptool_py +viralink32g01.bootloader.tool.default=esptool_py + +viralink32g01.upload.tool=esptool_py +viralink32g01.upload.tool.default=esptool_py +viralink32g01.upload.tool.network=esp_ota + +viralink32g01.upload.maximum_size=1310720 +viralink32g01.upload.maximum_data_size=327680 +viralink32g01.upload.flags= +viralink32g01.upload.extra_flags= + +viralink32g01.serial.disableDTR=true +viralink32g01.serial.disableRTS=true + +viralink32g01.build.tarch=xtensa +viralink32g01.build.bootloader_addr=0x1000 +viralink32g01.build.target=esp32 +viralink32g01.build.mcu=esp32 +viralink32g01.build.core=esp32 +viralink32g01.build.variant=ViraLink-G0.1 +viralink32g01.build.board=VIRALINK_GATE32_01 + +viralink32g01.build.f_cpu=240000000L +viralink32g01.build.flash_mode=dio +viralink32g01.build.flash_size=4MB +viralink32g01.build.boot=dio +viralink32g01.build.partitions=default +viralink32g01.build.defines= + +viralink32g01.menu.FlashFreq.80=80MHz +viralink32g01.menu.FlashFreq.80.build.flash_freq=80m +viralink32g01.menu.FlashFreq.40=40MHz +viralink32g01.menu.FlashFreq.40.build.flash_freq=40m + +viralink32g01.menu.PartitionScheme.default=Default +viralink32g01.menu.PartitionScheme.default.build.partitions=default +viralink32g01.menu.PartitionScheme.no_ota=No OTA (Large APP) +viralink32g01.menu.PartitionScheme.no_ota.build.partitions=no_ota +viralink32g01.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +viralink32g01.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA) +viralink32g01.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +viralink32g01.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 + +viralink32g01.menu.CPUFreq.240=240MHz (WiFi/BT) +viralink32g01.menu.CPUFreq.240.build.f_cpu=240000000L +viralink32g01.menu.CPUFreq.160=160MHz (WiFi/BT) +viralink32g01.menu.CPUFreq.160.build.f_cpu=160000000L +viralink32g01.menu.CPUFreq.80=80MHz (WiFi/BT) +viralink32g01.menu.CPUFreq.80.build.f_cpu=80000000L +viralink32g01.menu.CPUFreq.40=40MHz (40MHz XTAL) +viralink32g01.menu.CPUFreq.40.build.f_cpu=40000000L +viralink32g01.menu.CPUFreq.26=26MHz (26MHz XTAL) +viralink32g01.menu.CPUFreq.26.build.f_cpu=26000000L +viralink32g01.menu.CPUFreq.20=20MHz (40MHz XTAL) +viralink32g01.menu.CPUFreq.20.build.f_cpu=20000000L +viralink32g01.menu.CPUFreq.13=13MHz (26MHz XTAL) +viralink32g01.menu.CPUFreq.13.build.f_cpu=13000000L +viralink32g01.menu.CPUFreq.10=10MHz (40MHz XTAL) +viralink32g01.menu.CPUFreq.10.build.f_cpu=10000000L + +viralink32g01.menu.UploadSpeed.921600=921600 +viralink32g01.menu.UploadSpeed.921600.upload.speed=921600 +viralink32g01.menu.UploadSpeed.115200=115200 +viralink32g01.menu.UploadSpeed.115200.upload.speed=115200 +viralink32g01.menu.UploadSpeed.256000.windows=256000 +viralink32g01.menu.UploadSpeed.256000.upload.speed=256000 +viralink32g01.menu.UploadSpeed.230400.windows.upload.speed=256000 +viralink32g01.menu.UploadSpeed.230400=230400 +viralink32g01.menu.UploadSpeed.230400.upload.speed=230400 +viralink32g01.menu.UploadSpeed.460800.linux=460800 +viralink32g01.menu.UploadSpeed.460800.macosx=460800 +viralink32g01.menu.UploadSpeed.460800.upload.speed=460800 +viralink32g01.menu.UploadSpeed.512000.windows=512000 +viralink32g01.menu.UploadSpeed.512000.upload.speed=512000 + +viralink32g01.menu.DebugLevel.none=None +viralink32g01.menu.DebugLevel.none.build.code_debug=0 +viralink32g01.menu.DebugLevel.error=Error +viralink32g01.menu.DebugLevel.error.build.code_debug=1 +viralink32g01.menu.DebugLevel.warn=Warn +viralink32g01.menu.DebugLevel.warn.build.code_debug=2 +viralink32g01.menu.DebugLevel.info=Info +viralink32g01.menu.DebugLevel.info.build.code_debug=3 +viralink32g01.menu.DebugLevel.debug=Debug +viralink32g01.menu.DebugLevel.debug.build.code_debug=4 +viralink32g01.menu.DebugLevel.verbose=Verbose +viralink32g01.menu.DebugLevel.verbose.build.code_debug=5 + +viralink32g01.menu.EraseFlash.none=Disabled +viralink32g01.menu.EraseFlash.none.upload.erase_cmd= +viralink32g01.menu.EraseFlash.all=Enabled +viralink32g01.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +viralink32g11.name=ViraLink Gate32-1.1 + +viralink32g11.bootloader.tool=esptool_py +viralink32g11.bootloader.tool.default=esptool_py + +viralink32g11.upload.tool=esptool_py +viralink32g11.upload.tool.default=esptool_py +viralink32g11.upload.tool.network=esp_ota + +viralink32g11.upload.maximum_size=1310720 +viralink32g11.upload.maximum_data_size=327680 +viralink32g11.upload.flags= +viralink32g11.upload.extra_flags= + +viralink32g11.serial.disableDTR=true +viralink32g11.serial.disableRTS=true + +viralink32g11.build.tarch=xtensa +viralink32g11.build.bootloader_addr=0x1000 +viralink32g11.build.target=esp32 +viralink32g11.build.mcu=esp32 +viralink32g11.build.core=esp32 +viralink32g11.build.variant=ViraLink-G1.1 +viralink32g11.build.board=VIRALINK_GATE32_11 + +viralink32g11.build.f_cpu=240000000L +viralink32g11.build.flash_mode=dio +viralink32g11.build.flash_size=4MB +viralink32g11.build.boot=dio +viralink32g11.build.partitions=default +viralink32g11.build.defines= + +viralink32g11.menu.FlashFreq.80=80MHz +viralink32g11.menu.FlashFreq.80.build.flash_freq=80m +viralink32g11.menu.FlashFreq.40=40MHz +viralink32g11.menu.FlashFreq.40.build.flash_freq=40m + +viralink32g11.menu.PartitionScheme.default=Default +viralink32g11.menu.PartitionScheme.default.build.partitions=default +viralink32g11.menu.PartitionScheme.no_ota=No OTA (Large APP) +viralink32g11.menu.PartitionScheme.no_ota.build.partitions=no_ota +viralink32g11.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +viralink32g11.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA) +viralink32g11.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +viralink32g11.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 + +viralink32g11.menu.CPUFreq.240=240MHz (WiFi/BT) +viralink32g11.menu.CPUFreq.240.build.f_cpu=240000000L +viralink32g11.menu.CPUFreq.160=160MHz (WiFi/BT) +viralink32g11.menu.CPUFreq.160.build.f_cpu=160000000L +viralink32g11.menu.CPUFreq.80=80MHz (WiFi/BT) +viralink32g11.menu.CPUFreq.80.build.f_cpu=80000000L +viralink32g11.menu.CPUFreq.40=40MHz (40MHz XTAL) +viralink32g11.menu.CPUFreq.40.build.f_cpu=40000000L +viralink32g11.menu.CPUFreq.26=26MHz (26MHz XTAL) +viralink32g11.menu.CPUFreq.26.build.f_cpu=26000000L +viralink32g11.menu.CPUFreq.20=20MHz (40MHz XTAL) +viralink32g11.menu.CPUFreq.20.build.f_cpu=20000000L +viralink32g11.menu.CPUFreq.13=13MHz (26MHz XTAL) +viralink32g11.menu.CPUFreq.13.build.f_cpu=13000000L +viralink32g11.menu.CPUFreq.10=10MHz (40MHz XTAL) +viralink32g11.menu.CPUFreq.10.build.f_cpu=10000000L + +viralink32g11.menu.UploadSpeed.921600=921600 +viralink32g11.menu.UploadSpeed.921600.upload.speed=921600 +viralink32g11.menu.UploadSpeed.115200=115200 +viralink32g11.menu.UploadSpeed.115200.upload.speed=115200 +viralink32g11.menu.UploadSpeed.256000.windows=256000 +viralink32g11.menu.UploadSpeed.256000.upload.speed=256000 +viralink32g11.menu.UploadSpeed.230400.windows.upload.speed=256000 +viralink32g11.menu.UploadSpeed.230400=230400 +viralink32g11.menu.UploadSpeed.230400.upload.speed=230400 +viralink32g11.menu.UploadSpeed.460800.linux=460800 +viralink32g11.menu.UploadSpeed.460800.macosx=460800 +viralink32g11.menu.UploadSpeed.460800.upload.speed=460800 +viralink32g11.menu.UploadSpeed.512000.windows=512000 +viralink32g11.menu.UploadSpeed.512000.upload.speed=512000 + +viralink32g11.menu.DebugLevel.none=None +viralink32g11.menu.DebugLevel.none.build.code_debug=0 +viralink32g11.menu.DebugLevel.error=Error +viralink32g11.menu.DebugLevel.error.build.code_debug=1 +viralink32g11.menu.DebugLevel.warn=Warn +viralink32g11.menu.DebugLevel.warn.build.code_debug=2 +viralink32g11.menu.DebugLevel.info=Info +viralink32g11.menu.DebugLevel.info.build.code_debug=3 +viralink32g11.menu.DebugLevel.debug=Debug +viralink32g11.menu.DebugLevel.debug.build.code_debug=4 +viralink32g11.menu.DebugLevel.verbose=Verbose +viralink32g11.menu.DebugLevel.verbose.build.code_debug=5 + +viralink32g11.menu.EraseFlash.none=Disabled +viralink32g11.menu.EraseFlash.none.upload.erase_cmd= +viralink32g11.menu.EraseFlash.all=Enabled +viralink32g11.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + lolin32-lite.name=WEMOS LOLIN32 Lite lolin32-lite.bootloader.tool=esptool_py @@ -8935,9 +11255,12 @@ WeMosBat.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 WeMosBat.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) WeMosBat.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB WeMosBat.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -WeMosBat.menu.PartitionScheme.rainmaker=RainMaker +WeMosBat.menu.PartitionScheme.rainmaker=RainMaker 4MB WeMosBat.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -WeMosBat.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +WeMosBat.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +WeMosBat.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +WeMosBat.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +WeMosBat.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 WeMosBat.menu.FlashFreq.80=80MHz WeMosBat.menu.FlashFreq.80.build.flash_freq=80m @@ -9421,9 +11744,12 @@ dfrobot_beetle_esp32c3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 dfrobot_beetle_esp32c3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) dfrobot_beetle_esp32c3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB dfrobot_beetle_esp32c3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -dfrobot_beetle_esp32c3.menu.PartitionScheme.rainmaker=RainMaker +dfrobot_beetle_esp32c3.menu.PartitionScheme.rainmaker=RainMaker 4MB dfrobot_beetle_esp32c3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -dfrobot_beetle_esp32c3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +dfrobot_beetle_esp32c3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +dfrobot_beetle_esp32c3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +dfrobot_beetle_esp32c3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +dfrobot_beetle_esp32c3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 dfrobot_beetle_esp32c3.menu.CPUFreq.160=160MHz (WiFi) dfrobot_beetle_esp32c3.menu.CPUFreq.160.build.f_cpu=160000000L @@ -9564,9 +11890,12 @@ dfrobot_beetle_esp32c6.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 dfrobot_beetle_esp32c6.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) dfrobot_beetle_esp32c6.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs dfrobot_beetle_esp32c6.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -dfrobot_beetle_esp32c6.menu.PartitionScheme.rainmaker=RainMaker +dfrobot_beetle_esp32c6.menu.PartitionScheme.rainmaker=RainMaker 4MB dfrobot_beetle_esp32c6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -dfrobot_beetle_esp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +dfrobot_beetle_esp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +dfrobot_beetle_esp32c6.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +dfrobot_beetle_esp32c6.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +dfrobot_beetle_esp32c6.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 dfrobot_beetle_esp32c6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs dfrobot_beetle_esp32c6.menu.PartitionScheme.zigbee.build.partitions=zigbee dfrobot_beetle_esp32c6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 @@ -9641,13 +11970,10 @@ dfrobot_beetle_esp32c6.menu.ZigbeeMode.default.build.zigbee_mode= dfrobot_beetle_esp32c6.menu.ZigbeeMode.default.build.zigbee_libs= dfrobot_beetle_esp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) dfrobot_beetle_esp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED -dfrobot_beetle_esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -dfrobot_beetle_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +dfrobot_beetle_esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +dfrobot_beetle_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) dfrobot_beetle_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -dfrobot_beetle_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port -dfrobot_beetle_esp32c6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) -dfrobot_beetle_esp32c6.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP -dfrobot_beetle_esp32c6.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port +dfrobot_beetle_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native ############################################################## @@ -9721,9 +12047,15 @@ dfrobot_firebeetle2_esp32e.menu.PartitionScheme.fatflash.upload.maximum_size=209 dfrobot_firebeetle2_esp32e.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9MB FATFS) dfrobot_firebeetle2_esp32e.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB dfrobot_firebeetle2_esp32e.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -dfrobot_firebeetle2_esp32e.menu.PartitionScheme.rainmaker=RainMaker +dfrobot_firebeetle2_esp32e.menu.PartitionScheme.rainmaker=RainMaker 4MB dfrobot_firebeetle2_esp32e.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -dfrobot_firebeetle2_esp32e.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +dfrobot_firebeetle2_esp32e.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +dfrobot_firebeetle2_esp32e.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +dfrobot_firebeetle2_esp32e.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +dfrobot_firebeetle2_esp32e.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +dfrobot_firebeetle2_esp32e.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +dfrobot_firebeetle2_esp32e.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +dfrobot_firebeetle2_esp32e.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 dfrobot_firebeetle2_esp32e.menu.CPUFreq.240=240MHz (WiFi/BT) dfrobot_firebeetle2_esp32e.menu.CPUFreq.240.build.f_cpu=240000000L @@ -9758,10 +12090,8 @@ dfrobot_firebeetle2_esp32e.menu.FlashSize.4M=4MB (32Mb) dfrobot_firebeetle2_esp32e.menu.FlashSize.4M.build.flash_size=4MB dfrobot_firebeetle2_esp32e.menu.FlashSize.8M=8MB (64Mb) dfrobot_firebeetle2_esp32e.menu.FlashSize.8M.build.flash_size=8MB -dfrobot_firebeetle2_esp32e.menu.FlashSize.8M.build.partitions=default_8MB dfrobot_firebeetle2_esp32e.menu.FlashSize.2M=2MB (16Mb) dfrobot_firebeetle2_esp32e.menu.FlashSize.2M.build.flash_size=2MB -dfrobot_firebeetle2_esp32e.menu.FlashSize.2M.build.partitions=minimal dfrobot_firebeetle2_esp32e.menu.FlashSize.16M=16MB (128Mb) dfrobot_firebeetle2_esp32e.menu.FlashSize.16M.build.flash_size=16MB @@ -9895,7 +12225,6 @@ dfrobot_firebeetle2_esp32s3.menu.FlashSize.4M=4MB (32Mb) dfrobot_firebeetle2_esp32s3.menu.FlashSize.4M.build.flash_size=4MB dfrobot_firebeetle2_esp32s3.menu.FlashSize.8M=8MB (64Mb) dfrobot_firebeetle2_esp32s3.menu.FlashSize.8M.build.flash_size=8MB -dfrobot_firebeetle2_esp32s3.menu.FlashSize.8M.build.partitions=default_8MB dfrobot_firebeetle2_esp32s3.menu.FlashSize.16M=16MB (128Mb) dfrobot_firebeetle2_esp32s3.menu.FlashSize.16M.build.flash_size=16MB #dfrobot_firebeetle2_esp32s3.menu.FlashSize.32M=32MB (256Mb) @@ -9971,9 +12300,15 @@ dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.fatflash.upload.maximum_size=20 dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.rainmaker=RainMaker +dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.rainmaker=RainMaker 4MB dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +dfrobot_firebeetle2_esp32s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 dfrobot_firebeetle2_esp32s3.menu.CPUFreq.240=240MHz (WiFi) dfrobot_firebeetle2_esp32s3.menu.CPUFreq.240.build.f_cpu=240000000L @@ -10101,9 +12436,12 @@ dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.huge_app.upload.maximum_size=31 dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.rainmaker=RainMaker +dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.rainmaker=RainMaker 4MB dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.zigbee.build.partitions=zigbee dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 @@ -10178,14 +12516,10 @@ dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.default.build.zigbee_mode= dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.default.build.zigbee_libs= dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED -dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port -dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) -dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP -dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port - +dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native ############################################################## # dfrobot Romeo ESP32-S3 @@ -10327,9 +12661,15 @@ dfrobot_romeo_esp32s3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 dfrobot_romeo_esp32s3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) dfrobot_romeo_esp32s3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs dfrobot_romeo_esp32s3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -dfrobot_romeo_esp32s3.menu.PartitionScheme.rainmaker=RainMaker +dfrobot_romeo_esp32s3.menu.PartitionScheme.rainmaker=RainMaker 4MB dfrobot_romeo_esp32s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -dfrobot_romeo_esp32s3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +dfrobot_romeo_esp32s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +dfrobot_romeo_esp32s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +dfrobot_romeo_esp32s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +dfrobot_romeo_esp32s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +dfrobot_romeo_esp32s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +dfrobot_romeo_esp32s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +dfrobot_romeo_esp32s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 dfrobot_romeo_esp32s3.menu.CPUFreq.240=240MHz (WiFi) dfrobot_romeo_esp32s3.menu.CPUFreq.240.build.f_cpu=240000000L @@ -10772,9 +13112,9 @@ adafruit_metro_esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_metro_esp32s2.menu.ZigbeeMode.default=Disabled adafruit_metro_esp32s2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_metro_esp32s2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_metro_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_metro_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_metro_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_metro_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_metro_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit Metro ESP32-S3 @@ -10975,9 +13315,9 @@ adafruit_metro_esp32s3.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_metro_esp32s3.menu.ZigbeeMode.default=Disabled adafruit_metro_esp32s3.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_metro_esp32s3.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_metro_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_metro_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_metro_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_metro_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_metro_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit MagTag 2.9" @@ -11158,9 +13498,9 @@ adafruit_magtag29_esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_magtag29_esp32s2.menu.ZigbeeMode.default=Disabled adafruit_magtag29_esp32s2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_magtag29_esp32s2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_magtag29_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_magtag29_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_magtag29_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_magtag29_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_magtag29_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit FunHouse @@ -11341,9 +13681,9 @@ adafruit_funhouse_esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_funhouse_esp32s2.menu.ZigbeeMode.default=Disabled adafruit_funhouse_esp32s2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_funhouse_esp32s2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_funhouse_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_funhouse_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_funhouse_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_funhouse_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_funhouse_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit ESP32 Feather @@ -11475,9 +13815,9 @@ featheresp32.menu.EraseFlash.all.upload.erase_cmd=-e featheresp32.menu.ZigbeeMode.default=Disabled featheresp32.menu.ZigbeeMode.default.build.zigbee_mode= featheresp32.menu.ZigbeeMode.default.build.zigbee_libs= -featheresp32.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +featheresp32.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) featheresp32.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -featheresp32.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +featheresp32.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit Feather ESP32 V2 @@ -11535,6 +13875,9 @@ adafruit_feather_esp32_v2.menu.PSRAM.disabled.build.defines= adafruit_feather_esp32_v2.menu.PartitionScheme.default_8MB=Default (3MB APP/1.5MB SPIFFS) adafruit_feather_esp32_v2.menu.PartitionScheme.default_8MB.build.partitions=default_8MB adafruit_feather_esp32_v2.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +adafruit_feather_esp32_v2.menu.PartitionScheme.large_spiffs_8MB=Large SPIFFS (1.2MB APP / 5.3MB SPIFFS) +adafruit_feather_esp32_v2.menu.PartitionScheme.large_spiffs_8MB.build.partitions=large_spiffs_8MB +adafruit_feather_esp32_v2.menu.PartitionScheme.large_spiffs_8MB.upload.maximum_size=1310720 adafruit_feather_esp32_v2.menu.CPUFreq.240=240MHz (WiFi/BT) adafruit_feather_esp32_v2.menu.CPUFreq.240.build.f_cpu=240000000L @@ -11593,9 +13936,9 @@ adafruit_feather_esp32_v2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32_v2.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32_v2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32_v2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32_v2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32_v2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32_v2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_feather_esp32_v2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_feather_esp32_v2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit Feather ESP32-S2 @@ -11776,9 +14119,9 @@ adafruit_feather_esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s2.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_feather_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_feather_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit Feather ESP32-S2 TFT @@ -11959,9 +14302,9 @@ adafruit_feather_esp32s2_tft.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s2_tft.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s2_tft.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s2_tft.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s2_tft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s2_tft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s2_tft.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_feather_esp32s2_tft.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_feather_esp32s2_tft.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit Feather ESP32-S2 Reverse TFT @@ -12142,9 +14485,9 @@ adafruit_feather_esp32s2_reversetft.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit Feather ESP32-S3 2MB PSRAM @@ -12360,9 +14703,9 @@ adafruit_feather_esp32s3.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s3.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s3.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s3.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_feather_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_feather_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit Feather ESP32-S3 No PSRAM @@ -12547,9 +14890,9 @@ adafruit_feather_esp32s3_nopsram.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit Feather ESP32-S3 TFT @@ -12765,9 +15108,9 @@ adafruit_feather_esp32s3_tft.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s3_tft.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s3_tft.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s3_tft.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s3_tft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s3_tft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s3_tft.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_feather_esp32s3_tft.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_feather_esp32s3_tft.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit Feather ESP32-S3 Reverse TFT @@ -12983,9 +15326,184 @@ adafruit_feather_esp32s3_reversetft.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################# +# Feather C6 + + +adafruit_feather_esp32c6.name=Adafruit Feather ESP32-C6 + +adafruit_feather_esp32c6.bootloader.tool=esptool_py +adafruit_feather_esp32c6.bootloader.tool.default=esptool_py + +adafruit_feather_esp32c6.upload.tool=esptool_py +adafruit_feather_esp32c6.upload.tool.default=esptool_py +adafruit_feather_esp32c6.upload.tool.network=esp_ota + +adafruit_feather_esp32c6.upload.maximum_size=1310720 +adafruit_feather_esp32c6.upload.maximum_data_size=327680 +adafruit_feather_esp32c6.upload.flags= +adafruit_feather_esp32c6.upload.extra_flags= +adafruit_feather_esp32c6.upload.use_1200bps_touch=false +adafruit_feather_esp32c6.upload.wait_for_upload_port=false + +adafruit_feather_esp32c6.serial.disableDTR=false +adafruit_feather_esp32c6.serial.disableRTS=false + +adafruit_feather_esp32c6.build.tarch=riscv32 +adafruit_feather_esp32c6.build.target=esp +adafruit_feather_esp32c6.build.mcu=esp32c6 +adafruit_feather_esp32c6.build.core=esp32 +adafruit_feather_esp32c6.build.variant=adafruit_feather_esp32c6 +adafruit_feather_esp32c6.build.board=ADAFRUIT_FEATHER_ESP32C6 +adafruit_feather_esp32c6.build.bootloader_addr=0x0 + +adafruit_feather_esp32c6.build.cdc_on_boot=0 +adafruit_feather_esp32c6.build.f_cpu=160000000L +adafruit_feather_esp32c6.build.flash_size=4MB +adafruit_feather_esp32c6.build.flash_freq=80m +adafruit_feather_esp32c6.build.flash_mode=qio +adafruit_feather_esp32c6.build.boot=qio +adafruit_feather_esp32c6.build.partitions=default +adafruit_feather_esp32c6.build.defines= + +## IDE 2.0 Seems to not update the value +adafruit_feather_esp32c6.menu.JTAGAdapter.default=Disabled +adafruit_feather_esp32c6.menu.JTAGAdapter.default.build.copy_jtag_files=0 +adafruit_feather_esp32c6.menu.JTAGAdapter.builtin=Integrated USB JTAG +adafruit_feather_esp32c6.menu.JTAGAdapter.builtin.build.openocdscript=esp32c6-builtin.cfg +adafruit_feather_esp32c6.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +adafruit_feather_esp32c6.menu.JTAGAdapter.external=FTDI Adapter +adafruit_feather_esp32c6.menu.JTAGAdapter.external.build.openocdscript=esp32c6-ftdi.cfg +adafruit_feather_esp32c6.menu.JTAGAdapter.external.build.copy_jtag_files=1 +adafruit_feather_esp32c6.menu.JTAGAdapter.bridge=ESP USB Bridge +adafruit_feather_esp32c6.menu.JTAGAdapter.bridge.build.openocdscript=esp32c6-bridge.cfg +adafruit_feather_esp32c6.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +adafruit_feather_esp32c6.menu.CDCOnBoot.default=Disabled +adafruit_feather_esp32c6.menu.CDCOnBoot.default.build.cdc_on_boot=0 +adafruit_feather_esp32c6.menu.CDCOnBoot.cdc=Enabled +adafruit_feather_esp32c6.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +adafruit_feather_esp32c6.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +adafruit_feather_esp32c6.menu.PartitionScheme.default.build.partitions=default +adafruit_feather_esp32c6.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +adafruit_feather_esp32c6.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +adafruit_feather_esp32c6.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +adafruit_feather_esp32c6.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +adafruit_feather_esp32c6.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +adafruit_feather_esp32c6.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +adafruit_feather_esp32c6.menu.PartitionScheme.minimal.build.partitions=minimal +adafruit_feather_esp32c6.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +adafruit_feather_esp32c6.menu.PartitionScheme.no_ota.build.partitions=no_ota +adafruit_feather_esp32c6.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +adafruit_feather_esp32c6.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +adafruit_feather_esp32c6.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +adafruit_feather_esp32c6.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +adafruit_feather_esp32c6.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +adafruit_feather_esp32c6.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +adafruit_feather_esp32c6.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +adafruit_feather_esp32c6.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +adafruit_feather_esp32c6.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +adafruit_feather_esp32c6.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +adafruit_feather_esp32c6.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +adafruit_feather_esp32c6.menu.PartitionScheme.huge_app.build.partitions=huge_app +adafruit_feather_esp32c6.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +adafruit_feather_esp32c6.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +adafruit_feather_esp32c6.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +adafruit_feather_esp32c6.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +adafruit_feather_esp32c6.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +adafruit_feather_esp32c6.menu.PartitionScheme.fatflash.build.partitions=ffat +adafruit_feather_esp32c6.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +adafruit_feather_esp32c6.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +adafruit_feather_esp32c6.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +adafruit_feather_esp32c6.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +adafruit_feather_esp32c6.menu.PartitionScheme.rainmaker=RainMaker 4MB +adafruit_feather_esp32c6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +adafruit_feather_esp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +adafruit_feather_esp32c6.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +adafruit_feather_esp32c6.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +adafruit_feather_esp32c6.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +adafruit_feather_esp32c6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs +adafruit_feather_esp32c6.menu.PartitionScheme.zigbee.build.partitions=zigbee +adafruit_feather_esp32c6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 +adafruit_feather_esp32c6.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +adafruit_feather_esp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +adafruit_feather_esp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +adafruit_feather_esp32c6.menu.PartitionScheme.custom=Custom +adafruit_feather_esp32c6.menu.PartitionScheme.custom.build.partitions= +adafruit_feather_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +adafruit_feather_esp32c6.menu.CPUFreq.160=160MHz (WiFi) +adafruit_feather_esp32c6.menu.CPUFreq.160.build.f_cpu=160000000L +adafruit_feather_esp32c6.menu.CPUFreq.120=120MHz (WiFi) +adafruit_feather_esp32c6.menu.CPUFreq.120.build.f_cpu=120000000L +adafruit_feather_esp32c6.menu.CPUFreq.80=80MHz (WiFi) +adafruit_feather_esp32c6.menu.CPUFreq.80.build.f_cpu=80000000L +adafruit_feather_esp32c6.menu.CPUFreq.40=40MHz +adafruit_feather_esp32c6.menu.CPUFreq.40.build.f_cpu=40000000L +adafruit_feather_esp32c6.menu.CPUFreq.20=20MHz +adafruit_feather_esp32c6.menu.CPUFreq.20.build.f_cpu=20000000L +adafruit_feather_esp32c6.menu.CPUFreq.10=10MHz +adafruit_feather_esp32c6.menu.CPUFreq.10.build.f_cpu=10000000L + +adafruit_feather_esp32c6.menu.FlashMode.qio=QIO +adafruit_feather_esp32c6.menu.FlashMode.qio.build.flash_mode=dio +adafruit_feather_esp32c6.menu.FlashMode.qio.build.boot=qio +adafruit_feather_esp32c6.menu.FlashMode.dio=DIO +adafruit_feather_esp32c6.menu.FlashMode.dio.build.flash_mode=dio +adafruit_feather_esp32c6.menu.FlashMode.dio.build.boot=dio + +adafruit_feather_esp32c6.menu.FlashFreq.80=80MHz +adafruit_feather_esp32c6.menu.FlashFreq.80.build.flash_freq=80m +adafruit_feather_esp32c6.menu.FlashFreq.40=40MHz +adafruit_feather_esp32c6.menu.FlashFreq.40.build.flash_freq=40m + +adafruit_feather_esp32c6.menu.UploadSpeed.921600=921600 +adafruit_feather_esp32c6.menu.UploadSpeed.921600.upload.speed=921600 +adafruit_feather_esp32c6.menu.UploadSpeed.115200=115200 +adafruit_feather_esp32c6.menu.UploadSpeed.115200.upload.speed=115200 +adafruit_feather_esp32c6.menu.UploadSpeed.256000.windows=256000 +adafruit_feather_esp32c6.menu.UploadSpeed.256000.upload.speed=256000 +adafruit_feather_esp32c6.menu.UploadSpeed.230400.windows.upload.speed=256000 +adafruit_feather_esp32c6.menu.UploadSpeed.230400=230400 +adafruit_feather_esp32c6.menu.UploadSpeed.230400.upload.speed=230400 +adafruit_feather_esp32c6.menu.UploadSpeed.460800.linux=460800 +adafruit_feather_esp32c6.menu.UploadSpeed.460800.macosx=460800 +adafruit_feather_esp32c6.menu.UploadSpeed.460800.upload.speed=460800 +adafruit_feather_esp32c6.menu.UploadSpeed.512000.windows=512000 +adafruit_feather_esp32c6.menu.UploadSpeed.512000.upload.speed=512000 + +adafruit_feather_esp32c6.menu.DebugLevel.none=None +adafruit_feather_esp32c6.menu.DebugLevel.none.build.code_debug=0 +adafruit_feather_esp32c6.menu.DebugLevel.error=Error +adafruit_feather_esp32c6.menu.DebugLevel.error.build.code_debug=1 +adafruit_feather_esp32c6.menu.DebugLevel.warn=Warn +adafruit_feather_esp32c6.menu.DebugLevel.warn.build.code_debug=2 +adafruit_feather_esp32c6.menu.DebugLevel.info=Info +adafruit_feather_esp32c6.menu.DebugLevel.info.build.code_debug=3 +adafruit_feather_esp32c6.menu.DebugLevel.debug=Debug +adafruit_feather_esp32c6.menu.DebugLevel.debug.build.code_debug=4 +adafruit_feather_esp32c6.menu.DebugLevel.verbose=Verbose +adafruit_feather_esp32c6.menu.DebugLevel.verbose.build.code_debug=5 + +adafruit_feather_esp32c6.menu.EraseFlash.none=Disabled +adafruit_feather_esp32c6.menu.EraseFlash.none.upload.erase_cmd= +adafruit_feather_esp32c6.menu.EraseFlash.all=Enabled +adafruit_feather_esp32c6.menu.EraseFlash.all.upload.erase_cmd=-e + +adafruit_feather_esp32c6.menu.ZigbeeMode.default=Disabled +adafruit_feather_esp32c6.menu.ZigbeeMode.default.build.zigbee_mode= +adafruit_feather_esp32c6.menu.ZigbeeMode.default.build.zigbee_libs= +adafruit_feather_esp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) +adafruit_feather_esp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED +adafruit_feather_esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +adafruit_feather_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +adafruit_feather_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +adafruit_feather_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native ############################################################## # Adafruit QT Py ESP32 @@ -13043,6 +15561,9 @@ adafruit_qtpy_esp32_pico.menu.PSRAM.disabled.build.defines= adafruit_qtpy_esp32_pico.menu.PartitionScheme.default_8MB=Default (3MB APP/1.5MB SPIFFS) adafruit_qtpy_esp32_pico.menu.PartitionScheme.default_8MB.build.partitions=default_8MB adafruit_qtpy_esp32_pico.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +adafruit_qtpy_esp32_pico.menu.PartitionScheme.large_spiffs_8MB=Large SPIFFS (1.2MB APP / 5.3MB SPIFFS) +adafruit_qtpy_esp32_pico.menu.PartitionScheme.large_spiffs_8MB.build.partitions=large_spiffs_8MB +adafruit_qtpy_esp32_pico.menu.PartitionScheme.large_spiffs_8MB.upload.maximum_size=1310720 adafruit_qtpy_esp32_pico.menu.CPUFreq.240=240MHz (WiFi/BT) adafruit_qtpy_esp32_pico.menu.CPUFreq.240.build.f_cpu=240000000L @@ -13101,9 +15622,9 @@ adafruit_qtpy_esp32_pico.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_qtpy_esp32_pico.menu.ZigbeeMode.default=Disabled adafruit_qtpy_esp32_pico.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_qtpy_esp32_pico.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_qtpy_esp32_pico.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_qtpy_esp32_pico.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_qtpy_esp32_pico.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_qtpy_esp32_pico.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_qtpy_esp32_pico.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit QT Py ESP32-C3 @@ -13236,9 +15757,9 @@ adafruit_qtpy_esp32c3.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_qtpy_esp32c3.menu.ZigbeeMode.default=Disabled adafruit_qtpy_esp32c3.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_qtpy_esp32c3.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_qtpy_esp32c3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_qtpy_esp32c3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_qtpy_esp32c3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_qtpy_esp32c3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_qtpy_esp32c3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit QT Py ESP32-S2 @@ -13419,9 +15940,9 @@ adafruit_qtpy_esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_qtpy_esp32s2.menu.ZigbeeMode.default=Disabled adafruit_qtpy_esp32s2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_qtpy_esp32s2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_qtpy_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_qtpy_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_qtpy_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_qtpy_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_qtpy_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit QT Py ESP32-S3 No PSRAM @@ -13606,9 +16127,9 @@ adafruit_qtpy_esp32s3_nopsram.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.default=Disabled adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit QT Py ESP32-S3 (4M Flash 2M PSRAM) @@ -13824,9 +16345,9 @@ adafruit_qtpy_esp32s3_n4r2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.default=Disabled adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit ItsyBitsy ESP32 @@ -13942,9 +16463,9 @@ adafruit_itsybitsy_esp32.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_itsybitsy_esp32.menu.ZigbeeMode.default=Disabled adafruit_itsybitsy_esp32.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_itsybitsy_esp32.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_itsybitsy_esp32.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_itsybitsy_esp32.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_itsybitsy_esp32.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_itsybitsy_esp32.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_itsybitsy_esp32.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit MatrixPortal ESP32-S3 @@ -14139,9 +16660,9 @@ adafruit_matrixportal_esp32s3.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_matrixportal_esp32s3.menu.ZigbeeMode.default=Disabled adafruit_matrixportal_esp32s3.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_matrixportal_esp32s3.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_matrixportal_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_matrixportal_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_matrixportal_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_matrixportal_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_matrixportal_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit pyCamera S3 @@ -14357,9 +16878,9 @@ adafruit_camera_esp32s3.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_camera_esp32s3.menu.ZigbeeMode.default=Disabled adafruit_camera_esp32s3.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_camera_esp32s3.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_camera_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_camera_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_camera_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_camera_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_camera_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## # Adafruit Qualia ESP32-S3 RGB666 @@ -14560,9 +17081,277 @@ adafruit_qualia_s3_rgb666.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_qualia_s3_rgb666.menu.ZigbeeMode.default=Disabled adafruit_qualia_s3_rgb666.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_qualia_s3_rgb666.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_qualia_s3_rgb666.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_qualia_s3_rgb666.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_qualia_s3_rgb666.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -adafruit_qualia_s3_rgb666.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +adafruit_qualia_s3_rgb666.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################################################## +# Adafruit Sparkle Motion w/ESP32 + +sparklemotion.name=Adafruit Sparkle Motion (ESP32) + +sparklemotion.bootloader.tool=esptool_py +sparklemotion.bootloader.tool.default=esptool_py + +sparklemotion.upload.tool=esptool_py +sparklemotion.upload.tool.default=esptool_py +sparklemotion.upload.tool.network=esp_ota + +sparklemotion.upload.maximum_size=1310720 +sparklemotion.upload.maximum_data_size=327680 +sparklemotion.upload.flags= +sparklemotion.upload.extra_flags= + +sparklemotion.serial.disableDTR=true +sparklemotion.serial.disableRTS=true + +sparklemotion.build.tarch=xtensa +sparklemotion.build.bootloader_addr=0x1000 +sparklemotion.build.target=esp32 +sparklemotion.build.mcu=esp32 +sparklemotion.build.core=esp32 +sparklemotion.build.variant=adafruit_sparklemotion_esp32 +sparklemotion.build.board=SPARKLEMOTION_ESP32 + +sparklemotion.build.f_cpu=240000000L +sparklemotion.build.flash_size=4MB +sparklemotion.build.flash_freq=80m +sparklemotion.build.flash_mode=dio +sparklemotion.build.boot=dio +sparklemotion.build.partitions=default +sparklemotion.build.defines= +sparklemotion.build.loop_core= +sparklemotion.build.event_core= + +sparklemotion.menu.LoopCore.1=Core 1 +sparklemotion.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +sparklemotion.menu.LoopCore.0=Core 0 +sparklemotion.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +sparklemotion.menu.EventsCore.1=Core 1 +sparklemotion.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +sparklemotion.menu.EventsCore.0=Core 0 +sparklemotion.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +sparklemotion.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +sparklemotion.menu.PartitionScheme.default.build.partitions=default +sparklemotion.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +sparklemotion.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +sparklemotion.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +sparklemotion.menu.PartitionScheme.minimal.build.partitions=minimal +sparklemotion.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +sparklemotion.menu.PartitionScheme.no_ota.build.partitions=no_ota +sparklemotion.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +sparklemotion.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +sparklemotion.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +sparklemotion.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +sparklemotion.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +sparklemotion.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +sparklemotion.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +sparklemotion.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +sparklemotion.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +sparklemotion.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +sparklemotion.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +sparklemotion.menu.PartitionScheme.huge_app.build.partitions=huge_app +sparklemotion.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +sparklemotion.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +sparklemotion.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +sparklemotion.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 + +sparklemotion.menu.CPUFreq.240=240MHz (WiFi/BT) +sparklemotion.menu.CPUFreq.240.build.f_cpu=240000000L +sparklemotion.menu.CPUFreq.160=160MHz (WiFi/BT) +sparklemotion.menu.CPUFreq.160.build.f_cpu=160000000L +sparklemotion.menu.CPUFreq.80=80MHz (WiFi/BT) +sparklemotion.menu.CPUFreq.80.build.f_cpu=80000000L +sparklemotion.menu.CPUFreq.40=40MHz +sparklemotion.menu.CPUFreq.40.build.f_cpu=40000000L +sparklemotion.menu.CPUFreq.20=20MHz +sparklemotion.menu.CPUFreq.20.build.f_cpu=20000000L +sparklemotion.menu.CPUFreq.10=10MHz +sparklemotion.menu.CPUFreq.10.build.f_cpu=10000000L + +sparklemotion.menu.FlashFreq.80=80MHz +sparklemotion.menu.FlashFreq.80.build.flash_freq=80m +sparklemotion.menu.FlashFreq.40=40MHz +sparklemotion.menu.FlashFreq.40.build.flash_freq=40m + +sparklemotion.menu.FlashSize.4M=4MB (32Mb) +sparklemotion.menu.FlashSize.4M.build.flash_size=4MB + +sparklemotion.menu.UploadSpeed.921600=921600 +sparklemotion.menu.UploadSpeed.921600.upload.speed=921600 +sparklemotion.menu.UploadSpeed.115200=115200 +sparklemotion.menu.UploadSpeed.115200.upload.speed=115200 +sparklemotion.menu.UploadSpeed.256000.windows=256000 +sparklemotion.menu.UploadSpeed.256000.upload.speed=256000 +sparklemotion.menu.UploadSpeed.230400.windows.upload.speed=256000 +sparklemotion.menu.UploadSpeed.230400=230400 +sparklemotion.menu.UploadSpeed.230400.upload.speed=230400 +sparklemotion.menu.UploadSpeed.460800.linux=460800 +sparklemotion.menu.UploadSpeed.460800.macosx=460800 +sparklemotion.menu.UploadSpeed.460800.upload.speed=460800 +sparklemotion.menu.UploadSpeed.512000.windows=512000 +sparklemotion.menu.UploadSpeed.512000.upload.speed=512000 + +sparklemotion.menu.DebugLevel.none=None +sparklemotion.menu.DebugLevel.none.build.code_debug=0 +sparklemotion.menu.DebugLevel.error=Error +sparklemotion.menu.DebugLevel.error.build.code_debug=1 +sparklemotion.menu.DebugLevel.warn=Warn +sparklemotion.menu.DebugLevel.warn.build.code_debug=2 +sparklemotion.menu.DebugLevel.info=Info +sparklemotion.menu.DebugLevel.info.build.code_debug=3 +sparklemotion.menu.DebugLevel.debug=Debug +sparklemotion.menu.DebugLevel.debug.build.code_debug=4 +sparklemotion.menu.DebugLevel.verbose=Verbose +sparklemotion.menu.DebugLevel.verbose.build.code_debug=5 + +sparklemotion.menu.EraseFlash.none=Disabled +sparklemotion.menu.EraseFlash.none.upload.erase_cmd= +sparklemotion.menu.EraseFlash.all=Enabled +sparklemotion.menu.EraseFlash.all.upload.erase_cmd=-e + +sparklemotion.menu.ZigbeeMode.default=Disabled +sparklemotion.menu.ZigbeeMode.default.build.zigbee_mode= +sparklemotion.menu.ZigbeeMode.default.build.zigbee_libs= +sparklemotion.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +sparklemotion.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +sparklemotion.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################################################## +# Adafruit Sparkle Motion Mini w/ESP32 + +sparklemotionmini.name=Adafruit Sparkle Motion Mini (ESP32) + +sparklemotionmini.bootloader.tool=esptool_py +sparklemotionmini.bootloader.tool.default=esptool_py + +sparklemotionmini.upload.tool=esptool_py +sparklemotionmini.upload.tool.default=esptool_py +sparklemotionmini.upload.tool.network=esp_ota + +sparklemotionmini.upload.maximum_size=1310720 +sparklemotionmini.upload.maximum_data_size=327680 +sparklemotionmini.upload.flags= +sparklemotionmini.upload.extra_flags= + +sparklemotionmini.serial.disableDTR=true +sparklemotionmini.serial.disableRTS=true + +sparklemotionmini.build.tarch=xtensa +sparklemotionmini.build.bootloader_addr=0x1000 +sparklemotionmini.build.target=esp32 +sparklemotionmini.build.mcu=esp32 +sparklemotionmini.build.core=esp32 +sparklemotionmini.build.variant=adafruit_sparklemotionmini_esp32 +sparklemotionmini.build.board=SPARKLEMOTIONMINI_ESP32 + +sparklemotionmini.build.f_cpu=240000000L +sparklemotionmini.build.flash_size=4MB +sparklemotionmini.build.flash_freq=80m +sparklemotionmini.build.flash_mode=dio +sparklemotionmini.build.boot=dio +sparklemotionmini.build.partitions=default +sparklemotionmini.build.defines= +sparklemotionmini.build.loop_core= +sparklemotionmini.build.event_core= + +sparklemotionmini.menu.LoopCore.1=Core 1 +sparklemotionmini.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +sparklemotionmini.menu.LoopCore.0=Core 0 +sparklemotionmini.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +sparklemotionmini.menu.EventsCore.1=Core 1 +sparklemotionmini.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +sparklemotionmini.menu.EventsCore.0=Core 0 +sparklemotionmini.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +sparklemotionmini.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +sparklemotionmini.menu.PartitionScheme.default.build.partitions=default +sparklemotionmini.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +sparklemotionmini.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +sparklemotionmini.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +sparklemotionmini.menu.PartitionScheme.minimal.build.partitions=minimal +sparklemotionmini.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +sparklemotionmini.menu.PartitionScheme.no_ota.build.partitions=no_ota +sparklemotionmini.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +sparklemotionmini.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +sparklemotionmini.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +sparklemotionmini.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +sparklemotionmini.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +sparklemotionmini.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +sparklemotionmini.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +sparklemotionmini.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +sparklemotionmini.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +sparklemotionmini.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +sparklemotionmini.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +sparklemotionmini.menu.PartitionScheme.huge_app.build.partitions=huge_app +sparklemotionmini.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +sparklemotionmini.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +sparklemotionmini.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +sparklemotionmini.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 + +sparklemotionmini.menu.CPUFreq.240=240MHz (WiFi/BT) +sparklemotionmini.menu.CPUFreq.240.build.f_cpu=240000000L +sparklemotionmini.menu.CPUFreq.160=160MHz (WiFi/BT) +sparklemotionmini.menu.CPUFreq.160.build.f_cpu=160000000L +sparklemotionmini.menu.CPUFreq.80=80MHz (WiFi/BT) +sparklemotionmini.menu.CPUFreq.80.build.f_cpu=80000000L +sparklemotionmini.menu.CPUFreq.40=40MHz +sparklemotionmini.menu.CPUFreq.40.build.f_cpu=40000000L +sparklemotionmini.menu.CPUFreq.20=20MHz +sparklemotionmini.menu.CPUFreq.20.build.f_cpu=20000000L +sparklemotionmini.menu.CPUFreq.10=10MHz +sparklemotionmini.menu.CPUFreq.10.build.f_cpu=10000000L + +sparklemotionmini.menu.FlashFreq.80=80MHz +sparklemotionmini.menu.FlashFreq.80.build.flash_freq=80m +sparklemotionmini.menu.FlashFreq.40=40MHz +sparklemotionmini.menu.FlashFreq.40.build.flash_freq=40m + +sparklemotionmini.menu.FlashSize.4M=4MB (32Mb) +sparklemotionmini.menu.FlashSize.4M.build.flash_size=4MB + +sparklemotionmini.menu.UploadSpeed.921600=921600 +sparklemotionmini.menu.UploadSpeed.921600.upload.speed=921600 +sparklemotionmini.menu.UploadSpeed.115200=115200 +sparklemotionmini.menu.UploadSpeed.115200.upload.speed=115200 +sparklemotionmini.menu.UploadSpeed.256000.windows=256000 +sparklemotionmini.menu.UploadSpeed.256000.upload.speed=256000 +sparklemotionmini.menu.UploadSpeed.230400.windows.upload.speed=256000 +sparklemotionmini.menu.UploadSpeed.230400=230400 +sparklemotionmini.menu.UploadSpeed.230400.upload.speed=230400 +sparklemotionmini.menu.UploadSpeed.460800.linux=460800 +sparklemotionmini.menu.UploadSpeed.460800.macosx=460800 +sparklemotionmini.menu.UploadSpeed.460800.upload.speed=460800 +sparklemotionmini.menu.UploadSpeed.512000.windows=512000 +sparklemotionmini.menu.UploadSpeed.512000.upload.speed=512000 + +sparklemotionmini.menu.DebugLevel.none=None +sparklemotionmini.menu.DebugLevel.none.build.code_debug=0 +sparklemotionmini.menu.DebugLevel.error=Error +sparklemotionmini.menu.DebugLevel.error.build.code_debug=1 +sparklemotionmini.menu.DebugLevel.warn=Warn +sparklemotionmini.menu.DebugLevel.warn.build.code_debug=2 +sparklemotionmini.menu.DebugLevel.info=Info +sparklemotionmini.menu.DebugLevel.info.build.code_debug=3 +sparklemotionmini.menu.DebugLevel.debug=Debug +sparklemotionmini.menu.DebugLevel.debug.build.code_debug=4 +sparklemotionmini.menu.DebugLevel.verbose=Verbose +sparklemotionmini.menu.DebugLevel.verbose.build.code_debug=5 + +sparklemotionmini.menu.EraseFlash.none=Disabled +sparklemotionmini.menu.EraseFlash.none.upload.erase_cmd= +sparklemotionmini.menu.EraseFlash.all=Enabled +sparklemotionmini.menu.EraseFlash.all.upload.erase_cmd=-e + +sparklemotionmini.menu.ZigbeeMode.default=Disabled +sparklemotionmini.menu.ZigbeeMode.default.build.zigbee_mode= +sparklemotionmini.menu.ZigbeeMode.default.build.zigbee_libs= +sparklemotionmini.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +sparklemotionmini.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +sparklemotionmini.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## @@ -14589,7 +17378,7 @@ nodemcu-32s.build.target=esp32 nodemcu-32s.build.mcu=esp32 nodemcu-32s.build.core=esp32 nodemcu-32s.build.variant=nodemcu-32s -nodemcu-32s.build.board=NodeMCU_32S +nodemcu-32s.build.board=NODEMCU_32S nodemcu-32s.build.f_cpu=240000000L nodemcu-32s.build.flash_mode=dio @@ -14603,9 +17392,6 @@ nodemcu-32s.menu.FlashFreq.80.build.flash_freq=80m nodemcu-32s.menu.FlashFreq.40=40MHz nodemcu-32s.menu.FlashFreq.40.build.flash_freq=40m -nodemcu-32s.menu.UploadSpeed.460800.linux=460800 -nodemcu-32s.menu.UploadSpeed.460800.macosx=460800 -nodemcu-32s.menu.UploadSpeed.460800.upload.speed=460800 nodemcu-32s.menu.UploadSpeed.115200=115200 nodemcu-32s.menu.UploadSpeed.115200.upload.speed=115200 nodemcu-32s.menu.UploadSpeed.256000.windows=256000 @@ -14615,6 +17401,9 @@ nodemcu-32s.menu.UploadSpeed.230400=230400 nodemcu-32s.menu.UploadSpeed.230400.upload.speed=230400 nodemcu-32s.menu.UploadSpeed.512000.windows=512000 nodemcu-32s.menu.UploadSpeed.512000.upload.speed=512000 +nodemcu-32s.menu.UploadSpeed.460800.linux=460800 +nodemcu-32s.menu.UploadSpeed.460800.macosx=460800 +nodemcu-32s.menu.UploadSpeed.460800.upload.speed=460800 nodemcu-32s.menu.UploadSpeed.921600=921600 nodemcu-32s.menu.UploadSpeed.921600.upload.speed=921600 @@ -14866,7 +17655,6 @@ nologo_esp32s3_pico.menu.FlashMode.opi.build.flash_freq=80m nologo_esp32s3_pico.menu.FlashSize.8M=8MB (64Mb) nologo_esp32s3_pico.menu.FlashSize.8M.build.flash_size=8MB -nologo_esp32s3_pico.menu.FlashSize.8M.build.partitions=default_8MB nologo_esp32s3_pico.menu.FlashSize.16M=16MB (128Mb) nologo_esp32s3_pico.menu.FlashSize.16M.build.flash_size=16MB @@ -14940,9 +17728,15 @@ nologo_esp32s3_pico.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 nologo_esp32s3_pico.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) nologo_esp32s3_pico.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB nologo_esp32s3_pico.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -nologo_esp32s3_pico.menu.PartitionScheme.rainmaker=RainMaker +nologo_esp32s3_pico.menu.PartitionScheme.rainmaker=RainMaker 4MB nologo_esp32s3_pico.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -nologo_esp32s3_pico.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +nologo_esp32s3_pico.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +nologo_esp32s3_pico.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +nologo_esp32s3_pico.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +nologo_esp32s3_pico.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +nologo_esp32s3_pico.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +nologo_esp32s3_pico.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +nologo_esp32s3_pico.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 nologo_esp32s3_pico.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) nologo_esp32s3_pico.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB nologo_esp32s3_pico.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 @@ -15009,9 +17803,9 @@ nologo_esp32s3_pico.menu.EraseFlash.all.upload.erase_cmd=-e nologo_esp32s3_pico.menu.ZigbeeMode.default=Disabled nologo_esp32s3_pico.menu.ZigbeeMode.default.build.zigbee_mode= nologo_esp32s3_pico.menu.ZigbeeMode.default.build.zigbee_libs= -nologo_esp32s3_pico.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +nologo_esp32s3_pico.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) nologo_esp32s3_pico.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -nologo_esp32s3_pico.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +nologo_esp32s3_pico.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## @@ -15653,9 +18447,15 @@ esp32-poe.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32-poe.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32-poe.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32-poe.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32-poe.menu.PartitionScheme.rainmaker=RainMaker +esp32-poe.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32-poe.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32-poe.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32-poe.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32-poe.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32-poe.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32-poe.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32-poe.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32-poe.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32-poe.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32-poe.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs esp32-poe.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr esp32-poe.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 @@ -15790,9 +18590,15 @@ esp32-poe-iso.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32-poe-iso.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32-poe-iso.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32-poe-iso.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32-poe-iso.menu.PartitionScheme.rainmaker=RainMaker +esp32-poe-iso.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32-poe-iso.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32-poe-iso.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32-poe-iso.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32-poe-iso.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32-poe-iso.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32-poe-iso.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32-poe-iso.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32-poe-iso.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32-poe-iso.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32-poe-iso.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs esp32-poe-iso.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr esp32-poe-iso.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 @@ -16062,9 +18868,15 @@ esp32s2-devkitlipo.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32s2-devkitlipo.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32s2-devkitlipo.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32s2-devkitlipo.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32s2-devkitlipo.menu.PartitionScheme.rainmaker=RainMaker +esp32s2-devkitlipo.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32s2-devkitlipo.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32s2-devkitlipo.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32s2-devkitlipo.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32s2-devkitlipo.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32s2-devkitlipo.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32s2-devkitlipo.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32s2-devkitlipo.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32s2-devkitlipo.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32s2-devkitlipo.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32s2-devkitlipo.menu.PartitionScheme.custom=Custom esp32s2-devkitlipo.menu.PartitionScheme.custom.build.partitions= esp32s2-devkitlipo.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -16104,10 +18916,8 @@ esp32s2-devkitlipo.menu.FlashSize.4M=4MB (32Mb) esp32s2-devkitlipo.menu.FlashSize.4M.build.flash_size=4MB esp32s2-devkitlipo.menu.FlashSize.8M=8MB (64Mb) esp32s2-devkitlipo.menu.FlashSize.8M.build.flash_size=8MB -esp32s2-devkitlipo.menu.FlashSize.8M.build.partitions=default_8MB esp32s2-devkitlipo.menu.FlashSize.2M=2MB (16Mb) esp32s2-devkitlipo.menu.FlashSize.2M.build.flash_size=2MB -esp32s2-devkitlipo.menu.FlashSize.2M.build.partitions=minimal esp32s2-devkitlipo.menu.FlashSize.16M=16MB (128Mb) esp32s2-devkitlipo.menu.FlashSize.16M.build.flash_size=16MB @@ -16253,9 +19063,15 @@ esp32s2-devkitlipo-usb.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32s2-devkitlipo-usb.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32s2-devkitlipo-usb.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32s2-devkitlipo-usb.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32s2-devkitlipo-usb.menu.PartitionScheme.rainmaker=RainMaker +esp32s2-devkitlipo-usb.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32s2-devkitlipo-usb.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32s2-devkitlipo-usb.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32s2-devkitlipo-usb.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32s2-devkitlipo-usb.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32s2-devkitlipo-usb.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32s2-devkitlipo-usb.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32s2-devkitlipo-usb.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32s2-devkitlipo-usb.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32s2-devkitlipo-usb.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32s2-devkitlipo-usb.menu.PartitionScheme.custom=Custom esp32s2-devkitlipo-usb.menu.PartitionScheme.custom.build.partitions= esp32s2-devkitlipo-usb.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -16295,10 +19111,8 @@ esp32s2-devkitlipo-usb.menu.FlashSize.4M=4MB (32Mb) esp32s2-devkitlipo-usb.menu.FlashSize.4M.build.flash_size=4MB esp32s2-devkitlipo-usb.menu.FlashSize.8M=8MB (64Mb) esp32s2-devkitlipo-usb.menu.FlashSize.8M.build.flash_size=8MB -esp32s2-devkitlipo-usb.menu.FlashSize.8M.build.partitions=default_8MB esp32s2-devkitlipo-usb.menu.FlashSize.2M=2MB (16Mb) esp32s2-devkitlipo-usb.menu.FlashSize.2M.build.flash_size=2MB -esp32s2-devkitlipo-usb.menu.FlashSize.2M.build.partitions=minimal esp32s2-devkitlipo-usb.menu.FlashSize.16M=16MB (128Mb) esp32s2-devkitlipo-usb.menu.FlashSize.16M.build.flash_size=16MB @@ -16429,12 +19243,10 @@ esp32s3-devkitlipo.menu.FlashSize.4M=4MB (32Mb) esp32s3-devkitlipo.menu.FlashSize.4M.build.flash_size=4MB esp32s3-devkitlipo.menu.FlashSize.8M=8MB (64Mb) esp32s3-devkitlipo.menu.FlashSize.8M.build.flash_size=8MB -esp32s3-devkitlipo.menu.FlashSize.8M.build.partitions=default_8MB esp32s3-devkitlipo.menu.FlashSize.16M=16MB (128Mb) esp32s3-devkitlipo.menu.FlashSize.16M.build.flash_size=16MB esp32s3-devkitlipo.menu.FlashSize.32M=32MB (256Mb) esp32s3-devkitlipo.menu.FlashSize.32M.build.flash_size=32MB -esp32s3-devkitlipo.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB esp32s3-devkitlipo.menu.LoopCore.1=Core 1 esp32s3-devkitlipo.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -16506,9 +19318,15 @@ esp32s3-devkitlipo.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32s3-devkitlipo.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32s3-devkitlipo.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32s3-devkitlipo.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32s3-devkitlipo.menu.PartitionScheme.rainmaker=RainMaker +esp32s3-devkitlipo.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32s3-devkitlipo.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32s3-devkitlipo.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32s3-devkitlipo.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32s3-devkitlipo.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32s3-devkitlipo.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32s3-devkitlipo.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32s3-devkitlipo.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32s3-devkitlipo.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32s3-devkitlipo.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32s3-devkitlipo.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) esp32s3-devkitlipo.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB esp32s3-devkitlipo.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 @@ -16658,9 +19476,15 @@ esp32c3-devkitlipo.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32c3-devkitlipo.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32c3-devkitlipo.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32c3-devkitlipo.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32c3-devkitlipo.menu.PartitionScheme.rainmaker=RainMaker +esp32c3-devkitlipo.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32c3-devkitlipo.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32c3-devkitlipo.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32c3-devkitlipo.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32c3-devkitlipo.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32c3-devkitlipo.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32c3-devkitlipo.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32c3-devkitlipo.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32c3-devkitlipo.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32c3-devkitlipo.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32c3-devkitlipo.menu.PartitionScheme.custom=Custom esp32c3-devkitlipo.menu.PartitionScheme.custom.build.partitions= esp32c3-devkitlipo.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -16698,10 +19522,8 @@ esp32c3-devkitlipo.menu.FlashSize.4M=4MB (32Mb) esp32c3-devkitlipo.menu.FlashSize.4M.build.flash_size=4MB esp32c3-devkitlipo.menu.FlashSize.8M=8MB (64Mb) esp32c3-devkitlipo.menu.FlashSize.8M.build.flash_size=8MB -esp32c3-devkitlipo.menu.FlashSize.8M.build.partitions=default_8MB esp32c3-devkitlipo.menu.FlashSize.2M=2MB (16Mb) esp32c3-devkitlipo.menu.FlashSize.2M.build.flash_size=2MB -esp32c3-devkitlipo.menu.FlashSize.2M.build.partitions=minimal esp32c3-devkitlipo.menu.FlashSize.16M=16MB (128Mb) esp32c3-devkitlipo.menu.FlashSize.16M.build.flash_size=16MB @@ -16827,9 +19649,15 @@ esp32c6-evb.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32c6-evb.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32c6-evb.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32c6-evb.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32c6-evb.menu.PartitionScheme.rainmaker=RainMaker +esp32c6-evb.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32c6-evb.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32c6-evb.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32c6-evb.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32c6-evb.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32c6-evb.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32c6-evb.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32c6-evb.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32c6-evb.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32c6-evb.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32c6-evb.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs esp32c6-evb.menu.PartitionScheme.zigbee.build.partitions=zigbee esp32c6-evb.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 @@ -16867,10 +19695,8 @@ esp32c6-evb.menu.FlashSize.4M=4MB (32Mb) esp32c6-evb.menu.FlashSize.4M.build.flash_size=4MB esp32c6-evb.menu.FlashSize.8M=8MB (64Mb) esp32c6-evb.menu.FlashSize.8M.build.flash_size=8MB -esp32c6-evb.menu.FlashSize.8M.build.partitions=default_8MB esp32c6-evb.menu.FlashSize.2M=2MB (16Mb) esp32c6-evb.menu.FlashSize.2M.build.flash_size=2MB -esp32c6-evb.menu.FlashSize.2M.build.partitions=minimal esp32c6-evb.menu.FlashSize.16M=16MB (128Mb) esp32c6-evb.menu.FlashSize.16M.build.flash_size=16MB @@ -16912,13 +19738,10 @@ esp32c6-evb.menu.ZigbeeMode.default.build.zigbee_mode= esp32c6-evb.menu.ZigbeeMode.default.build.zigbee_libs= esp32c6-evb.menu.ZigbeeMode.ed=Zigbee ED (end device) esp32c6-evb.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED -esp32c6-evb.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -esp32c6-evb.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32c6-evb.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +esp32c6-evb.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32c6-evb.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -esp32c6-evb.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port -esp32c6-evb.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) -esp32c6-evb.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP -esp32c6-evb.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port +esp32c6-evb.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native ############################################################## @@ -17009,9 +19832,15 @@ esp32h2-devkitlipo.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32h2-devkitlipo.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32h2-devkitlipo.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32h2-devkitlipo.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32h2-devkitlipo.menu.PartitionScheme.rainmaker=RainMaker -esp32h2-devkitlipo.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32h2-devkitlipo.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +#esp32h2-devkitlipo.menu.PartitionScheme.rainmaker=RainMaker 4MB +#esp32h2-devkitlipo.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +#esp32h2-devkitlipo.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +#esp32h2-devkitlipo.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +#esp32h2-devkitlipo.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +#esp32h2-devkitlipo.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +#esp32h2-devkitlipo.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +#esp32h2-devkitlipo.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +#esp32h2-devkitlipo.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32h2-devkitlipo.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs esp32h2-devkitlipo.menu.PartitionScheme.zigbee.build.partitions=zigbee esp32h2-devkitlipo.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 @@ -17043,10 +19872,8 @@ esp32h2-devkitlipo.menu.FlashSize.4M=4MB (32Mb) esp32h2-devkitlipo.menu.FlashSize.4M.build.flash_size=4MB esp32h2-devkitlipo.menu.FlashSize.8M=8MB (64Mb) esp32h2-devkitlipo.menu.FlashSize.8M.build.flash_size=8MB -esp32h2-devkitlipo.menu.FlashSize.8M.build.partitions=default_8MB esp32h2-devkitlipo.menu.FlashSize.2M=2MB (16Mb) esp32h2-devkitlipo.menu.FlashSize.2M.build.flash_size=2MB -esp32h2-devkitlipo.menu.FlashSize.2M.build.partitions=minimal esp32h2-devkitlipo.menu.FlashSize.16M=16MB (128Mb) esp32h2-devkitlipo.menu.FlashSize.16M.build.flash_size=16MB @@ -17088,13 +19915,10 @@ esp32h2-devkitlipo.menu.ZigbeeMode.default.build.zigbee_mode= esp32h2-devkitlipo.menu.ZigbeeMode.default.build.zigbee_libs= esp32h2-devkitlipo.menu.ZigbeeMode.ed=Zigbee ED (end device) esp32h2-devkitlipo.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED -esp32h2-devkitlipo.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -esp32h2-devkitlipo.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32h2-devkitlipo.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +esp32h2-devkitlipo.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32h2-devkitlipo.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -esp32h2-devkitlipo.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port -esp32h2-devkitlipo.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) -esp32h2-devkitlipo.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP -esp32h2-devkitlipo.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port +esp32h2-devkitlipo.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native ############################################################## @@ -17183,9 +20007,15 @@ esp32-sbc-fabgl.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32-sbc-fabgl.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) esp32-sbc-fabgl.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB esp32-sbc-fabgl.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -esp32-sbc-fabgl.menu.PartitionScheme.rainmaker=RainMaker +esp32-sbc-fabgl.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32-sbc-fabgl.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32-sbc-fabgl.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32-sbc-fabgl.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32-sbc-fabgl.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32-sbc-fabgl.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32-sbc-fabgl.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +esp32-sbc-fabgl.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +esp32-sbc-fabgl.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +esp32-sbc-fabgl.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 esp32-sbc-fabgl.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs esp32-sbc-fabgl.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr esp32-sbc-fabgl.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 @@ -17226,10 +20056,8 @@ esp32-sbc-fabgl.menu.FlashSize.4M=4MB (32Mb) esp32-sbc-fabgl.menu.FlashSize.4M.build.flash_size=4MB esp32-sbc-fabgl.menu.FlashSize.8M=8MB (64Mb) esp32-sbc-fabgl.menu.FlashSize.8M.build.flash_size=8MB -esp32-sbc-fabgl.menu.FlashSize.8M.build.partitions=default_8MB esp32-sbc-fabgl.menu.FlashSize.2M=2MB (16Mb) esp32-sbc-fabgl.menu.FlashSize.2M.build.flash_size=2MB -esp32-sbc-fabgl.menu.FlashSize.2M.build.partitions=minimal esp32-sbc-fabgl.menu.FlashSize.16M=16MB (128Mb) esp32-sbc-fabgl.menu.FlashSize.16M.build.flash_size=16MB @@ -17279,9 +20107,9 @@ esp32-sbc-fabgl.menu.EraseFlash.all.upload.erase_cmd=-e esp32-sbc-fabgl.menu.ZigbeeMode.default=Disabled esp32-sbc-fabgl.menu.ZigbeeMode.default.build.zigbee_mode= esp32-sbc-fabgl.menu.ZigbeeMode.default.build.zigbee_libs= -esp32-sbc-fabgl.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32-sbc-fabgl.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32-sbc-fabgl.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -esp32-sbc-fabgl.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port +esp32-sbc-fabgl.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## @@ -17422,9 +20250,15 @@ m5stack_core.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 m5stack_core.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) m5stack_core.menu.PartitionScheme.fatflash.build.partitions=ffat m5stack_core.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -m5stack_core.menu.PartitionScheme.rainmaker=RainMaker +m5stack_core.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_core.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_core.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_core.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_core.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_core.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_core.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_core.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_core.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_core.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_core.menu.PartitionScheme.custom=Custom m5stack_core.menu.PartitionScheme.custom.build.partitions= m5stack_core.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -17592,9 +20426,15 @@ m5stack_fire.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_fire.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) m5stack_fire.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB m5stack_fire.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -m5stack_fire.menu.PartitionScheme.rainmaker=RainMaker +m5stack_fire.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_fire.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_fire.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_fire.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_fire.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_fire.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_fire.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_fire.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_fire.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_fire.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_fire.menu.PartitionScheme.custom=Custom m5stack_fire.menu.PartitionScheme.custom.build.partitions= m5stack_fire.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -17760,9 +20600,15 @@ m5stack_core2.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_core2.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) m5stack_core2.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB m5stack_core2.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -m5stack_core2.menu.PartitionScheme.rainmaker=RainMaker +m5stack_core2.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_core2.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_core2.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_core2.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_core2.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_core2.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_core2.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_core2.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_core2.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_core2.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_core2.menu.PartitionScheme.custom=Custom m5stack_core2.menu.PartitionScheme.custom.build.partitions= m5stack_core2.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -17928,9 +20774,15 @@ m5stack_tough.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_tough.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) m5stack_tough.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB m5stack_tough.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -m5stack_tough.menu.PartitionScheme.rainmaker=RainMaker +m5stack_tough.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_tough.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_tough.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_tough.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_tough.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_tough.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_tough.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_tough.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_tough.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_tough.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_tough.menu.PartitionScheme.custom=Custom m5stack_tough.menu.PartitionScheme.custom.build.partitions= m5stack_tough.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -18089,9 +20941,15 @@ m5stack_station.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_station.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) m5stack_station.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB m5stack_station.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -m5stack_station.menu.PartitionScheme.rainmaker=RainMaker +m5stack_station.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_station.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_station.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_station.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_station.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_station.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_station.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_station.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_station.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_station.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_station.menu.PartitionScheme.custom=Custom m5stack_station.menu.PartitionScheme.custom.build.partitions= m5stack_station.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -18246,9 +21104,12 @@ m5stack_stickc.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 m5stack_stickc.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) m5stack_stickc.menu.PartitionScheme.fatflash.build.partitions=ffat m5stack_stickc.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -m5stack_stickc.menu.PartitionScheme.rainmaker=RainMaker +m5stack_stickc.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_stickc.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_stickc.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_stickc.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_stickc.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_stickc.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_stickc.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 m5stack_stickc.menu.PartitionScheme.custom=Custom m5stack_stickc.menu.PartitionScheme.custom.build.partitions= m5stack_stickc.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -18330,6 +21191,7 @@ m5stack_stickc.menu.EraseFlash.none.upload.erase_cmd= m5stack_stickc.menu.EraseFlash.all=Enabled m5stack_stickc.menu.EraseFlash.all.upload.erase_cmd=-e + ############################################################## m5stack_stickc_plus.name=M5StickCPlus @@ -18397,9 +21259,12 @@ m5stack_stickc_plus.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 m5stack_stickc_plus.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) m5stack_stickc_plus.menu.PartitionScheme.fatflash.build.partitions=ffat m5stack_stickc_plus.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -m5stack_stickc_plus.menu.PartitionScheme.rainmaker=RainMaker +m5stack_stickc_plus.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_stickc_plus.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_stickc_plus.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_stickc_plus.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_stickc_plus.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_stickc_plus.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_stickc_plus.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 m5stack_stickc_plus.menu.PartitionScheme.custom=Custom m5stack_stickc_plus.menu.PartitionScheme.custom.build.partitions= m5stack_stickc_plus.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -18481,8 +21346,6 @@ m5stack_stickc_plus.menu.EraseFlash.none.upload.erase_cmd= m5stack_stickc_plus.menu.EraseFlash.all=Enabled m5stack_stickc_plus.menu.EraseFlash.all.upload.erase_cmd=-e - - ############################################################## m5stack_stickc_plus2.name=M5StickCPlus2 @@ -18557,9 +21420,15 @@ m5stack_stickc_plus2.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 m5stack_stickc_plus2.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) m5stack_stickc_plus2.menu.PartitionScheme.fatflash.build.partitions=ffat m5stack_stickc_plus2.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -m5stack_stickc_plus2.menu.PartitionScheme.rainmaker=RainMaker +m5stack_stickc_plus2.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_stickc_plus2.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_stickc_plus2.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_stickc_plus2.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_stickc_plus2.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_stickc_plus2.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_stickc_plus2.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_stickc_plus2.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_stickc_plus2.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_stickc_plus2.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_stickc_plus2.menu.PartitionScheme.custom=Custom m5stack_stickc_plus2.menu.PartitionScheme.custom.build.partitions= m5stack_stickc_plus2.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -18641,7 +21510,6 @@ m5stack_stickc_plus2.menu.EraseFlash.none.upload.erase_cmd= m5stack_stickc_plus2.menu.EraseFlash.all=Enabled m5stack_stickc_plus2.menu.EraseFlash.all.upload.erase_cmd=-e - ############################################################## m5stack_atom.name=M5Atom @@ -18709,9 +21577,12 @@ m5stack_atom.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 m5stack_atom.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) m5stack_atom.menu.PartitionScheme.fatflash.build.partitions=ffat m5stack_atom.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -m5stack_atom.menu.PartitionScheme.rainmaker=RainMaker +m5stack_atom.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_atom.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_atom.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_atom.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_atom.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_atom.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_atom.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 m5stack_atom.menu.PartitionScheme.custom=Custom m5stack_atom.menu.PartitionScheme.custom.build.partitions= m5stack_atom.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -18885,7 +21756,6 @@ m5stack_atoms3.menu.FlashMode.opi.build.flash_freq=80m m5stack_atoms3.menu.FlashSize.8M=8MB (64Mb) m5stack_atoms3.menu.FlashSize.8M.build.flash_size=8MB -m5stack_atoms3.menu.FlashSize.8M.build.partitions=default_8MB m5stack_atoms3.menu.LoopCore.1=Core 1 m5stack_atoms3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -18957,9 +21827,15 @@ m5stack_atoms3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_atoms3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) m5stack_atoms3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB m5stack_atoms3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -m5stack_atoms3.menu.PartitionScheme.rainmaker=RainMaker +m5stack_atoms3.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_atoms3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_atoms3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_atoms3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_atoms3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_atoms3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_atoms3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_atoms3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_atoms3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_atoms3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_atoms3.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) m5stack_atoms3.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB m5stack_atoms3.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 @@ -19113,7 +21989,6 @@ m5stack_cores3.menu.FlashSize.16M=16MB (128Mb) m5stack_cores3.menu.FlashSize.16M.build.flash_size=16MB m5stack_cores3.menu.FlashSize.32M=32MB (256Mb) m5stack_cores3.menu.FlashSize.32M.build.flash_size=32MB -m5stack_cores3.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_cores3.menu.LoopCore.1=Core 1 m5stack_cores3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -19185,9 +22060,15 @@ m5stack_cores3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 m5stack_cores3.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) m5stack_cores3.menu.PartitionScheme.fatflash.build.partitions=ffat m5stack_cores3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -m5stack_cores3.menu.PartitionScheme.rainmaker=RainMaker +m5stack_cores3.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_cores3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_cores3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_cores3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_cores3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_cores3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_cores3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_cores3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_cores3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_cores3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_cores3.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) m5stack_cores3.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB m5stack_cores3.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 @@ -19405,7 +22286,6 @@ m5stack_timer_cam.menu.EraseFlash.none.upload.erase_cmd= m5stack_timer_cam.menu.EraseFlash.all=Enabled m5stack_timer_cam.menu.EraseFlash.all.upload.erase_cmd=-e - ############################################################## @@ -19559,6 +22439,7 @@ m5stack_unit_cam.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## + m5stack_unit_cams3.name=M5UnitCAMS3 m5stack_unit_cams3.bootloader.tool=esptool_py m5stack_unit_cams3.bootloader.tool.default=esptool_py @@ -19599,7 +22480,7 @@ m5stack_unit_cams3.build.partitions=default m5stack_unit_cams3.build.defines= m5stack_unit_cams3.build.loop_core= m5stack_unit_cams3.build.event_core= -m5stack_unit_cams3.build.psram_type=opi +m5stack_unit_cams3.build.psram_type=qspi m5stack_unit_cams3.build.memory_type={build.boot}_{build.psram_type} ## IDE 2.0 Seems to not update the value @@ -19615,12 +22496,15 @@ m5stack_unit_cams3.menu.JTAGAdapter.bridge=ESP USB Bridge m5stack_unit_cams3.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg m5stack_unit_cams3.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 -m5stack_unit_cams3.menu.PSRAM.opi=OPI PSRAM -m5stack_unit_cams3.menu.PSRAM.opi.build.defines=-DBOARD_HAS_PSRAM -m5stack_unit_cams3.menu.PSRAM.opi.build.psram_type=opi +m5stack_unit_cams3.menu.PSRAM.enabled=QSPI PSRAM +m5stack_unit_cams3.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +m5stack_unit_cams3.menu.PSRAM.enabled.build.psram_type=qspi m5stack_unit_cams3.menu.PSRAM.disabled=Disabled m5stack_unit_cams3.menu.PSRAM.disabled.build.defines= m5stack_unit_cams3.menu.PSRAM.disabled.build.psram_type=qspi +m5stack_unit_cams3.menu.PSRAM.opi=OPI PSRAM +m5stack_unit_cams3.menu.PSRAM.opi.build.defines=-DBOARD_HAS_PSRAM +m5stack_unit_cams3.menu.PSRAM.opi.build.psram_type=opi m5stack_unit_cams3.menu.FlashMode.qio=QIO 80MHz m5stack_unit_cams3.menu.FlashMode.qio.build.flash_mode=dio @@ -19647,7 +22531,6 @@ m5stack_unit_cams3.menu.FlashSize.16M=16MB (128Mb) m5stack_unit_cams3.menu.FlashSize.16M.build.flash_size=16MB m5stack_unit_cams3.menu.FlashSize.32M=32MB (256Mb) m5stack_unit_cams3.menu.FlashSize.32M.build.flash_size=32MB -m5stack_unit_cams3.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_unit_cams3.menu.LoopCore.1=Core 1 m5stack_unit_cams3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -19719,9 +22602,15 @@ m5stack_unit_cams3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 m5stack_unit_cams3.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) m5stack_unit_cams3.menu.PartitionScheme.fatflash.build.partitions=ffat m5stack_unit_cams3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -m5stack_unit_cams3.menu.PartitionScheme.rainmaker=RainMaker +m5stack_unit_cams3.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_unit_cams3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_unit_cams3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_unit_cams3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_unit_cams3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_unit_cams3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_unit_cams3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_unit_cams3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_unit_cams3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_unit_cams3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_unit_cams3.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) m5stack_unit_cams3.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB m5stack_unit_cams3.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 @@ -19782,7 +22671,6 @@ m5stack_unit_cams3.menu.EraseFlash.none.upload.erase_cmd= m5stack_unit_cams3.menu.EraseFlash.all=Enabled m5stack_unit_cams3.menu.EraseFlash.all.upload.erase_cmd=-e - ############################################################## m5stack_poe_cam.name=M5PoECAM @@ -19933,7 +22821,6 @@ m5stack_poe_cam.menu.EraseFlash.none.upload.erase_cmd= m5stack_poe_cam.menu.EraseFlash.all=Enabled m5stack_poe_cam.menu.EraseFlash.all.upload.erase_cmd=-e - ############################################################## m5stack_paper.name=M5Paper @@ -20012,9 +22899,15 @@ m5stack_paper.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_paper.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) m5stack_paper.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB m5stack_paper.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -m5stack_paper.menu.PartitionScheme.rainmaker=RainMaker +m5stack_paper.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_paper.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_paper.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_paper.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_paper.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_paper.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_paper.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_paper.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_paper.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_paper.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_paper.menu.PartitionScheme.custom=Custom m5stack_paper.menu.PartitionScheme.custom.build.partitions= m5stack_paper.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -20102,7 +22995,6 @@ m5stack_paper.menu.EraseFlash.none.upload.erase_cmd= m5stack_paper.menu.EraseFlash.all=Enabled m5stack_paper.menu.EraseFlash.all.upload.erase_cmd=-e - ############################################################## m5stack_coreink.name=M5CoreInk @@ -20170,9 +23062,12 @@ m5stack_coreink.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 m5stack_coreink.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) m5stack_coreink.menu.PartitionScheme.fatflash.build.partitions=ffat m5stack_coreink.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -m5stack_coreink.menu.PartitionScheme.rainmaker=RainMaker +m5stack_coreink.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_coreink.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_coreink.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_coreink.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_coreink.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_coreink.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_coreink.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 m5stack_coreink.menu.PartitionScheme.custom=Custom m5stack_coreink.menu.PartitionScheme.custom.build.partitions= m5stack_coreink.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -20254,7 +23149,6 @@ m5stack_coreink.menu.EraseFlash.none.upload.erase_cmd= m5stack_coreink.menu.EraseFlash.all=Enabled m5stack_coreink.menu.EraseFlash.all.upload.erase_cmd=-e - ############################################################### m5stack_stamp_pico.name=M5StampPico @@ -20322,9 +23216,12 @@ m5stack_stamp_pico.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 m5stack_stamp_pico.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) m5stack_stamp_pico.menu.PartitionScheme.fatflash.build.partitions=ffat m5stack_stamp_pico.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -m5stack_stamp_pico.menu.PartitionScheme.rainmaker=RainMaker +m5stack_stamp_pico.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_stamp_pico.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_stamp_pico.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_stamp_pico.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_stamp_pico.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_stamp_pico.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_stamp_pico.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 m5stack_stamp_pico.menu.PartitionScheme.custom=Custom m5stack_stamp_pico.menu.PartitionScheme.custom.build.partitions= m5stack_stamp_pico.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -20406,7 +23303,6 @@ m5stack_stamp_pico.menu.EraseFlash.none.upload.erase_cmd= m5stack_stamp_pico.menu.EraseFlash.all=Enabled m5stack_stamp_pico.menu.EraseFlash.all.upload.erase_cmd=-e - ############################################################## m5stack_stamp_c3.name=M5StampC3 @@ -20591,7 +23487,7 @@ m5stack_stamp_s3.build.flash_freq=80m m5stack_stamp_s3.build.flash_mode=dio m5stack_stamp_s3.build.boot=qio m5stack_stamp_s3.build.boot_freq=80m -m5stack_stamp_s3.build.partitions=default +m5stack_stamp_s3.build.partitions=default_8MB m5stack_stamp_s3.build.defines= m5stack_stamp_s3.build.loop_core= m5stack_stamp_s3.build.event_core= @@ -20646,12 +23542,10 @@ m5stack_stamp_s3.menu.FlashSize.4M=4MB (32Mb) m5stack_stamp_s3.menu.FlashSize.4M.build.flash_size=4MB m5stack_stamp_s3.menu.FlashSize.8M=8MB (64Mb) m5stack_stamp_s3.menu.FlashSize.8M.build.flash_size=8MB -m5stack_stamp_s3.menu.FlashSize.8M.build.partitions=default_8MB m5stack_stamp_s3.menu.FlashSize.16M=16MB (128Mb) m5stack_stamp_s3.menu.FlashSize.16M.build.flash_size=16MB m5stack_stamp_s3.menu.FlashSize.32M=32MB (256Mb) m5stack_stamp_s3.menu.FlashSize.32M.build.flash_size=32MB -m5stack_stamp_s3.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_stamp_s3.menu.LoopCore.1=Core 1 m5stack_stamp_s3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -20723,9 +23617,15 @@ m5stack_stamp_s3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_stamp_s3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) m5stack_stamp_s3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB m5stack_stamp_s3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -m5stack_stamp_s3.menu.PartitionScheme.rainmaker=RainMaker +m5stack_stamp_s3.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_stamp_s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_stamp_s3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_stamp_s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_stamp_s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_stamp_s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_stamp_s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_stamp_s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_stamp_s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_stamp_s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_stamp_s3.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) m5stack_stamp_s3.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB m5stack_stamp_s3.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 @@ -20786,7 +23686,6 @@ m5stack_stamp_s3.menu.EraseFlash.none.upload.erase_cmd= m5stack_stamp_s3.menu.EraseFlash.all=Enabled m5stack_stamp_s3.menu.EraseFlash.all.upload.erase_cmd=-e - ############################################################## m5stack_capsule.name=M5Capsule @@ -20880,12 +23779,10 @@ m5stack_capsule.menu.FlashSize.4M=4MB (32Mb) m5stack_capsule.menu.FlashSize.4M.build.flash_size=4MB m5stack_capsule.menu.FlashSize.8M=8MB (64Mb) m5stack_capsule.menu.FlashSize.8M.build.flash_size=8MB -m5stack_capsule.menu.FlashSize.8M.build.partitions=default_8MB m5stack_capsule.menu.FlashSize.16M=16MB (128Mb) m5stack_capsule.menu.FlashSize.16M.build.flash_size=16MB m5stack_capsule.menu.FlashSize.32M=32MB (256Mb) m5stack_capsule.menu.FlashSize.32M.build.flash_size=32MB -m5stack_capsule.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_capsule.menu.LoopCore.1=Core 1 m5stack_capsule.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -20957,9 +23854,15 @@ m5stack_capsule.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_capsule.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) m5stack_capsule.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB m5stack_capsule.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -m5stack_capsule.menu.PartitionScheme.rainmaker=RainMaker +m5stack_capsule.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_capsule.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_capsule.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_capsule.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_capsule.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_capsule.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_capsule.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_capsule.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_capsule.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_capsule.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_capsule.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) m5stack_capsule.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB m5stack_capsule.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 @@ -21116,12 +24019,10 @@ m5stack_cardputer.menu.FlashSize.4M=4MB (32Mb) m5stack_cardputer.menu.FlashSize.4M.build.flash_size=4MB m5stack_cardputer.menu.FlashSize.8M=8MB (64Mb) m5stack_cardputer.menu.FlashSize.8M.build.flash_size=8MB -m5stack_cardputer.menu.FlashSize.8M.build.partitions=default_8MB m5stack_cardputer.menu.FlashSize.16M=16MB (128Mb) m5stack_cardputer.menu.FlashSize.16M.build.flash_size=16MB m5stack_cardputer.menu.FlashSize.32M=32MB (256Mb) m5stack_cardputer.menu.FlashSize.32M.build.flash_size=32MB -m5stack_cardputer.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_cardputer.menu.LoopCore.1=Core 1 m5stack_cardputer.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -21193,9 +24094,15 @@ m5stack_cardputer.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_cardputer.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) m5stack_cardputer.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB m5stack_cardputer.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -m5stack_cardputer.menu.PartitionScheme.rainmaker=RainMaker +m5stack_cardputer.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_cardputer.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_cardputer.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_cardputer.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_cardputer.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_cardputer.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_cardputer.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_cardputer.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_cardputer.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_cardputer.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_cardputer.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) m5stack_cardputer.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB m5stack_cardputer.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 @@ -21294,7 +24201,7 @@ m5stack_dial.build.flash_freq=80m m5stack_dial.build.flash_mode=dio m5stack_dial.build.boot=qio m5stack_dial.build.boot_freq=80m -m5stack_dial.build.partitions=default +m5stack_dial.build.partitions=default_8MB m5stack_dial.build.defines= m5stack_dial.build.loop_core= m5stack_dial.build.event_core= @@ -21349,12 +24256,10 @@ m5stack_dial.menu.FlashSize.4M=4MB (32Mb) m5stack_dial.menu.FlashSize.4M.build.flash_size=4MB m5stack_dial.menu.FlashSize.8M=8MB (64Mb) m5stack_dial.menu.FlashSize.8M.build.flash_size=8MB -m5stack_dial.menu.FlashSize.8M.build.partitions=default_8MB m5stack_dial.menu.FlashSize.16M=16MB (128Mb) m5stack_dial.menu.FlashSize.16M.build.flash_size=16MB m5stack_dial.menu.FlashSize.32M=32MB (256Mb) m5stack_dial.menu.FlashSize.32M.build.flash_size=32MB -m5stack_dial.menu.FlashSize.32M.build.partitions=app5M_fat24M_32MB m5stack_dial.menu.LoopCore.1=Core 1 m5stack_dial.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -21426,9 +24331,15 @@ m5stack_dial.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_dial.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) m5stack_dial.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB m5stack_dial.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -m5stack_dial.menu.PartitionScheme.rainmaker=RainMaker +m5stack_dial.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_dial.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -m5stack_dial.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +m5stack_dial.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_dial.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_dial.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_dial.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_dial.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_dial.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_dial.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 m5stack_dial.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) m5stack_dial.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB m5stack_dial.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 @@ -21491,6 +24402,394 @@ m5stack_dial.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +m5stack_dinmeter.name=M5DinMeter +m5stack_dinmeter.bootloader.tool=esptool_py +m5stack_dinmeter.bootloader.tool.default=esptool_py + +m5stack_dinmeter.upload.tool=esptool_py +m5stack_dinmeter.upload.tool.default=esptool_py +m5stack_dinmeter.upload.tool.network=esp_ota + +m5stack_dinmeter.upload.maximum_size=1310720 +m5stack_dinmeter.upload.maximum_data_size=327680 +m5stack_dinmeter.upload.flags= +m5stack_dinmeter.upload.extra_flags= +m5stack_dinmeter.upload.use_1200bps_touch=false +m5stack_dinmeter.upload.wait_for_upload_port=false + +m5stack_dinmeter.serial.disableDTR=false +m5stack_dinmeter.serial.disableRTS=false + +m5stack_dinmeter.build.tarch=xtensa +m5stack_dinmeter.build.bootloader_addr=0x0 +m5stack_dinmeter.build.target=esp32s3 +m5stack_dinmeter.build.mcu=esp32s3 +m5stack_dinmeter.build.core=esp32 +m5stack_dinmeter.build.variant=m5stack_dinmeter +m5stack_dinmeter.build.board=M5STACK_DINMETER + +m5stack_dinmeter.build.usb_mode=1 +m5stack_dinmeter.build.cdc_on_boot=1 +m5stack_dinmeter.build.msc_on_boot=0 +m5stack_dinmeter.build.dfu_on_boot=0 +m5stack_dinmeter.build.f_cpu=240000000L +m5stack_dinmeter.build.flash_size=8MB +m5stack_dinmeter.build.flash_freq=80m +m5stack_dinmeter.build.flash_mode=dio +m5stack_dinmeter.build.boot=qio +m5stack_dinmeter.build.boot_freq=80m +m5stack_dinmeter.build.partitions=default +m5stack_dinmeter.build.defines= +m5stack_dinmeter.build.loop_core= +m5stack_dinmeter.build.event_core= +m5stack_dinmeter.build.psram_type=qspi +m5stack_dinmeter.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +m5stack_dinmeter.menu.JTAGAdapter.default=Disabled +m5stack_dinmeter.menu.JTAGAdapter.default.build.copy_jtag_files=0 +m5stack_dinmeter.menu.JTAGAdapter.builtin=Integrated USB JTAG +m5stack_dinmeter.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +m5stack_dinmeter.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +m5stack_dinmeter.menu.JTAGAdapter.external=FTDI Adapter +m5stack_dinmeter.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +m5stack_dinmeter.menu.JTAGAdapter.external.build.copy_jtag_files=1 +m5stack_dinmeter.menu.JTAGAdapter.bridge=ESP USB Bridge +m5stack_dinmeter.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +m5stack_dinmeter.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +m5stack_dinmeter.menu.PSRAM.disabled=Disabled +m5stack_dinmeter.menu.PSRAM.disabled.build.defines= +m5stack_dinmeter.menu.PSRAM.disabled.build.psram_type=qspi +m5stack_dinmeter.menu.PSRAM.enabled=QSPI PSRAM +m5stack_dinmeter.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +m5stack_dinmeter.menu.PSRAM.enabled.build.psram_type=qspi +m5stack_dinmeter.menu.PSRAM.opi=OPI PSRAM +m5stack_dinmeter.menu.PSRAM.opi.build.defines=-DBOARD_HAS_PSRAM +m5stack_dinmeter.menu.PSRAM.opi.build.psram_type=opi + +m5stack_dinmeter.menu.FlashMode.qio=QIO 80MHz +m5stack_dinmeter.menu.FlashMode.qio.build.flash_mode=dio +m5stack_dinmeter.menu.FlashMode.qio.build.boot=qio +m5stack_dinmeter.menu.FlashMode.qio.build.boot_freq=80m +m5stack_dinmeter.menu.FlashMode.qio.build.flash_freq=80m +m5stack_dinmeter.menu.FlashMode.qio120=QIO 120MHz +m5stack_dinmeter.menu.FlashMode.qio120.build.flash_mode=dio +m5stack_dinmeter.menu.FlashMode.qio120.build.boot=qio +m5stack_dinmeter.menu.FlashMode.qio120.build.boot_freq=120m +m5stack_dinmeter.menu.FlashMode.qio120.build.flash_freq=80m +m5stack_dinmeter.menu.FlashMode.dio=DIO 80MHz +m5stack_dinmeter.menu.FlashMode.dio.build.flash_mode=dio +m5stack_dinmeter.menu.FlashMode.dio.build.boot=dio +m5stack_dinmeter.menu.FlashMode.dio.build.boot_freq=80m +m5stack_dinmeter.menu.FlashMode.dio.build.flash_freq=80m +m5stack_dinmeter.menu.FlashMode.opi=OPI 80MHz +m5stack_dinmeter.menu.FlashMode.opi.build.flash_mode=dout +m5stack_dinmeter.menu.FlashMode.opi.build.boot=opi +m5stack_dinmeter.menu.FlashMode.opi.build.boot_freq=80m +m5stack_dinmeter.menu.FlashMode.opi.build.flash_freq=80m + +m5stack_dinmeter.menu.FlashSize.4M=4MB (32Mb) +m5stack_dinmeter.menu.FlashSize.4M.build.flash_size=4MB +m5stack_dinmeter.menu.FlashSize.8M=8MB (64Mb) +m5stack_dinmeter.menu.FlashSize.8M.build.flash_size=8MB +m5stack_dinmeter.menu.FlashSize.16M=16MB (128Mb) +m5stack_dinmeter.menu.FlashSize.16M.build.flash_size=16MB +m5stack_dinmeter.menu.FlashSize.32M=32MB (256Mb) +m5stack_dinmeter.menu.FlashSize.32M.build.flash_size=32MB + +m5stack_dinmeter.menu.LoopCore.1=Core 1 +m5stack_dinmeter.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +m5stack_dinmeter.menu.LoopCore.0=Core 0 +m5stack_dinmeter.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +m5stack_dinmeter.menu.EventsCore.1=Core 1 +m5stack_dinmeter.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +m5stack_dinmeter.menu.EventsCore.0=Core 0 +m5stack_dinmeter.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +m5stack_dinmeter.menu.USBMode.hwcdc=Hardware CDC and JTAG +m5stack_dinmeter.menu.USBMode.hwcdc.build.usb_mode=1 +m5stack_dinmeter.menu.USBMode.default=USB-OTG (TinyUSB) +m5stack_dinmeter.menu.USBMode.default.build.usb_mode=0 + +m5stack_dinmeter.menu.CDCOnBoot.cdc=Enabled +m5stack_dinmeter.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 +m5stack_dinmeter.menu.CDCOnBoot.default=Disabled +m5stack_dinmeter.menu.CDCOnBoot.default.build.cdc_on_boot=0 + +m5stack_dinmeter.menu.MSCOnBoot.default=Disabled +m5stack_dinmeter.menu.MSCOnBoot.default.build.msc_on_boot=0 +m5stack_dinmeter.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +m5stack_dinmeter.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +m5stack_dinmeter.menu.DFUOnBoot.default=Disabled +m5stack_dinmeter.menu.DFUOnBoot.default.build.dfu_on_boot=0 +m5stack_dinmeter.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +m5stack_dinmeter.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +m5stack_dinmeter.menu.UploadMode.default=UART0 / Hardware CDC +m5stack_dinmeter.menu.UploadMode.default.upload.use_1200bps_touch=false +m5stack_dinmeter.menu.UploadMode.default.upload.wait_for_upload_port=false +m5stack_dinmeter.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +m5stack_dinmeter.menu.UploadMode.cdc.upload.use_1200bps_touch=true +m5stack_dinmeter.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +m5stack_dinmeter.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +m5stack_dinmeter.menu.PartitionScheme.default.build.partitions=default +m5stack_dinmeter.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +m5stack_dinmeter.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +m5stack_dinmeter.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +m5stack_dinmeter.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +m5stack_dinmeter.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +m5stack_dinmeter.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +m5stack_dinmeter.menu.PartitionScheme.minimal.build.partitions=minimal +m5stack_dinmeter.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +m5stack_dinmeter.menu.PartitionScheme.no_ota.build.partitions=no_ota +m5stack_dinmeter.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +m5stack_dinmeter.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +m5stack_dinmeter.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +m5stack_dinmeter.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +m5stack_dinmeter.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +m5stack_dinmeter.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +m5stack_dinmeter.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +m5stack_dinmeter.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +m5stack_dinmeter.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +m5stack_dinmeter.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +m5stack_dinmeter.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +m5stack_dinmeter.menu.PartitionScheme.huge_app.build.partitions=huge_app +m5stack_dinmeter.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +m5stack_dinmeter.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +m5stack_dinmeter.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +m5stack_dinmeter.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +m5stack_dinmeter.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +m5stack_dinmeter.menu.PartitionScheme.fatflash.build.partitions=ffat +m5stack_dinmeter.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +m5stack_dinmeter.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +m5stack_dinmeter.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +m5stack_dinmeter.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +m5stack_dinmeter.menu.PartitionScheme.rainmaker=RainMaker 4MB +m5stack_dinmeter.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +m5stack_dinmeter.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +m5stack_dinmeter.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +m5stack_dinmeter.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +m5stack_dinmeter.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +m5stack_dinmeter.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +m5stack_dinmeter.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +m5stack_dinmeter.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +m5stack_dinmeter.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) +m5stack_dinmeter.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB +m5stack_dinmeter.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 +m5stack_dinmeter.menu.PartitionScheme.app5M_little24M_32MB=32M Flash (4.8MB APP/22MB LittleFS) +m5stack_dinmeter.menu.PartitionScheme.app5M_little24M_32MB.build.partitions=large_littlefs_32MB +m5stack_dinmeter.menu.PartitionScheme.app5M_little24M_32MB.upload.maximum_size=4718592 +m5stack_dinmeter.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +m5stack_dinmeter.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +m5stack_dinmeter.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +m5stack_dinmeter.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +m5stack_dinmeter.menu.PartitionScheme.custom=Custom +m5stack_dinmeter.menu.PartitionScheme.custom.build.partitions= +m5stack_dinmeter.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +m5stack_dinmeter.menu.CPUFreq.240=240MHz (WiFi) +m5stack_dinmeter.menu.CPUFreq.240.build.f_cpu=240000000L +m5stack_dinmeter.menu.CPUFreq.160=160MHz (WiFi) +m5stack_dinmeter.menu.CPUFreq.160.build.f_cpu=160000000L +m5stack_dinmeter.menu.CPUFreq.80=80MHz (WiFi) +m5stack_dinmeter.menu.CPUFreq.80.build.f_cpu=80000000L +m5stack_dinmeter.menu.CPUFreq.40=40MHz +m5stack_dinmeter.menu.CPUFreq.40.build.f_cpu=40000000L +m5stack_dinmeter.menu.CPUFreq.20=20MHz +m5stack_dinmeter.menu.CPUFreq.20.build.f_cpu=20000000L +m5stack_dinmeter.menu.CPUFreq.10=10MHz +m5stack_dinmeter.menu.CPUFreq.10.build.f_cpu=10000000L + +m5stack_dinmeter.menu.UploadSpeed.921600=921600 +m5stack_dinmeter.menu.UploadSpeed.921600.upload.speed=921600 +m5stack_dinmeter.menu.UploadSpeed.115200=115200 +m5stack_dinmeter.menu.UploadSpeed.115200.upload.speed=115200 +m5stack_dinmeter.menu.UploadSpeed.256000.windows=256000 +m5stack_dinmeter.menu.UploadSpeed.256000.upload.speed=256000 +m5stack_dinmeter.menu.UploadSpeed.230400.windows.upload.speed=256000 +m5stack_dinmeter.menu.UploadSpeed.230400=230400 +m5stack_dinmeter.menu.UploadSpeed.230400.upload.speed=230400 +m5stack_dinmeter.menu.UploadSpeed.460800.linux=460800 +m5stack_dinmeter.menu.UploadSpeed.460800.macosx=460800 +m5stack_dinmeter.menu.UploadSpeed.460800.upload.speed=460800 +m5stack_dinmeter.menu.UploadSpeed.512000.windows=512000 +m5stack_dinmeter.menu.UploadSpeed.512000.upload.speed=512000 + +m5stack_dinmeter.menu.DebugLevel.none=None +m5stack_dinmeter.menu.DebugLevel.none.build.code_debug=0 +m5stack_dinmeter.menu.DebugLevel.error=Error +m5stack_dinmeter.menu.DebugLevel.error.build.code_debug=1 +m5stack_dinmeter.menu.DebugLevel.warn=Warn +m5stack_dinmeter.menu.DebugLevel.warn.build.code_debug=2 +m5stack_dinmeter.menu.DebugLevel.info=Info +m5stack_dinmeter.menu.DebugLevel.info.build.code_debug=3 +m5stack_dinmeter.menu.DebugLevel.debug=Debug +m5stack_dinmeter.menu.DebugLevel.debug.build.code_debug=4 +m5stack_dinmeter.menu.DebugLevel.verbose=Verbose +m5stack_dinmeter.menu.DebugLevel.verbose.build.code_debug=5 + +m5stack_dinmeter.menu.EraseFlash.none=Disabled +m5stack_dinmeter.menu.EraseFlash.none.upload.erase_cmd= +m5stack_dinmeter.menu.EraseFlash.all=Enabled +m5stack_dinmeter.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +m5stack_nanoc6.name=M5NanoC6 + +m5stack_nanoc6.bootloader.tool=esptool_py +m5stack_nanoc6.bootloader.tool.default=esptool_py + +m5stack_nanoc6.upload.tool=esptool_py +m5stack_nanoc6.upload.tool.default=esptool_py +m5stack_nanoc6.upload.tool.network=esp_ota + +m5stack_nanoc6.upload.maximum_size=1310720 +m5stack_nanoc6.upload.maximum_data_size=327680 +m5stack_nanoc6.upload.flags= +m5stack_nanoc6.upload.extra_flags= +m5stack_nanoc6.upload.use_1200bps_touch=false +m5stack_nanoc6.upload.wait_for_upload_port=false + +m5stack_nanoc6.serial.disableDTR=false +m5stack_nanoc6.serial.disableRTS=false + +m5stack_nanoc6.build.tarch=riscv32 +m5stack_nanoc6.build.target=esp +m5stack_nanoc6.build.mcu=esp32c6 +m5stack_nanoc6.build.core=esp32 +m5stack_nanoc6.build.variant=m5stack_nanoc6 +m5stack_nanoc6.build.board=M5STACK_NANOC6 +m5stack_nanoc6.build.bootloader_addr=0x0 + +m5stack_nanoc6.build.cdc_on_boot=1 +m5stack_nanoc6.build.f_cpu=160000000L +m5stack_nanoc6.build.flash_size=4MB +m5stack_nanoc6.build.flash_freq=80m +m5stack_nanoc6.build.flash_mode=qio +m5stack_nanoc6.build.boot=qio +m5stack_nanoc6.build.partitions=default +m5stack_nanoc6.build.defines= + +## IDE 2.0 Seems to not update the value +m5stack_nanoc6.menu.JTAGAdapter.default=Disabled +m5stack_nanoc6.menu.JTAGAdapter.default.build.copy_jtag_files=0 +m5stack_nanoc6.menu.JTAGAdapter.builtin=Integrated USB JTAG +m5stack_nanoc6.menu.JTAGAdapter.builtin.build.openocdscript=esp32c6-builtin.cfg +m5stack_nanoc6.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +m5stack_nanoc6.menu.JTAGAdapter.external=FTDI Adapter +m5stack_nanoc6.menu.JTAGAdapter.external.build.openocdscript=esp32c6-ftdi.cfg +m5stack_nanoc6.menu.JTAGAdapter.external.build.copy_jtag_files=1 +m5stack_nanoc6.menu.JTAGAdapter.bridge=ESP USB Bridge +m5stack_nanoc6.menu.JTAGAdapter.bridge.build.openocdscript=esp32c6-bridge.cfg +m5stack_nanoc6.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +m5stack_nanoc6.menu.CDCOnBoot.cdc=Enabled +m5stack_nanoc6.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 +m5stack_nanoc6.menu.CDCOnBoot.default=Enabled +m5stack_nanoc6.menu.CDCOnBoot.default.build.cdc_on_boot=1 + +m5stack_nanoc6.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +m5stack_nanoc6.menu.PartitionScheme.default.build.partitions=default +m5stack_nanoc6.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +m5stack_nanoc6.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +m5stack_nanoc6.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +m5stack_nanoc6.menu.PartitionScheme.no_ota.build.partitions=no_ota +m5stack_nanoc6.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +m5stack_nanoc6.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +m5stack_nanoc6.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +m5stack_nanoc6.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +m5stack_nanoc6.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +m5stack_nanoc6.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +m5stack_nanoc6.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +m5stack_nanoc6.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +m5stack_nanoc6.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +m5stack_nanoc6.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +m5stack_nanoc6.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +m5stack_nanoc6.menu.PartitionScheme.huge_app.build.partitions=huge_app +m5stack_nanoc6.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +m5stack_nanoc6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs +m5stack_nanoc6.menu.PartitionScheme.zigbee.build.partitions=zigbee +m5stack_nanoc6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 +m5stack_nanoc6.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +m5stack_nanoc6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +m5stack_nanoc6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 + +m5stack_nanoc6.menu.CPUFreq.160=160MHz (WiFi) +m5stack_nanoc6.menu.CPUFreq.160.build.f_cpu=160000000L +m5stack_nanoc6.menu.CPUFreq.80=80MHz (WiFi) +m5stack_nanoc6.menu.CPUFreq.80.build.f_cpu=80000000L +m5stack_nanoc6.menu.CPUFreq.40=40MHz +m5stack_nanoc6.menu.CPUFreq.40.build.f_cpu=40000000L +m5stack_nanoc6.menu.CPUFreq.20=20MHz +m5stack_nanoc6.menu.CPUFreq.20.build.f_cpu=20000000L +m5stack_nanoc6.menu.CPUFreq.10=10MHz +m5stack_nanoc6.menu.CPUFreq.10.build.f_cpu=10000000L + +m5stack_nanoc6.menu.FlashMode.qio=QIO +m5stack_nanoc6.menu.FlashMode.qio.build.flash_mode=dio +m5stack_nanoc6.menu.FlashMode.qio.build.boot=qio +m5stack_nanoc6.menu.FlashMode.dio=DIO +m5stack_nanoc6.menu.FlashMode.dio.build.flash_mode=dio +m5stack_nanoc6.menu.FlashMode.dio.build.boot=dio + +m5stack_nanoc6.menu.FlashFreq.80=80MHz +m5stack_nanoc6.menu.FlashFreq.80.build.flash_freq=80m +m5stack_nanoc6.menu.FlashFreq.40=40MHz +m5stack_nanoc6.menu.FlashFreq.40.build.flash_freq=40m + +m5stack_nanoc6.menu.FlashSize.4M=4MB (32Mb) +m5stack_nanoc6.menu.FlashSize.4M.build.flash_size=4MB + +m5stack_nanoc6.menu.UploadSpeed.921600=921600 +m5stack_nanoc6.menu.UploadSpeed.921600.upload.speed=921600 +m5stack_nanoc6.menu.UploadSpeed.115200=115200 +m5stack_nanoc6.menu.UploadSpeed.115200.upload.speed=115200 +m5stack_nanoc6.menu.UploadSpeed.256000.windows=256000 +m5stack_nanoc6.menu.UploadSpeed.256000.upload.speed=256000 +m5stack_nanoc6.menu.UploadSpeed.230400.windows.upload.speed=256000 +m5stack_nanoc6.menu.UploadSpeed.230400=230400 +m5stack_nanoc6.menu.UploadSpeed.230400.upload.speed=230400 +m5stack_nanoc6.menu.UploadSpeed.460800.linux=460800 +m5stack_nanoc6.menu.UploadSpeed.460800.macosx=460800 +m5stack_nanoc6.menu.UploadSpeed.460800.upload.speed=460800 +m5stack_nanoc6.menu.UploadSpeed.512000.windows=512000 +m5stack_nanoc6.menu.UploadSpeed.512000.upload.speed=512000 + +m5stack_nanoc6.menu.DebugLevel.none=None +m5stack_nanoc6.menu.DebugLevel.none.build.code_debug=0 +m5stack_nanoc6.menu.DebugLevel.error=Error +m5stack_nanoc6.menu.DebugLevel.error.build.code_debug=1 +m5stack_nanoc6.menu.DebugLevel.warn=Warn +m5stack_nanoc6.menu.DebugLevel.warn.build.code_debug=2 +m5stack_nanoc6.menu.DebugLevel.info=Info +m5stack_nanoc6.menu.DebugLevel.info.build.code_debug=3 +m5stack_nanoc6.menu.DebugLevel.debug=Debug +m5stack_nanoc6.menu.DebugLevel.debug.build.code_debug=4 +m5stack_nanoc6.menu.DebugLevel.verbose=Verbose +m5stack_nanoc6.menu.DebugLevel.verbose.build.code_debug=5 + +m5stack_nanoc6.menu.EraseFlash.none=Disabled +m5stack_nanoc6.menu.EraseFlash.none.upload.erase_cmd= +m5stack_nanoc6.menu.EraseFlash.all=Enabled +m5stack_nanoc6.menu.EraseFlash.all.upload.erase_cmd=-e + +m5stack_nanoc6.menu.ZigbeeMode.default=Disabled +m5stack_nanoc6.menu.ZigbeeMode.default.build.zigbee_mode= +m5stack_nanoc6.menu.ZigbeeMode.default.build.zigbee_libs= +m5stack_nanoc6.menu.ZigbeeMode.ed=Zigbee ED (end device) +m5stack_nanoc6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED +m5stack_nanoc6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +m5stack_nanoc6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +m5stack_nanoc6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +m5stack_nanoc6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native + +############################################################## + odroid_esp32.name=ODROID ESP32 odroid_esp32.bootloader.tool=esptool_py @@ -21615,12 +24914,25 @@ heltec_wifi_kit_32.build.defines= heltec_wifi_kit_32.build.band=LoRaWAN_NONE heltec_wifi_kit_32.build.LoRaWanDebugLevel=0 -heltec_wifi_kit_32.menu.PSRAM.disabled=Disabled -heltec_wifi_kit_32.menu.PSRAM.disabled.build.defines= -heltec_wifi_kit_32.menu.PSRAM.disabled.build.extra_libs= -heltec_wifi_kit_32.menu.PSRAM.enabled=Enabled -heltec_wifi_kit_32.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw -heltec_wifi_kit_32.menu.PSRAM.enabled.build.extra_libs= +heltec_wifi_kit_32.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +heltec_wifi_kit_32.menu.PartitionScheme.default.build.partitions=default +heltec_wifi_kit_32.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +heltec_wifi_kit_32.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +heltec_wifi_kit_32.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +heltec_wifi_kit_32.menu.PartitionScheme.no_ota.build.partitions=no_ota +heltec_wifi_kit_32.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +heltec_wifi_kit_32.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +heltec_wifi_kit_32.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +heltec_wifi_kit_32.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +heltec_wifi_kit_32.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +heltec_wifi_kit_32.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +heltec_wifi_kit_32.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +heltec_wifi_kit_32.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +heltec_wifi_kit_32.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +heltec_wifi_kit_32.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +heltec_wifi_kit_32.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +heltec_wifi_kit_32.menu.PartitionScheme.huge_app.build.partitions=huge_app +heltec_wifi_kit_32.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 heltec_wifi_kit_32.menu.CPUFreq.240=240MHz (WiFi/BT) heltec_wifi_kit_32.menu.CPUFreq.240.build.f_cpu=240000000L @@ -21791,14 +25103,34 @@ heltec_wifi_lora_32.build.variant=heltec_wifi_lora_32 heltec_wifi_lora_32.build.board=HELTEC_WIFI_LORA_32 heltec_wifi_lora_32.build.f_cpu=240000000L -heltec_wifi_lora_32.build.flash_size=8MB +heltec_wifi_lora_32.build.flash_size=4MB heltec_wifi_lora_32.build.flash_freq=80m heltec_wifi_lora_32.build.flash_mode=dio heltec_wifi_lora_32.build.boot=qio -heltec_wifi_lora_32.build.partitions=default_8MB +heltec_wifi_lora_32.build.partitions=default heltec_wifi_lora_32.build.psram= heltec_wifi_lora_32.build.defines=-D{build.band} -DMCU_ESP32_D0 -DWIFI_LORA_32 -DHELTEC_BOARD=1 -DRADIO_CHIP_SX127X -DSLOW_CLK_TPYE=0 -DLoRaWAN_DEBUG_LEVEL={build.LoRaWanDebugLevel} -DACTIVE_REGION=LORAMAC_{build.band} -DLORAWAN_PREAMBLE_LENGTH={build.LORAWAN_PREAMBLE_LENGTH} -DLORAWAN_DEVEUI_AUTO={build.LORAWAN_DEVEUI_AUTO} {build.psram} +heltec_wifi_lora_32.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +heltec_wifi_lora_32.menu.PartitionScheme.default.build.partitions=default +heltec_wifi_lora_32.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +heltec_wifi_lora_32.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +heltec_wifi_lora_32.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +heltec_wifi_lora_32.menu.PartitionScheme.no_ota.build.partitions=no_ota +heltec_wifi_lora_32.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +heltec_wifi_lora_32.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +heltec_wifi_lora_32.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +heltec_wifi_lora_32.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +heltec_wifi_lora_32.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +heltec_wifi_lora_32.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +heltec_wifi_lora_32.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +heltec_wifi_lora_32.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +heltec_wifi_lora_32.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +heltec_wifi_lora_32.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +heltec_wifi_lora_32.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +heltec_wifi_lora_32.menu.PartitionScheme.huge_app.build.partitions=huge_app +heltec_wifi_lora_32.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 + heltec_wifi_lora_32.menu.CPUFreq.240=240MHz (WiFi/BT) heltec_wifi_lora_32.menu.CPUFreq.240.build.f_cpu=240000000L heltec_wifi_lora_32.menu.CPUFreq.160=160MHz (WiFi/BT) @@ -23665,6 +26997,531 @@ heltec_ht_de01.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +heltec_vision_master_e290.name=Heltec Vision Master E290 + +heltec_vision_master_e290.bootloader.tool=esptool_py +heltec_vision_master_e290.bootloader.tool.default=esptool_py + +heltec_vision_master_e290.upload.tool=esptool_py +heltec_vision_master_e290.upload.tool.default=esptool_py +heltec_vision_master_e290.upload.tool.network=esp_ota + +heltec_vision_master_e290.upload.maximum_size=3342336 +heltec_vision_master_e290.upload.maximum_data_size=327680 +heltec_vision_master_e290.upload.flags= +heltec_vision_master_e290.upload.extra_flags= +heltec_vision_master_e290.upload.use_1200bps_touch=false +heltec_vision_master_e290.upload.wait_for_upload_port=false + +heltec_vision_master_e290.serial.disableDTR=false +heltec_vision_master_e290.serial.disableRTS=false + +heltec_vision_master_e290.build.tarch=xtensa +heltec_vision_master_e290.build.bootloader_addr=0x0 +heltec_vision_master_e290.build.target=esp32s3 +heltec_vision_master_e290.build.mcu=esp32s3 +heltec_vision_master_e290.build.core=esp32 +heltec_vision_master_e290.build.variant=heltec_vision_master_e290 +heltec_vision_master_e290.build.board=HELTEC_VISION_MASTER_E290 + +heltec_vision_master_e290.build.usb_mode=1 +heltec_vision_master_e290.build.cdc_on_boot=0 +heltec_vision_master_e290.build.msc_on_boot=0 +heltec_vision_master_e290.build.dfu_on_boot=0 +heltec_vision_master_e290.build.f_cpu=240000000L +heltec_vision_master_e290.build.flash_size=8MB +heltec_vision_master_e290.build.flash_freq=80m +heltec_vision_master_e290.build.flash_mode=dio +heltec_vision_master_e290.build.boot=qio +heltec_vision_master_e290.build.boot_freq=80m +heltec_vision_master_e290.build.partitions=default_8MB +heltec_vision_master_e290.build.loop_core= +heltec_vision_master_e290.build.event_core= +heltec_vision_master_e290.build.psram_type=qspi +heltec_vision_master_e290.build.memory_type={build.boot}_{build.psram_type} + +heltec_vision_master_e290.menu.LoopCore.1=Core 1 +heltec_vision_master_e290.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +heltec_vision_master_e290.menu.LoopCore.0=Core 0 +heltec_vision_master_e290.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +heltec_vision_master_e290.menu.EventsCore.1=Core 1 +heltec_vision_master_e290.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +heltec_vision_master_e290.menu.EventsCore.0=Core 0 +heltec_vision_master_e290.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +heltec_vision_master_e290.menu.USBMode.hwcdc=Hardware CDC and JTAG +heltec_vision_master_e290.menu.USBMode.hwcdc.build.usb_mode=1 +heltec_vision_master_e290.menu.USBMode.default=USB-OTG (TinyUSB) +heltec_vision_master_e290.menu.USBMode.default.build.usb_mode=0 + +heltec_vision_master_e290.menu.CDCOnBoot.default=Enabled +heltec_vision_master_e290.menu.CDCOnBoot.default.build.cdc_on_boot=1 +heltec_vision_master_e290.menu.CDCOnBoot.cdc=Disabled +heltec_vision_master_e290.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +heltec_vision_master_e290.menu.MSCOnBoot.default=Disabled +heltec_vision_master_e290.menu.MSCOnBoot.default.build.msc_on_boot=0 +heltec_vision_master_e290.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +heltec_vision_master_e290.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +heltec_vision_master_e290.menu.DFUOnBoot.default=Disabled +heltec_vision_master_e290.menu.DFUOnBoot.default.build.dfu_on_boot=0 +heltec_vision_master_e290.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +heltec_vision_master_e290.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +heltec_vision_master_e290.menu.UploadMode.default=UART0 / Hardware CDC +heltec_vision_master_e290.menu.UploadMode.default.upload.use_1200bps_touch=false +heltec_vision_master_e290.menu.UploadMode.default.upload.wait_for_upload_port=false +heltec_vision_master_e290.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +heltec_vision_master_e290.menu.UploadMode.cdc.upload.use_1200bps_touch=true +heltec_vision_master_e290.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +heltec_vision_master_e290.menu.CPUFreq.240=240MHz (WiFi) +heltec_vision_master_e290.menu.CPUFreq.240.build.f_cpu=240000000L +heltec_vision_master_e290.menu.CPUFreq.160=160MHz (WiFi) +heltec_vision_master_e290.menu.CPUFreq.160.build.f_cpu=160000000L +heltec_vision_master_e290.menu.CPUFreq.80=80MHz (WiFi) +heltec_vision_master_e290.menu.CPUFreq.80.build.f_cpu=80000000L +heltec_vision_master_e290.menu.CPUFreq.40=40MHz +heltec_vision_master_e290.menu.CPUFreq.40.build.f_cpu=40000000L +heltec_vision_master_e290.menu.CPUFreq.20=20MHz +heltec_vision_master_e290.menu.CPUFreq.20.build.f_cpu=20000000L +heltec_vision_master_e290.menu.CPUFreq.10=10MHz +heltec_vision_master_e290.menu.CPUFreq.10.build.f_cpu=10000000L + +heltec_vision_master_e290.menu.UploadSpeed.921600=921600 +heltec_vision_master_e290.menu.UploadSpeed.921600.upload.speed=921600 +heltec_vision_master_e290.menu.UploadSpeed.115200=115200 +heltec_vision_master_e290.menu.UploadSpeed.115200.upload.speed=115200 +heltec_vision_master_e290.menu.UploadSpeed.256000.windows=256000 +heltec_vision_master_e290.menu.UploadSpeed.256000.upload.speed=256000 +heltec_vision_master_e290.menu.UploadSpeed.230400.windows.upload.speed=256000 +heltec_vision_master_e290.menu.UploadSpeed.230400=230400 +heltec_vision_master_e290.menu.UploadSpeed.230400.upload.speed=230400 +heltec_vision_master_e290.menu.UploadSpeed.460800.linux=460800 +heltec_vision_master_e290.menu.UploadSpeed.460800.macosx=460800 +heltec_vision_master_e290.menu.UploadSpeed.460800.upload.speed=460800 +heltec_vision_master_e290.menu.UploadSpeed.512000.windows=512000 +heltec_vision_master_e290.menu.UploadSpeed.512000.upload.speed=512000 + +heltec_vision_master_e290.menu.DebugLevel.none=None +heltec_vision_master_e290.menu.DebugLevel.none.build.code_debug=0 +heltec_vision_master_e290.menu.DebugLevel.error=Error +heltec_vision_master_e290.menu.DebugLevel.error.build.code_debug=1 +heltec_vision_master_e290.menu.DebugLevel.warn=Warn +heltec_vision_master_e290.menu.DebugLevel.warn.build.code_debug=2 +heltec_vision_master_e290.menu.DebugLevel.info=Info +heltec_vision_master_e290.menu.DebugLevel.info.build.code_debug=3 +heltec_vision_master_e290.menu.DebugLevel.debug=Debug +heltec_vision_master_e290.menu.DebugLevel.debug.build.code_debug=4 +heltec_vision_master_e290.menu.DebugLevel.verbose=Verbose +heltec_vision_master_e290.menu.DebugLevel.verbose.build.code_debug=5 + +heltec_vision_master_e290.menu.LORAWAN_REGION.0=REGION_EU868 +heltec_vision_master_e290.menu.LORAWAN_REGION.0.build.band=REGION_EU868 +heltec_vision_master_e290.menu.LORAWAN_REGION.1=REGION_EU433 +heltec_vision_master_e290.menu.LORAWAN_REGION.1.build.band=REGION_EU433 +heltec_vision_master_e290.menu.LORAWAN_REGION.2=REGION_CN470 +heltec_vision_master_e290.menu.LORAWAN_REGION.2.build.band=REGION_CN470 +heltec_vision_master_e290.menu.LORAWAN_REGION.3=REGION_US915 +heltec_vision_master_e290.menu.LORAWAN_REGION.3.build.band=REGION_US915 +heltec_vision_master_e290.menu.LORAWAN_REGION.4=REGION_AU915 +heltec_vision_master_e290.menu.LORAWAN_REGION.4.build.band=REGION_AU915 +heltec_vision_master_e290.menu.LORAWAN_REGION.5=REGION_CN779 +heltec_vision_master_e290.menu.LORAWAN_REGION.5.build.band=REGION_CN779 +heltec_vision_master_e290.menu.LORAWAN_REGION.6=REGION_AS923 +heltec_vision_master_e290.menu.LORAWAN_REGION.6.build.band=REGION_AS923 +heltec_vision_master_e290.menu.LORAWAN_REGION.7=REGION_KR920 +heltec_vision_master_e290.menu.LORAWAN_REGION.7.build.band=REGION_KR920 +heltec_vision_master_e290.menu.LORAWAN_REGION.8=REGION_IN865 +heltec_vision_master_e290.menu.LORAWAN_REGION.8.build.band=REGION_IN865 +heltec_vision_master_e290.menu.LORAWAN_REGION.9=REGION_US915_HYBRID +heltec_vision_master_e290.menu.LORAWAN_REGION.9.build.band=REGION_US915_HYBRID + +heltec_vision_master_e290.menu.LoRaWanDebugLevel.0=None +heltec_vision_master_e290.menu.LoRaWanDebugLevel.0.build.LoRaWanDebugLevel=0 +heltec_vision_master_e290.menu.LoRaWanDebugLevel.1=Freq +heltec_vision_master_e290.menu.LoRaWanDebugLevel.1.build.LoRaWanDebugLevel=1 +heltec_vision_master_e290.menu.LoRaWanDebugLevel.2=Freq && DIO +heltec_vision_master_e290.menu.LoRaWanDebugLevel.2.build.LoRaWanDebugLevel=2 +heltec_vision_master_e290.menu.LoRaWanDebugLevel.3=Freq && DIO && PW +heltec_vision_master_e290.menu.LoRaWanDebugLevel.3.build.LoRaWanDebugLevel=3 + +heltec_vision_master_e290.menu.LORAWAN_DEVEUI.0=CUSTOM +heltec_vision_master_e290.menu.LORAWAN_DEVEUI.0.build.LORAWAN_DEVEUI_AUTO=0 +heltec_vision_master_e290.menu.LORAWAN_DEVEUI.1=Generate By ChipID +heltec_vision_master_e290.menu.LORAWAN_DEVEUI.1.build.LORAWAN_DEVEUI_AUTO=1 + +heltec_vision_master_e290.menu.LORAWAN_PREAMBLE_LENGTH.0=8(default) +heltec_vision_master_e290.menu.LORAWAN_PREAMBLE_LENGTH.0.build.LORAWAN_PREAMBLE_LENGTH=8 +heltec_vision_master_e290.menu.LORAWAN_PREAMBLE_LENGTH.1=16(For M00 and M00L) +heltec_vision_master_e290.menu.LORAWAN_PREAMBLE_LENGTH.1.build.LORAWAN_PREAMBLE_LENGTH=16 + +heltec_vision_master_e290.menu.SLOW_CLK_TPYE.0=Internal (default) +heltec_vision_master_e290.menu.SLOW_CLK_TPYE.0.build.SLOW_CLK_TPYE=0 +heltec_vision_master_e290.menu.SLOW_CLK_TPYE.1=External 32K +heltec_vision_master_e290.menu.SLOW_CLK_TPYE.1.build.SLOW_CLK_TPYE=1 + +heltec_vision_master_e290.build.defines=-D{build.band} -DMCU_ESP32_S3 -DHELTEC_BOARD=37 -DHELTEC_VISION_MASTER_E290 -DSLOW_CLK_TPYE={build.SLOW_CLK_TPYE} -DRADIO_CHIP_SX1262 -DLoRaWAN_DEBUG_LEVEL={build.LoRaWanDebugLevel} -DACTIVE_REGION=LORAMAC_{build.band} -DLORAWAN_PREAMBLE_LENGTH={build.LORAWAN_PREAMBLE_LENGTH} -DLORAWAN_DEVEUI_AUTO={build.LORAWAN_DEVEUI_AUTO} -D{build.board} + +heltec_vision_master_e290.menu.EraseFlash.none=Disabled +heltec_vision_master_e290.menu.EraseFlash.none.upload.erase_cmd= +heltec_vision_master_e290.menu.EraseFlash.all=Enabled +heltec_vision_master_e290.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +heltec_vision_master_t190.name=Heltec Vision Master T190 + +heltec_vision_master_t190.bootloader.tool=esptool_py +heltec_vision_master_t190.bootloader.tool.default=esptool_py + +heltec_vision_master_t190.upload.tool=esptool_py +heltec_vision_master_t190.upload.tool.default=esptool_py +heltec_vision_master_t190.upload.tool.network=esp_ota + +heltec_vision_master_t190.upload.maximum_size=3342336 +heltec_vision_master_t190.upload.maximum_data_size=327680 +heltec_vision_master_t190.upload.flags= +heltec_vision_master_t190.upload.extra_flags= +heltec_vision_master_t190.upload.use_1200bps_touch=false +heltec_vision_master_t190.upload.wait_for_upload_port=false + +heltec_vision_master_t190.serial.disableDTR=false +heltec_vision_master_t190.serial.disableRTS=false + +heltec_vision_master_t190.build.tarch=xtensa +heltec_vision_master_t190.build.bootloader_addr=0x0 +heltec_vision_master_t190.build.target=esp32s3 +heltec_vision_master_t190.build.mcu=esp32s3 +heltec_vision_master_t190.build.core=esp32 +heltec_vision_master_t190.build.variant=heltec_vision_master_t190 +heltec_vision_master_t190.build.board=HELTEC_VISION_MASTER_T190 + +heltec_vision_master_t190.build.usb_mode=1 +heltec_vision_master_t190.build.cdc_on_boot=0 +heltec_vision_master_t190.build.msc_on_boot=0 +heltec_vision_master_t190.build.dfu_on_boot=0 +heltec_vision_master_t190.build.f_cpu=240000000L +heltec_vision_master_t190.build.flash_size=8MB +heltec_vision_master_t190.build.flash_freq=80m +heltec_vision_master_t190.build.flash_mode=dio +heltec_vision_master_t190.build.boot=qio +heltec_vision_master_t190.build.boot_freq=80m +heltec_vision_master_t190.build.partitions=default_8MB +heltec_vision_master_t190.build.loop_core= +heltec_vision_master_t190.build.event_core= +heltec_vision_master_t190.build.psram_type=qspi +heltec_vision_master_t190.build.memory_type={build.boot}_{build.psram_type} + +heltec_vision_master_t190.menu.LoopCore.1=Core 1 +heltec_vision_master_t190.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +heltec_vision_master_t190.menu.LoopCore.0=Core 0 +heltec_vision_master_t190.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +heltec_vision_master_t190.menu.EventsCore.1=Core 1 +heltec_vision_master_t190.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +heltec_vision_master_t190.menu.EventsCore.0=Core 0 +heltec_vision_master_t190.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +heltec_vision_master_t190.menu.USBMode.hwcdc=Hardware CDC and JTAG +heltec_vision_master_t190.menu.USBMode.hwcdc.build.usb_mode=1 +heltec_vision_master_t190.menu.USBMode.default=USB-OTG (TinyUSB) +heltec_vision_master_t190.menu.USBMode.default.build.usb_mode=0 + +heltec_vision_master_t190.menu.CDCOnBoot.default=Enabled +heltec_vision_master_t190.menu.CDCOnBoot.default.build.cdc_on_boot=1 +heltec_vision_master_t190.menu.CDCOnBoot.cdc=Disabled +heltec_vision_master_t190.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +heltec_vision_master_t190.menu.MSCOnBoot.default=Disabled +heltec_vision_master_t190.menu.MSCOnBoot.default.build.msc_on_boot=0 +heltec_vision_master_t190.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +heltec_vision_master_t190.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +heltec_vision_master_t190.menu.DFUOnBoot.default=Disabled +heltec_vision_master_t190.menu.DFUOnBoot.default.build.dfu_on_boot=0 +heltec_vision_master_t190.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +heltec_vision_master_t190.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +heltec_vision_master_t190.menu.UploadMode.default=UART0 / Hardware CDC +heltec_vision_master_t190.menu.UploadMode.default.upload.use_1200bps_touch=false +heltec_vision_master_t190.menu.UploadMode.default.upload.wait_for_upload_port=false +heltec_vision_master_t190.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +heltec_vision_master_t190.menu.UploadMode.cdc.upload.use_1200bps_touch=true +heltec_vision_master_t190.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +heltec_vision_master_t190.menu.CPUFreq.240=240MHz (WiFi) +heltec_vision_master_t190.menu.CPUFreq.240.build.f_cpu=240000000L +heltec_vision_master_t190.menu.CPUFreq.160=160MHz (WiFi) +heltec_vision_master_t190.menu.CPUFreq.160.build.f_cpu=160000000L +heltec_vision_master_t190.menu.CPUFreq.80=80MHz (WiFi) +heltec_vision_master_t190.menu.CPUFreq.80.build.f_cpu=80000000L +heltec_vision_master_t190.menu.CPUFreq.40=40MHz +heltec_vision_master_t190.menu.CPUFreq.40.build.f_cpu=40000000L +heltec_vision_master_t190.menu.CPUFreq.20=20MHz +heltec_vision_master_t190.menu.CPUFreq.20.build.f_cpu=20000000L +heltec_vision_master_t190.menu.CPUFreq.10=10MHz +heltec_vision_master_t190.menu.CPUFreq.10.build.f_cpu=10000000L + +heltec_vision_master_t190.menu.UploadSpeed.921600=921600 +heltec_vision_master_t190.menu.UploadSpeed.921600.upload.speed=921600 +heltec_vision_master_t190.menu.UploadSpeed.115200=115200 +heltec_vision_master_t190.menu.UploadSpeed.115200.upload.speed=115200 +heltec_vision_master_t190.menu.UploadSpeed.256000.windows=256000 +heltec_vision_master_t190.menu.UploadSpeed.256000.upload.speed=256000 +heltec_vision_master_t190.menu.UploadSpeed.230400.windows.upload.speed=256000 +heltec_vision_master_t190.menu.UploadSpeed.230400=230400 +heltec_vision_master_t190.menu.UploadSpeed.230400.upload.speed=230400 +heltec_vision_master_t190.menu.UploadSpeed.460800.linux=460800 +heltec_vision_master_t190.menu.UploadSpeed.460800.macosx=460800 +heltec_vision_master_t190.menu.UploadSpeed.460800.upload.speed=460800 +heltec_vision_master_t190.menu.UploadSpeed.512000.windows=512000 +heltec_vision_master_t190.menu.UploadSpeed.512000.upload.speed=512000 + +heltec_vision_master_t190.menu.DebugLevel.none=None +heltec_vision_master_t190.menu.DebugLevel.none.build.code_debug=0 +heltec_vision_master_t190.menu.DebugLevel.error=Error +heltec_vision_master_t190.menu.DebugLevel.error.build.code_debug=1 +heltec_vision_master_t190.menu.DebugLevel.warn=Warn +heltec_vision_master_t190.menu.DebugLevel.warn.build.code_debug=2 +heltec_vision_master_t190.menu.DebugLevel.info=Info +heltec_vision_master_t190.menu.DebugLevel.info.build.code_debug=3 +heltec_vision_master_t190.menu.DebugLevel.debug=Debug +heltec_vision_master_t190.menu.DebugLevel.debug.build.code_debug=4 +heltec_vision_master_t190.menu.DebugLevel.verbose=Verbose +heltec_vision_master_t190.menu.DebugLevel.verbose.build.code_debug=5 + +heltec_vision_master_t190.menu.LORAWAN_REGION.0=REGION_EU868 +heltec_vision_master_t190.menu.LORAWAN_REGION.0.build.band=REGION_EU868 +heltec_vision_master_t190.menu.LORAWAN_REGION.1=REGION_EU433 +heltec_vision_master_t190.menu.LORAWAN_REGION.1.build.band=REGION_EU433 +heltec_vision_master_t190.menu.LORAWAN_REGION.2=REGION_CN470 +heltec_vision_master_t190.menu.LORAWAN_REGION.2.build.band=REGION_CN470 +heltec_vision_master_t190.menu.LORAWAN_REGION.3=REGION_US915 +heltec_vision_master_t190.menu.LORAWAN_REGION.3.build.band=REGION_US915 +heltec_vision_master_t190.menu.LORAWAN_REGION.4=REGION_AU915 +heltec_vision_master_t190.menu.LORAWAN_REGION.4.build.band=REGION_AU915 +heltec_vision_master_t190.menu.LORAWAN_REGION.5=REGION_CN779 +heltec_vision_master_t190.menu.LORAWAN_REGION.5.build.band=REGION_CN779 +heltec_vision_master_t190.menu.LORAWAN_REGION.6=REGION_AS923 +heltec_vision_master_t190.menu.LORAWAN_REGION.6.build.band=REGION_AS923 +heltec_vision_master_t190.menu.LORAWAN_REGION.7=REGION_KR920 +heltec_vision_master_t190.menu.LORAWAN_REGION.7.build.band=REGION_KR920 +heltec_vision_master_t190.menu.LORAWAN_REGION.8=REGION_IN865 +heltec_vision_master_t190.menu.LORAWAN_REGION.8.build.band=REGION_IN865 +heltec_vision_master_t190.menu.LORAWAN_REGION.9=REGION_US915_HYBRID +heltec_vision_master_t190.menu.LORAWAN_REGION.9.build.band=REGION_US915_HYBRID + +heltec_vision_master_t190.menu.LoRaWanDebugLevel.0=None +heltec_vision_master_t190.menu.LoRaWanDebugLevel.0.build.LoRaWanDebugLevel=0 +heltec_vision_master_t190.menu.LoRaWanDebugLevel.1=Freq +heltec_vision_master_t190.menu.LoRaWanDebugLevel.1.build.LoRaWanDebugLevel=1 +heltec_vision_master_t190.menu.LoRaWanDebugLevel.2=Freq && DIO +heltec_vision_master_t190.menu.LoRaWanDebugLevel.2.build.LoRaWanDebugLevel=2 +heltec_vision_master_t190.menu.LoRaWanDebugLevel.3=Freq && DIO && PW +heltec_vision_master_t190.menu.LoRaWanDebugLevel.3.build.LoRaWanDebugLevel=3 + +heltec_vision_master_t190.menu.LORAWAN_DEVEUI.0=CUSTOM +heltec_vision_master_t190.menu.LORAWAN_DEVEUI.0.build.LORAWAN_DEVEUI_AUTO=0 +heltec_vision_master_t190.menu.LORAWAN_DEVEUI.1=Generate By ChipID +heltec_vision_master_t190.menu.LORAWAN_DEVEUI.1.build.LORAWAN_DEVEUI_AUTO=1 + +heltec_vision_master_t190.menu.LORAWAN_PREAMBLE_LENGTH.0=8(default) +heltec_vision_master_t190.menu.LORAWAN_PREAMBLE_LENGTH.0.build.LORAWAN_PREAMBLE_LENGTH=8 +heltec_vision_master_t190.menu.LORAWAN_PREAMBLE_LENGTH.1=16(For M00 and M00L) +heltec_vision_master_t190.menu.LORAWAN_PREAMBLE_LENGTH.1.build.LORAWAN_PREAMBLE_LENGTH=16 + +heltec_vision_master_t190.menu.SLOW_CLK_TPYE.0=Internal (default) +heltec_vision_master_t190.menu.SLOW_CLK_TPYE.0.build.SLOW_CLK_TPYE=0 +heltec_vision_master_t190.menu.SLOW_CLK_TPYE.1=External 32K +heltec_vision_master_t190.menu.SLOW_CLK_TPYE.1.build.SLOW_CLK_TPYE=1 + +heltec_vision_master_t190.build.defines=-D{build.band} -DMCU_ESP32_S3 -DHELTEC_BOARD=38 -DHELTEC_VISION_MASTER_T190 -DSLOW_CLK_TPYE={build.SLOW_CLK_TPYE} -DRADIO_CHIP_SX1262 -DLoRaWAN_DEBUG_LEVEL={build.LoRaWanDebugLevel} -DACTIVE_REGION=LORAMAC_{build.band} -DLORAWAN_PREAMBLE_LENGTH={build.LORAWAN_PREAMBLE_LENGTH} -DLORAWAN_DEVEUI_AUTO={build.LORAWAN_DEVEUI_AUTO} -D{build.board} + +heltec_vision_master_t190.menu.EraseFlash.none=Disabled +heltec_vision_master_t190.menu.EraseFlash.none.upload.erase_cmd= +heltec_vision_master_t190.menu.EraseFlash.all=Enabled +heltec_vision_master_t190.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +heltec_vision_master_e_213.name=Heltec Vision Master E213 + +heltec_vision_master_e_213.bootloader.tool=esptool_py +heltec_vision_master_e_213.bootloader.tool.default=esptool_py + +heltec_vision_master_e_213.upload.tool=esptool_py +heltec_vision_master_e_213.upload.tool.default=esptool_py +heltec_vision_master_e_213.upload.tool.network=esp_ota + +heltec_vision_master_e_213.upload.maximum_size=3342336 +heltec_vision_master_e_213.upload.maximum_data_size=327680 +heltec_vision_master_e_213.upload.flags= +heltec_vision_master_e_213.upload.extra_flags= +heltec_vision_master_e_213.upload.use_1200bps_touch=false +heltec_vision_master_e_213.upload.wait_for_upload_port=false + +heltec_vision_master_e_213.serial.disableDTR=false +heltec_vision_master_e_213.serial.disableRTS=false + +heltec_vision_master_e_213.build.tarch=xtensa +heltec_vision_master_e_213.build.bootloader_addr=0x0 +heltec_vision_master_e_213.build.target=esp32s3 +heltec_vision_master_e_213.build.mcu=esp32s3 +heltec_vision_master_e_213.build.core=esp32 +heltec_vision_master_e_213.build.variant=heltec_vision_master_e_213 +heltec_vision_master_e_213.build.board=HELTEC_VISION_MASTER_E_213 + +heltec_vision_master_e_213.build.usb_mode=1 +heltec_vision_master_e_213.build.cdc_on_boot=0 +heltec_vision_master_e_213.build.msc_on_boot=0 +heltec_vision_master_e_213.build.dfu_on_boot=0 +heltec_vision_master_e_213.build.f_cpu=240000000L +heltec_vision_master_e_213.build.flash_size=8MB +heltec_vision_master_e_213.build.flash_freq=80m +heltec_vision_master_e_213.build.flash_mode=dio +heltec_vision_master_e_213.build.boot=qio +heltec_vision_master_e_213.build.boot_freq=80m +heltec_vision_master_e_213.build.partitions=default_8MB +heltec_vision_master_e_213.build.loop_core= +heltec_vision_master_e_213.build.event_core= +heltec_vision_master_e_213.build.psram_type=qspi +heltec_vision_master_e_213.build.memory_type={build.boot}_{build.psram_type} + +heltec_vision_master_e_213.menu.LoopCore.1=Core 1 +heltec_vision_master_e_213.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +heltec_vision_master_e_213.menu.LoopCore.0=Core 0 +heltec_vision_master_e_213.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +heltec_vision_master_e_213.menu.EventsCore.1=Core 1 +heltec_vision_master_e_213.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +heltec_vision_master_e_213.menu.EventsCore.0=Core 0 +heltec_vision_master_e_213.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +heltec_vision_master_e_213.menu.USBMode.hwcdc=Hardware CDC and JTAG +heltec_vision_master_e_213.menu.USBMode.hwcdc.build.usb_mode=1 +heltec_vision_master_e_213.menu.USBMode.default=USB-OTG (TinyUSB) +heltec_vision_master_e_213.menu.USBMode.default.build.usb_mode=0 + +heltec_vision_master_e_213.menu.CDCOnBoot.default=Enabled +heltec_vision_master_e_213.menu.CDCOnBoot.default.build.cdc_on_boot=1 +heltec_vision_master_e_213.menu.CDCOnBoot.cdc=Disabled +heltec_vision_master_e_213.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +heltec_vision_master_e_213.menu.MSCOnBoot.default=Disabled +heltec_vision_master_e_213.menu.MSCOnBoot.default.build.msc_on_boot=0 +heltec_vision_master_e_213.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +heltec_vision_master_e_213.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +heltec_vision_master_e_213.menu.DFUOnBoot.default=Disabled +heltec_vision_master_e_213.menu.DFUOnBoot.default.build.dfu_on_boot=0 +heltec_vision_master_e_213.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +heltec_vision_master_e_213.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +heltec_vision_master_e_213.menu.UploadMode.default=UART0 / Hardware CDC +heltec_vision_master_e_213.menu.UploadMode.default.upload.use_1200bps_touch=false +heltec_vision_master_e_213.menu.UploadMode.default.upload.wait_for_upload_port=false +heltec_vision_master_e_213.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +heltec_vision_master_e_213.menu.UploadMode.cdc.upload.use_1200bps_touch=true +heltec_vision_master_e_213.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +heltec_vision_master_e_213.menu.CPUFreq.240=240MHz (WiFi) +heltec_vision_master_e_213.menu.CPUFreq.240.build.f_cpu=240000000L +heltec_vision_master_e_213.menu.CPUFreq.160=160MHz (WiFi) +heltec_vision_master_e_213.menu.CPUFreq.160.build.f_cpu=160000000L +heltec_vision_master_e_213.menu.CPUFreq.80=80MHz (WiFi) +heltec_vision_master_e_213.menu.CPUFreq.80.build.f_cpu=80000000L +heltec_vision_master_e_213.menu.CPUFreq.40=40MHz +heltec_vision_master_e_213.menu.CPUFreq.40.build.f_cpu=40000000L +heltec_vision_master_e_213.menu.CPUFreq.20=20MHz +heltec_vision_master_e_213.menu.CPUFreq.20.build.f_cpu=20000000L +heltec_vision_master_e_213.menu.CPUFreq.10=10MHz +heltec_vision_master_e_213.menu.CPUFreq.10.build.f_cpu=10000000L + +heltec_vision_master_e_213.menu.UploadSpeed.921600=921600 +heltec_vision_master_e_213.menu.UploadSpeed.921600.upload.speed=921600 +heltec_vision_master_e_213.menu.UploadSpeed.115200=115200 +heltec_vision_master_e_213.menu.UploadSpeed.115200.upload.speed=115200 +heltec_vision_master_e_213.menu.UploadSpeed.256000.windows=256000 +heltec_vision_master_e_213.menu.UploadSpeed.256000.upload.speed=256000 +heltec_vision_master_e_213.menu.UploadSpeed.230400.windows.upload.speed=256000 +heltec_vision_master_e_213.menu.UploadSpeed.230400=230400 +heltec_vision_master_e_213.menu.UploadSpeed.230400.upload.speed=230400 +heltec_vision_master_e_213.menu.UploadSpeed.460800.linux=460800 +heltec_vision_master_e_213.menu.UploadSpeed.460800.macosx=460800 +heltec_vision_master_e_213.menu.UploadSpeed.460800.upload.speed=460800 +heltec_vision_master_e_213.menu.UploadSpeed.512000.windows=512000 +heltec_vision_master_e_213.menu.UploadSpeed.512000.upload.speed=512000 + +heltec_vision_master_e_213.menu.DebugLevel.none=None +heltec_vision_master_e_213.menu.DebugLevel.none.build.code_debug=0 +heltec_vision_master_e_213.menu.DebugLevel.error=Error +heltec_vision_master_e_213.menu.DebugLevel.error.build.code_debug=1 +heltec_vision_master_e_213.menu.DebugLevel.warn=Warn +heltec_vision_master_e_213.menu.DebugLevel.warn.build.code_debug=2 +heltec_vision_master_e_213.menu.DebugLevel.info=Info +heltec_vision_master_e_213.menu.DebugLevel.info.build.code_debug=3 +heltec_vision_master_e_213.menu.DebugLevel.debug=Debug +heltec_vision_master_e_213.menu.DebugLevel.debug.build.code_debug=4 +heltec_vision_master_e_213.menu.DebugLevel.verbose=Verbose +heltec_vision_master_e_213.menu.DebugLevel.verbose.build.code_debug=5 + +heltec_vision_master_e_213.menu.LORAWAN_REGION.0=REGION_EU868 +heltec_vision_master_e_213.menu.LORAWAN_REGION.0.build.band=REGION_EU868 +heltec_vision_master_e_213.menu.LORAWAN_REGION.1=REGION_EU433 +heltec_vision_master_e_213.menu.LORAWAN_REGION.1.build.band=REGION_EU433 +heltec_vision_master_e_213.menu.LORAWAN_REGION.2=REGION_CN470 +heltec_vision_master_e_213.menu.LORAWAN_REGION.2.build.band=REGION_CN470 +heltec_vision_master_e_213.menu.LORAWAN_REGION.3=REGION_US915 +heltec_vision_master_e_213.menu.LORAWAN_REGION.3.build.band=REGION_US915 +heltec_vision_master_e_213.menu.LORAWAN_REGION.4=REGION_AU915 +heltec_vision_master_e_213.menu.LORAWAN_REGION.4.build.band=REGION_AU915 +heltec_vision_master_e_213.menu.LORAWAN_REGION.5=REGION_CN779 +heltec_vision_master_e_213.menu.LORAWAN_REGION.5.build.band=REGION_CN779 +heltec_vision_master_e_213.menu.LORAWAN_REGION.6=REGION_AS923 +heltec_vision_master_e_213.menu.LORAWAN_REGION.6.build.band=REGION_AS923 +heltec_vision_master_e_213.menu.LORAWAN_REGION.7=REGION_KR920 +heltec_vision_master_e_213.menu.LORAWAN_REGION.7.build.band=REGION_KR920 +heltec_vision_master_e_213.menu.LORAWAN_REGION.8=REGION_IN865 +heltec_vision_master_e_213.menu.LORAWAN_REGION.8.build.band=REGION_IN865 +heltec_vision_master_e_213.menu.LORAWAN_REGION.9=REGION_US915_HYBRID +heltec_vision_master_e_213.menu.LORAWAN_REGION.9.build.band=REGION_US915_HYBRID + +heltec_vision_master_e_213.menu.LoRaWanDebugLevel.0=None +heltec_vision_master_e_213.menu.LoRaWanDebugLevel.0.build.LoRaWanDebugLevel=0 +heltec_vision_master_e_213.menu.LoRaWanDebugLevel.1=Freq +heltec_vision_master_e_213.menu.LoRaWanDebugLevel.1.build.LoRaWanDebugLevel=1 +heltec_vision_master_e_213.menu.LoRaWanDebugLevel.2=Freq && DIO +heltec_vision_master_e_213.menu.LoRaWanDebugLevel.2.build.LoRaWanDebugLevel=2 +heltec_vision_master_e_213.menu.LoRaWanDebugLevel.3=Freq && DIO && PW +heltec_vision_master_e_213.menu.LoRaWanDebugLevel.3.build.LoRaWanDebugLevel=3 + +heltec_vision_master_e_213.menu.LORAWAN_DEVEUI.0=CUSTOM +heltec_vision_master_e_213.menu.LORAWAN_DEVEUI.0.build.LORAWAN_DEVEUI_AUTO=0 +heltec_vision_master_e_213.menu.LORAWAN_DEVEUI.1=Generate By ChipID +heltec_vision_master_e_213.menu.LORAWAN_DEVEUI.1.build.LORAWAN_DEVEUI_AUTO=1 + +heltec_vision_master_e_213.menu.LORAWAN_PREAMBLE_LENGTH.0=8(default) +heltec_vision_master_e_213.menu.LORAWAN_PREAMBLE_LENGTH.0.build.LORAWAN_PREAMBLE_LENGTH=8 +heltec_vision_master_e_213.menu.LORAWAN_PREAMBLE_LENGTH.1=16(For M00 and M00L) +heltec_vision_master_e_213.menu.LORAWAN_PREAMBLE_LENGTH.1.build.LORAWAN_PREAMBLE_LENGTH=16 + +heltec_vision_master_e_213.menu.SLOW_CLK_TPYE.0=Internal (default) +heltec_vision_master_e_213.menu.SLOW_CLK_TPYE.0.build.SLOW_CLK_TPYE=0 +heltec_vision_master_e_213.menu.SLOW_CLK_TPYE.1=External 32K +heltec_vision_master_e_213.menu.SLOW_CLK_TPYE.1.build.SLOW_CLK_TPYE=1 + +heltec_vision_master_e_213.build.defines=-D{build.band} -DMCU_ESP32_S3 -DHELTEC_BOARD=36 -DHELTEC_VISION_MASTER_E_213 -DSLOW_CLK_TPYE={build.SLOW_CLK_TPYE} -DRADIO_CHIP_SX1262 -DLoRaWAN_DEBUG_LEVEL={build.LoRaWanDebugLevel} -DACTIVE_REGION=LORAMAC_{build.band} -DLORAWAN_PREAMBLE_LENGTH={build.LORAWAN_PREAMBLE_LENGTH} -DLORAWAN_DEVEUI_AUTO={build.LORAWAN_DEVEUI_AUTO} -D{build.board} + +heltec_vision_master_e_213.menu.EraseFlash.none=Disabled +heltec_vision_master_e_213.menu.EraseFlash.none.upload.erase_cmd= +heltec_vision_master_e_213.menu.EraseFlash.all=Enabled +heltec_vision_master_e_213.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + espectro32.name=ESPectro32 espectro32.bootloader.tool=esptool_py @@ -23713,7 +27570,6 @@ espectro32.menu.FlashSize.4M=4MB (32Mb) espectro32.menu.FlashSize.4M.build.flash_size=4MB espectro32.menu.FlashSize.2M=2MB (16Mb) espectro32.menu.FlashSize.2M.build.flash_size=2MB -espectro32.menu.FlashSize.2M.build.partitions=minimal espectro32.menu.UploadSpeed.921600=921600 espectro32.menu.UploadSpeed.921600.upload.speed=921600 @@ -23942,10 +27798,8 @@ alksesp32.menu.FlashSize.4M=4MB (32Mb) alksesp32.menu.FlashSize.4M.build.flash_size=4MB alksesp32.menu.FlashSize.2M=2MB (16Mb) alksesp32.menu.FlashSize.2M.build.flash_size=2MB -alksesp32.menu.FlashSize.2M.build.partitions=minimal alksesp32.menu.FlashSize.16M=16MB (128Mb) alksesp32.menu.FlashSize.16M.build.flash_size=16MB -alksesp32.menu.FlashSize.16M.build.partitions=ffat alksesp32.menu.UploadSpeed.921600=921600 alksesp32.menu.UploadSpeed.921600.upload.speed=921600 @@ -24462,7 +28316,6 @@ bpi_leaf_s3.menu.FlashMode.opi.build.flash_freq=80m bpi_leaf_s3.menu.FlashSize.8M=8MB (64Mb) bpi_leaf_s3.menu.FlashSize.8M.build.flash_size=8MB -bpi_leaf_s3.menu.FlashSize.8M.build.partitions=default_8MB bpi_leaf_s3.menu.FlashSize.4M=4MB (32Mb) bpi_leaf_s3.menu.FlashSize.4M.build.flash_size=4MB bpi_leaf_s3.menu.FlashSize.16M=16MB (128Mb) @@ -24540,9 +28393,15 @@ bpi_leaf_s3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 bpi_leaf_s3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) bpi_leaf_s3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB bpi_leaf_s3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -bpi_leaf_s3.menu.PartitionScheme.rainmaker=RainMaker +bpi_leaf_s3.menu.PartitionScheme.rainmaker=RainMaker 4MB bpi_leaf_s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -bpi_leaf_s3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +bpi_leaf_s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +bpi_leaf_s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +bpi_leaf_s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +bpi_leaf_s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +bpi_leaf_s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +bpi_leaf_s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +bpi_leaf_s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 bpi_leaf_s3.menu.CPUFreq.240=240MHz (WiFi) bpi_leaf_s3.menu.CPUFreq.240.build.f_cpu=240000000L @@ -25130,6 +28989,223 @@ fm-devkit.menu.EraseFlash.none.upload.erase_cmd= fm-devkit.menu.EraseFlash.all=Enabled fm-devkit.menu.EraseFlash.all.upload.erase_cmd=-e +############################################################## +### Fri3d Badge 2024 (ESP32-S3-WROOM-1) + +fri3d_2024_esp32s3.name=Fri3d Badge 2024 (ESP32-S3-WROOM-1) + +fri3d_2024_esp32s3.bootloader.tool=esptool_py +fri3d_2024_esp32s3.bootloader.tool.default=esptool_py + +fri3d_2024_esp32s3.upload.tool=esptool_py +fri3d_2024_esp32s3.upload.tool.default=esptool_py +fri3d_2024_esp32s3.upload.tool.network=esp_ota + +fri3d_2024_esp32s3.upload.maximum_size=1310720 +fri3d_2024_esp32s3.upload.maximum_data_size=327680 +fri3d_2024_esp32s3.upload.flags= +fri3d_2024_esp32s3.upload.extra_flags= +fri3d_2024_esp32s3.upload.use_1200bps_touch=false +fri3d_2024_esp32s3.upload.wait_for_upload_port=false + +fri3d_2024_esp32s3.serial.disableDTR=false +fri3d_2024_esp32s3.serial.disableRTS=false + +fri3d_2024_esp32s3.build.tarch=xtensa +fri3d_2024_esp32s3.build.bootloader_addr=0x0 +fri3d_2024_esp32s3.build.target=esp32s3 +fri3d_2024_esp32s3.build.mcu=esp32s3 +fri3d_2024_esp32s3.build.core=esp32 +fri3d_2024_esp32s3.build.variant=fri3d_2024_esp32s3 +fri3d_2024_esp32s3.build.board=FRI3D_2024_ESP32S3 + +fri3d_2024_esp32s3.build.usb_mode=1 +fri3d_2024_esp32s3.build.cdc_on_boot=0 +fri3d_2024_esp32s3.build.msc_on_boot=0 +fri3d_2024_esp32s3.build.dfu_on_boot=0 +fri3d_2024_esp32s3.build.f_cpu=240000000L +fri3d_2024_esp32s3.build.flash_size=16MB +fri3d_2024_esp32s3.build.flash_freq=80m +fri3d_2024_esp32s3.build.flash_mode=dio +fri3d_2024_esp32s3.build.boot=qio +fri3d_2024_esp32s3.build.boot_freq=80m +fri3d_2024_esp32s3.build.partitions=default +fri3d_2024_esp32s3.build.defines= +fri3d_2024_esp32s3.build.loop_core= +fri3d_2024_esp32s3.build.event_core= +fri3d_2024_esp32s3.build.psram_type=opi +fri3d_2024_esp32s3.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +fri3d_2024_esp32s3.menu.JTAGAdapter.default=Disabled +fri3d_2024_esp32s3.menu.JTAGAdapter.default.build.copy_jtag_files=0 +fri3d_2024_esp32s3.menu.JTAGAdapter.builtin=Integrated USB JTAG +fri3d_2024_esp32s3.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +fri3d_2024_esp32s3.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +fri3d_2024_esp32s3.menu.JTAGAdapter.external=FTDI Adapter +fri3d_2024_esp32s3.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +fri3d_2024_esp32s3.menu.JTAGAdapter.external.build.copy_jtag_files=1 +fri3d_2024_esp32s3.menu.JTAGAdapter.bridge=ESP USB Bridge +fri3d_2024_esp32s3.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +fri3d_2024_esp32s3.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +fri3d_2024_esp32s3.menu.PSRAM.default=OPI PSRAM +fri3d_2024_esp32s3.menu.PSRAM.default.build.defines=-DBOARD_HAS_PSRAM +fri3d_2024_esp32s3.menu.PSRAM.default.build.psram_type=opi +fri3d_2024_esp32s3.menu.PSRAM.disabled=Disabled +fri3d_2024_esp32s3.menu.PSRAM.disabled.build.defines= +fri3d_2024_esp32s3.menu.PSRAM.disabled.build.psram_type=qspi + +fri3d_2024_esp32s3.menu.FlashMode.qio=QIO 80MHz +fri3d_2024_esp32s3.menu.FlashMode.qio.build.flash_mode=dio +fri3d_2024_esp32s3.menu.FlashMode.qio.build.boot=qio +fri3d_2024_esp32s3.menu.FlashMode.qio.build.boot_freq=80m +fri3d_2024_esp32s3.menu.FlashMode.qio.build.flash_freq=80m +fri3d_2024_esp32s3.menu.FlashMode.qio120=QIO 120MHz +fri3d_2024_esp32s3.menu.FlashMode.qio120.build.flash_mode=dio +fri3d_2024_esp32s3.menu.FlashMode.qio120.build.boot=qio +fri3d_2024_esp32s3.menu.FlashMode.qio120.build.boot_freq=120m +fri3d_2024_esp32s3.menu.FlashMode.qio120.build.flash_freq=80m +fri3d_2024_esp32s3.menu.FlashMode.dio=DIO 80MHz +fri3d_2024_esp32s3.menu.FlashMode.dio.build.flash_mode=dio +fri3d_2024_esp32s3.menu.FlashMode.dio.build.boot=dio +fri3d_2024_esp32s3.menu.FlashMode.dio.build.boot_freq=80m +fri3d_2024_esp32s3.menu.FlashMode.dio.build.flash_freq=80m +fri3d_2024_esp32s3.menu.FlashMode.opi=OPI 80MHz +fri3d_2024_esp32s3.menu.FlashMode.opi.build.flash_mode=dout +fri3d_2024_esp32s3.menu.FlashMode.opi.build.boot=opi +fri3d_2024_esp32s3.menu.FlashMode.opi.build.boot_freq=80m +fri3d_2024_esp32s3.menu.FlashMode.opi.build.flash_freq=80m + +fri3d_2024_esp32s3.menu.FlashSize.default=16MB (128Mb) +fri3d_2024_esp32s3.menu.FlashSize.default.build.flash_size=16MB + +fri3d_2024_esp32s3.menu.LoopCore.1=Core 1 +fri3d_2024_esp32s3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +fri3d_2024_esp32s3.menu.LoopCore.0=Core 0 +fri3d_2024_esp32s3.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +fri3d_2024_esp32s3.menu.EventsCore.1=Core 1 +fri3d_2024_esp32s3.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +fri3d_2024_esp32s3.menu.EventsCore.0=Core 0 +fri3d_2024_esp32s3.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +fri3d_2024_esp32s3.menu.USBMode.hwcdc=Hardware CDC and JTAG +fri3d_2024_esp32s3.menu.USBMode.hwcdc.build.usb_mode=1 +fri3d_2024_esp32s3.menu.USBMode.default=USB-OTG (TinyUSB) +fri3d_2024_esp32s3.menu.USBMode.default.build.usb_mode=0 + +fri3d_2024_esp32s3.menu.CDCOnBoot.default=Enabled +fri3d_2024_esp32s3.menu.CDCOnBoot.default.build.cdc_on_boot=1 +fri3d_2024_esp32s3.menu.CDCOnBoot.disabled=Disabled +fri3d_2024_esp32s3.menu.CDCOnBoot.disabled.build.cdc_on_boot=0 + +fri3d_2024_esp32s3.menu.MSCOnBoot.default=Disabled +fri3d_2024_esp32s3.menu.MSCOnBoot.default.build.msc_on_boot=0 +fri3d_2024_esp32s3.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +fri3d_2024_esp32s3.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +fri3d_2024_esp32s3.menu.DFUOnBoot.default=Disabled +fri3d_2024_esp32s3.menu.DFUOnBoot.default.build.dfu_on_boot=0 +fri3d_2024_esp32s3.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +fri3d_2024_esp32s3.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +fri3d_2024_esp32s3.menu.UploadMode.default=UART0 / Hardware CDC +fri3d_2024_esp32s3.menu.UploadMode.default.upload.use_1200bps_touch=false +fri3d_2024_esp32s3.menu.UploadMode.default.upload.wait_for_upload_port=false +fri3d_2024_esp32s3.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +fri3d_2024_esp32s3.menu.UploadMode.cdc.upload.use_1200bps_touch=true +fri3d_2024_esp32s3.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +fri3d_2024_esp32s3.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +fri3d_2024_esp32s3.menu.PartitionScheme.default.build.partitions=default +fri3d_2024_esp32s3.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +fri3d_2024_esp32s3.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +fri3d_2024_esp32s3.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +fri3d_2024_esp32s3.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +fri3d_2024_esp32s3.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +fri3d_2024_esp32s3.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +fri3d_2024_esp32s3.menu.PartitionScheme.minimal.build.partitions=minimal +fri3d_2024_esp32s3.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +fri3d_2024_esp32s3.menu.PartitionScheme.no_ota.build.partitions=no_ota +fri3d_2024_esp32s3.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +fri3d_2024_esp32s3.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +fri3d_2024_esp32s3.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +fri3d_2024_esp32s3.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +fri3d_2024_esp32s3.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +fri3d_2024_esp32s3.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +fri3d_2024_esp32s3.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +fri3d_2024_esp32s3.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +fri3d_2024_esp32s3.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +fri3d_2024_esp32s3.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +fri3d_2024_esp32s3.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +fri3d_2024_esp32s3.menu.PartitionScheme.huge_app.build.partitions=huge_app +fri3d_2024_esp32s3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +fri3d_2024_esp32s3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +fri3d_2024_esp32s3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +fri3d_2024_esp32s3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +fri3d_2024_esp32s3.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +fri3d_2024_esp32s3.menu.PartitionScheme.fatflash.build.partitions=ffat +fri3d_2024_esp32s3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +fri3d_2024_esp32s3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +fri3d_2024_esp32s3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +fri3d_2024_esp32s3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +fri3d_2024_esp32s3.menu.PartitionScheme.rainmaker=RainMaker +fri3d_2024_esp32s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +fri3d_2024_esp32s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +fri3d_2024_esp32s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +fri3d_2024_esp32s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +fri3d_2024_esp32s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +fri3d_2024_esp32s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +fri3d_2024_esp32s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +fri3d_2024_esp32s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 + +fri3d_2024_esp32s3.menu.CPUFreq.240=240MHz (WiFi) +fri3d_2024_esp32s3.menu.CPUFreq.240.build.f_cpu=240000000L +fri3d_2024_esp32s3.menu.CPUFreq.160=160MHz (WiFi) +fri3d_2024_esp32s3.menu.CPUFreq.160.build.f_cpu=160000000L +fri3d_2024_esp32s3.menu.CPUFreq.80=80MHz (WiFi) +fri3d_2024_esp32s3.menu.CPUFreq.80.build.f_cpu=80000000L +fri3d_2024_esp32s3.menu.CPUFreq.40=40MHz +fri3d_2024_esp32s3.menu.CPUFreq.40.build.f_cpu=40000000L +fri3d_2024_esp32s3.menu.CPUFreq.20=20MHz +fri3d_2024_esp32s3.menu.CPUFreq.20.build.f_cpu=20000000L +fri3d_2024_esp32s3.menu.CPUFreq.10=10MHz +fri3d_2024_esp32s3.menu.CPUFreq.10.build.f_cpu=10000000L + +fri3d_2024_esp32s3.menu.UploadSpeed.921600=921600 +fri3d_2024_esp32s3.menu.UploadSpeed.921600.upload.speed=921600 +fri3d_2024_esp32s3.menu.UploadSpeed.115200=115200 +fri3d_2024_esp32s3.menu.UploadSpeed.115200.upload.speed=115200 +fri3d_2024_esp32s3.menu.UploadSpeed.256000.windows=256000 +fri3d_2024_esp32s3.menu.UploadSpeed.256000.upload.speed=256000 +fri3d_2024_esp32s3.menu.UploadSpeed.230400.windows.upload.speed=256000 +fri3d_2024_esp32s3.menu.UploadSpeed.230400=230400 +fri3d_2024_esp32s3.menu.UploadSpeed.230400.upload.speed=230400 +fri3d_2024_esp32s3.menu.UploadSpeed.460800.linux=460800 +fri3d_2024_esp32s3.menu.UploadSpeed.460800.macosx=460800 +fri3d_2024_esp32s3.menu.UploadSpeed.460800.upload.speed=460800 +fri3d_2024_esp32s3.menu.UploadSpeed.512000.windows=512000 +fri3d_2024_esp32s3.menu.UploadSpeed.512000.upload.speed=512000 + +fri3d_2024_esp32s3.menu.DebugLevel.none=None +fri3d_2024_esp32s3.menu.DebugLevel.none.build.code_debug=0 +fri3d_2024_esp32s3.menu.DebugLevel.error=Error +fri3d_2024_esp32s3.menu.DebugLevel.error.build.code_debug=1 +fri3d_2024_esp32s3.menu.DebugLevel.warn=Warn +fri3d_2024_esp32s3.menu.DebugLevel.warn.build.code_debug=2 +fri3d_2024_esp32s3.menu.DebugLevel.info=Info +fri3d_2024_esp32s3.menu.DebugLevel.info.build.code_debug=3 +fri3d_2024_esp32s3.menu.DebugLevel.debug=Debug +fri3d_2024_esp32s3.menu.DebugLevel.debug.build.code_debug=4 +fri3d_2024_esp32s3.menu.DebugLevel.verbose=Verbose +fri3d_2024_esp32s3.menu.DebugLevel.verbose.build.code_debug=5 + +fri3d_2024_esp32s3.menu.EraseFlash.none=Disabled +fri3d_2024_esp32s3.menu.EraseFlash.none.upload.erase_cmd= +fri3d_2024_esp32s3.menu.EraseFlash.all=Enabled +fri3d_2024_esp32s3.menu.EraseFlash.all.upload.erase_cmd=-e + ############################################################## frogboard.name=Frog Board ESP32 @@ -25196,7 +29272,6 @@ frogboard.menu.FlashSize.4M=4MB (32Mb) frogboard.menu.FlashSize.4M.build.flash_size=4MB frogboard.menu.FlashSize.2M=2MB (16Mb) frogboard.menu.FlashSize.2M.build.flash_size=2MB -frogboard.menu.FlashSize.2M.build.partitions=minimal frogboard.menu.UploadSpeed.921600=921600 frogboard.menu.UploadSpeed.921600.upload.speed=921600 @@ -25793,10 +29868,8 @@ vintlabs-devkit-v1.menu.FlashSize.4M=4MB (32Mb) vintlabs-devkit-v1.menu.FlashSize.4M.build.flash_size=4MB vintlabs-devkit-v1.menu.FlashSize.8M=8MB (64Mb) vintlabs-devkit-v1.menu.FlashSize.8M.build.flash_size=8MB -vintlabs-devkit-v1.menu.FlashSize.8M.build.partitions=default_8MB vintlabs-devkit-v1.menu.FlashSize.2M=2MB (16Mb) vintlabs-devkit-v1.menu.FlashSize.2M.build.flash_size=2MB -vintlabs-devkit-v1.menu.FlashSize.2M.build.partitions=minimal vintlabs-devkit-v1.menu.FlashSize.16M=16MB (128Mb) vintlabs-devkit-v1.menu.FlashSize.16M.build.flash_size=16MB @@ -25997,10 +30070,8 @@ mgbot-iotik32a.menu.FlashSize.4M=4MB (32Mb) mgbot-iotik32a.menu.FlashSize.4M.build.flash_size=4MB mgbot-iotik32a.menu.FlashSize.8M=8MB (64Mb) mgbot-iotik32a.menu.FlashSize.8M.build.flash_size=8MB -mgbot-iotik32a.menu.FlashSize.8M.build.partitions=default_8MB mgbot-iotik32a.menu.FlashSize.2M=2MB (16Mb) mgbot-iotik32a.menu.FlashSize.2M.build.flash_size=2MB -mgbot-iotik32a.menu.FlashSize.2M.build.partitions=minimal mgbot-iotik32a.menu.FlashSize.16M=16MB (128Mb) mgbot-iotik32a.menu.FlashSize.16M.build.flash_size=16MB @@ -26146,10 +30217,8 @@ mgbot-iotik32b.menu.FlashSize.4M=4MB (32Mb) mgbot-iotik32b.menu.FlashSize.4M.build.flash_size=4MB mgbot-iotik32b.menu.FlashSize.8M=8MB (64Mb) mgbot-iotik32b.menu.FlashSize.8M.build.flash_size=8MB -mgbot-iotik32b.menu.FlashSize.8M.build.partitions=default_8MB mgbot-iotik32b.menu.FlashSize.2M=2MB (16Mb) mgbot-iotik32b.menu.FlashSize.2M.build.flash_size=2MB -mgbot-iotik32b.menu.FlashSize.2M.build.partitions=minimal mgbot-iotik32b.menu.FlashSize.16M=16MB (128Mb) mgbot-iotik32b.menu.FlashSize.16M.build.flash_size=16MB @@ -26848,9 +30917,15 @@ wifiduino32c3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 wifiduino32c3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) wifiduino32c3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB wifiduino32c3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -wifiduino32c3.menu.PartitionScheme.rainmaker=RainMaker +wifiduino32c3.menu.PartitionScheme.rainmaker=RainMaker 4MB wifiduino32c3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -wifiduino32c3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +wifiduino32c3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +wifiduino32c3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +wifiduino32c3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +wifiduino32c3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +wifiduino32c3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +wifiduino32c3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +wifiduino32c3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 wifiduino32c3.menu.CPUFreq.160=160MHz (WiFi) wifiduino32c3.menu.CPUFreq.160.build.f_cpu=160000000L @@ -26879,10 +30954,8 @@ wifiduino32c3.menu.FlashSize.4M=4MB (32Mb) wifiduino32c3.menu.FlashSize.4M.build.flash_size=4MB wifiduino32c3.menu.FlashSize.8M=8MB (64Mb) wifiduino32c3.menu.FlashSize.8M.build.flash_size=8MB -wifiduino32c3.menu.FlashSize.8M.build.partitions=default_8MB wifiduino32c3.menu.FlashSize.2M=2MB (16Mb) wifiduino32c3.menu.FlashSize.2M.build.flash_size=2MB -wifiduino32c3.menu.FlashSize.2M.build.partitions=minimal wifiduino32c3.menu.FlashSize.16M=16MB (128Mb) wifiduino32c3.menu.FlashSize.16M.build.flash_size=16MB @@ -27000,7 +31073,6 @@ wifiduino32s3.menu.FlashSize.4M=4MB (32Mb) wifiduino32s3.menu.FlashSize.4M.build.flash_size=4MB wifiduino32s3.menu.FlashSize.8M=8MB (64Mb) wifiduino32s3.menu.FlashSize.8M.build.flash_size=8MB -wifiduino32s3.menu.FlashSize.8M.build.partitions=default_8MB wifiduino32s3.menu.FlashSize.16M=16MB (128Mb) wifiduino32s3.menu.FlashSize.16M.build.flash_size=16MB #wifiduino32s3.menu.FlashSize.32M=32MB (256Mb) @@ -27076,9 +31148,15 @@ wifiduino32s3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 wifiduino32s3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) wifiduino32s3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB wifiduino32s3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -wifiduino32s3.menu.PartitionScheme.rainmaker=RainMaker +wifiduino32s3.menu.PartitionScheme.rainmaker=RainMaker 4MB wifiduino32s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -wifiduino32s3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +wifiduino32s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +wifiduino32s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +wifiduino32s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +wifiduino32s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +wifiduino32s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +wifiduino32s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +wifiduino32s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 wifiduino32s3.menu.CPUFreq.240=240MHz (WiFi) wifiduino32s3.menu.CPUFreq.240.build.f_cpu=240000000L @@ -28283,9 +32361,15 @@ kb32.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 kb32.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) kb32.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB kb32.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -kb32.menu.PartitionScheme.rainmaker=RainMaker +kb32.menu.PartitionScheme.rainmaker=RainMaker 4MB kb32.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -kb32.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +kb32.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +kb32.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +kb32.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +kb32.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +kb32.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +kb32.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +kb32.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 kb32.menu.CPUFreq.240=240MHz (WiFi/BT) kb32.menu.CPUFreq.240.build.f_cpu=240000000L @@ -28320,10 +32404,8 @@ kb32.menu.FlashSize.4M=4MB (32Mb) kb32.menu.FlashSize.4M.build.flash_size=4MB kb32.menu.FlashSize.8M=8MB (64Mb) kb32.menu.FlashSize.8M.build.flash_size=8MB -kb32.menu.FlashSize.8M.build.partitions=default_8MB kb32.menu.FlashSize.2M=2MB (16Mb) kb32.menu.FlashSize.2M.build.flash_size=2MB -kb32.menu.FlashSize.2M.build.partitions=minimal kb32.menu.FlashSize.16M=16MB (128Mb) kb32.menu.FlashSize.16M.build.flash_size=16MB @@ -28457,9 +32539,15 @@ deneyapkart.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 deneyapkart.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) deneyapkart.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB deneyapkart.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -deneyapkart.menu.PartitionScheme.rainmaker=RainMaker +deneyapkart.menu.PartitionScheme.rainmaker=RainMaker 4MB deneyapkart.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -deneyapkart.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +deneyapkart.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +deneyapkart.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +deneyapkart.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +deneyapkart.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +deneyapkart.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +deneyapkart.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +deneyapkart.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 deneyapkart.menu.CPUFreq.240=240MHz (WiFi/BT) deneyapkart.menu.CPUFreq.240.build.f_cpu=240000000L @@ -28494,10 +32582,8 @@ deneyapkart.menu.FlashSize.4M=4MB (32Mb) deneyapkart.menu.FlashSize.4M.build.flash_size=4MB deneyapkart.menu.FlashSize.8M=8MB (64Mb) deneyapkart.menu.FlashSize.8M.build.flash_size=8MB -deneyapkart.menu.FlashSize.8M.build.partitions=default_8MB deneyapkart.menu.FlashSize.2M=2MB (16Mb) deneyapkart.menu.FlashSize.2M.build.flash_size=2MB -deneyapkart.menu.FlashSize.2M.build.partitions=minimal deneyapkart.menu.FlashSize.16M=16MB (128Mb) deneyapkart.menu.FlashSize.16M.build.flash_size=16MB @@ -28631,9 +32717,15 @@ deneyapkart1A.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 deneyapkart1A.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) deneyapkart1A.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB deneyapkart1A.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -deneyapkart1A.menu.PartitionScheme.rainmaker=RainMaker +deneyapkart1A.menu.PartitionScheme.rainmaker=RainMaker 4MB deneyapkart1A.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -deneyapkart1A.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +deneyapkart1A.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +deneyapkart1A.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +deneyapkart1A.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +deneyapkart1A.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +deneyapkart1A.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +deneyapkart1A.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +deneyapkart1A.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 deneyapkart1A.menu.CPUFreq.240=240MHz (WiFi/BT) deneyapkart1A.menu.CPUFreq.240.build.f_cpu=240000000L @@ -28668,10 +32760,8 @@ deneyapkart1A.menu.FlashSize.4M=4MB (32Mb) deneyapkart1A.menu.FlashSize.4M.build.flash_size=4MB deneyapkart1A.menu.FlashSize.8M=8MB (64Mb) deneyapkart1A.menu.FlashSize.8M.build.flash_size=8MB -deneyapkart1A.menu.FlashSize.8M.build.partitions=default_8MB deneyapkart1A.menu.FlashSize.2M=2MB (16Mb) deneyapkart1A.menu.FlashSize.2M.build.flash_size=2MB -deneyapkart1A.menu.FlashSize.2M.build.partitions=minimal deneyapkart1A.menu.FlashSize.16M=16MB (128Mb) deneyapkart1A.menu.FlashSize.16M.build.flash_size=16MB @@ -28815,7 +32905,6 @@ deneyapkart1Av2.menu.FlashSize.4M=4MB (32Mb) deneyapkart1Av2.menu.FlashSize.4M.build.flash_size=4MB deneyapkart1Av2.menu.FlashSize.8M=8MB (64Mb) deneyapkart1Av2.menu.FlashSize.8M.build.flash_size=8MB -deneyapkart1Av2.menu.FlashSize.8M.build.partitions=default_8MB deneyapkart1Av2.menu.FlashSize.16M=16MB (128Mb) deneyapkart1Av2.menu.FlashSize.16M.build.flash_size=16MB #deneyapkart1Av2.menu.FlashSize.32M=32MB (256Mb) @@ -28891,9 +32980,15 @@ deneyapkart1Av2.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 deneyapkart1Av2.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) deneyapkart1Av2.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB deneyapkart1Av2.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -deneyapkart1Av2.menu.PartitionScheme.rainmaker=RainMaker +deneyapkart1Av2.menu.PartitionScheme.rainmaker=RainMaker 4MB deneyapkart1Av2.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -deneyapkart1Av2.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +deneyapkart1Av2.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +deneyapkart1Av2.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +deneyapkart1Av2.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +deneyapkart1Av2.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +deneyapkart1Av2.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +deneyapkart1Av2.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +deneyapkart1Av2.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 deneyapkart1Av2.menu.CPUFreq.240=240MHz (WiFi) deneyapkart1Av2.menu.CPUFreq.240.build.f_cpu=240000000L @@ -29054,9 +33149,15 @@ deneyapmini.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 deneyapmini.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) deneyapmini.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB deneyapmini.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -deneyapmini.menu.PartitionScheme.rainmaker=RainMaker +deneyapmini.menu.PartitionScheme.rainmaker=RainMaker 4MB deneyapmini.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -deneyapmini.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +deneyapmini.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +deneyapmini.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +deneyapmini.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +deneyapmini.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +deneyapmini.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +deneyapmini.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +deneyapmini.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 deneyapmini.menu.CPUFreq.240=240MHz (WiFi) deneyapmini.menu.CPUFreq.240.build.f_cpu=240000000L @@ -29087,10 +33188,8 @@ deneyapmini.menu.FlashSize.4M=4MB (32Mb) deneyapmini.menu.FlashSize.4M.build.flash_size=4MB deneyapmini.menu.FlashSize.8M=8MB (64Mb) deneyapmini.menu.FlashSize.8M.build.flash_size=8MB -deneyapmini.menu.FlashSize.8M.build.partitions=default_8MB deneyapmini.menu.FlashSize.2M=2MB (16Mb) deneyapmini.menu.FlashSize.2M.build.flash_size=2MB -deneyapmini.menu.FlashSize.2M.build.partitions=minimal deneyapmini.menu.FlashSize.16M=16MB (128Mb) deneyapmini.menu.FlashSize.16M.build.flash_size=16MB @@ -29240,9 +33339,15 @@ deneyapminiv2.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 deneyapminiv2.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) deneyapminiv2.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB deneyapminiv2.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -deneyapminiv2.menu.PartitionScheme.rainmaker=RainMaker +deneyapminiv2.menu.PartitionScheme.rainmaker=RainMaker 4MB deneyapminiv2.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -deneyapminiv2.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +deneyapminiv2.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +deneyapminiv2.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +deneyapminiv2.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +deneyapminiv2.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +deneyapminiv2.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +deneyapminiv2.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +deneyapminiv2.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 deneyapminiv2.menu.CPUFreq.240=240MHz (WiFi) deneyapminiv2.menu.CPUFreq.240.build.f_cpu=240000000L @@ -29273,10 +33378,8 @@ deneyapminiv2.menu.FlashSize.4M=4MB (32Mb) deneyapminiv2.menu.FlashSize.4M.build.flash_size=4MB deneyapminiv2.menu.FlashSize.8M=8MB (64Mb) deneyapminiv2.menu.FlashSize.8M.build.flash_size=8MB -deneyapminiv2.menu.FlashSize.8M.build.partitions=default_8MB deneyapminiv2.menu.FlashSize.2M=2MB (16Mb) deneyapminiv2.menu.FlashSize.2M.build.flash_size=2MB -deneyapminiv2.menu.FlashSize.2M.build.partitions=minimal deneyapminiv2.menu.FlashSize.16M=16MB (128Mb) deneyapminiv2.menu.FlashSize.16M.build.flash_size=16MB @@ -29405,9 +33508,15 @@ deneyapkartg.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 deneyapkartg.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) deneyapkartg.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB deneyapkartg.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -deneyapkartg.menu.PartitionScheme.rainmaker=RainMaker +deneyapkartg.menu.PartitionScheme.rainmaker=RainMaker 4MB deneyapkartg.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -deneyapkartg.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +deneyapkartg.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +deneyapkartg.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +deneyapkartg.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +deneyapkartg.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +deneyapkartg.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +deneyapkartg.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +deneyapkartg.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 deneyapkartg.menu.CPUFreq.160=160MHz (WiFi) deneyapkartg.menu.CPUFreq.160.build.f_cpu=160000000L @@ -29436,10 +33545,8 @@ deneyapkartg.menu.FlashSize.4M=4MB (32Mb) deneyapkartg.menu.FlashSize.4M.build.flash_size=4MB deneyapkartg.menu.FlashSize.8M=8MB (64Mb) deneyapkartg.menu.FlashSize.8M.build.flash_size=8MB -deneyapkartg.menu.FlashSize.8M.build.partitions=default_8MB deneyapkartg.menu.FlashSize.2M=2MB (16Mb) deneyapkartg.menu.FlashSize.2M.build.flash_size=2MB -deneyapkartg.menu.FlashSize.2M.build.partitions=minimal deneyapkartg.menu.FlashSize.16M=16MB (128Mb) deneyapkartg.menu.FlashSize.16M.build.flash_size=16MB @@ -29743,10 +33850,8 @@ atmegazero_esp32s2.menu.FlashSize.4M=4MB (32Mb) atmegazero_esp32s2.menu.FlashSize.4M.build.flash_size=4MB atmegazero_esp32s2.menu.FlashSize.8M=8MB (64Mb) atmegazero_esp32s2.menu.FlashSize.8M.build.flash_size=8MB -atmegazero_esp32s2.menu.FlashSize.8M.build.partitions=default_8MB atmegazero_esp32s2.menu.FlashSize.2M=2MB (16Mb) atmegazero_esp32s2.menu.FlashSize.2M.build.flash_size=2MB -atmegazero_esp32s2.menu.FlashSize.2M.build.partitions=minimal atmegazero_esp32s2.menu.FlashSize.16M=16MB (128Mb) atmegazero_esp32s2.menu.FlashSize.16M.build.flash_size=16MB @@ -29835,7 +33940,6 @@ franzininho_wifi_esp32s2.menu.FlashSize.4M=4MB (32Mb) franzininho_wifi_esp32s2.menu.FlashSize.4M.build.flash_size=4MB franzininho_wifi_esp32s2.menu.FlashSize.8M=8MB (64Mb) franzininho_wifi_esp32s2.menu.FlashSize.8M.build.flash_size=8MB -franzininho_wifi_esp32s2.menu.FlashSize.8M.build.partitions=default_8MB franzininho_wifi_esp32s2.menu.FlashSize.16M=16MB (128Mb) franzininho_wifi_esp32s2.menu.FlashSize.16M.build.flash_size=16MB @@ -29943,7 +34047,6 @@ franzininho_wifi_msc_esp32s2.menu.FlashSize.4M=4MB (32Mb) franzininho_wifi_msc_esp32s2.menu.FlashSize.4M.build.flash_size=4MB franzininho_wifi_msc_esp32s2.menu.FlashSize.8M=8MB (64Mb) franzininho_wifi_msc_esp32s2.menu.FlashSize.8M.build.flash_size=8MB -franzininho_wifi_msc_esp32s2.menu.FlashSize.8M.build.partitions=default_8MB franzininho_wifi_msc_esp32s2.menu.FlashSize.16M=16MB (128Mb) franzininho_wifi_msc_esp32s2.menu.FlashSize.16M.build.flash_size=16MB @@ -30080,7 +34183,6 @@ tamc_termod_s3.menu.FlashSize.4M=4MB (32Mb) tamc_termod_s3.menu.FlashSize.4M.build.flash_size=4MB tamc_termod_s3.menu.FlashSize.8M=8MB (64Mb) tamc_termod_s3.menu.FlashSize.8M.build.flash_size=8MB -tamc_termod_s3.menu.FlashSize.8M.build.partitions=default_8MB tamc_termod_s3.menu.FlashSize.16M=16MB (128Mb) tamc_termod_s3.menu.FlashSize.16M.build.flash_size=16MB @@ -30154,9 +34256,15 @@ tamc_termod_s3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 tamc_termod_s3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9MB FATFS) tamc_termod_s3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB tamc_termod_s3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -tamc_termod_s3.menu.PartitionScheme.rainmaker=RainMaker +tamc_termod_s3.menu.PartitionScheme.rainmaker=RainMaker 4MB tamc_termod_s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -tamc_termod_s3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +tamc_termod_s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +tamc_termod_s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +tamc_termod_s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +tamc_termod_s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +tamc_termod_s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +tamc_termod_s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +tamc_termod_s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 tamc_termod_s3.menu.CPUFreq.240=240MHz (WiFi) tamc_termod_s3.menu.CPUFreq.240.build.f_cpu=240000000L @@ -30355,9 +34463,12 @@ sonoff_dualr3.build.defines= sonoff_dualr3.build.loop_core= sonoff_dualr3.build.event_core= -sonoff_dualr3.menu.PartitionScheme.rainmaker=RainMaker +sonoff_dualr3.menu.PartitionScheme.rainmaker=RainMaker 4MB sonoff_dualr3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -sonoff_dualr3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +sonoff_dualr3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +sonoff_dualr3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +sonoff_dualr3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +sonoff_dualr3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 sonoff_dualr3.menu.CPUFreq.240=240MHz (WiFi/BT) sonoff_dualr3.menu.CPUFreq.240.build.f_cpu=240000000L @@ -30494,9 +34605,12 @@ lionbit.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 lionbit.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) lionbit.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB lionbit.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -lionbit.menu.PartitionScheme.rainmaker=RainMaker +lionbit.menu.PartitionScheme.rainmaker=RainMaker 4MB lionbit.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -lionbit.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +lionbit.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +lionbit.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +lionbit.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +lionbit.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 lionbit.menu.CPUFreq.240=240MHz (WiFi/BT) lionbit.menu.CPUFreq.240.build.f_cpu=240000000L @@ -30530,7 +34644,6 @@ lionbit.menu.FlashFreq.40.build.flash_freq=40m lionbit.menu.FlashSize.4M=4MB (32Mb) lionbit.menu.FlashSize.4M.build.flash_size=4MB -lionbit.menu.FlashSize.4M.build.partitions=default @@ -30841,9 +34954,15 @@ XIAO_ESP32C3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 XIAO_ESP32C3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) XIAO_ESP32C3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB XIAO_ESP32C3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -XIAO_ESP32C3.menu.PartitionScheme.rainmaker=RainMaker +XIAO_ESP32C3.menu.PartitionScheme.rainmaker=RainMaker 4MB XIAO_ESP32C3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -XIAO_ESP32C3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +XIAO_ESP32C3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +XIAO_ESP32C3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +XIAO_ESP32C3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +XIAO_ESP32C3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +XIAO_ESP32C3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +XIAO_ESP32C3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +XIAO_ESP32C3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 XIAO_ESP32C3.menu.CPUFreq.160=160MHz (WiFi) XIAO_ESP32C3.menu.CPUFreq.160.build.f_cpu=160000000L @@ -30872,10 +34991,8 @@ XIAO_ESP32C3.menu.FlashSize.4M=4MB (32Mb) XIAO_ESP32C3.menu.FlashSize.4M.build.flash_size=4MB XIAO_ESP32C3.menu.FlashSize.8M=8MB (64Mb) XIAO_ESP32C3.menu.FlashSize.8M.build.flash_size=8MB -XIAO_ESP32C3.menu.FlashSize.8M.build.partitions=default_8MB XIAO_ESP32C3.menu.FlashSize.2M=2MB (16Mb) XIAO_ESP32C3.menu.FlashSize.2M.build.flash_size=2MB -XIAO_ESP32C3.menu.FlashSize.2M.build.partitions=minimal XIAO_ESP32C3.menu.FlashSize.16M=16MB (128Mb) XIAO_ESP32C3.menu.FlashSize.16M.build.flash_size=16MB @@ -30938,7 +35055,7 @@ XIAO_ESP32C6.build.target=esp XIAO_ESP32C6.build.mcu=esp32c6 XIAO_ESP32C6.build.core=esp32 XIAO_ESP32C6.build.variant=XIAO_ESP32C6 -XIAO_ESP32C6.build.board=XIAO_ESP32C3 +XIAO_ESP32C6.build.board=XIAO_ESP32C6 XIAO_ESP32C6.build.bootloader_addr=0x0 XIAO_ESP32C6.build.cdc_on_boot=1 @@ -31058,13 +35175,10 @@ XIAO_ESP32C6.menu.ZigbeeMode.default.build.zigbee_mode= XIAO_ESP32C6.menu.ZigbeeMode.default.build.zigbee_libs= XIAO_ESP32C6.menu.ZigbeeMode.ed=Zigbee ED (end device) XIAO_ESP32C6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED -XIAO_ESP32C6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -XIAO_ESP32C6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +XIAO_ESP32C6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +XIAO_ESP32C6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) XIAO_ESP32C6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -XIAO_ESP32C6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port -XIAO_ESP32C6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) -XIAO_ESP32C6.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP -XIAO_ESP32C6.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port +XIAO_ESP32C6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native ############################################################## @@ -31148,7 +35262,6 @@ XIAO_ESP32S3.menu.FlashMode.dio.build.flash_freq=80m XIAO_ESP32S3.menu.FlashSize.8M=8MB (64Mb) XIAO_ESP32S3.menu.FlashSize.8M.build.flash_size=8MB -XIAO_ESP32S3.menu.FlashSize.8M.build.partitions=default_8MB XIAO_ESP32S3.menu.LoopCore.1=Core 1 XIAO_ESP32S3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -31247,6 +35360,192 @@ XIAO_ESP32S3.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +XIAO_ESP32S3_Plus.name=XIAO_ESP32S3_PLUS +XIAO_ESP32S3_Plus.vid.0=0x2886 +XIAO_ESP32S3_Plus.pid.0=0x0063 +XIAO_ESP32S3_Plus.vid.1=0x2886 +XIAO_ESP32S3_Plus.pid.1=0x8063 + +XIAO_ESP32S3_Plus.bootloader.tool=esptool_py +XIAO_ESP32S3_Plus.bootloader.tool.default=esptool_py + +XIAO_ESP32S3_Plus.upload.tool=esptool_py +XIAO_ESP32S3_Plus.upload.tool.default=esptool_py +XIAO_ESP32S3_Plus.upload.tool.network=esp_ota + +XIAO_ESP32S3_Plus.upload.maximum_size=1310720 +XIAO_ESP32S3_Plus.upload.maximum_data_size=327680 +XIAO_ESP32S3_Plus.upload.flags= +XIAO_ESP32S3_Plus.upload.extra_flags= +XIAO_ESP32S3_Plus.upload.use_1200bps_touch=false +XIAO_ESP32S3_Plus.upload.wait_for_upload_port=false + +XIAO_ESP32S3_Plus.serial.disableDTR=false +XIAO_ESP32S3_Plus.serial.disableRTS=false + +XIAO_ESP32S3_Plus.build.tarch=xtensa +XIAO_ESP32S3_Plus.build.bootloader_addr=0x0 +XIAO_ESP32S3_Plus.build.target=esp32s3 +XIAO_ESP32S3_Plus.build.mcu=esp32s3 +XIAO_ESP32S3_Plus.build.core=esp32 +XIAO_ESP32S3_Plus.build.variant=XIAO_ESP32S3_Plus +XIAO_ESP32S3_Plus.build.board=XIAO_ESP32S3_PLUS + +XIAO_ESP32S3_Plus.build.usb_mode=0 +XIAO_ESP32S3_Plus.build.cdc_on_boot=1 +XIAO_ESP32S3_Plus.build.msc_on_boot=0 +XIAO_ESP32S3_Plus.build.dfu_on_boot=0 +XIAO_ESP32S3_Plus.build.f_cpu=240000000L +XIAO_ESP32S3_Plus.build.flash_size=8MB +XIAO_ESP32S3_Plus.build.flash_freq=80m +XIAO_ESP32S3_Plus.build.flash_mode=dio +XIAO_ESP32S3_Plus.build.boot=qio +XIAO_ESP32S3_Plus.build.boot_freq=80m +XIAO_ESP32S3_Plus.build.partitions=default_8MB +XIAO_ESP32S3_Plus.build.defines= +XIAO_ESP32S3_Plus.build.loop_core= +XIAO_ESP32S3_Plus.build.event_core= +XIAO_ESP32S3_Plus.build.psram_type=qspi +XIAO_ESP32S3_Plus.build.memory_type={build.boot}_{build.psram_type} + +XIAO_ESP32S3_Plus.menu.JTAGAdapter.default=Disabled +XIAO_ESP32S3_Plus.menu.JTAGAdapter.default.build.copy_jtag_files=0 +XIAO_ESP32S3_Plus.menu.JTAGAdapter.builtin=Integrated USB JTAG +XIAO_ESP32S3_Plus.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +XIAO_ESP32S3_Plus.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +XIAO_ESP32S3_Plus.menu.JTAGAdapter.external=FTDI Adapter +XIAO_ESP32S3_Plus.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +XIAO_ESP32S3_Plus.menu.JTAGAdapter.external.build.copy_jtag_files=1 +XIAO_ESP32S3_Plus.menu.JTAGAdapter.bridge=ESP USB Bridge +XIAO_ESP32S3_Plus.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +XIAO_ESP32S3_Plus.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +XIAO_ESP32S3_Plus.menu.PSRAM.disabled=Disabled +XIAO_ESP32S3_Plus.menu.PSRAM.disabled.build.defines= +XIAO_ESP32S3_Plus.menu.PSRAM.disabled.build.psram_type=qspi +XIAO_ESP32S3_Plus.menu.PSRAM.opi=OPI PSRAM +XIAO_ESP32S3_Plus.menu.PSRAM.opi.build.defines=-DBOARD_HAS_PSRAM +XIAO_ESP32S3_Plus.menu.PSRAM.opi.build.psram_type=opi + +XIAO_ESP32S3_Plus.menu.FlashMode.qio=QIO 80MHz +XIAO_ESP32S3_Plus.menu.FlashMode.qio.build.flash_mode=dio +XIAO_ESP32S3_Plus.menu.FlashMode.qio.build.boot=qio +XIAO_ESP32S3_Plus.menu.FlashMode.qio.build.boot_freq=80m +XIAO_ESP32S3_Plus.menu.FlashMode.qio.build.flash_freq=80m +XIAO_ESP32S3_Plus.menu.FlashMode.dio=DIO 80MHz +XIAO_ESP32S3_Plus.menu.FlashMode.dio.build.flash_mode=dio +XIAO_ESP32S3_Plus.menu.FlashMode.dio.build.boot=dio +XIAO_ESP32S3_Plus.menu.FlashMode.dio.build.boot_freq=80m +XIAO_ESP32S3_Plus.menu.FlashMode.dio.build.flash_freq=80m + +XIAO_ESP32S3_Plus.menu.FlashSize.8M=8MB (64Mb) +XIAO_ESP32S3_Plus.menu.FlashSize.8M.build.flash_size=8MB +XIAO_ESP32S3_Plus.menu.FlashSize.16M=16MB (128Mb) +XIAO_ESP32S3_Plus.menu.FlashSize.16M.build.flash_size=16MB + +XIAO_ESP32S3_Plus.menu.LoopCore.1=Core 1 +XIAO_ESP32S3_Plus.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +XIAO_ESP32S3_Plus.menu.LoopCore.0=Core 0 +XIAO_ESP32S3_Plus.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +XIAO_ESP32S3_Plus.menu.EventsCore.1=Core 1 +XIAO_ESP32S3_Plus.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +XIAO_ESP32S3_Plus.menu.EventsCore.0=Core 0 +XIAO_ESP32S3_Plus.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +XIAO_ESP32S3_Plus.menu.USBMode.hwcdc=Hardware CDC and JTAG +XIAO_ESP32S3_Plus.menu.USBMode.hwcdc.build.usb_mode=1 +XIAO_ESP32S3_Plus.menu.USBMode.default=USB-OTG (TinyUSB) +XIAO_ESP32S3_Plus.menu.USBMode.default.build.usb_mode=0 + +XIAO_ESP32S3_Plus.menu.CDCOnBoot.default=Enabled +XIAO_ESP32S3_Plus.menu.CDCOnBoot.default.build.cdc_on_boot=1 +XIAO_ESP32S3_Plus.menu.CDCOnBoot.cdc=Disabled +XIAO_ESP32S3_Plus.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +XIAO_ESP32S3_Plus.menu.MSCOnBoot.default=Disabled +XIAO_ESP32S3_Plus.menu.MSCOnBoot.default.build.msc_on_boot=0 +XIAO_ESP32S3_Plus.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +XIAO_ESP32S3_Plus.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +XIAO_ESP32S3_Plus.menu.DFUOnBoot.default=Disabled +XIAO_ESP32S3_Plus.menu.DFUOnBoot.default.build.dfu_on_boot=0 +XIAO_ESP32S3_Plus.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +XIAO_ESP32S3_Plus.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +XIAO_ESP32S3_Plus.menu.UploadMode.default=UART0 / Hardware CDC +XIAO_ESP32S3_Plus.menu.UploadMode.default.upload.use_1200bps_touch=false +XIAO_ESP32S3_Plus.menu.UploadMode.default.upload.wait_for_upload_port=false +XIAO_ESP32S3_Plus.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +XIAO_ESP32S3_Plus.menu.UploadMode.cdc.upload.use_1200bps_touch=true +XIAO_ESP32S3_Plus.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +XIAO_ESP32S3_Plus.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +XIAO_ESP32S3_Plus.menu.PartitionScheme.fatflash.build.partitions=ffat +XIAO_ESP32S3_Plus.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +XIAO_ESP32S3_Plus.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +XIAO_ESP32S3_Plus.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +XIAO_ESP32S3_Plus.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +XIAO_ESP32S3_Plus.menu.PartitionScheme.default_8MB=Default with spiffs (3MB APP/1.5MB SPIFFS) +XIAO_ESP32S3_Plus.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +XIAO_ESP32S3_Plus.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +XIAO_ESP32S3_Plus.menu.PartitionScheme.max_app_8MB=Maximum APP (7.9MB APP No OTA/No FS) +XIAO_ESP32S3_Plus.menu.PartitionScheme.max_app_8MB.build.partitions=max_app_8MB +XIAO_ESP32S3_Plus.menu.PartitionScheme.max_app_8MB.upload.maximum_size=8257536 +XIAO_ESP32S3_Plus.menu.PartitionScheme.tinyuf2=TinyUF2 8MB (2MB APP/3.7MB FFAT) +XIAO_ESP32S3_Plus.menu.PartitionScheme.tinyuf2.build.custom_bootloader=bootloader-tinyuf2 +XIAO_ESP32S3_Plus.menu.PartitionScheme.tinyuf2.build.custom_partitions=partitions-8MB +XIAO_ESP32S3_Plus.menu.PartitionScheme.tinyuf2.upload.maximum_size=2097152 +XIAO_ESP32S3_Plus.menu.PartitionScheme.tinyuf2.upload.extra_flags=0x410000 "{runtime.platform.path}/variants/{build.variant}/tinyuf2.bin" + +XIAO_ESP32S3_Plus.menu.CPUFreq.240=240MHz (WiFi) +XIAO_ESP32S3_Plus.menu.CPUFreq.240.build.f_cpu=240000000L +XIAO_ESP32S3_Plus.menu.CPUFreq.160=160MHz (WiFi) +XIAO_ESP32S3_Plus.menu.CPUFreq.160.build.f_cpu=160000000L +XIAO_ESP32S3_Plus.menu.CPUFreq.80=80MHz (WiFi) +XIAO_ESP32S3_Plus.menu.CPUFreq.80.build.f_cpu=80000000L +XIAO_ESP32S3_Plus.menu.CPUFreq.40=40MHz +XIAO_ESP32S3_Plus.menu.CPUFreq.40.build.f_cpu=40000000L +XIAO_ESP32S3_Plus.menu.CPUFreq.20=20MHz +XIAO_ESP32S3_Plus.menu.CPUFreq.20.build.f_cpu=20000000L +XIAO_ESP32S3_Plus.menu.CPUFreq.10=10MHz +XIAO_ESP32S3_Plus.menu.CPUFreq.10.build.f_cpu=10000000L + +XIAO_ESP32S3_Plus.menu.UploadSpeed.921600=921600 +XIAO_ESP32S3_Plus.menu.UploadSpeed.921600.upload.speed=921600 +XIAO_ESP32S3_Plus.menu.UploadSpeed.115200=115200 +XIAO_ESP32S3_Plus.menu.UploadSpeed.115200.upload.speed=115200 +XIAO_ESP32S3_Plus.menu.UploadSpeed.256000.windows=256000 +XIAO_ESP32S3_Plus.menu.UploadSpeed.256000.upload.speed=256000 +XIAO_ESP32S3_Plus.menu.UploadSpeed.230400.windows.upload.speed=256000 +XIAO_ESP32S3_Plus.menu.UploadSpeed.230400=230400 +XIAO_ESP32S3_Plus.menu.UploadSpeed.230400.upload.speed=230400 +XIAO_ESP32S3_Plus.menu.UploadSpeed.460800.linux=460800 +XIAO_ESP32S3_Plus.menu.UploadSpeed.460800.macosx=460800 +XIAO_ESP32S3_Plus.menu.UploadSpeed.460800.upload.speed=460800 +XIAO_ESP32S3_Plus.menu.UploadSpeed.512000.windows=512000 +XIAO_ESP32S3_Plus.menu.UploadSpeed.512000.upload.speed=512000 + +XIAO_ESP32S3_Plus.menu.DebugLevel.none=None +XIAO_ESP32S3_Plus.menu.DebugLevel.none.build.code_debug=0 +XIAO_ESP32S3_Plus.menu.DebugLevel.error=Error +XIAO_ESP32S3_Plus.menu.DebugLevel.error.build.code_debug=1 +XIAO_ESP32S3_Plus.menu.DebugLevel.warn=Warn +XIAO_ESP32S3_Plus.menu.DebugLevel.warn.build.code_debug=2 +XIAO_ESP32S3_Plus.menu.DebugLevel.info=Info +XIAO_ESP32S3_Plus.menu.DebugLevel.info.build.code_debug=3 +XIAO_ESP32S3_Plus.menu.DebugLevel.debug=Debug +XIAO_ESP32S3_Plus.menu.DebugLevel.debug.build.code_debug=4 +XIAO_ESP32S3_Plus.menu.DebugLevel.verbose=Verbose +XIAO_ESP32S3_Plus.menu.DebugLevel.verbose.build.code_debug=5 + +XIAO_ESP32S3_Plus.menu.EraseFlash.none=Disabled +XIAO_ESP32S3_Plus.menu.EraseFlash.none.upload.erase_cmd= +XIAO_ESP32S3_Plus.menu.EraseFlash.all=Enabled +XIAO_ESP32S3_Plus.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + connaxio_espoir.name=Connaxio's Espoir connaxio_espoir.vid.0=0x10C4 connaxio_espoir.pid.0=0x8D9A @@ -31308,9 +35607,12 @@ connaxio_espoir.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 connaxio_espoir.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) connaxio_espoir.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs connaxio_espoir.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -connaxio_espoir.menu.PartitionScheme.rainmaker=RainMaker +connaxio_espoir.menu.PartitionScheme.rainmaker=RainMaker 4MB connaxio_espoir.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -connaxio_espoir.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +connaxio_espoir.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +connaxio_espoir.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +connaxio_espoir.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +connaxio_espoir.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 connaxio_espoir.menu.CPUFreq.240=240MHz (WiFi/BT) connaxio_espoir.menu.CPUFreq.240.build.f_cpu=240000000L @@ -31568,10 +35870,8 @@ department_of_alchemy_minimain_esp32s2.menu.FlashSize.4M=4MB (32Mb) department_of_alchemy_minimain_esp32s2.menu.FlashSize.4M.build.flash_size=4MB department_of_alchemy_minimain_esp32s2.menu.FlashSize.8M=8MB (64Mb) department_of_alchemy_minimain_esp32s2.menu.FlashSize.8M.build.flash_size=8MB -department_of_alchemy_minimain_esp32s2.menu.FlashSize.8M.build.partitions=default_8MB department_of_alchemy_minimain_esp32s2.menu.FlashSize.2M=2MB (16Mb) department_of_alchemy_minimain_esp32s2.menu.FlashSize.2M.build.flash_size=2MB -department_of_alchemy_minimain_esp32s2.menu.FlashSize.2M.build.partitions=minimal department_of_alchemy_minimain_esp32s2.menu.FlashSize.16M=16MB (128Mb) department_of_alchemy_minimain_esp32s2.menu.FlashSize.16M.build.flash_size=16MB @@ -31613,9 +35913,9 @@ department_of_alchemy_minimain_esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e Bee_Data_Logger.name=Bee Data Logger Bee_Data_Logger.vid.0=0x303a -Bee_Data_Logger.pid.0=815C +Bee_Data_Logger.pid.0=0x815C Bee_Data_Logger.upload_port.0.vid=0x303a -Bee_Data_Logger.upload_port.0.pid=815C +Bee_Data_Logger.upload_port.0.pid=0x815C Bee_Data_Logger.bootloader.tool=esptool_py Bee_Data_Logger.bootloader.tool.default=esptool_py @@ -31837,7 +36137,7 @@ Bee_Motion.name=Bee Motion Bee_Motion.vid.0=0x303a Bee_Motion.pid.0=0x810D Bee_Motion.vid.upload_port.0.vid=0x303a -Bee_Motion.pid.upload_port.0.vid=0x810D +Bee_Motion.pid.upload_port.0.pid=0x810D Bee_Motion.bootloader.tool=esptool_py Bee_Motion.bootloader.tool.default=esptool_py @@ -32056,7 +36356,7 @@ Bee_S3.name=Bee S3 Bee_S3.vid.0=0x303a Bee_S3.pid.0=0x8110 Bee_S3.vid.upload_port.0.vid=0x303a -Bee_S3.pid.upload_port.0.vid=0x8110 +Bee_S3.pid.upload_port.0.pid=0x8110 Bee_S3.bootloader.tool=esptool_py Bee_S3.bootloader.tool.default=esptool_py @@ -32390,9 +36690,15 @@ unphone8.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 unphone8.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) unphone8.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs unphone8.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -unphone8.menu.PartitionScheme.rainmaker=RainMaker +unphone8.menu.PartitionScheme.rainmaker=RainMaker 4MB unphone8.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -unphone8.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +unphone8.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +unphone8.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +unphone8.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +unphone8.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +unphone8.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +unphone8.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +unphone8.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 unphone8.menu.PartitionScheme.max_app_8MB=Maximum APP (7.9MB APP No OTA/No FS) unphone8.menu.PartitionScheme.max_app_8MB.build.partitions=max_app_8MB @@ -32540,9 +36846,15 @@ unphone9.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 unphone9.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) unphone9.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs unphone9.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -unphone9.menu.PartitionScheme.rainmaker=RainMaker +unphone9.menu.PartitionScheme.rainmaker=RainMaker 4MB unphone9.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -unphone9.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +unphone9.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +unphone9.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +unphone9.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +unphone9.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +unphone9.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +unphone9.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +unphone9.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 unphone9.menu.PartitionScheme.max_app_8MB=Maximum APP (7.9MB APP No OTA/No FS) unphone9.menu.PartitionScheme.max_app_8MB.build.partitions=max_app_8MB @@ -33007,9 +37319,12 @@ esp32c3m1IKit.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 esp32c3m1IKit.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) esp32c3m1IKit.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs esp32c3m1IKit.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -esp32c3m1IKit.menu.PartitionScheme.rainmaker=RainMaker +esp32c3m1IKit.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32c3m1IKit.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -esp32c3m1IKit.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +esp32c3m1IKit.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +esp32c3m1IKit.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +esp32c3m1IKit.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +esp32c3m1IKit.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 esp32c3m1IKit.menu.CPUFreq.160=160MHz (WiFi) esp32c3m1IKit.menu.CPUFreq.160.build.f_cpu=160000000L @@ -33120,9 +37435,12 @@ roboheart_hercules.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 roboheart_hercules.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9MB FATFS) roboheart_hercules.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB roboheart_hercules.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -roboheart_hercules.menu.PartitionScheme.rainmaker=RainMaker +roboheart_hercules.menu.PartitionScheme.rainmaker=RainMaker 4MB roboheart_hercules.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -roboheart_hercules.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +roboheart_hercules.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +roboheart_hercules.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +roboheart_hercules.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +roboheart_hercules.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 roboheart_hercules.menu.CPUFreq.240=240MHz (WiFi/BT) roboheart_hercules.menu.CPUFreq.240.build.f_cpu=240000000L @@ -33257,9 +37575,15 @@ VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.fatflash.upload.maximum_size=20971 VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.rainmaker=RainMaker +VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.rainmaker=RainMaker 4MB VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +VALTRACK_V4_VTS_ESP32_C3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 VALTRACK_V4_VTS_ESP32_C3.menu.CPUFreq.160=160MHz (WiFi) VALTRACK_V4_VTS_ESP32_C3.menu.CPUFreq.160.build.f_cpu=160000000L @@ -33288,10 +37612,8 @@ VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.4M=4MB (32Mb) VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.4M.build.flash_size=4MB VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.8M=8MB (64Mb) VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.8M.build.flash_size=8MB -VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.8M.build.partitions=default_8MB VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.2M=2MB (16Mb) VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.2M.build.flash_size=2MB -VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.2M.build.partitions=minimal VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.16M=16MB (128Mb) VALTRACK_V4_VTS_ESP32_C3.menu.FlashSize.16M.build.flash_size=16MB @@ -33404,9 +37726,15 @@ VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.fatflash.upload.maximum_size=20971 VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.rainmaker=RainMaker +VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.rainmaker=RainMaker 4MB VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +VALTRACK_V4_MFW_ESP32_C3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 VALTRACK_V4_MFW_ESP32_C3.menu.CPUFreq.160=160MHz (WiFi) VALTRACK_V4_MFW_ESP32_C3.menu.CPUFreq.160.build.f_cpu=160000000L @@ -33435,10 +37763,8 @@ VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.4M=4MB (32Mb) VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.4M.build.flash_size=4MB VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.8M=8MB (64Mb) VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.8M.build.flash_size=8MB -VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.8M.build.partitions=default_8MB VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.2M=2MB (16Mb) VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.2M.build.flash_size=2MB -VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.2M.build.partitions=minimal VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.16M=16MB (128Mb) VALTRACK_V4_MFW_ESP32_C3.menu.FlashSize.16M.build.flash_size=16MB @@ -33556,7 +37882,6 @@ Edgebox-ESP-100.menu.FlashSize.4M=4MB (32Mb) Edgebox-ESP-100.menu.FlashSize.4M.build.flash_size=4MB Edgebox-ESP-100.menu.FlashSize.8M=8MB (64Mb) Edgebox-ESP-100.menu.FlashSize.8M.build.flash_size=8MB -Edgebox-ESP-100.menu.FlashSize.8M.build.partitions=default_8MB Edgebox-ESP-100.menu.FlashSize.16M=16MB (128Mb) Edgebox-ESP-100.menu.FlashSize.16M.build.flash_size=16MB #Edgebox-ESP-100.menu.FlashSize.32M=32MB (256Mb) @@ -33632,9 +37957,15 @@ Edgebox-ESP-100.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 Edgebox-ESP-100.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) Edgebox-ESP-100.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB Edgebox-ESP-100.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -Edgebox-ESP-100.menu.PartitionScheme.rainmaker=RainMaker +Edgebox-ESP-100.menu.PartitionScheme.rainmaker=RainMaker 4MB Edgebox-ESP-100.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -Edgebox-ESP-100.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +Edgebox-ESP-100.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +Edgebox-ESP-100.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +Edgebox-ESP-100.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +Edgebox-ESP-100.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +Edgebox-ESP-100.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +Edgebox-ESP-100.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +Edgebox-ESP-100.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 Edgebox-ESP-100.menu.CPUFreq.240=240MHz (WiFi) Edgebox-ESP-100.menu.CPUFreq.240.build.f_cpu=240000000L @@ -33923,7 +38254,6 @@ nebulas3.menu.FlashSize.4M=4MB (32Mb) nebulas3.menu.FlashSize.4M.build.flash_size=4MB nebulas3.menu.FlashSize.8M=8MB (64Mb) nebulas3.menu.FlashSize.8M.build.flash_size=8MB -nebulas3.menu.FlashSize.8M.build.partitions=default_8MB nebulas3.menu.FlashSize.16M=16MB (128Mb) nebulas3.menu.FlashSize.16M.build.flash_size=16MB @@ -33997,9 +38327,15 @@ nebulas3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 nebulas3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) nebulas3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB nebulas3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -nebulas3.menu.PartitionScheme.rainmaker=RainMaker +nebulas3.menu.PartitionScheme.rainmaker=RainMaker 4MB nebulas3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -nebulas3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +nebulas3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +nebulas3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +nebulas3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +nebulas3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +nebulas3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +nebulas3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +nebulas3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 nebulas3.menu.CPUFreq.240=240MHz (WiFi) nebulas3.menu.CPUFreq.240.build.f_cpu=240000000L @@ -34142,7 +38478,6 @@ lionbits3.menu.FlashSize.4M=4MB (32Mb) lionbits3.menu.FlashSize.4M.build.flash_size=4MB lionbits3.menu.FlashSize.8M=8MB (64Mb) lionbits3.menu.FlashSize.8M.build.flash_size=8MB -lionbits3.menu.FlashSize.8M.build.partitions=default_8MB lionbits3.menu.FlashSize.16M=16MB (128Mb) lionbits3.menu.FlashSize.16M.build.flash_size=16MB #lionbits3.menu.FlashSize.32M=32MB (256Mb) @@ -34218,9 +38553,15 @@ lionbits3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 lionbits3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) lionbits3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB lionbits3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 -lionbits3.menu.PartitionScheme.rainmaker=RainMaker +lionbits3.menu.PartitionScheme.rainmaker=RainMaker 4MB lionbits3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -lionbits3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +lionbits3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +lionbits3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +lionbits3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +lionbits3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +lionbits3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +lionbits3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +lionbits3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 lionbits3.menu.CPUFreq.240=240MHz (WiFi) lionbits3.menu.CPUFreq.240.build.f_cpu=240000000L @@ -34992,6 +39333,8 @@ namino_bianco.menu.EraseFlash.all=Enabled namino_bianco.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +# IOXESP32, IOXESP32U + ioxesp32.name=IOXESP32 ioxesp32.bootloader.tool=esptool_py @@ -35056,9 +39399,12 @@ ioxesp32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 ioxesp32.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) ioxesp32.menu.PartitionScheme.fatflash.build.partitions=ffat ioxesp32.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -ioxesp32.menu.PartitionScheme.rainmaker=RainMaker +ioxesp32.menu.PartitionScheme.rainmaker=RainMaker 4MB ioxesp32.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -ioxesp32.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +ioxesp32.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +ioxesp32.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +ioxesp32.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +ioxesp32.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 ioxesp32.menu.FlashFreq.80=80MHz ioxesp32.menu.FlashFreq.80.build.flash_freq=80m @@ -35099,6 +39445,7 @@ ioxesp32.menu.EraseFlash.all=Enabled ioxesp32.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +# IOXESP32PS ioxesp32ps.name=IOXESP32PS @@ -35164,9 +39511,12 @@ ioxesp32ps.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 ioxesp32ps.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) ioxesp32ps.menu.PartitionScheme.fatflash.build.partitions=ffat ioxesp32ps.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -ioxesp32ps.menu.PartitionScheme.rainmaker=RainMaker +ioxesp32ps.menu.PartitionScheme.rainmaker=RainMaker 4MB ioxesp32ps.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -ioxesp32ps.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +ioxesp32ps.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +ioxesp32ps.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +ioxesp32ps.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +ioxesp32ps.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 ioxesp32ps.menu.FlashFreq.80=80MHz ioxesp32ps.menu.FlashFreq.80.build.flash_freq=80m @@ -35207,6 +39557,175 @@ ioxesp32ps.menu.EraseFlash.all=Enabled ioxesp32ps.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +# IOXESP32-C6 + +ioxesp32c6.name=IOXESP32-C6 + +ioxesp32c6.bootloader.tool=esptool_py +ioxesp32c6.bootloader.tool.default=esptool_py + +ioxesp32c6.upload.tool=esptool_py +ioxesp32c6.upload.tool.default=esptool_py +ioxesp32c6.upload.tool.network=esp_ota + +ioxesp32c6.upload.maximum_size=1310720 +ioxesp32c6.upload.maximum_data_size=327680 +ioxesp32c6.upload.flags= +ioxesp32c6.upload.extra_flags= +ioxesp32c6.upload.use_1200bps_touch=false +ioxesp32c6.upload.wait_for_upload_port=false + +ioxesp32c6.serial.disableDTR=false +ioxesp32c6.serial.disableRTS=false + +ioxesp32c6.build.tarch=riscv32 +ioxesp32c6.build.target=esp +ioxesp32c6.build.mcu=esp32c6 +ioxesp32c6.build.core=esp32 +ioxesp32c6.build.variant=ioxesp32c6 +ioxesp32c6.build.board=ESP32C6_DEV +ioxesp32c6.build.bootloader_addr=0x0 + +ioxesp32c6.build.cdc_on_boot=0 +ioxesp32c6.build.f_cpu=160000000L +ioxesp32c6.build.flash_size=4MB +ioxesp32c6.build.flash_freq=80m +ioxesp32c6.build.flash_mode=qio +ioxesp32c6.build.boot=qio +ioxesp32c6.build.partitions=default +ioxesp32c6.build.defines= + +## IDE 2.0 Seems to not update the value +ioxesp32c6.menu.JTAGAdapter.default=Disabled +ioxesp32c6.menu.JTAGAdapter.default.build.copy_jtag_files=0 +ioxesp32c6.menu.JTAGAdapter.builtin=Integrated USB JTAG +ioxesp32c6.menu.JTAGAdapter.builtin.build.openocdscript=esp32c6-builtin.cfg +ioxesp32c6.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +ioxesp32c6.menu.JTAGAdapter.external=FTDI Adapter +ioxesp32c6.menu.JTAGAdapter.external.build.openocdscript=esp32c6-ftdi.cfg +ioxesp32c6.menu.JTAGAdapter.external.build.copy_jtag_files=1 +ioxesp32c6.menu.JTAGAdapter.bridge=ESP USB Bridge +ioxesp32c6.menu.JTAGAdapter.bridge.build.openocdscript=esp32c6-bridge.cfg +ioxesp32c6.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +ioxesp32c6.menu.CDCOnBoot.default=Disabled +ioxesp32c6.menu.CDCOnBoot.default.build.cdc_on_boot=0 +ioxesp32c6.menu.CDCOnBoot.cdc=Enabled +ioxesp32c6.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +ioxesp32c6.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +ioxesp32c6.menu.PartitionScheme.default.build.partitions=default +ioxesp32c6.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +ioxesp32c6.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +ioxesp32c6.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +ioxesp32c6.menu.PartitionScheme.minimal.build.partitions=minimal +ioxesp32c6.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +ioxesp32c6.menu.PartitionScheme.no_fs.build.partitions=no_fs +ioxesp32c6.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +ioxesp32c6.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +ioxesp32c6.menu.PartitionScheme.no_ota.build.partitions=no_ota +ioxesp32c6.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +ioxesp32c6.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +ioxesp32c6.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +ioxesp32c6.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +ioxesp32c6.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +ioxesp32c6.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +ioxesp32c6.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +ioxesp32c6.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +ioxesp32c6.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +ioxesp32c6.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +ioxesp32c6.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +ioxesp32c6.menu.PartitionScheme.huge_app.build.partitions=huge_app +ioxesp32c6.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +ioxesp32c6.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +ioxesp32c6.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +ioxesp32c6.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +ioxesp32c6.menu.PartitionScheme.rainmaker=RainMaker 4MB +ioxesp32c6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +ioxesp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +ioxesp32c6.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +ioxesp32c6.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +ioxesp32c6.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +ioxesp32c6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs +ioxesp32c6.menu.PartitionScheme.zigbee.build.partitions=zigbee +ioxesp32c6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 +ioxesp32c6.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +ioxesp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +ioxesp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +ioxesp32c6.menu.PartitionScheme.custom=Custom +ioxesp32c6.menu.PartitionScheme.custom.build.partitions= +ioxesp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +ioxesp32c6.menu.CPUFreq.160=160MHz (WiFi) +ioxesp32c6.menu.CPUFreq.160.build.f_cpu=160000000L +ioxesp32c6.menu.CPUFreq.120=120MHz (WiFi) +ioxesp32c6.menu.CPUFreq.120.build.f_cpu=120000000L +ioxesp32c6.menu.CPUFreq.80=80MHz (WiFi) +ioxesp32c6.menu.CPUFreq.80.build.f_cpu=80000000L +ioxesp32c6.menu.CPUFreq.40=40MHz +ioxesp32c6.menu.CPUFreq.40.build.f_cpu=40000000L +ioxesp32c6.menu.CPUFreq.20=20MHz +ioxesp32c6.menu.CPUFreq.20.build.f_cpu=20000000L +ioxesp32c6.menu.CPUFreq.10=10MHz +ioxesp32c6.menu.CPUFreq.10.build.f_cpu=10000000L + +ioxesp32c6.menu.FlashMode.qio=QIO +ioxesp32c6.menu.FlashMode.qio.build.flash_mode=dio +ioxesp32c6.menu.FlashMode.qio.build.boot=qio +ioxesp32c6.menu.FlashMode.dio=DIO +ioxesp32c6.menu.FlashMode.dio.build.flash_mode=dio +ioxesp32c6.menu.FlashMode.dio.build.boot=dio + +ioxesp32c6.menu.FlashFreq.80=80MHz +ioxesp32c6.menu.FlashFreq.80.build.flash_freq=80m +ioxesp32c6.menu.FlashFreq.40=40MHz +ioxesp32c6.menu.FlashFreq.40.build.flash_freq=40m + +ioxesp32c6.menu.UploadSpeed.921600=921600 +ioxesp32c6.menu.UploadSpeed.921600.upload.speed=921600 +ioxesp32c6.menu.UploadSpeed.115200=115200 +ioxesp32c6.menu.UploadSpeed.115200.upload.speed=115200 +ioxesp32c6.menu.UploadSpeed.256000.windows=256000 +ioxesp32c6.menu.UploadSpeed.256000.upload.speed=256000 +ioxesp32c6.menu.UploadSpeed.230400.windows.upload.speed=256000 +ioxesp32c6.menu.UploadSpeed.230400=230400 +ioxesp32c6.menu.UploadSpeed.230400.upload.speed=230400 +ioxesp32c6.menu.UploadSpeed.460800.linux=460800 +ioxesp32c6.menu.UploadSpeed.460800.macosx=460800 +ioxesp32c6.menu.UploadSpeed.460800.upload.speed=460800 +ioxesp32c6.menu.UploadSpeed.512000.windows=512000 +ioxesp32c6.menu.UploadSpeed.512000.upload.speed=512000 + +ioxesp32c6.menu.DebugLevel.none=None +ioxesp32c6.menu.DebugLevel.none.build.code_debug=0 +ioxesp32c6.menu.DebugLevel.error=Error +ioxesp32c6.menu.DebugLevel.error.build.code_debug=1 +ioxesp32c6.menu.DebugLevel.warn=Warn +ioxesp32c6.menu.DebugLevel.warn.build.code_debug=2 +ioxesp32c6.menu.DebugLevel.info=Info +ioxesp32c6.menu.DebugLevel.info.build.code_debug=3 +ioxesp32c6.menu.DebugLevel.debug=Debug +ioxesp32c6.menu.DebugLevel.debug.build.code_debug=4 +ioxesp32c6.menu.DebugLevel.verbose=Verbose +ioxesp32c6.menu.DebugLevel.verbose.build.code_debug=5 + +ioxesp32c6.menu.EraseFlash.none=Disabled +ioxesp32c6.menu.EraseFlash.none.upload.erase_cmd= +ioxesp32c6.menu.EraseFlash.all=Enabled +ioxesp32c6.menu.EraseFlash.all.upload.erase_cmd=-e + +ioxesp32c6.menu.ZigbeeMode.default=Disabled +ioxesp32c6.menu.ZigbeeMode.default.build.zigbee_mode= +ioxesp32c6.menu.ZigbeeMode.default.build.zigbee_libs= +ioxesp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) +ioxesp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED +ioxesp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +ioxesp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +ioxesp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +ioxesp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native + +############################################################## +# ATD1.47-S3 atd147_s3.name=ATD1.47-S3 @@ -35332,9 +39851,15 @@ atd147_s3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 atd147_s3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) atd147_s3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs atd147_s3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -atd147_s3.menu.PartitionScheme.rainmaker=RainMaker +atd147_s3.menu.PartitionScheme.rainmaker=RainMaker 4MB atd147_s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -atd147_s3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +atd147_s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +atd147_s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +atd147_s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +atd147_s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +atd147_s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +atd147_s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +atd147_s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 atd147_s3.menu.CPUFreq.240=240MHz (WiFi) atd147_s3.menu.CPUFreq.240.build.f_cpu=240000000L @@ -35382,6 +39907,189 @@ atd147_s3.menu.EraseFlash.none.upload.erase_cmd= atd147_s3.menu.EraseFlash.all=Enabled atd147_s3.menu.EraseFlash.all.upload.erase_cmd=-e +############################################################## +# ATD3.5-S3 + +atd35s3.name=ATD3.5-S3 + +atd35s3.bootloader.tool=esptool_py +atd35s3.bootloader.tool.default=esptool_py + +atd35s3.upload.tool=esptool_py +atd35s3.upload.tool.default=esptool_py +atd35s3.upload.tool.network=esp_ota + +atd35s3.upload.maximum_size=1310720 +atd35s3.upload.maximum_data_size=327680 +atd35s3.upload.flags= +atd35s3.upload.extra_flags= +atd35s3.upload.use_1200bps_touch=false +atd35s3.upload.wait_for_upload_port=false + +atd35s3.serial.disableDTR=false +atd35s3.serial.disableRTS=false + +atd35s3.build.tarch=xtensa +atd35s3.build.bootloader_addr=0x0 +atd35s3.build.target=esp32s3 +atd35s3.build.mcu=esp32s3 +atd35s3.build.core=esp32 +atd35s3.build.variant=atd35s3 +atd35s3.build.board=ATD143_S3 + +atd35s3.build.usb_mode=1 +atd35s3.build.cdc_on_boot=0 +atd35s3.build.msc_on_boot=0 +atd35s3.build.dfu_on_boot=0 +atd35s3.build.f_cpu=240000000L +atd35s3.build.flash_size=8MB +atd35s3.build.flash_freq=80m +atd35s3.build.flash_mode=dio +atd35s3.build.boot=qio +atd35s3.build.boot_freq=80m +atd35s3.build.partitions=default_8MB +atd35s3.build.defines= +atd35s3.build.loop_core= +atd35s3.build.event_core= +atd35s3.build.psram_type=opi +atd35s3.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +atd35s3.menu.JTAGAdapter.default=Disabled +atd35s3.menu.JTAGAdapter.default.build.copy_jtag_files=0 +atd35s3.menu.JTAGAdapter.builtin=Integrated USB JTAG +atd35s3.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +atd35s3.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +atd35s3.menu.JTAGAdapter.external=FTDI Adapter +atd35s3.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +atd35s3.menu.JTAGAdapter.external.build.copy_jtag_files=1 +atd35s3.menu.JTAGAdapter.bridge=ESP USB Bridge +atd35s3.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +atd35s3.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +atd35s3.menu.PSRAM.disabled=Disabled +atd35s3.menu.PSRAM.disabled.build.defines= +atd35s3.menu.PSRAM.disabled.build.psram_type=opi +atd35s3.menu.PSRAM.enabled=Enable +atd35s3.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +atd35s3.menu.PSRAM.enabled.build.psram_type=opi + +atd35s3.menu.LoopCore.1=Core 1 +atd35s3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +atd35s3.menu.LoopCore.0=Core 0 +atd35s3.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +atd35s3.menu.EventsCore.1=Core 1 +atd35s3.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +atd35s3.menu.EventsCore.0=Core 0 +atd35s3.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +atd35s3.menu.USBMode.hwcdc=Hardware CDC and JTAG +atd35s3.menu.USBMode.hwcdc.build.usb_mode=1 +atd35s3.menu.USBMode.default=USB-OTG (TinyUSB) +atd35s3.menu.USBMode.default.build.usb_mode=0 + +atd35s3.menu.CDCOnBoot.default=Disabled +atd35s3.menu.CDCOnBoot.default.build.cdc_on_boot=0 +atd35s3.menu.CDCOnBoot.cdc=Enabled +atd35s3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +atd35s3.menu.MSCOnBoot.default=Disabled +atd35s3.menu.MSCOnBoot.default.build.msc_on_boot=0 +atd35s3.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +atd35s3.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +atd35s3.menu.DFUOnBoot.default=Disabled +atd35s3.menu.DFUOnBoot.default.build.dfu_on_boot=0 +atd35s3.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +atd35s3.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +atd35s3.menu.UploadMode.default=UART0 / Hardware CDC +atd35s3.menu.UploadMode.default.upload.use_1200bps_touch=false +atd35s3.menu.UploadMode.default.upload.wait_for_upload_port=false +atd35s3.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +atd35s3.menu.UploadMode.cdc.upload.use_1200bps_touch=true +atd35s3.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +atd35s3.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +atd35s3.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +atd35s3.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +atd35s3.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +atd35s3.menu.PartitionScheme.minimal.build.partitions=minimal +atd35s3.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +atd35s3.menu.PartitionScheme.no_ota.build.partitions=no_ota +atd35s3.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +atd35s3.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +atd35s3.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +atd35s3.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +atd35s3.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +atd35s3.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +atd35s3.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +atd35s3.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +atd35s3.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +atd35s3.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +atd35s3.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +atd35s3.menu.PartitionScheme.huge_app.build.partitions=huge_app +atd35s3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +atd35s3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +atd35s3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +atd35s3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +atd35s3.menu.PartitionScheme.rainmaker=RainMaker 4MB +atd35s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +atd35s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +atd35s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +atd35s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +atd35s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +atd35s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +atd35s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +atd35s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 + +atd35s3.menu.CPUFreq.240=240MHz (WiFi) +atd35s3.menu.CPUFreq.240.build.f_cpu=240000000L +atd35s3.menu.CPUFreq.160=160MHz (WiFi) +atd35s3.menu.CPUFreq.160.build.f_cpu=160000000L +atd35s3.menu.CPUFreq.80=80MHz (WiFi) +atd35s3.menu.CPUFreq.80.build.f_cpu=80000000L +atd35s3.menu.CPUFreq.40=40MHz +atd35s3.menu.CPUFreq.40.build.f_cpu=40000000L +atd35s3.menu.CPUFreq.20=20MHz +atd35s3.menu.CPUFreq.20.build.f_cpu=20000000L +atd35s3.menu.CPUFreq.10=10MHz +atd35s3.menu.CPUFreq.10.build.f_cpu=10000000L + +atd35s3.menu.UploadSpeed.921600=921600 +atd35s3.menu.UploadSpeed.921600.upload.speed=921600 +atd35s3.menu.UploadSpeed.115200=115200 +atd35s3.menu.UploadSpeed.115200.upload.speed=115200 +atd35s3.menu.UploadSpeed.256000.windows=256000 +atd35s3.menu.UploadSpeed.256000.upload.speed=256000 +atd35s3.menu.UploadSpeed.230400.windows.upload.speed=256000 +atd35s3.menu.UploadSpeed.230400=230400 +atd35s3.menu.UploadSpeed.230400.upload.speed=230400 +atd35s3.menu.UploadSpeed.460800.linux=460800 +atd35s3.menu.UploadSpeed.460800.macosx=460800 +atd35s3.menu.UploadSpeed.460800.upload.speed=460800 +atd35s3.menu.UploadSpeed.512000.windows=512000 +atd35s3.menu.UploadSpeed.512000.upload.speed=512000 + +atd35s3.menu.DebugLevel.none=None +atd35s3.menu.DebugLevel.none.build.code_debug=0 +atd35s3.menu.DebugLevel.error=Error +atd35s3.menu.DebugLevel.error.build.code_debug=1 +atd35s3.menu.DebugLevel.warn=Warn +atd35s3.menu.DebugLevel.warn.build.code_debug=2 +atd35s3.menu.DebugLevel.info=Info +atd35s3.menu.DebugLevel.info.build.code_debug=3 +atd35s3.menu.DebugLevel.debug=Debug +atd35s3.menu.DebugLevel.debug.build.code_debug=4 +atd35s3.menu.DebugLevel.verbose=Verbose +atd35s3.menu.DebugLevel.verbose.build.code_debug=5 + +atd35s3.menu.EraseFlash.none=Disabled +atd35s3.menu.EraseFlash.none.upload.erase_cmd= +atd35s3.menu.EraseFlash.all=Enabled +atd35s3.menu.EraseFlash.all.upload.erase_cmd=-e + ############################################################## # ESP32-S3 PowerFeather @@ -36108,9 +40816,12 @@ epulse_feather_c6.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 epulse_feather_c6.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) epulse_feather_c6.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs epulse_feather_c6.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -epulse_feather_c6.menu.PartitionScheme.rainmaker=RainMaker +epulse_feather_c6.menu.PartitionScheme.rainmaker=RainMaker 4MB epulse_feather_c6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -epulse_feather_c6.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +epulse_feather_c6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +epulse_feather_c6.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +epulse_feather_c6.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +epulse_feather_c6.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 epulse_feather_c6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs epulse_feather_c6.menu.PartitionScheme.zigbee.build.partitions=zigbee epulse_feather_c6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 @@ -36150,7 +40861,6 @@ epulse_feather_c6.menu.FlashSize.4M=4MB (32Mb) epulse_feather_c6.menu.FlashSize.4M.build.flash_size=4MB epulse_feather_c6.menu.FlashSize.2M=2MB (16Mb) epulse_feather_c6.menu.FlashSize.2M.build.flash_size=2MB -epulse_feather_c6.menu.FlashSize.2M.build.partitions=minimal epulse_feather_c6.menu.UploadSpeed.921600=921600 epulse_feather_c6.menu.UploadSpeed.921600.upload.speed=921600 @@ -36190,13 +40900,10 @@ epulse_feather_c6.menu.ZigbeeMode.default.build.zigbee_mode= epulse_feather_c6.menu.ZigbeeMode.default.build.zigbee_libs= epulse_feather_c6.menu.ZigbeeMode.ed=Zigbee ED (end device) epulse_feather_c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED -epulse_feather_c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -epulse_feather_c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +epulse_feather_c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +epulse_feather_c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) epulse_feather_c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR -epulse_feather_c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port -epulse_feather_c6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) -epulse_feather_c6.menu.ZigbeeMode.rcp.build.zigbee_mode=-DZIGBEE_MODE_RCP -epulse_feather_c6.menu.ZigbeeMode.rcp.build.zigbee_libs=-lesp_zb_api_rcp -lesp_zb_cli_command -lzboss_stack.rcp -lzboss_port +epulse_feather_c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native ############################################################## @@ -36293,7 +41000,6 @@ Geekble_ESP32C3.menu.FlashSize.4M=4MB (Default) Geekble_ESP32C3.menu.FlashSize.4M.build.flash_size=4MB Geekble_ESP32C3.menu.FlashSize.2M=2MB Geekble_ESP32C3.menu.FlashSize.2M.build.flash_size=2MB -Geekble_ESP32C3.menu.FlashSize.2M.build.partitions=minimal Geekble_ESP32C3.menu.UploadSpeed.921600=921600 (Default) Geekble_ESP32C3.menu.UploadSpeed.921600.upload.speed=921600 @@ -36330,9 +41036,1107 @@ Geekble_ESP32C3.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## +Geekble_Nano_ESP32S3.name=Geekble nano ESP32-S3 +Geekble_Nano_ESP32S3.vid.0=0x303a +Geekble_Nano_ESP32S3.pid.0= 0x82C5 +Geekble_Nano_ESP32S3.upload_port.0.vid=0x303a +Geekble_Nano_ESP32S3.upload_port.0.pid= 0x82C5 + +Geekble_Nano_ESP32S3.bootloader.tool=esptool_py +Geekble_Nano_ESP32S3.bootloader.tool.default=esptool_py + +Geekble_Nano_ESP32S3.upload.tool=esptool_py +Geekble_Nano_ESP32S3.upload.tool.default=esptool_py +Geekble_Nano_ESP32S3.upload.tool.network=esp_ota + +Geekble_Nano_ESP32S3.upload.maximum_size=1310720 +Geekble_Nano_ESP32S3.upload.maximum_data_size=327680 +Geekble_Nano_ESP32S3.upload.speed=921600 +Geekble_Nano_ESP32S3.upload.flags= +Geekble_Nano_ESP32S3.upload.extra_flags= +Geekble_Nano_ESP32S3.upload.use_1200bps_touch=false +Geekble_Nano_ESP32S3.upload.wait_for_upload_port=false + +Geekble_Nano_ESP32S3.serial.disableDTR=false +Geekble_Nano_ESP32S3.serial.disableRTS=false + +Geekble_Nano_ESP32S3.build.tarch=xtensa +Geekble_Nano_ESP32S3.build.bootloader_addr=0x0 +Geekble_Nano_ESP32S3.build.target=esp32s3 +Geekble_Nano_ESP32S3.build.mcu=esp32s3 +Geekble_Nano_ESP32S3.build.core=esp32 +Geekble_Nano_ESP32S3.build.variant=Geekble_Nano_ESP32S3 +Geekble_Nano_ESP32S3.build.board=GEEKBLE_NANO_ESP32S3 + +Geekble_Nano_ESP32S3.build.usb_mode=1 +Geekble_Nano_ESP32S3.build.cdc_on_boot=1 +Geekble_Nano_ESP32S3.build.msc_on_boot=0 +Geekble_Nano_ESP32S3.build.dfu_on_boot=0 +Geekble_Nano_ESP32S3.build.f_cpu=240000000L +Geekble_Nano_ESP32S3.build.flash_size=4MB +Geekble_Nano_ESP32S3.build.flash_freq=80m +Geekble_Nano_ESP32S3.build.flash_mode=dio +Geekble_Nano_ESP32S3.build.boot=qio +Geekble_Nano_ESP32S3.build.partitions=default +Geekble_Nano_ESP32S3.build.defines= +Geekble_Nano_ESP32S3.build.memory_type=qio_qspi +Geekble_Nano_ESP32S3.build.loop_core=-DARDUINO_RUNNING_CORE=1 +Geekble_Nano_ESP32S3.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +Geekble_Nano_ESP32S3.menu.USBMode.default=USB-OTG (TinyUSB) +Geekble_Nano_ESP32S3.menu.USBMode.default.build.usb_mode=0 +Geekble_Nano_ESP32S3.menu.USBMode.default.build.cdc_on_boot=1 +Geekble_Nano_ESP32S3.menu.USBMode.hwcdc=Hardware CDC and JTAG +Geekble_Nano_ESP32S3.menu.USBMode.hwcdc.build.usb_mode=1 +Geekble_Nano_ESP32S3.menu.USBMode.hwcdc.build.cdc_on_boot=1 + +Geekble_Nano_ESP32S3.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +Geekble_Nano_ESP32S3.menu.UploadMode.cdc.upload.use_1200bps_touch=true +Geekble_Nano_ESP32S3.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +Geekble_Nano_ESP32S3.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +Geekble_Nano_ESP32S3.menu.PartitionScheme.default.build.partitions=default +Geekble_Nano_ESP32S3.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +Geekble_Nano_ESP32S3.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +Geekble_Nano_ESP32S3.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +Geekble_Nano_ESP32S3.menu.PartitionScheme.no_ota.build.partitions=no_ota +Geekble_Nano_ESP32S3.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +Geekble_Nano_ESP32S3.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +Geekble_Nano_ESP32S3.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +Geekble_Nano_ESP32S3.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +Geekble_Nano_ESP32S3.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +Geekble_Nano_ESP32S3.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +Geekble_Nano_ESP32S3.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +Geekble_Nano_ESP32S3.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +Geekble_Nano_ESP32S3.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +Geekble_Nano_ESP32S3.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +Geekble_Nano_ESP32S3.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +Geekble_Nano_ESP32S3.menu.PartitionScheme.huge_app.build.partitions=huge_app +Geekble_Nano_ESP32S3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +Geekble_Nano_ESP32S3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +Geekble_Nano_ESP32S3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +Geekble_Nano_ESP32S3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +Geekble_Nano_ESP32S3.menu.PartitionScheme.rainmaker=RainMaker 4MB +Geekble_Nano_ESP32S3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +Geekble_Nano_ESP32S3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +Geekble_Nano_ESP32S3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +Geekble_Nano_ESP32S3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +Geekble_Nano_ESP32S3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +Geekble_Nano_ESP32S3.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +Geekble_Nano_ESP32S3.menu.PartitionScheme.otanofs.build.custom_partitions=ota_nofs_4MB +Geekble_Nano_ESP32S3.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +Geekble_Nano_ESP32S3.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +Geekble_Nano_ESP32S3.menu.PartitionScheme.all_app.build.custom_partitions=max_app_4MB +Geekble_Nano_ESP32S3.menu.PartitionScheme.all_app.upload.maximum_size=4063232 +Geekble_Nano_ESP32S3.menu.PartitionScheme.custom=Custom +Geekble_Nano_ESP32S3.menu.PartitionScheme.custom.build.partitions= +Geekble_Nano_ESP32S3.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +Geekble_Nano_ESP32S3.menu.DebugLevel.none=None +Geekble_Nano_ESP32S3.menu.DebugLevel.none.build.code_debug=0 +Geekble_Nano_ESP32S3.menu.DebugLevel.error=Error +Geekble_Nano_ESP32S3.menu.DebugLevel.error.build.code_debug=1 +Geekble_Nano_ESP32S3.menu.DebugLevel.warn=Warn +Geekble_Nano_ESP32S3.menu.DebugLevel.warn.build.code_debug=2 +Geekble_Nano_ESP32S3.menu.DebugLevel.info=Info +Geekble_Nano_ESP32S3.menu.DebugLevel.info.build.code_debug=3 +Geekble_Nano_ESP32S3.menu.DebugLevel.debug=Debug +Geekble_Nano_ESP32S3.menu.DebugLevel.debug.build.code_debug=4 +Geekble_Nano_ESP32S3.menu.DebugLevel.verbose=Verbose +Geekble_Nano_ESP32S3.menu.DebugLevel.verbose.build.code_debug=5 + +Geekble_Nano_ESP32S3.menu.EraseFlash.none=Disabled +Geekble_Nano_ESP32S3.menu.EraseFlash.none.upload.erase_cmd= +Geekble_Nano_ESP32S3.menu.EraseFlash.all=Enabled +Geekble_Nano_ESP32S3.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_zero.name=Waveshare ESP32-S3-Zero +waveshare_esp32_s3_zero.vid.0=0x303a +waveshare_esp32_s3_zero.pid.0=0x822B +waveshare_esp32_s3_zero.upload_port.0.vid=0x303a +waveshare_esp32_s3_zero.upload_port.0.pid=0x822B + +waveshare_esp32_s3_zero.bootloader.tool=esptool_py +waveshare_esp32_s3_zero.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_zero.upload.tool=esptool_py +waveshare_esp32_s3_zero.upload.tool.default=esptool_py +waveshare_esp32_s3_zero.upload.tool.network=esp_ota + +waveshare_esp32_s3_zero.upload.maximum_size=1310720 + +waveshare_esp32_s3_zero.upload.maximum_data_size=327680 +waveshare_esp32_s3_zero.upload.flags= +waveshare_esp32_s3_zero.upload.extra_flags= +waveshare_esp32_s3_zero.upload.use_1200bps_touch=false +waveshare_esp32_s3_zero.upload.wait_for_upload_port=false + +waveshare_esp32_s3_zero.serial.disableDTR=false +waveshare_esp32_s3_zero.serial.disableRTS=false + +waveshare_esp32_s3_zero.build.tarch=xtensa +waveshare_esp32_s3_zero.build.bootloader_addr=0x0 +waveshare_esp32_s3_zero.build.target=esp32s3 +waveshare_esp32_s3_zero.build.mcu=esp32s3 +waveshare_esp32_s3_zero.build.core=esp32 +waveshare_esp32_s3_zero.build.variant=waveshare_esp32_s3_zero +waveshare_esp32_s3_zero.build.board=WAVESHARE_ESP32_S3_ZERO + +waveshare_esp32_s3_zero.build.usb_mode=1 +waveshare_esp32_s3_zero.build.cdc_on_boot=0 +waveshare_esp32_s3_zero.build.msc_on_boot=0 +waveshare_esp32_s3_zero.build.dfu_on_boot=0 +waveshare_esp32_s3_zero.build.f_cpu=240000000L +waveshare_esp32_s3_zero.build.flash_size=4MB +waveshare_esp32_s3_zero.build.flash_freq=80m +waveshare_esp32_s3_zero.build.flash_mode=dio +waveshare_esp32_s3_zero.build.boot=qio +waveshare_esp32_s3_zero.build.boot_freq=80m +waveshare_esp32_s3_zero.build.partitions=default +waveshare_esp32_s3_zero.build.defines= +waveshare_esp32_s3_zero.build.loop_core= +waveshare_esp32_s3_zero.build.event_core= +waveshare_esp32_s3_zero.build.psram_type=qspi +waveshare_esp32_s3_zero.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_zero.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_zero.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_zero.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_zero.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_zero.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_zero.menu.PSRAM.enabled.build.psram_type=qspi + +waveshare_esp32_s3_zero.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_zero.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_zero.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_zero.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_zero.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_zero.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_zero.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_zero.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_zero.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_zero.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_zero.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_zero.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_zero.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_zero.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_zero.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_zero.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_zero.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_zero.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_zero.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_zero.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_zero.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_zero.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_zero.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_zero.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_zero.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_zero.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_zero.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_zero.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_zero.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_zero.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_zero.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_zero.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_zero.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_zero.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_zero.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_zero.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_zero.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_zero.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_zero.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_zero.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_zero.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_zero.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_zero.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_zero.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_zero.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_zero.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_zero.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_zero.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_zero.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_zero.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_zero.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_zero.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_zero.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_zero.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_zero.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_zero.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_zero.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_zero.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_zero.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_zero.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_zero.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_zero.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_zero.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_zero.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_zero.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_zero.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_zero.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_zero.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 + +waveshare_esp32_s3_zero.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_zero.menu.PartitionScheme.otanofs.build.custom_partitions=ota_nofs_4MB +waveshare_esp32_s3_zero.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_zero.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_zero.menu.PartitionScheme.all_app.build.custom_partitions=max_app_4MB +waveshare_esp32_s3_zero.menu.PartitionScheme.all_app.upload.maximum_size=4063232 + +waveshare_esp32_s3_zero.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_zero.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_zero.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_zero.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_zero.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_zero.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_zero.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_zero.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_zero.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_zero.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_zero.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_zero.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_zero.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_zero.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_zero.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_zero.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_zero.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_zero.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_zero.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_zero.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_zero.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_zero.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_zero.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_zero.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_zero.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_zero.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_zero.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_zero.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_zero.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_zero.menu.DebugLevel.none=None +waveshare_esp32_s3_zero.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_zero.menu.DebugLevel.error=Error +waveshare_esp32_s3_zero.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_zero.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_zero.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_zero.menu.DebugLevel.info=Info +waveshare_esp32_s3_zero.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_zero.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_zero.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_zero.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_zero.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_zero.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_zero.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_zero.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_zero.menu.EraseFlash.all.upload.erase_cmd=-e + +###################################################### + +ws_esp32_s3_matrix.name=Waveshare ESP32-S3-Matrix +ws_esp32_s3_matrix.vid.0=0x303a +ws_esp32_s3_matrix.pid.0=0x81FB +ws_esp32_s3_matrix.upload_port.0.vid=0x303a +ws_esp32_s3_matrix.upload_port.0.pid=0x81FB + +ws_esp32_s3_matrix.bootloader.tool=esptool_py +ws_esp32_s3_matrix.bootloader.tool.default=esptool_py + +ws_esp32_s3_matrix.upload.tool=esptool_py +ws_esp32_s3_matrix.upload.tool.default=esptool_py +ws_esp32_s3_matrix.upload.tool.network=esp_ota + +ws_esp32_s3_matrix.upload.maximum_size=1310720 + +ws_esp32_s3_matrix.upload.maximum_data_size=327680 +ws_esp32_s3_matrix.upload.flags= +ws_esp32_s3_matrix.upload.extra_flags= +ws_esp32_s3_matrix.upload.use_1200bps_touch=false +ws_esp32_s3_matrix.upload.wait_for_upload_port=false + +ws_esp32_s3_matrix.serial.disableDTR=false +ws_esp32_s3_matrix.serial.disableRTS=false + +ws_esp32_s3_matrix.build.tarch=xtensa +ws_esp32_s3_matrix.build.bootloader_addr=0x0 +ws_esp32_s3_matrix.build.target=esp32s3 +ws_esp32_s3_matrix.build.mcu=esp32s3 +ws_esp32_s3_matrix.build.core=esp32 +ws_esp32_s3_matrix.build.variant=ws_esp32_s3_matrix +ws_esp32_s3_matrix.build.board=WS_ESP32_S3_MATRIX + +ws_esp32_s3_matrix.build.usb_mode=1 +ws_esp32_s3_matrix.build.cdc_on_boot=0 +ws_esp32_s3_matrix.build.msc_on_boot=0 +ws_esp32_s3_matrix.build.dfu_on_boot=0 +ws_esp32_s3_matrix.build.f_cpu=240000000L +ws_esp32_s3_matrix.build.flash_size=4MB +ws_esp32_s3_matrix.build.flash_freq=80m +ws_esp32_s3_matrix.build.flash_mode=dio +ws_esp32_s3_matrix.build.boot=qio +ws_esp32_s3_matrix.build.boot_freq=80m +ws_esp32_s3_matrix.build.partitions=default +ws_esp32_s3_matrix.build.defines= +ws_esp32_s3_matrix.build.loop_core= +ws_esp32_s3_matrix.build.event_core= +ws_esp32_s3_matrix.build.psram_type=qspi +ws_esp32_s3_matrix.build.memory_type={build.boot}_{build.psram_type} + +ws_esp32_s3_matrix.menu.PSRAM.disabled=Disabled +ws_esp32_s3_matrix.menu.PSRAM.disabled.build.defines= +ws_esp32_s3_matrix.menu.PSRAM.disabled.build.psram_type=qspi +ws_esp32_s3_matrix.menu.PSRAM.enabled=Enabled +ws_esp32_s3_matrix.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +ws_esp32_s3_matrix.menu.PSRAM.enabled.build.psram_type=qspi + +ws_esp32_s3_matrix.menu.FlashMode.qio=QIO 80MHz +ws_esp32_s3_matrix.menu.FlashMode.qio.build.flash_mode=dio +ws_esp32_s3_matrix.menu.FlashMode.qio.build.boot=qio +ws_esp32_s3_matrix.menu.FlashMode.qio.build.boot_freq=80m +ws_esp32_s3_matrix.menu.FlashMode.qio.build.flash_freq=80m +ws_esp32_s3_matrix.menu.FlashMode.qio120=QIO 120MHz +ws_esp32_s3_matrix.menu.FlashMode.qio120.build.flash_mode=dio +ws_esp32_s3_matrix.menu.FlashMode.qio120.build.boot=qio +ws_esp32_s3_matrix.menu.FlashMode.qio120.build.boot_freq=120m +ws_esp32_s3_matrix.menu.FlashMode.qio120.build.flash_freq=80m + +ws_esp32_s3_matrix.menu.FlashSize.4M=4MB (32Mb) +ws_esp32_s3_matrix.menu.FlashSize.4M.build.flash_size=4MB + +ws_esp32_s3_matrix.menu.LoopCore.1=Core 1 +ws_esp32_s3_matrix.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +ws_esp32_s3_matrix.menu.LoopCore.0=Core 0 +ws_esp32_s3_matrix.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +ws_esp32_s3_matrix.menu.EventsCore.1=Core 1 +ws_esp32_s3_matrix.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +ws_esp32_s3_matrix.menu.EventsCore.0=Core 0 +ws_esp32_s3_matrix.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +ws_esp32_s3_matrix.menu.USBMode.hwcdc=Hardware CDC and JTAG +ws_esp32_s3_matrix.menu.USBMode.hwcdc.build.usb_mode=1 +ws_esp32_s3_matrix.menu.USBMode.default=USB-OTG (TinyUSB) +ws_esp32_s3_matrix.menu.USBMode.default.build.usb_mode=0 + +ws_esp32_s3_matrix.menu.CDCOnBoot.default=Disabled +ws_esp32_s3_matrix.menu.CDCOnBoot.default.build.cdc_on_boot=0 +ws_esp32_s3_matrix.menu.CDCOnBoot.cdc=Enabled +ws_esp32_s3_matrix.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +ws_esp32_s3_matrix.menu.MSCOnBoot.default=Disabled +ws_esp32_s3_matrix.menu.MSCOnBoot.default.build.msc_on_boot=0 +ws_esp32_s3_matrix.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +ws_esp32_s3_matrix.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +ws_esp32_s3_matrix.menu.DFUOnBoot.default=Disabled +ws_esp32_s3_matrix.menu.DFUOnBoot.default.build.dfu_on_boot=0 +ws_esp32_s3_matrix.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +ws_esp32_s3_matrix.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +ws_esp32_s3_matrix.menu.UploadMode.default=UART0 / Hardware CDC +ws_esp32_s3_matrix.menu.UploadMode.default.upload.use_1200bps_touch=false +ws_esp32_s3_matrix.menu.UploadMode.default.upload.wait_for_upload_port=false +ws_esp32_s3_matrix.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +ws_esp32_s3_matrix.menu.UploadMode.cdc.upload.use_1200bps_touch=true +ws_esp32_s3_matrix.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +ws_esp32_s3_matrix.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +ws_esp32_s3_matrix.menu.PartitionScheme.default.build.partitions=default +ws_esp32_s3_matrix.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +ws_esp32_s3_matrix.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +ws_esp32_s3_matrix.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +ws_esp32_s3_matrix.menu.PartitionScheme.no_ota.build.partitions=no_ota +ws_esp32_s3_matrix.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +ws_esp32_s3_matrix.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +ws_esp32_s3_matrix.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +ws_esp32_s3_matrix.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +ws_esp32_s3_matrix.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +ws_esp32_s3_matrix.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +ws_esp32_s3_matrix.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +ws_esp32_s3_matrix.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +ws_esp32_s3_matrix.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +ws_esp32_s3_matrix.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +ws_esp32_s3_matrix.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +ws_esp32_s3_matrix.menu.PartitionScheme.huge_app.build.partitions=huge_app +ws_esp32_s3_matrix.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +ws_esp32_s3_matrix.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +ws_esp32_s3_matrix.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +ws_esp32_s3_matrix.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +ws_esp32_s3_matrix.menu.PartitionScheme.rainmaker=RainMaker 4MB +ws_esp32_s3_matrix.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +ws_esp32_s3_matrix.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +ws_esp32_s3_matrix.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +ws_esp32_s3_matrix.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +ws_esp32_s3_matrix.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 + +ws_esp32_s3_matrix.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +ws_esp32_s3_matrix.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +ws_esp32_s3_matrix.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +ws_esp32_s3_matrix.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +ws_esp32_s3_matrix.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +ws_esp32_s3_matrix.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +ws_esp32_s3_matrix.menu.PartitionScheme.custom=Custom +ws_esp32_s3_matrix.menu.PartitionScheme.custom.build.partitions= +ws_esp32_s3_matrix.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +ws_esp32_s3_matrix.menu.CPUFreq.240=240MHz (WiFi) +ws_esp32_s3_matrix.menu.CPUFreq.240.build.f_cpu=240000000L +ws_esp32_s3_matrix.menu.CPUFreq.160=160MHz (WiFi) +ws_esp32_s3_matrix.menu.CPUFreq.160.build.f_cpu=160000000L +ws_esp32_s3_matrix.menu.CPUFreq.80=80MHz (WiFi) +ws_esp32_s3_matrix.menu.CPUFreq.80.build.f_cpu=80000000L +ws_esp32_s3_matrix.menu.CPUFreq.40=40MHz +ws_esp32_s3_matrix.menu.CPUFreq.40.build.f_cpu=40000000L +ws_esp32_s3_matrix.menu.CPUFreq.20=20MHz +ws_esp32_s3_matrix.menu.CPUFreq.20.build.f_cpu=20000000L +ws_esp32_s3_matrix.menu.CPUFreq.10=10MHz +ws_esp32_s3_matrix.menu.CPUFreq.10.build.f_cpu=10000000L + +ws_esp32_s3_matrix.menu.UploadSpeed.921600=921600 +ws_esp32_s3_matrix.menu.UploadSpeed.921600.upload.speed=921600 +ws_esp32_s3_matrix.menu.UploadSpeed.115200=115200 +ws_esp32_s3_matrix.menu.UploadSpeed.115200.upload.speed=115200 +ws_esp32_s3_matrix.menu.UploadSpeed.256000.windows=256000 +ws_esp32_s3_matrix.menu.UploadSpeed.256000.upload.speed=256000 +ws_esp32_s3_matrix.menu.UploadSpeed.230400.windows.upload.speed=256000 +ws_esp32_s3_matrix.menu.UploadSpeed.230400=230400 +ws_esp32_s3_matrix.menu.UploadSpeed.230400.upload.speed=230400 +ws_esp32_s3_matrix.menu.UploadSpeed.460800.linux=460800 +ws_esp32_s3_matrix.menu.UploadSpeed.460800.macosx=460800 +ws_esp32_s3_matrix.menu.UploadSpeed.460800.upload.speed=460800 +ws_esp32_s3_matrix.menu.UploadSpeed.512000.windows=512000 +ws_esp32_s3_matrix.menu.UploadSpeed.512000.upload.speed=512000 + +ws_esp32_s3_matrix.menu.DebugLevel.none=None +ws_esp32_s3_matrix.menu.DebugLevel.none.build.code_debug=0 +ws_esp32_s3_matrix.menu.DebugLevel.error=Error +ws_esp32_s3_matrix.menu.DebugLevel.error.build.code_debug=1 +ws_esp32_s3_matrix.menu.DebugLevel.warn=Warn +ws_esp32_s3_matrix.menu.DebugLevel.warn.build.code_debug=2 +ws_esp32_s3_matrix.menu.DebugLevel.info=Info +ws_esp32_s3_matrix.menu.DebugLevel.info.build.code_debug=3 +ws_esp32_s3_matrix.menu.DebugLevel.debug=Debug +ws_esp32_s3_matrix.menu.DebugLevel.debug.build.code_debug=4 +ws_esp32_s3_matrix.menu.DebugLevel.verbose=Verbose +ws_esp32_s3_matrix.menu.DebugLevel.verbose.build.code_debug=5 + +ws_esp32_s3_matrix.menu.EraseFlash.none=Disabled +ws_esp32_s3_matrix.menu.EraseFlash.none.upload.erase_cmd= +ws_esp32_s3_matrix.menu.EraseFlash.all=Enabled +ws_esp32_s3_matrix.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_169.name=Waveshare ESP32-S3-Touch-LCD-1.69 +waveshare_esp32_s3_touch_lcd_169.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_169.pid.0=0x821E +waveshare_esp32_s3_touch_lcd_169.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_169.upload_port.0.pid=0x821E + +waveshare_esp32_s3_touch_lcd_169.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_169.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_169.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_169.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_169.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_169.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_169.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_169.upload.flags= +waveshare_esp32_s3_touch_lcd_169.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_169.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_169.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_169.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_169.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_169.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_169.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_169.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_169.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_169.build.core=esp32 +waveshare_esp32_s3_touch_lcd_169.build.variant=waveshare_esp32_s3_touch_lcd_169 +waveshare_esp32_s3_touch_lcd_169.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_169 + +waveshare_esp32_s3_touch_lcd_169.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_169.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_169.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_169.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_169.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_169.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_169.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_169.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_169.build.boot=qio +waveshare_esp32_s3_touch_lcd_169.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_169.build.partitions=default +waveshare_esp32_s3_touch_lcd_169.build.defines= +waveshare_esp32_s3_touch_lcd_169.build.loop_core= +waveshare_esp32_s3_touch_lcd_169.build.event_core= +waveshare_esp32_s3_touch_lcd_169.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_169.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_169.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_169.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_169.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_169.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_169.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_169.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_169.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_169.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_169.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_169.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_169.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_169.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_169.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_169.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_169.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_169.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_169.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_169.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_169.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_169.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_169.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_169.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_169.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_169.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_169.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_169.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_169.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_169.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_169.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_169.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_169.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_169.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_169.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_169.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_169.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_169.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_169.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_169.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_169.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_169.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_169.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_169.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_169.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_169.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_169.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_169.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_169.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_169.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_169.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_169.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_169.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_169.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_169.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_169.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_169.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_169.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_169.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_169.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_169.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_169.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_169.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_169.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_169.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_169.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_169.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_169.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_169.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_169.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_169.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_169.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_169.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_169.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_169.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_169.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_169.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_amoled_18.name=Waveshare ESP32-S3-Touch-AMOLED-1.8 +waveshare_esp32_s3_touch_amoled_18.vid.0=0x303a +waveshare_esp32_s3_touch_amoled_18.pid.0=0x8255 +waveshare_esp32_s3_touch_amoled_18.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_amoled_18.upload_port.0.pid=0x8255 + +waveshare_esp32_s3_touch_amoled_18.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_amoled_18.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_amoled_18.upload.tool=esptool_py +waveshare_esp32_s3_touch_amoled_18.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_amoled_18.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_amoled_18.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_amoled_18.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_amoled_18.upload.flags= +waveshare_esp32_s3_touch_amoled_18.upload.extra_flags= +waveshare_esp32_s3_touch_amoled_18.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_18.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_amoled_18.serial.disableDTR=false +waveshare_esp32_s3_touch_amoled_18.serial.disableRTS=false + +waveshare_esp32_s3_touch_amoled_18.build.tarch=xtensa +waveshare_esp32_s3_touch_amoled_18.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_amoled_18.build.target=esp32s3 +waveshare_esp32_s3_touch_amoled_18.build.mcu=esp32s3 +waveshare_esp32_s3_touch_amoled_18.build.core=esp32 +waveshare_esp32_s3_touch_amoled_18.build.variant=waveshare_esp32_s3_touch_amoled_18 +waveshare_esp32_s3_touch_amoled_18.build.board=WAVESHARE_ESP32_S3_TOUCH_AMOLED_18 + +waveshare_esp32_s3_touch_amoled_18.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_18.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_18.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_18.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_18.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_18.build.flash_size=16MB +waveshare_esp32_s3_touch_amoled_18.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_18.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_18.build.boot=qio +waveshare_esp32_s3_touch_amoled_18.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_18.build.partitions=default +waveshare_esp32_s3_touch_amoled_18.build.defines= +waveshare_esp32_s3_touch_amoled_18.build.loop_core= +waveshare_esp32_s3_touch_amoled_18.build.event_core= +waveshare_esp32_s3_touch_amoled_18.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_18.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_amoled_18.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_amoled_18.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_amoled_18.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_18.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_amoled_18.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_amoled_18.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_amoled_18.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_amoled_18.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_18.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_18.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_18.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_18.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_18.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_18.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_18.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_18.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_amoled_18.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_18.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_amoled_18.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_amoled_18.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_18.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_18.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_amoled_18.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_18.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_18.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_18.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_18.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_18.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_18.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_18.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_18.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_amoled_18.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_amoled_18.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_amoled_18.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_amoled_18.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_amoled_18.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_amoled_18.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_amoled_18.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_lcd_169.name=Waveshare ESP32-S3-LCD-1.69 +waveshare_esp32_s3_lcd_169.vid.0=0x303a +waveshare_esp32_s3_lcd_169.pid.0=0x8221 +waveshare_esp32_s3_lcd_169.upload_port.0.vid=0x303a +waveshare_esp32_s3_lcd_169.upload_port.0.pid=0x8221 + +waveshare_esp32_s3_lcd_169.bootloader.tool=esptool_py +waveshare_esp32_s3_lcd_169.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_lcd_169.upload.tool=esptool_py +waveshare_esp32_s3_lcd_169.upload.tool.default=esptool_py +waveshare_esp32_s3_lcd_169.upload.tool.network=esp_ota + +waveshare_esp32_s3_lcd_169.upload.maximum_size=1310720 + +waveshare_esp32_s3_lcd_169.upload.maximum_data_size=327680 +waveshare_esp32_s3_lcd_169.upload.flags= +waveshare_esp32_s3_lcd_169.upload.extra_flags= +waveshare_esp32_s3_lcd_169.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_169.upload.wait_for_upload_port=false + +waveshare_esp32_s3_lcd_169.serial.disableDTR=false +waveshare_esp32_s3_lcd_169.serial.disableRTS=false + +waveshare_esp32_s3_lcd_169.build.tarch=xtensa +waveshare_esp32_s3_lcd_169.build.bootloader_addr=0x0 +waveshare_esp32_s3_lcd_169.build.target=esp32s3 +waveshare_esp32_s3_lcd_169.build.mcu=esp32s3 +waveshare_esp32_s3_lcd_169.build.core=esp32 +waveshare_esp32_s3_lcd_169.build.variant=waveshare_esp32_s3_lcd_169 +waveshare_esp32_s3_lcd_169.build.board=WAVESHARE_ESP32_S3_LCD_169 + +waveshare_esp32_s3_lcd_169.build.usb_mode=1 +waveshare_esp32_s3_lcd_169.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_169.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_169.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_169.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_169.build.flash_size=16MB +waveshare_esp32_s3_lcd_169.build.flash_freq=80m +waveshare_esp32_s3_lcd_169.build.flash_mode=dio +waveshare_esp32_s3_lcd_169.build.boot=qio +waveshare_esp32_s3_lcd_169.build.boot_freq=80m +waveshare_esp32_s3_lcd_169.build.partitions=default +waveshare_esp32_s3_lcd_169.build.defines= +waveshare_esp32_s3_lcd_169.build.loop_core= +waveshare_esp32_s3_lcd_169.build.event_core= +waveshare_esp32_s3_lcd_169.build.psram_type=qspi +waveshare_esp32_s3_lcd_169.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_lcd_169.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_lcd_169.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_lcd_169.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_lcd_169.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_lcd_169.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_lcd_169.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_lcd_169.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_lcd_169.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_lcd_169.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_lcd_169.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_lcd_169.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_lcd_169.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_lcd_169.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_lcd_169.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_lcd_169.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_lcd_169.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_lcd_169.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_lcd_169.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_lcd_169.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_lcd_169.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_lcd_169.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_lcd_169.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_lcd_169.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_lcd_169.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_lcd_169.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_lcd_169.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_lcd_169.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_lcd_169.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_lcd_169.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_169.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_169.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_lcd_169.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_lcd_169.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_169.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_169.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_169.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_lcd_169.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_lcd_169.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_169.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_169.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_lcd_169.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_lcd_169.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_169.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_lcd_169.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_lcd_169.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_lcd_169.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_lcd_169.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_lcd_169.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_169.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_lcd_169.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_lcd_169.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_lcd_169.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_lcd_169.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_lcd_169.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_lcd_169.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_lcd_169.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_lcd_169.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_lcd_169.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_lcd_169.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_lcd_169.menu.DebugLevel.none=None +waveshare_esp32_s3_lcd_169.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_lcd_169.menu.DebugLevel.error=Error +waveshare_esp32_s3_lcd_169.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_lcd_169.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_lcd_169.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_lcd_169.menu.DebugLevel.info=Info +waveshare_esp32_s3_lcd_169.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_lcd_169.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_lcd_169.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_lcd_169.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_lcd_169.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_lcd_169.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_lcd_169.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_lcd_169.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_lcd_169.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + waveshare_esp32s3_touch_lcd_128.name=Waveshare ESP32S3 Touch LCD 128 -waveshare_esp32s3_touch_lcd_128.vid.0=0x1a86 -waveshare_esp32s3_touch_lcd_128.pid.0=0x55d3 waveshare_esp32s3_touch_lcd_128.upload.tool=esptool_py waveshare_esp32s3_touch_lcd_128.upload.tool.default=esptool_py @@ -36770,9 +42574,15 @@ aslcanx2.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 aslcanx2.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) aslcanx2.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs aslcanx2.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -aslcanx2.menu.PartitionScheme.rainmaker=RainMaker +aslcanx2.menu.PartitionScheme.rainmaker=RainMaker 4MB aslcanx2.menu.PartitionScheme.rainmaker.build.partitions=rainmaker -aslcanx2.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 +aslcanx2.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +aslcanx2.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +aslcanx2.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +aslcanx2.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +aslcanx2.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +aslcanx2.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +aslcanx2.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 aslcanx2.menu.CPUFreq.240=240MHz (WiFi) aslcanx2.menu.CPUFreq.240.build.f_cpu=240000000L @@ -36821,3 +42631,7087 @@ aslcanx2.menu.EraseFlash.all=Enabled aslcanx2.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## + +walter.name=DPTechnics Walter + +walter.bootloader.tool=esptool_py +walter.bootloader.tool.default=esptool_py + +walter.upload.tool=esptool_py +walter.upload.tool.default=esptool_py +walter.upload.tool.network=esp_ota + +walter.upload.maximum_size=1310720 +walter.upload.maximum_data_size=327680 +walter.upload.flags= +walter.upload.extra_flags= +walter.upload.use_1200bps_touch=false +walter.upload.wait_for_upload_port=false + +walter.serial.disableDTR=false +walter.serial.disableRTS=false + +walter.build.tarch=xtensa +walter.build.bootloader_addr=0x0 +walter.build.target=esp32s3 +walter.build.mcu=esp32s3 +walter.build.core=esp32 +walter.build.variant=walter +walter.build.board=DPTECHNICS_WALTER + +walter.build.usb_mode=1 +walter.build.cdc_on_boot=1 +walter.build.msc_on_boot=0 +walter.build.dfu_on_boot=0 +walter.build.f_cpu=240000000L +walter.build.flash_size=16MB +walter.build.flash_freq=80m +walter.build.flash_mode=dio +walter.build.boot=qio +walter.build.boot_freq=80m +walter.build.partitions=default +walter.build.defines= +walter.build.loop_core= +walter.build.event_core= +walter.build.psram_type=qspi +walter.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +walter.menu.JTAGAdapter.default=Disabled +walter.menu.JTAGAdapter.default.build.copy_jtag_files=0 +walter.menu.JTAGAdapter.builtin=Integrated USB JTAG +walter.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +walter.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +walter.menu.JTAGAdapter.external=FTDI Adapter +walter.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +walter.menu.JTAGAdapter.external.build.copy_jtag_files=1 +walter.menu.JTAGAdapter.bridge=ESP USB Bridge +walter.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +walter.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +walter.menu.PSRAM.enabled=QSPI PSRAM +walter.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +walter.menu.PSRAM.enabled.build.psram_type=qspi +walter.menu.PSRAM.disabled=Disabled +walter.menu.PSRAM.disabled.build.defines= +walter.menu.PSRAM.disabled.build.psram_type=qspi + +walter.menu.FlashMode.qio=QIO 80MHz +walter.menu.FlashMode.qio.build.flash_mode=dio +walter.menu.FlashMode.qio.build.boot=qio +walter.menu.FlashMode.qio.build.boot_freq=80m +walter.menu.FlashMode.qio.build.flash_freq=80m +walter.menu.FlashMode.dio=DIO 80MHz +walter.menu.FlashMode.dio.build.flash_mode=dio +walter.menu.FlashMode.dio.build.boot=dio +walter.menu.FlashMode.dio.build.boot_freq=80m +walter.menu.FlashMode.dio.build.flash_freq=80m + +walter.menu.FlashSize.16M=16MB (128Mb) +walter.menu.FlashSize.16M.build.flash_size=16MB + +walter.menu.LoopCore.1=Core 1 +walter.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +walter.menu.LoopCore.0=Core 0 +walter.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +walter.menu.EventsCore.1=Core 1 +walter.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +walter.menu.EventsCore.0=Core 0 +walter.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +walter.menu.USBMode.hwcdc=Hardware CDC and JTAG +walter.menu.USBMode.hwcdc.build.usb_mode=1 +walter.menu.USBMode.default=USB-OTG (TinyUSB) +walter.menu.USBMode.default.build.usb_mode=0 + +walter.menu.CDCOnBoot.cdc=Enabled +walter.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 +walter.menu.CDCOnBoot.default=Disabled +walter.menu.CDCOnBoot.default.build.cdc_on_boot=0 + +walter.menu.MSCOnBoot.default=Disabled +walter.menu.MSCOnBoot.default.build.msc_on_boot=0 +walter.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +walter.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +walter.menu.DFUOnBoot.default=Disabled +walter.menu.DFUOnBoot.default.build.dfu_on_boot=0 +walter.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +walter.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +walter.menu.UploadMode.default=UART0 / Hardware CDC +walter.menu.UploadMode.default.upload.use_1200bps_touch=false +walter.menu.UploadMode.default.upload.wait_for_upload_port=false +walter.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +walter.menu.UploadMode.cdc.upload.use_1200bps_touch=true +walter.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +walter.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +walter.menu.PartitionScheme.fatflash.build.partitions=ffat +walter.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +walter.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +walter.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +walter.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +walter.menu.PartitionScheme.default_16MB=Default (6.25MB APP/3.43MB SPIFFS) +walter.menu.PartitionScheme.default_16MB.build.partitions=default_16MB +walter.menu.PartitionScheme.default_16MB.upload.maximum_size=6553600 + +walter.menu.CPUFreq.240=240MHz (WiFi) +walter.menu.CPUFreq.240.build.f_cpu=240000000L +walter.menu.CPUFreq.160=160MHz (WiFi) +walter.menu.CPUFreq.160.build.f_cpu=160000000L +walter.menu.CPUFreq.80=80MHz (WiFi) +walter.menu.CPUFreq.80.build.f_cpu=80000000L +walter.menu.CPUFreq.40=40MHz +walter.menu.CPUFreq.40.build.f_cpu=40000000L +walter.menu.CPUFreq.20=20MHz +walter.menu.CPUFreq.20.build.f_cpu=20000000L +walter.menu.CPUFreq.10=10MHz +walter.menu.CPUFreq.10.build.f_cpu=10000000L + +walter.menu.UploadSpeed.921600=921600 +walter.menu.UploadSpeed.921600.upload.speed=921600 +walter.menu.UploadSpeed.115200=115200 +walter.menu.UploadSpeed.115200.upload.speed=115200 +walter.menu.UploadSpeed.256000.windows=256000 +walter.menu.UploadSpeed.256000.upload.speed=256000 +walter.menu.UploadSpeed.230400.windows.upload.speed=256000 +walter.menu.UploadSpeed.230400=230400 +walter.menu.UploadSpeed.230400.upload.speed=230400 +walter.menu.UploadSpeed.460800.linux=460800 +walter.menu.UploadSpeed.460800.macosx=460800 +walter.menu.UploadSpeed.460800.upload.speed=460800 +walter.menu.UploadSpeed.512000.windows=512000 +walter.menu.UploadSpeed.512000.upload.speed=512000 + +walter.menu.DebugLevel.none=None +walter.menu.DebugLevel.none.build.code_debug=0 +walter.menu.DebugLevel.error=Error +walter.menu.DebugLevel.error.build.code_debug=1 +walter.menu.DebugLevel.warn=Warn +walter.menu.DebugLevel.warn.build.code_debug=2 +walter.menu.DebugLevel.info=Info +walter.menu.DebugLevel.info.build.code_debug=3 +walter.menu.DebugLevel.debug=Debug +walter.menu.DebugLevel.debug.build.code_debug=4 +walter.menu.DebugLevel.verbose=Verbose +walter.menu.DebugLevel.verbose.build.code_debug=5 + +walter.menu.EraseFlash.none=Disabled +walter.menu.EraseFlash.none.upload.erase_cmd= +walter.menu.EraseFlash.all=Enabled +walter.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +elecrow_crowpanel_7.name=Elecrow CrowPanel 7.0P + +elecrow_crowpanel_7.upload.tool=esptool_py +elecrow_crowpanel_7.upload.tool.default=esptool_py +elecrow_crowpanel_7.upload.tool.network=esp_ota +elecrow_crowpanel_7.upload.maximum_size=1310720 +elecrow_crowpanel_7.upload.maximum_data_size=327680 +elecrow_crowpanel_7.upload.wait_for_upload_port=false +elecrow_crowpanel_7.upload.speed=460800 +elecrow_crowpanel_7.upload.flags= +elecrow_crowpanel_7.upload.extra_flags= + +elecrow_crowpanel_7.bootloader.tool=esptool_py +elecrow_crowpanel_7.bootloader.tool.default=esptool_py + +elecrow_crowpanel_7.serial.disableDTR=true +elecrow_crowpanel_7.serial.disableRTS=true + +elecrow_crowpanel_7.build.tarch=xtensa +elecrow_crowpanel_7.build.bootloader_addr=0x0 +elecrow_crowpanel_7.build.mcu=esp32s3 +elecrow_crowpanel_7.build.core=esp32 +elecrow_crowpanel_7.build.target=esp32s3 +elecrow_crowpanel_7.build.variant=elecrow_crowpanel_7 +elecrow_crowpanel_7.build.board=ELECROW_CROWPANEL_7 + +elecrow_crowpanel_7.build.usb_mode=1 +elecrow_crowpanel_7.build.cdc_on_boot=1 +elecrow_crowpanel_7.build.msc_on_boot=0 +elecrow_crowpanel_7.build.dfu_on_boot=0 + +elecrow_crowpanel_7.build.f_cpu=240000000L +elecrow_crowpanel_7.build.flash_size=4MB +elecrow_crowpanel_7.build.flash_freq=80m +elecrow_crowpanel_7.build.flash_mode=dio +elecrow_crowpanel_7.build.boot=dio +elecrow_crowpanel_7.build.partitions=default + +elecrow_crowpanel_7.menu.PSRAM.disabled=Disabled +elecrow_crowpanel_7.menu.PSRAM.disabled.build.defines= +elecrow_crowpanel_7.menu.PSRAM.enabled=Enabled +elecrow_crowpanel_7.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +elecrow_crowpanel_7.menu.PSRAM.enabled.build.psram_type=opi + +elecrow_crowpanel_7.menu.LoopCore.1=Core 1 +elecrow_crowpanel_7.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +elecrow_crowpanel_7.menu.LoopCore.0=Core 0 +elecrow_crowpanel_7.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +elecrow_crowpanel_7.menu.EventsCore.1=Core 1 +elecrow_crowpanel_7.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +elecrow_crowpanel_7.menu.EventsCore.0=Core 0 +elecrow_crowpanel_7.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +elecrow_crowpanel_7.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +elecrow_crowpanel_7.menu.PartitionScheme.default.build.partitions=default +elecrow_crowpanel_7.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +elecrow_crowpanel_7.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +elecrow_crowpanel_7.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +elecrow_crowpanel_7.menu.PartitionScheme.minimal.build.partitions=minimal +elecrow_crowpanel_7.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +elecrow_crowpanel_7.menu.PartitionScheme.no_ota.build.partitions=no_ota +elecrow_crowpanel_7.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +elecrow_crowpanel_7.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +elecrow_crowpanel_7.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +elecrow_crowpanel_7.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +elecrow_crowpanel_7.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +elecrow_crowpanel_7.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +elecrow_crowpanel_7.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +elecrow_crowpanel_7.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +elecrow_crowpanel_7.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +elecrow_crowpanel_7.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +elecrow_crowpanel_7.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +elecrow_crowpanel_7.menu.PartitionScheme.huge_app.build.partitions=huge_app +elecrow_crowpanel_7.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +elecrow_crowpanel_7.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +elecrow_crowpanel_7.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +elecrow_crowpanel_7.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 + +elecrow_crowpanel_7.menu.CPUFreq.240=240MHz (WiFi/BT) +elecrow_crowpanel_7.menu.CPUFreq.240.build.f_cpu=240000000L +elecrow_crowpanel_7.menu.CPUFreq.160=160MHz (WiFi/BT) +elecrow_crowpanel_7.menu.CPUFreq.160.build.f_cpu=160000000L +elecrow_crowpanel_7.menu.CPUFreq.80=80MHz (WiFi/BT) +elecrow_crowpanel_7.menu.CPUFreq.80.build.f_cpu=80000000L +elecrow_crowpanel_7.menu.CPUFreq.40=40MHz (40MHz XTAL) +elecrow_crowpanel_7.menu.CPUFreq.40.build.f_cpu=40000000L +elecrow_crowpanel_7.menu.CPUFreq.26=26MHz (26MHz XTAL) +elecrow_crowpanel_7.menu.CPUFreq.26.build.f_cpu=26000000L +elecrow_crowpanel_7.menu.CPUFreq.20=20MHz (40MHz XTAL) +elecrow_crowpanel_7.menu.CPUFreq.20.build.f_cpu=20000000L +elecrow_crowpanel_7.menu.CPUFreq.13=13MHz (26MHz XTAL) +elecrow_crowpanel_7.menu.CPUFreq.13.build.f_cpu=13000000L +elecrow_crowpanel_7.menu.CPUFreq.10=10MHz (40MHz XTAL) +elecrow_crowpanel_7.menu.CPUFreq.10.build.f_cpu=10000000L + +elecrow_crowpanel_7.menu.FlashMode.qio=QIO +elecrow_crowpanel_7.menu.FlashMode.qio.build.flash_mode=dio +elecrow_crowpanel_7.menu.FlashMode.qio.build.boot=qio +elecrow_crowpanel_7.menu.FlashMode.dio=DIO +elecrow_crowpanel_7.menu.FlashMode.dio.build.flash_mode=dio +elecrow_crowpanel_7.menu.FlashMode.dio.build.boot=dio + +elecrow_crowpanel_7.menu.FlashFreq.80=80MHz +elecrow_crowpanel_7.menu.FlashFreq.80.build.flash_freq=80m +elecrow_crowpanel_7.menu.FlashFreq.40=40MHz +elecrow_crowpanel_7.menu.FlashFreq.40.build.flash_freq=40m + +elecrow_crowpanel_7.menu.FlashSize.4MB=4MB (32Mb) +elecrow_crowpanel_7.menu.FlashSize.4MB.build.flash_size=4MB + +elecrow_crowpanel_7.menu.UploadSpeed.921600=921600 +elecrow_crowpanel_7.menu.UploadSpeed.921600.upload.speed=921600 +elecrow_crowpanel_7.menu.UploadSpeed.115200=115200 +elecrow_crowpanel_7.menu.UploadSpeed.115200.upload.speed=115200 +elecrow_crowpanel_7.menu.UploadSpeed.256000.windows=256000 +elecrow_crowpanel_7.menu.UploadSpeed.256000.upload.speed=256000 +elecrow_crowpanel_7.menu.UploadSpeed.230400.windows.upload.speed=256000 +elecrow_crowpanel_7.menu.UploadSpeed.230400=230400 +elecrow_crowpanel_7.menu.UploadSpeed.230400.upload.speed=230400 +elecrow_crowpanel_7.menu.UploadSpeed.460800.linux=460800 +elecrow_crowpanel_7.menu.UploadSpeed.460800.macosx=460800 +elecrow_crowpanel_7.menu.UploadSpeed.460800.upload.speed=460800 +elecrow_crowpanel_7.menu.UploadSpeed.512000.windows=512000 +elecrow_crowpanel_7.menu.UploadSpeed.512000.upload.speed=512000 + +elecrow_crowpanel_7.menu.DebugLevel.none=None +elecrow_crowpanel_7.menu.DebugLevel.none.build.code_debug=0 +elecrow_crowpanel_7.menu.DebugLevel.error=Error +elecrow_crowpanel_7.menu.DebugLevel.error.build.code_debug=1 +elecrow_crowpanel_7.menu.DebugLevel.warn=Warn +elecrow_crowpanel_7.menu.DebugLevel.warn.build.code_debug=2 +elecrow_crowpanel_7.menu.DebugLevel.info=Info +elecrow_crowpanel_7.menu.DebugLevel.info.build.code_debug=3 +elecrow_crowpanel_7.menu.DebugLevel.debug=Debug +elecrow_crowpanel_7.menu.DebugLevel.debug.build.code_debug=4 +elecrow_crowpanel_7.menu.DebugLevel.verbose=Verbose +elecrow_crowpanel_7.menu.DebugLevel.verbose.build.code_debug=5 + +elecrow_crowpanel_7.menu.EraseFlash.none=Disabled +elecrow_crowpanel_7.menu.EraseFlash.none.upload.erase_cmd= +elecrow_crowpanel_7.menu.EraseFlash.all=Enabled +elecrow_crowpanel_7.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +circuitart_zero_s3.name=CircuitART Zero S3 +circuitart_zero_s3.vid.0=0x303a +circuitart_zero_s3.pid.0=0x80DB + +circuitart_zero_s3.bootloader.tool=esptool_py +circuitart_zero_s3.bootloader.tool.default=esptool_py + +circuitart_zero_s3.upload.tool=esptool_py +circuitart_zero_s3.upload.tool.default=esptool_py +circuitart_zero_s3.upload.tool.network=esp_ota + +circuitart_zero_s3.upload.maximum_size=1310720 +circuitart_zero_s3.upload.maximum_data_size=327680 +circuitart_zero_s3.upload.flags= +circuitart_zero_s3.upload.extra_flags= +circuitart_zero_s3.upload.use_1200bps_touch=false +circuitart_zero_s3.upload.wait_for_upload_port=false + +circuitart_zero_s3.serial.disableDTR=false +circuitart_zero_s3.serial.disableRTS=false + +circuitart_zero_s3.build.tarch=xtensa +circuitart_zero_s3.build.bootloader_addr=0x0 +circuitart_zero_s3.build.target=esp32s3 +circuitart_zero_s3.build.mcu=esp32s3 +circuitart_zero_s3.build.core=esp32 +circuitart_zero_s3.build.variant=circuitart_zero_s3 +circuitart_zero_s3.build.board=CIRCUITART_ZERO_S3 + +circuitart_zero_s3.build.usb_mode=1 +circuitart_zero_s3.build.cdc_on_boot=0 +circuitart_zero_s3.build.msc_on_boot=0 +circuitart_zero_s3.build.dfu_on_boot=0 +circuitart_zero_s3.build.f_cpu=240000000L +circuitart_zero_s3.build.flash_size=16MB +circuitart_zero_s3.build.flash_freq=80m +circuitart_zero_s3.build.flash_mode=dio +circuitart_zero_s3.build.boot=qio +circuitart_zero_s3.build.partitions=default +circuitart_zero_s3.build.defines= +circuitart_zero_s3.build.loop_core= +circuitart_zero_s3.build.event_core= +circuitart_zero_s3.build.flash_type=qio +circuitart_zero_s3.build.psram_type=qspi +circuitart_zero_s3.build.memory_type=qio_qspi + +circuitart_zero_s3.menu.LoopCore.1=Core 1 +circuitart_zero_s3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +circuitart_zero_s3.menu.LoopCore.0=Core 0 +circuitart_zero_s3.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +circuitart_zero_s3.menu.EventsCore.1=Core 1 +circuitart_zero_s3.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +circuitart_zero_s3.menu.EventsCore.0=Core 0 +circuitart_zero_s3.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +circuitart_zero_s3.menu.USBMode.default=USB-OTG (TinyUSB) +circuitart_zero_s3.menu.USBMode.default.build.usb_mode=0 +circuitart_zero_s3.menu.USBMode.hwcdc=Hardware CDC and JTAG +circuitart_zero_s3.menu.USBMode.hwcdc.build.usb_mode=1 + +circuitart_zero_s3.menu.CDCOnBoot.cdc=Enabled +circuitart_zero_s3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 +circuitart_zero_s3.menu.CDCOnBoot.default=Disabled +circuitart_zero_s3.menu.CDCOnBoot.default.build.cdc_on_boot=0 + +circuitart_zero_s3.menu.MSCOnBoot.default=Disabled +circuitart_zero_s3.menu.MSCOnBoot.default.build.msc_on_boot=0 +circuitart_zero_s3.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +circuitart_zero_s3.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +circuitart_zero_s3.menu.DFUOnBoot.default=Disabled +circuitart_zero_s3.menu.DFUOnBoot.default.build.dfu_on_boot=0 +circuitart_zero_s3.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +circuitart_zero_s3.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +circuitart_zero_s3.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +circuitart_zero_s3.menu.UploadMode.cdc.upload.use_1200bps_touch=true +circuitart_zero_s3.menu.UploadMode.cdc.upload.wait_for_upload_port=true +circuitart_zero_s3.menu.UploadMode.default=UART0 / Hardware CDC +circuitart_zero_s3.menu.UploadMode.default.upload.use_1200bps_touch=false +circuitart_zero_s3.menu.UploadMode.default.upload.wait_for_upload_port=false + +circuitart_zero_s3.menu.PSRAM.enabled=Enabled +circuitart_zero_s3.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +circuitart_zero_s3.menu.PSRAM.disabled=Disabled +circuitart_zero_s3.menu.PSRAM.disabled.build.defines= + +circuitart_zero_s3.menu.PartitionScheme.default_16MB=Default (6.25MB APP/3.43MB SPIFFS) +circuitart_zero_s3.menu.PartitionScheme.default_16MB.build.partitions=default_16MB +circuitart_zero_s3.menu.PartitionScheme.default_16MB.upload.maximum_size=6553600 +circuitart_zero_s3.menu.PartitionScheme.tinyuf2=TinyUF2 Compatibility (2MB APP/12MB FFAT) +circuitart_zero_s3.menu.PartitionScheme.tinyuf2.build.custom_bootloader=bootloader_tinyuf2 +circuitart_zero_s3.menu.PartitionScheme.tinyuf2.build.custom_partitions=partitions_tinyuf2 +circuitart_zero_s3.menu.PartitionScheme.tinyuf2.upload.extra_flags=0x410000 "{runtime.platform.path}/variants/{build.variant}/tinyuf2.bin" +circuitart_zero_s3.menu.PartitionScheme.tinyuf2.upload.maximum_size=2097152 +circuitart_zero_s3.menu.PartitionScheme.large_spiffs=Large SPIFFS (4.5MB APP/6.93MB SPIFFS) +circuitart_zero_s3.menu.PartitionScheme.large_spiffs.build.partitions=large_spiffs_16MB +circuitart_zero_s3.menu.PartitionScheme.large_spiffs.upload.maximum_size=4718592 +circuitart_zero_s3.menu.PartitionScheme.app3M_fat9M_16MB=FFAT (3MB APP/9MB FATFS) +circuitart_zero_s3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +circuitart_zero_s3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +circuitart_zero_s3.menu.PartitionScheme.fatflash=Large FFAT (2MB APP/12.5MB FATFS) +circuitart_zero_s3.menu.PartitionScheme.fatflash.build.partitions=ffat +circuitart_zero_s3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 + +circuitart_zero_s3.menu.CPUFreq.240=240MHz (WiFi) +circuitart_zero_s3.menu.CPUFreq.240.build.f_cpu=240000000L +circuitart_zero_s3.menu.CPUFreq.160=160MHz (WiFi) +circuitart_zero_s3.menu.CPUFreq.160.build.f_cpu=160000000L +circuitart_zero_s3.menu.CPUFreq.80=80MHz (WiFi) +circuitart_zero_s3.menu.CPUFreq.80.build.f_cpu=80000000L +circuitart_zero_s3.menu.CPUFreq.40=40MHz +circuitart_zero_s3.menu.CPUFreq.40.build.f_cpu=40000000L +circuitart_zero_s3.menu.CPUFreq.20=20MHz +circuitart_zero_s3.menu.CPUFreq.20.build.f_cpu=20000000L +circuitart_zero_s3.menu.CPUFreq.10=10MHz +circuitart_zero_s3.menu.CPUFreq.10.build.f_cpu=10000000L + +circuitart_zero_s3.menu.FlashMode.qio=QIO +circuitart_zero_s3.menu.FlashMode.qio.build.flash_mode=dio +circuitart_zero_s3.menu.FlashMode.qio.build.boot=qio +circuitart_zero_s3.menu.FlashMode.dio=DIO +circuitart_zero_s3.menu.FlashMode.dio.build.flash_mode=dio +circuitart_zero_s3.menu.FlashMode.dio.build.boot=dio + +circuitart_zero_s3.menu.UploadSpeed.921600=921600 +circuitart_zero_s3.menu.UploadSpeed.921600.upload.speed=921600 +circuitart_zero_s3.menu.UploadSpeed.115200=115200 +circuitart_zero_s3.menu.UploadSpeed.115200.upload.speed=115200 +circuitart_zero_s3.menu.UploadSpeed.256000.windows=256000 +circuitart_zero_s3.menu.UploadSpeed.256000.upload.speed=256000 +circuitart_zero_s3.menu.UploadSpeed.230400.windows.upload.speed=256000 +circuitart_zero_s3.menu.UploadSpeed.230400=230400 +circuitart_zero_s3.menu.UploadSpeed.230400.upload.speed=230400 +circuitart_zero_s3.menu.UploadSpeed.460800.linux=460800 +circuitart_zero_s3.menu.UploadSpeed.460800.macosx=460800 +circuitart_zero_s3.menu.UploadSpeed.460800.upload.speed=460800 +circuitart_zero_s3.menu.UploadSpeed.512000.windows=512000 +circuitart_zero_s3.menu.UploadSpeed.512000.upload.speed=512000 + +circuitart_zero_s3.menu.DebugLevel.none=None +circuitart_zero_s3.menu.DebugLevel.none.build.code_debug=0 +circuitart_zero_s3.menu.DebugLevel.error=Error +circuitart_zero_s3.menu.DebugLevel.error.build.code_debug=1 +circuitart_zero_s3.menu.DebugLevel.warn=Warn +circuitart_zero_s3.menu.DebugLevel.warn.build.code_debug=2 +circuitart_zero_s3.menu.DebugLevel.info=Info +circuitart_zero_s3.menu.DebugLevel.info.build.code_debug=3 +circuitart_zero_s3.menu.DebugLevel.debug=Debug +circuitart_zero_s3.menu.DebugLevel.debug.build.code_debug=4 +circuitart_zero_s3.menu.DebugLevel.verbose=Verbose +circuitart_zero_s3.menu.DebugLevel.verbose.build.code_debug=5 + +circuitart_zero_s3.menu.EraseFlash.none=Disabled +circuitart_zero_s3.menu.EraseFlash.none.upload.erase_cmd= +circuitart_zero_s3.menu.EraseFlash.all=Enabled +circuitart_zero_s3.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +# Alfredo NoU3 + +alfredo-nou3.name=Alfredo NoU3 +alfredo-nou3.vid.0=0xAFD0 +alfredo-nou3.pid.0=0x0003 +alfredo-nou3.upload_port.0.vid=0xAFD0 +alfredo-nou3.upload_port.0.pid=0x0003 + +alfredo-nou3.bootloader.tool=esptool_py +alfredo-nou3.bootloader.tool.default=esptool_py + +alfredo-nou3.upload.tool=esptool_py +alfredo-nou3.upload.tool.default=esptool_py +alfredo-nou3.upload.tool.network=esp_ota + +alfredo-nou3.upload.maximum_size=3342336 +alfredo-nou3.upload.maximum_data_size=327680 +alfredo-nou3.upload.flags= +alfredo-nou3.upload.extra_flags= +alfredo-nou3.upload.use_1200bps_touch=false +alfredo-nou3.upload.wait_for_upload_port=false + +alfredo-nou3.serial.disableDTR=false +alfredo-nou3.serial.disableRTS=false + +alfredo-nou3.build.tarch=xtensa +alfredo-nou3.build.bootloader_addr=0x0 +alfredo-nou3.build.target=esp32s3 +alfredo-nou3.build.mcu=esp32s3 +alfredo-nou3.build.core=esp32 +alfredo-nou3.build.variant=alfredo-nou3 +alfredo-nou3.build.board=ALFREDO_NOU3 + +alfredo-nou3.build.usb_mode=1 +alfredo-nou3.build.cdc_on_boot=1 +alfredo-nou3.build.msc_on_boot=0 +alfredo-nou3.build.dfu_on_boot=0 +alfredo-nou3.build.f_cpu=240000000L +alfredo-nou3.build.flash_size=8MB +alfredo-nou3.build.flash_freq=80m +alfredo-nou3.build.flash_mode=dio +alfredo-nou3.build.boot=qio +alfredo-nou3.build.partitions=default +alfredo-nou3.build.defines= +alfredo-nou3.build.loop_core= +alfredo-nou3.build.event_core= +alfredo-nou3.build.flash_type=qio +alfredo-nou3.build.psram_type=qspi +alfredo-nou3.build.memory_type={build.flash_type}_{build.psram_type} + +alfredo-nou3.menu.LoopCore.1=Core 1 +alfredo-nou3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +alfredo-nou3.menu.LoopCore.0=Core 0 +alfredo-nou3.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +alfredo-nou3.menu.EventsCore.1=Core 1 +alfredo-nou3.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +alfredo-nou3.menu.EventsCore.0=Core 0 +alfredo-nou3.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +alfredo-nou3.menu.USBMode.default=Hardware CDC and JTAG +alfredo-nou3.menu.USBMode.default.build.usb_mode=1 +alfredo-nou3.menu.USBMode.usbotg=USB-OTG (TinyUSB) +alfredo-nou3.menu.USBMode.usbotg.build.usb_mode=0 + +alfredo-nou3.menu.CDCOnBoot.cdc=Enabled +alfredo-nou3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 +alfredo-nou3.menu.CDCOnBoot.default=Disabled +alfredo-nou3.menu.CDCOnBoot.default.build.cdc_on_boot=0 + +alfredo-nou3.menu.MSCOnBoot.default=Disabled +alfredo-nou3.menu.MSCOnBoot.default.build.msc_on_boot=0 +alfredo-nou3.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +alfredo-nou3.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +alfredo-nou3.menu.DFUOnBoot.default=Disabled +alfredo-nou3.menu.DFUOnBoot.default.build.dfu_on_boot=0 +alfredo-nou3.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +alfredo-nou3.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +alfredo-nou3.menu.UploadMode.default=UART0 / Hardware CDC +alfredo-nou3.menu.UploadMode.default.upload.use_1200bps_touch=false +alfredo-nou3.menu.UploadMode.default.upload.wait_for_upload_port=false +alfredo-nou3.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +alfredo-nou3.menu.UploadMode.cdc.upload.use_1200bps_touch=true +alfredo-nou3.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +alfredo-nou3.menu.PartitionScheme.default_8MB=Default (3MB APP/1.5MB SPIFFS) +alfredo-nou3.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +alfredo-nou3.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +alfredo-nou3.menu.PartitionScheme.big_8MB=Max App (8MB APP) +alfredo-nou3.menu.PartitionScheme.big_8MB.build.partitions=max_app_8MB +alfredo-nou3.menu.PartitionScheme.big_8MB.upload.maximum_size=8257536 + +alfredo-nou3.menu.CPUFreq.240=240MHz (WiFi) +alfredo-nou3.menu.CPUFreq.240.build.f_cpu=240000000L +alfredo-nou3.menu.CPUFreq.160=160MHz (WiFi) +alfredo-nou3.menu.CPUFreq.160.build.f_cpu=160000000L +alfredo-nou3.menu.CPUFreq.80=80MHz (WiFi) +alfredo-nou3.menu.CPUFreq.80.build.f_cpu=80000000L +alfredo-nou3.menu.CPUFreq.40=40MHz +alfredo-nou3.menu.CPUFreq.40.build.f_cpu=40000000L +alfredo-nou3.menu.CPUFreq.20=20MHz +alfredo-nou3.menu.CPUFreq.20.build.f_cpu=20000000L +alfredo-nou3.menu.CPUFreq.10=10MHz +alfredo-nou3.menu.CPUFreq.10.build.f_cpu=10000000L + +alfredo-nou3.menu.FlashMode.qio=QIO 80MHz +alfredo-nou3.menu.FlashMode.qio.build.flash_mode=dio +alfredo-nou3.menu.FlashMode.qio.build.boot=qio +alfredo-nou3.menu.FlashMode.qio.build.boot_freq=80m +alfredo-nou3.menu.FlashMode.qio.build.flash_freq=80m +alfredo-nou3.menu.FlashMode.qio120=QIO 120MHz +alfredo-nou3.menu.FlashMode.qio120.build.flash_mode=dio +alfredo-nou3.menu.FlashMode.qio120.build.boot=qio +alfredo-nou3.menu.FlashMode.qio120.build.boot_freq=120m +alfredo-nou3.menu.FlashMode.qio120.build.flash_freq=80m +alfredo-nou3.menu.FlashMode.dio=DIO 80MHz +alfredo-nou3.menu.FlashMode.dio.build.flash_mode=dio +alfredo-nou3.menu.FlashMode.dio.build.boot=dio +alfredo-nou3.menu.FlashMode.dio.build.boot_freq=80m +alfredo-nou3.menu.FlashMode.dio.build.flash_freq=80m +alfredo-nou3.menu.FlashMode.opi=OPI 80MHz +alfredo-nou3.menu.FlashMode.opi.build.flash_mode=dout +alfredo-nou3.menu.FlashMode.opi.build.boot=opi +alfredo-nou3.menu.FlashMode.opi.build.boot_freq=80m +alfredo-nou3.menu.FlashMode.opi.build.flash_freq=80m + +alfredo-nou3.menu.FlashSize.8M=8MB (64Mb) +alfredo-nou3.menu.FlashSize.8M.build.flash_size=8MB + +alfredo-nou3.menu.UploadSpeed.921600=921600 +alfredo-nou3.menu.UploadSpeed.921600.upload.speed=921600 +alfredo-nou3.menu.UploadSpeed.512000.windows=512000 +alfredo-nou3.menu.UploadSpeed.512000.upload.speed=512000 +alfredo-nou3.menu.UploadSpeed.460800.linux=460800 +alfredo-nou3.menu.UploadSpeed.460800.macosx=460800 +alfredo-nou3.menu.UploadSpeed.460800.upload.speed=460800 +alfredo-nou3.menu.UploadSpeed.256000.windows=256000 +alfredo-nou3.menu.UploadSpeed.256000.upload.speed=256000 +alfredo-nou3.menu.UploadSpeed.230400.windows.upload.speed=256000 +alfredo-nou3.menu.UploadSpeed.230400=230400 +alfredo-nou3.menu.UploadSpeed.230400.upload.speed=230400 +alfredo-nou3.menu.UploadSpeed.115200=115200 +alfredo-nou3.menu.UploadSpeed.115200.upload.speed=115200 + +alfredo-nou3.menu.DebugLevel.none=None +alfredo-nou3.menu.DebugLevel.none.build.code_debug=0 +alfredo-nou3.menu.DebugLevel.error=Error +alfredo-nou3.menu.DebugLevel.error.build.code_debug=1 +alfredo-nou3.menu.DebugLevel.warn=Warn +alfredo-nou3.menu.DebugLevel.warn.build.code_debug=2 +alfredo-nou3.menu.DebugLevel.info=Info +alfredo-nou3.menu.DebugLevel.info.build.code_debug=3 +alfredo-nou3.menu.DebugLevel.debug=Debug +alfredo-nou3.menu.DebugLevel.debug.build.code_debug=4 +alfredo-nou3.menu.DebugLevel.verbose=Verbose +alfredo-nou3.menu.DebugLevel.verbose.build.code_debug=5 + +alfredo-nou3.menu.EraseFlash.none=Disabled +alfredo-nou3.menu.EraseFlash.none.upload.erase_cmd= +alfredo-nou3.menu.EraseFlash.all=Enabled +alfredo-nou3.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## +codecell.name=CodeCell C3 + +codecell.bootloader.tool=esptool_py +codecell.bootloader.tool.default=esptool_py + +codecell.upload.tool=esptool_py +codecell.upload.tool.default=esptool_py +codecell.upload.tool.network=esp_ota + +codecell.upload.maximum_size=1310720 +codecell.upload.maximum_data_size=327680 +codecell.upload.flags= +codecell.upload.extra_flags= +codecell.upload.use_1200bps_touch=false +codecell.upload.wait_for_upload_port=false + +codecell.serial.disableDTR=false +codecell.serial.disableRTS=false + +codecell.build.tarch=riscv32 +codecell.build.target=esp +codecell.build.mcu=esp32c3 +codecell.build.core=esp32 +codecell.build.variant=codecell +codecell.build.board=CODECELLC3 +codecell.build.bootloader_addr=0x0 + +codecell.build.cdc_on_boot=1 +codecell.build.f_cpu=160000000L +codecell.build.flash_size=4MB +codecell.build.flash_freq=80m +codecell.build.flash_mode=qio +codecell.build.boot=qio +codecell.build.partitions=default +codecell.build.defines= + + +codecell.menu.JTAGAdapter.default=Disabled +codecell.menu.JTAGAdapter.default.build.copy_jtag_files=0 +codecell.menu.JTAGAdapter.builtin=Integrated USB JTAG +codecell.menu.JTAGAdapter.builtin.build.openocdscript=esp32c3-builtin.cfg +codecell.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +codecell.menu.JTAGAdapter.external=FTDI Adapter +codecell.menu.JTAGAdapter.external.build.openocdscript=esp32c3-ftdi.cfg +codecell.menu.JTAGAdapter.external.build.copy_jtag_files=1 +codecell.menu.JTAGAdapter.bridge=ESP USB Bridge +codecell.menu.JTAGAdapter.bridge.build.openocdscript=esp32c3-bridge.cfg +codecell.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +codecell.menu.CDCOnBoot.default=Enabled +codecell.menu.CDCOnBoot.default.build.cdc_on_boot=0 +codecell.menu.CDCOnBoot.cdc=Enabled +codecell.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +codecell.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +codecell.menu.PartitionScheme.default.build.partitions=default +codecell.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +codecell.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +codecell.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +codecell.menu.PartitionScheme.minimal.build.partitions=minimal +codecell.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +codecell.menu.PartitionScheme.no_fs.build.partitions=no_fs +codecell.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +codecell.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +codecell.menu.PartitionScheme.no_ota.build.partitions=no_ota +codecell.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +codecell.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +codecell.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +codecell.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +codecell.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +codecell.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +codecell.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +codecell.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +codecell.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +codecell.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +codecell.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +codecell.menu.PartitionScheme.huge_app.build.partitions=huge_app +codecell.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +codecell.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +codecell.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +codecell.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +codecell.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +codecell.menu.PartitionScheme.fatflash.build.partitions=ffat +codecell.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +codecell.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +codecell.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +codecell.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +codecell.menu.PartitionScheme.rainmaker=RainMaker 4MB +codecell.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +codecell.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +codecell.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +codecell.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +codecell.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +codecell.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +codecell.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +codecell.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +codecell.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +codecell.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +codecell.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +codecell.menu.PartitionScheme.zigbee_zczr_8MB=Zigbee ZCZR 8MB with spiffs +codecell.menu.PartitionScheme.zigbee_zczr_8MB.build.partitions=zigbee_zczr_8MB +codecell.menu.PartitionScheme.zigbee_zczr_8MB.upload.maximum_size=3407872 +codecell.menu.PartitionScheme.custom=Custom +codecell.menu.PartitionScheme.custom.build.partitions= +codecell.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +codecell.menu.CPUFreq.160=160MHz (WiFi) +codecell.menu.CPUFreq.160.build.f_cpu=160000000L +codecell.menu.CPUFreq.80=80MHz (WiFi) +codecell.menu.CPUFreq.80.build.f_cpu=80000000L +codecell.menu.CPUFreq.40=40MHz +codecell.menu.CPUFreq.40.build.f_cpu=40000000L +codecell.menu.CPUFreq.20=20MHz +codecell.menu.CPUFreq.20.build.f_cpu=20000000L +codecell.menu.CPUFreq.10=10MHz +codecell.menu.CPUFreq.10.build.f_cpu=10000000L + +codecell.menu.FlashMode.qio=QIO +codecell.menu.FlashMode.qio.build.flash_mode=dio +codecell.menu.FlashMode.qio.build.boot=qio +codecell.menu.FlashMode.dio=DIO +codecell.menu.FlashMode.dio.build.flash_mode=dio +codecell.menu.FlashMode.dio.build.boot=dio + +codecell.menu.FlashFreq.80=80MHz +codecell.menu.FlashFreq.80.build.flash_freq=80m +codecell.menu.FlashFreq.40=40MHz +codecell.menu.FlashFreq.40.build.flash_freq=40m + +codecell.menu.FlashSize.4M=4MB (32Mb) +codecell.menu.FlashSize.4M.build.flash_size=4MB + +codecell.menu.UploadSpeed.921600=921600 +codecell.menu.UploadSpeed.921600.upload.speed=921600 +codecell.menu.UploadSpeed.115200=115200 +codecell.menu.UploadSpeed.115200.upload.speed=115200 +codecell.menu.UploadSpeed.256000.windows=256000 +codecell.menu.UploadSpeed.256000.upload.speed=256000 +codecell.menu.UploadSpeed.230400.windows.upload.speed=256000 +codecell.menu.UploadSpeed.230400=230400 +codecell.menu.UploadSpeed.230400.upload.speed=230400 +codecell.menu.UploadSpeed.460800.linux=460800 +codecell.menu.UploadSpeed.460800.macosx=460800 +codecell.menu.UploadSpeed.460800.upload.speed=460800 +codecell.menu.UploadSpeed.512000.windows=512000 +codecell.menu.UploadSpeed.512000.upload.speed=512000 + +codecell.menu.DebugLevel.none=None +codecell.menu.DebugLevel.none.build.code_debug=0 +codecell.menu.DebugLevel.error=Error +codecell.menu.DebugLevel.error.build.code_debug=1 +codecell.menu.DebugLevel.warn=Warn +codecell.menu.DebugLevel.warn.build.code_debug=2 +codecell.menu.DebugLevel.info=Info +codecell.menu.DebugLevel.info.build.code_debug=3 +codecell.menu.DebugLevel.debug=Debug +codecell.menu.DebugLevel.debug.build.code_debug=4 +codecell.menu.DebugLevel.verbose=Verbose +codecell.menu.DebugLevel.verbose.build.code_debug=5 + +codecell.menu.EraseFlash.none=Disabled +codecell.menu.EraseFlash.none.upload.erase_cmd= +codecell.menu.EraseFlash.all=Enabled +codecell.menu.EraseFlash.all.upload.erase_cmd=-e + +codecell.menu.ZigbeeMode.default=Disabled +codecell.menu.ZigbeeMode.default.build.zigbee_mode= +codecell.menu.ZigbeeMode.default.build.zigbee_libs= +codecell.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +codecell.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +codecell.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote +############################################################## + +jczn_2432s028r.name=ESP32-2432S028R CYD + +jczn_2432s028r.bootloader.tool=esptool_py +jczn_2432s028r.bootloader.tool.default=esptool_py + +jczn_2432s028r.upload.tool=esptool_py +jczn_2432s028r.upload.tool.default=esptool_py +jczn_2432s028r.upload.tool.network=esp_ota + +jczn_2432s028r.upload.maximum_size=1310720 +jczn_2432s028r.upload.maximum_data_size=327680 +jczn_2432s028r.upload.flags= +jczn_2432s028r.upload.extra_flags= + +jczn_2432s028r.serial.disableDTR=true +jczn_2432s028r.serial.disableRTS=true + +jczn_2432s028r.build.tarch=xtensa +jczn_2432s028r.build.bootloader_addr=0x1000 +jczn_2432s028r.build.target=esp32 +jczn_2432s028r.build.mcu=esp32 +jczn_2432s028r.build.core=esp32 +jczn_2432s028r.build.variant=jczn_2432s028r +jczn_2432s028r.build.board=ESP32_2432S028R + +jczn_2432s028r.build.f_cpu=240000000L +jczn_2432s028r.build.flash_size=4MB +jczn_2432s028r.build.flash_freq=40m +jczn_2432s028r.build.flash_mode=dio +jczn_2432s028r.build.boot=dio +jczn_2432s028r.build.partitions=default +jczn_2432s028r.build.defines= +jczn_2432s028r.build.loop_core= +jczn_2432s028r.build.event_core= + +## IDE 2.0 Seems to not update the value +jczn_2432s028r.menu.JTAGAdapter.default=Disabled +jczn_2432s028r.menu.JTAGAdapter.default.build.copy_jtag_files=0 +jczn_2432s028r.menu.JTAGAdapter.external=FTDI Adapter +jczn_2432s028r.menu.JTAGAdapter.external.build.openocdscript=esp32-wrover-kit-3.3v.cfg +jczn_2432s028r.menu.JTAGAdapter.external.build.copy_jtag_files=1 +jczn_2432s028r.menu.JTAGAdapter.bridge=ESP USB Bridge +jczn_2432s028r.menu.JTAGAdapter.bridge.build.openocdscript=esp32-bridge.cfg +jczn_2432s028r.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +jczn_2432s028r.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +jczn_2432s028r.menu.PartitionScheme.default.build.partitions=default +jczn_2432s028r.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +jczn_2432s028r.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +jczn_2432s028r.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +jczn_2432s028r.menu.PartitionScheme.no_ota.build.partitions=no_ota +jczn_2432s028r.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +jczn_2432s028r.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +jczn_2432s028r.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +jczn_2432s028r.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +jczn_2432s028r.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +jczn_2432s028r.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +jczn_2432s028r.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +jczn_2432s028r.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +jczn_2432s028r.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +jczn_2432s028r.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +jczn_2432s028r.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +jczn_2432s028r.menu.PartitionScheme.huge_app.build.partitions=huge_app +jczn_2432s028r.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +jczn_2432s028r.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +jczn_2432s028r.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +jczn_2432s028r.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +jczn_2432s028r.menu.PartitionScheme.rainmaker=RainMaker 4MB +jczn_2432s028r.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +jczn_2432s028r.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +jczn_2432s028r.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +jczn_2432s028r.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +jczn_2432s028r.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +jczn_2432s028r.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +jczn_2432s028r.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +jczn_2432s028r.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 + +jczn_2432s028r.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +jczn_2432s028r.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +jczn_2432s028r.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +jczn_2432s028r.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +jczn_2432s028r.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +jczn_2432s028r.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +jczn_2432s028r.menu.PartitionScheme.custom=Custom +jczn_2432s028r.menu.PartitionScheme.custom.build.partitions= +jczn_2432s028r.menu.PartitionScheme.custom.upload.maximum_size=4128768 + +jczn_2432s028r.menu.CPUFreq.240=240MHz (WiFi/BT) +jczn_2432s028r.menu.CPUFreq.240.build.f_cpu=240000000L +jczn_2432s028r.menu.CPUFreq.160=160MHz (WiFi/BT) +jczn_2432s028r.menu.CPUFreq.160.build.f_cpu=160000000L +jczn_2432s028r.menu.CPUFreq.80=80MHz (WiFi/BT) +jczn_2432s028r.menu.CPUFreq.80.build.f_cpu=80000000L +jczn_2432s028r.menu.CPUFreq.40=40MHz +jczn_2432s028r.menu.CPUFreq.40.build.f_cpu=40000000L +jczn_2432s028r.menu.CPUFreq.20=20MHz +jczn_2432s028r.menu.CPUFreq.20.build.f_cpu=20000000L +jczn_2432s028r.menu.CPUFreq.10=10MHz +jczn_2432s028r.menu.CPUFreq.10.build.f_cpu=10000000L + +jczn_2432s028r.menu.FlashMode.qio=QIO +jczn_2432s028r.menu.FlashMode.qio.build.flash_mode=dio +jczn_2432s028r.menu.FlashMode.qio.build.boot=qio + +jczn_2432s028r.menu.FlashFreq.80=80MHz +jczn_2432s028r.menu.FlashFreq.80.build.flash_freq=80m +jczn_2432s028r.menu.FlashFreq.40=40MHz +jczn_2432s028r.menu.FlashFreq.40.build.flash_freq=40m + +jczn_2432s028r.menu.FlashSize.4M=4MB +jczn_2432s028r.menu.FlashSize.4M.build.flash_size=4MB + +jczn_2432s028r.menu.UploadSpeed.921600=921600 +jczn_2432s028r.menu.UploadSpeed.921600.upload.speed=921600 +jczn_2432s028r.menu.UploadSpeed.115200=115200 +jczn_2432s028r.menu.UploadSpeed.115200.upload.speed=115200 +jczn_2432s028r.menu.UploadSpeed.256000.windows=256000 +jczn_2432s028r.menu.UploadSpeed.256000.upload.speed=256000 +jczn_2432s028r.menu.UploadSpeed.230400.windows.upload.speed=256000 +jczn_2432s028r.menu.UploadSpeed.230400=230400 +jczn_2432s028r.menu.UploadSpeed.230400.upload.speed=230400 +jczn_2432s028r.menu.UploadSpeed.460800.linux=460800 +jczn_2432s028r.menu.UploadSpeed.460800.macosx=460800 +jczn_2432s028r.menu.UploadSpeed.460800.upload.speed=460800 +jczn_2432s028r.menu.UploadSpeed.512000.windows=512000 +jczn_2432s028r.menu.UploadSpeed.512000.upload.speed=512000 + +jczn_2432s028r.menu.LoopCore.1=Core 1 +jczn_2432s028r.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +jczn_2432s028r.menu.LoopCore.0=Core 0 +jczn_2432s028r.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +jczn_2432s028r.menu.EventsCore.1=Core 1 +jczn_2432s028r.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +jczn_2432s028r.menu.EventsCore.0=Core 0 +jczn_2432s028r.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +jczn_2432s028r.menu.DebugLevel.none=None +jczn_2432s028r.menu.DebugLevel.none.build.code_debug=0 +jczn_2432s028r.menu.DebugLevel.error=Error +jczn_2432s028r.menu.DebugLevel.error.build.code_debug=1 +jczn_2432s028r.menu.DebugLevel.warn=Warn +jczn_2432s028r.menu.DebugLevel.warn.build.code_debug=2 +jczn_2432s028r.menu.DebugLevel.info=Info +jczn_2432s028r.menu.DebugLevel.info.build.code_debug=3 +jczn_2432s028r.menu.DebugLevel.debug=Debug +jczn_2432s028r.menu.DebugLevel.debug.build.code_debug=4 +jczn_2432s028r.menu.DebugLevel.verbose=Verbose +jczn_2432s028r.menu.DebugLevel.verbose.build.code_debug=5 + +jczn_2432s028r.menu.EraseFlash.none=Disabled +jczn_2432s028r.menu.EraseFlash.none.upload.erase_cmd= +jczn_2432s028r.menu.EraseFlash.all=Enabled +jczn_2432s028r.menu.EraseFlash.all.upload.erase_cmd=-e + +jczn_2432s028r.menu.ZigbeeMode.default=Disabled +jczn_2432s028r.menu.ZigbeeMode.default.build.zigbee_mode= +jczn_2432s028r.menu.ZigbeeMode.default.build.zigbee_libs= +jczn_2432s028r.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +jczn_2432s028r.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +jczn_2432s028r.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################################################## + +waveshare_esp32_s3_touch_amoled_241.name=Waveshare ESP32-S3-Touch-AMOLED-2.41 +waveshare_esp32_s3_touch_amoled_241.vid.0=0x303a +waveshare_esp32_s3_touch_amoled_241.pid.0=0x8242 +waveshare_esp32_s3_touch_amoled_241.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_amoled_241.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_touch_amoled_241.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_amoled_241.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_amoled_241.upload.tool=esptool_py +waveshare_esp32_s3_touch_amoled_241.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_amoled_241.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_amoled_241.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_amoled_241.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_amoled_241.upload.flags= +waveshare_esp32_s3_touch_amoled_241.upload.extra_flags= +waveshare_esp32_s3_touch_amoled_241.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_241.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_amoled_241.serial.disableDTR=false +waveshare_esp32_s3_touch_amoled_241.serial.disableRTS=false + +waveshare_esp32_s3_touch_amoled_241.build.tarch=xtensa +waveshare_esp32_s3_touch_amoled_241.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_amoled_241.build.target=esp32s3 +waveshare_esp32_s3_touch_amoled_241.build.mcu=esp32s3 +waveshare_esp32_s3_touch_amoled_241.build.core=esp32 +waveshare_esp32_s3_touch_amoled_241.build.variant=waveshare_esp32_s3_touch_amoled_241 +waveshare_esp32_s3_touch_amoled_241.build.board=WAVESHARE_ESP32_S3_TOUCH_AMOLED_241 + +waveshare_esp32_s3_touch_amoled_241.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_241.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_241.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_241.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_241.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_241.build.flash_size=16MB + +waveshare_esp32_s3_touch_amoled_241.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_241.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_241.build.boot=qio +waveshare_esp32_s3_touch_amoled_241.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_241.build.partitions=default +waveshare_esp32_s3_touch_amoled_241.build.defines= +waveshare_esp32_s3_touch_amoled_241.build.loop_core= +waveshare_esp32_s3_touch_amoled_241.build.event_core= +waveshare_esp32_s3_touch_amoled_241.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_241.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_amoled_241.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_amoled_241.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_amoled_241.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_241.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_amoled_241.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_amoled_241.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_amoled_241.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_amoled_241.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_241.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_amoled_241.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_241.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_241.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_amoled_241.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_241.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_amoled_241.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_amoled_241.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_amoled_241.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_241.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_241.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_241.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_241.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_241.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_241.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_241.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_241.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_amoled_241.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_241.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_amoled_241.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_amoled_241.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_241.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_241.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_amoled_241.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_241.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_241.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_241.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_241.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_241.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_241.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_241.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_241.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_amoled_241.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_amoled_241.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_241.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_amoled_241.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_amoled_241.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_amoled_241.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) + +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 + +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_amoled_241.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_amoled_241.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_241.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_amoled_241.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_amoled_241.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_amoled_241.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_amoled_241.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_amoled_241.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_amoled_241.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_amoled_241.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_amoled_241.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_amoled_241.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_amoled_241.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_amoled_241.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_amoled_241.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_amoled_241.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_amoled_241.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_amoled_241.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_amoled_241.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_amoled_241.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_amoled_241.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_amoled_241.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_amoled_241.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_amoled_241.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_amoled_241.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_amoled_241.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_amoled_241.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_amoled_241.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_amoled_241.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_43.name=Waveshare ESP32-S3-Touch-LCD-4.3 +waveshare_esp32_s3_touch_lcd_43.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_43.pid.0=0x822E +waveshare_esp32_s3_touch_lcd_43.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_43.upload_port.0.pid=0x822E + +waveshare_esp32_s3_touch_lcd_43.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_43.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_43.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_43.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_43.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_43.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_43.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_43.upload.flags= +waveshare_esp32_s3_touch_lcd_43.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_43.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_43.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_43.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_43.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_43.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_43.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_43.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_43.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_43.build.core=esp32 +waveshare_esp32_s3_touch_lcd_43.build.variant=waveshare_esp32_s3_touch_lcd_43 +waveshare_esp32_s3_touch_lcd_43.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_43 + +waveshare_esp32_s3_touch_lcd_43.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_43.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_43.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_43.build.flash_size=8MB +waveshare_esp32_s3_touch_lcd_43.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_43.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_43.build.boot=qio +waveshare_esp32_s3_touch_lcd_43.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_43.build.partitions=default +waveshare_esp32_s3_touch_lcd_43.build.defines= +waveshare_esp32_s3_touch_lcd_43.build.loop_core= +waveshare_esp32_s3_touch_lcd_43.build.event_core= +waveshare_esp32_s3_touch_lcd_43.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_43.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_43.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_43.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_43.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_43.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_43.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_43.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_43.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_43.menu.FlashSize.8M=8MB (64Mb) +waveshare_esp32_s3_touch_lcd_43.menu.FlashSize.8M.build.flash_size=8MB +waveshare_esp32_s3_touch_lcd_43.menu.FlashSize.16M=16MB (128Mb) +waveshare_esp32_s3_touch_lcd_43.menu.FlashSize.16M.build.flash_size=16MB + +waveshare_esp32_s3_touch_lcd_43.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_43.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_43.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_43.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_43.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_43.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_43.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_43.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_43.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_43.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_43.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_43.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_43.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_43.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_43.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_43.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_43.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_43.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_43.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_43.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_43.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_43.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_43.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_43.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_43.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_43.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_43.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_43.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_43.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_43B.name=Waveshare ESP32-S3-Touch-LCD-4.3B +waveshare_esp32_s3_touch_lcd_43B.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_43B.pid.0=0x8231 +waveshare_esp32_s3_touch_lcd_43B.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_43B.upload_port.0.pid=0x8231 + +waveshare_esp32_s3_touch_lcd_43B.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_43B.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_43B.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_43B.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_43B.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_43B.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_43B.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_43B.upload.flags= +waveshare_esp32_s3_touch_lcd_43B.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_43B.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_43B.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_43B.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_43B.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_43B.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_43B.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_43B.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_43B.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_43B.build.core=esp32 +waveshare_esp32_s3_touch_lcd_43B.build.variant=waveshare_esp32_s3_touch_lcd_43b +waveshare_esp32_s3_touch_lcd_43B.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_43B + +waveshare_esp32_s3_touch_lcd_43B.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_43B.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43B.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43B.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_43B.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_43B.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_43B.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_43B.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_43B.build.boot=qio +waveshare_esp32_s3_touch_lcd_43B.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_43B.build.partitions=default +waveshare_esp32_s3_touch_lcd_43B.build.defines= +waveshare_esp32_s3_touch_lcd_43B.build.loop_core= +waveshare_esp32_s3_touch_lcd_43B.build.event_core= +waveshare_esp32_s3_touch_lcd_43B.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_43B.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_43B.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_43B.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_43B.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_43B.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_43B.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_43B.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_43B.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_43B.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_43B.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_43B.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_43B.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_43B.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_43B.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_43B.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_43B.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_43B.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_43B.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_43B.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_43B.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_43B.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_43B.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43B.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_43B.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_43B.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_43B.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_43B.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_43B.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_43B.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_43B.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_43B.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_43B.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_43B.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_43B.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_43B.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_43B.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_43B.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_43B.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_43B.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_7.name=Waveshare ESP32-S3-Touch-LCD-7 +waveshare_esp32_s3_touch_lcd_7.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_7.pid.0=0x8234 +waveshare_esp32_s3_touch_lcd_7.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_7.upload_port.0.pid=0x8234 + +waveshare_esp32_s3_touch_lcd_7.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_7.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_7.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_7.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_7.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_7.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_7.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_7.upload.flags= +waveshare_esp32_s3_touch_lcd_7.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_7.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_7.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_7.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_7.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_7.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_7.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_7.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_7.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_7.build.core=esp32 +waveshare_esp32_s3_touch_lcd_7.build.variant=waveshare_esp32_s3_touch_lcd_7 +waveshare_esp32_s3_touch_lcd_7.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_7 + +waveshare_esp32_s3_touch_lcd_7.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_7.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_7.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_7.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_7.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_7.build.flash_size=8MB +waveshare_esp32_s3_touch_lcd_7.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_7.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_7.build.boot=qio +waveshare_esp32_s3_touch_lcd_7.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_7.build.partitions=default +waveshare_esp32_s3_touch_lcd_7.build.defines= +waveshare_esp32_s3_touch_lcd_7.build.loop_core= +waveshare_esp32_s3_touch_lcd_7.build.event_core= +waveshare_esp32_s3_touch_lcd_7.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_7.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_7.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_7.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_7.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_7.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_7.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_7.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_7.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_7.menu.FlashSize.8M=8MB (64Mb) +waveshare_esp32_s3_touch_lcd_7.menu.FlashSize.8M.build.flash_size=8MB +waveshare_esp32_s3_touch_lcd_7.menu.FlashSize.16M=16MB (128Mb) +waveshare_esp32_s3_touch_lcd_7.menu.FlashSize.16M.build.flash_size=16MB + +waveshare_esp32_s3_touch_lcd_7.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_7.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_7.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_7.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_7.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_7.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_7.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_7.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_7.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_7.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_7.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_7.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_7.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_7.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_7.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_7.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_7.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_7.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_7.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_7.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_7.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_7.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_7.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_7.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_7.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_7.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_7.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_7.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_7.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_7.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_7.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_5.name=Waveshare ESP32-S3-Touch-LCD-5 +waveshare_esp32_s3_touch_lcd_5.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_5.pid.0=0x8237 +waveshare_esp32_s3_touch_lcd_5.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_5.upload_port.0.pid=0x8237 + +waveshare_esp32_s3_touch_lcd_5.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_5.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_5.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_5.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_5.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_5.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_5.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_5.upload.flags= +waveshare_esp32_s3_touch_lcd_5.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_5.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_5.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_5.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_5.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_5.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_5.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_5.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_5.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_5.build.core=esp32 +waveshare_esp32_s3_touch_lcd_5.build.variant=waveshare_esp32_s3_touch_lcd_5 +waveshare_esp32_s3_touch_lcd_5.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_5 + +waveshare_esp32_s3_touch_lcd_5.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_5.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_5.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_5.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_5.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_5.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_5.build.boot=qio +waveshare_esp32_s3_touch_lcd_5.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_5.build.partitions=default +waveshare_esp32_s3_touch_lcd_5.build.defines= +waveshare_esp32_s3_touch_lcd_5.build.loop_core= +waveshare_esp32_s3_touch_lcd_5.build.event_core= +waveshare_esp32_s3_touch_lcd_5.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_5.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_5.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_5.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_5.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_5.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_5.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_5.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_5.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_5.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_5.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_5.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_5.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_5.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_5.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_5.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_5.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_5.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_5.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_5.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_5.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_5.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_5.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_5.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_5.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_5.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_5.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_5.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_5.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_5.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_5.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_5.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_5.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_5.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_5.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_5.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_5.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_5.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_5B.name=Waveshare ESP32-S3-Touch-LCD-5B +waveshare_esp32_s3_touch_lcd_5B.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_5B.pid.0=0x823A +waveshare_esp32_s3_touch_lcd_5B.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_5B.upload_port.0.pid=0x823A + +waveshare_esp32_s3_touch_lcd_5B.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_5B.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_5B.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_5B.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_5B.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_5B.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_5B.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_5B.upload.flags= +waveshare_esp32_s3_touch_lcd_5B.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_5B.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_5B.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_5B.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_5B.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_5B.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_5B.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_5B.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_5B.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_5B.build.core=esp32 +waveshare_esp32_s3_touch_lcd_5B.build.variant=waveshare_esp32_s3_touch_lcd_5b +waveshare_esp32_s3_touch_lcd_5B.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_5B + +waveshare_esp32_s3_touch_lcd_5B.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_5B.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5B.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5B.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_5B.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_5B.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_5B.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_5B.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_5B.build.boot=qio +waveshare_esp32_s3_touch_lcd_5B.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_5B.build.partitions=default +waveshare_esp32_s3_touch_lcd_5B.build.defines= +waveshare_esp32_s3_touch_lcd_5B.build.loop_core= +waveshare_esp32_s3_touch_lcd_5B.build.event_core= +waveshare_esp32_s3_touch_lcd_5B.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_5B.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_5B.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_5B.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_5B.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_5B.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_5B.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_5B.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_5B.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_5B.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_5B.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_5B.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_5B.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_5B.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_5B.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_5B.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_5B.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_5B.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_5B.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_5B.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_5B.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_5B.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_5B.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5B.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_5B.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_5B.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_5B.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_5B.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_5B.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_5B.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_5B.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_5B.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_5B.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_5B.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_5B.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_5B.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_5B.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_5B.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_5B.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_5B.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_4.name=Waveshare ESP32-S3-Touch-LCD-4 +waveshare_esp32_s3_touch_lcd_4.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_4.pid.0=0x823D +waveshare_esp32_s3_touch_lcd_4.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_4.upload_port.0.pid=0x823D + +waveshare_esp32_s3_touch_lcd_4.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_4.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_4.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_4.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_4.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_4.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_lcd_4.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_4.upload.flags= +waveshare_esp32_s3_touch_lcd_4.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_4.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_4.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_4.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_4.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_4.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_4.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_4.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_4.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_4.build.core=esp32 +waveshare_esp32_s3_touch_lcd_4.build.variant=waveshare_esp32_s3_touch_lcd_4 +waveshare_esp32_s3_touch_lcd_4.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_4 + +waveshare_esp32_s3_touch_lcd_4.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_4.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_4.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_4.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_4.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_4.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_4.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_4.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_4.build.boot=qio +waveshare_esp32_s3_touch_lcd_4.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_4.build.partitions=default +waveshare_esp32_s3_touch_lcd_4.build.defines= +waveshare_esp32_s3_touch_lcd_4.build.loop_core= +waveshare_esp32_s3_touch_lcd_4.build.event_core= +waveshare_esp32_s3_touch_lcd_4.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_4.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_lcd_4.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_4.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_4.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_lcd_4.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_4.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_4.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_4.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_4.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_4.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_4.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_4.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_4.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_4.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_4.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_4.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_4.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_4.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_4.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_4.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_4.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_4.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_4.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_4.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_4.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_4.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_4.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_4.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_4.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_4.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_4.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_4.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_4.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_4.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_4.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_4.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_4.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_4.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_4.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_lcd_185.name=Waveshare ESP32-S3-Touch-LCD-1.85 +waveshare_esp32_s3_touch_lcd_185.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_185.pid.0=0x8290 +waveshare_esp32_s3_touch_lcd_185.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_185.upload_port.0.pid=0x8290 + +waveshare_esp32_s3_touch_lcd_185.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_185.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_185.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_185.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_185.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_185.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_185.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_185.upload.flags= +waveshare_esp32_s3_touch_lcd_185.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_185.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_185.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_185.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_185.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_185.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_185.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_185.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_185.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_185.build.core=esp32 +waveshare_esp32_s3_touch_lcd_185.build.variant=waveshare_esp32_s3_touch_lcd_185 +waveshare_esp32_s3_touch_lcd_185.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_185 + +waveshare_esp32_s3_touch_lcd_185.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_185.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_185.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_185.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_185.build.flash_freq=120m +waveshare_esp32_s3_touch_lcd_185.build.flash_mode=qio +waveshare_esp32_s3_touch_lcd_185.build.boot=qio +waveshare_esp32_s3_touch_lcd_185.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185.build.partitions=default +waveshare_esp32_s3_touch_lcd_185.build.defines= +waveshare_esp32_s3_touch_lcd_185.build.loop_core= +waveshare_esp32_s3_touch_lcd_185.build.event_core= +waveshare_esp32_s3_touch_lcd_185.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_185.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_touch_lcd_185.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_touch_lcd_185.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_185.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_185.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_185.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_185.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_185.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_185.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_185.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_185.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_185.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_185.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 +waveshare_esp32_s3_touch_lcd_185.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_185.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +waveshare_esp32_s3_touch_lcd_185.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_185.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_185.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_185.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_185.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_185.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_185.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_185.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_185.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_185.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_185.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_185.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_185.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_185.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_185.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_185.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_185.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_185.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_185.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_185.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_185.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_185.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_185.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_185.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_touch_lcd_185.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_touch_lcd_185.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_touch_lcd_185.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_touch_lcd_185.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_touch_lcd_185.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_touch_lcd_185.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################################################## + +cezerio_dev_esp32c6.name=cezerio dev ESP32C6 + +cezerio_dev_esp32c6.bootloader.tool=esptool_py +cezerio_dev_esp32c6.bootloader.tool.default=esptool_py + +cezerio_dev_esp32c6.upload.tool=esptool_py +cezerio_dev_esp32c6.upload.tool.default=esptool_py +cezerio_dev_esp32c6.upload.tool.network=esp_ota + +cezerio_dev_esp32c6.upload.maximum_size=1310720 +cezerio_dev_esp32c6.upload.maximum_data_size=327680 +cezerio_dev_esp32c6.upload.flags= +cezerio_dev_esp32c6.upload.extra_flags= +cezerio_dev_esp32c6.upload.use_1200bps_touch=false +cezerio_dev_esp32c6.upload.wait_for_upload_port=false + +cezerio_dev_esp32c6.serial.disableDTR=false +cezerio_dev_esp32c6.serial.disableRTS=false + +cezerio_dev_esp32c6.build.tarch=riscv32 +cezerio_dev_esp32c6.build.target=esp +cezerio_dev_esp32c6.build.mcu=esp32c6 +cezerio_dev_esp32c6.build.core=esp32 +cezerio_dev_esp32c6.build.variant=cezerio_dev_esp32c6 +cezerio_dev_esp32c6.build.board=CEZERIO_DEV_ESP32C6 +cezerio_dev_esp32c6.build.bootloader_addr=0x0 + +cezerio_dev_esp32c6.build.cdc_on_boot=0 +cezerio_dev_esp32c6.build.f_cpu=160000000L +cezerio_dev_esp32c6.build.flash_size=4MB +cezerio_dev_esp32c6.build.flash_freq=80m +cezerio_dev_esp32c6.build.flash_mode=qio +cezerio_dev_esp32c6.build.boot=qio +cezerio_dev_esp32c6.build.partitions=default +cezerio_dev_esp32c6.build.defines= + +## IDE 2.0 Seems to not update the value +cezerio_dev_esp32c6.menu.JTAGAdapter.default=Disabled +cezerio_dev_esp32c6.menu.JTAGAdapter.default.build.copy_jtag_files=0 +cezerio_dev_esp32c6.menu.JTAGAdapter.builtin=Integrated USB JTAG +cezerio_dev_esp32c6.menu.JTAGAdapter.builtin.build.openocdscript=esp32c6-builtin.cfg +cezerio_dev_esp32c6.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +cezerio_dev_esp32c6.menu.JTAGAdapter.external=FTDI Adapter +cezerio_dev_esp32c6.menu.JTAGAdapter.external.build.openocdscript=esp32c6-ftdi.cfg +cezerio_dev_esp32c6.menu.JTAGAdapter.external.build.copy_jtag_files=1 +cezerio_dev_esp32c6.menu.JTAGAdapter.bridge=ESP USB Bridge +cezerio_dev_esp32c6.menu.JTAGAdapter.bridge.build.openocdscript=esp32c6-bridge.cfg +cezerio_dev_esp32c6.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +cezerio_dev_esp32c6.menu.CDCOnBoot.default=Enabled +cezerio_dev_esp32c6.menu.CDCOnBoot.default.build.cdc_on_boot=1 +cezerio_dev_esp32c6.menu.CDCOnBoot.cdc=Disabled +cezerio_dev_esp32c6.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +cezerio_dev_esp32c6.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +cezerio_dev_esp32c6.menu.PartitionScheme.default.build.partitions=default +cezerio_dev_esp32c6.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +cezerio_dev_esp32c6.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +cezerio_dev_esp32c6.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +cezerio_dev_esp32c6.menu.PartitionScheme.minimal.build.partitions=minimal +cezerio_dev_esp32c6.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +cezerio_dev_esp32c6.menu.PartitionScheme.no_fs.build.partitions=no_fs +cezerio_dev_esp32c6.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +cezerio_dev_esp32c6.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +cezerio_dev_esp32c6.menu.PartitionScheme.no_ota.build.partitions=no_ota +cezerio_dev_esp32c6.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +cezerio_dev_esp32c6.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +cezerio_dev_esp32c6.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +cezerio_dev_esp32c6.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +cezerio_dev_esp32c6.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +cezerio_dev_esp32c6.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +cezerio_dev_esp32c6.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +cezerio_dev_esp32c6.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +cezerio_dev_esp32c6.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +cezerio_dev_esp32c6.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +cezerio_dev_esp32c6.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +cezerio_dev_esp32c6.menu.PartitionScheme.huge_app.build.partitions=huge_app +cezerio_dev_esp32c6.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +cezerio_dev_esp32c6.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +cezerio_dev_esp32c6.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +cezerio_dev_esp32c6.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +cezerio_dev_esp32c6.menu.PartitionScheme.rainmaker=RainMaker 4MB +cezerio_dev_esp32c6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +cezerio_dev_esp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +cezerio_dev_esp32c6.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +cezerio_dev_esp32c6.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +cezerio_dev_esp32c6.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +cezerio_dev_esp32c6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs +cezerio_dev_esp32c6.menu.PartitionScheme.zigbee.build.partitions=zigbee +cezerio_dev_esp32c6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 +cezerio_dev_esp32c6.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +cezerio_dev_esp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +cezerio_dev_esp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +cezerio_dev_esp32c6.menu.PartitionScheme.custom=Custom +cezerio_dev_esp32c6.menu.PartitionScheme.custom.build.partitions= +cezerio_dev_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +cezerio_dev_esp32c6.menu.CPUFreq.160=160MHz (WiFi) +cezerio_dev_esp32c6.menu.CPUFreq.160.build.f_cpu=160000000L +cezerio_dev_esp32c6.menu.CPUFreq.120=120MHz (WiFi) +cezerio_dev_esp32c6.menu.CPUFreq.120.build.f_cpu=120000000L +cezerio_dev_esp32c6.menu.CPUFreq.80=80MHz (WiFi) +cezerio_dev_esp32c6.menu.CPUFreq.80.build.f_cpu=80000000L +cezerio_dev_esp32c6.menu.CPUFreq.40=40MHz +cezerio_dev_esp32c6.menu.CPUFreq.40.build.f_cpu=40000000L +cezerio_dev_esp32c6.menu.CPUFreq.20=20MHz +cezerio_dev_esp32c6.menu.CPUFreq.20.build.f_cpu=20000000L +cezerio_dev_esp32c6.menu.CPUFreq.10=10MHz +cezerio_dev_esp32c6.menu.CPUFreq.10.build.f_cpu=10000000L + +cezerio_dev_esp32c6.menu.FlashMode.qio=QIO +cezerio_dev_esp32c6.menu.FlashMode.qio.build.flash_mode=dio +cezerio_dev_esp32c6.menu.FlashMode.qio.build.boot=qio +cezerio_dev_esp32c6.menu.FlashMode.dio=DIO +cezerio_dev_esp32c6.menu.FlashMode.dio.build.flash_mode=dio +cezerio_dev_esp32c6.menu.FlashMode.dio.build.boot=dio + +cezerio_dev_esp32c6.menu.FlashFreq.80=80MHz +cezerio_dev_esp32c6.menu.FlashFreq.80.build.flash_freq=80m +cezerio_dev_esp32c6.menu.FlashFreq.40=40MHz +cezerio_dev_esp32c6.menu.FlashFreq.40.build.flash_freq=40m + +cezerio_dev_esp32c6.menu.FlashSize.4M=4MB (32Mb) +cezerio_dev_esp32c6.menu.FlashSize.4M.build.flash_size=4MB + +cezerio_dev_esp32c6.menu.UploadSpeed.921600=921600 +cezerio_dev_esp32c6.menu.UploadSpeed.921600.upload.speed=921600 +cezerio_dev_esp32c6.menu.UploadSpeed.115200=115200 +cezerio_dev_esp32c6.menu.UploadSpeed.115200.upload.speed=115200 +cezerio_dev_esp32c6.menu.UploadSpeed.256000.windows=256000 +cezerio_dev_esp32c6.menu.UploadSpeed.256000.upload.speed=256000 +cezerio_dev_esp32c6.menu.UploadSpeed.230400.windows.upload.speed=256000 +cezerio_dev_esp32c6.menu.UploadSpeed.230400=230400 +cezerio_dev_esp32c6.menu.UploadSpeed.230400.upload.speed=230400 +cezerio_dev_esp32c6.menu.UploadSpeed.460800.linux=460800 +cezerio_dev_esp32c6.menu.UploadSpeed.460800.macosx=460800 +cezerio_dev_esp32c6.menu.UploadSpeed.460800.upload.speed=460800 +cezerio_dev_esp32c6.menu.UploadSpeed.512000.windows=512000 +cezerio_dev_esp32c6.menu.UploadSpeed.512000.upload.speed=512000 + +cezerio_dev_esp32c6.menu.DebugLevel.none=None +cezerio_dev_esp32c6.menu.DebugLevel.none.build.code_debug=0 +cezerio_dev_esp32c6.menu.DebugLevel.error=Error +cezerio_dev_esp32c6.menu.DebugLevel.error.build.code_debug=1 +cezerio_dev_esp32c6.menu.DebugLevel.warn=Warn +cezerio_dev_esp32c6.menu.DebugLevel.warn.build.code_debug=2 +cezerio_dev_esp32c6.menu.DebugLevel.info=Info +cezerio_dev_esp32c6.menu.DebugLevel.info.build.code_debug=3 +cezerio_dev_esp32c6.menu.DebugLevel.debug=Debug +cezerio_dev_esp32c6.menu.DebugLevel.debug.build.code_debug=4 +cezerio_dev_esp32c6.menu.DebugLevel.verbose=Verbose +cezerio_dev_esp32c6.menu.DebugLevel.verbose.build.code_debug=5 + +cezerio_dev_esp32c6.menu.EraseFlash.none=Disabled +cezerio_dev_esp32c6.menu.EraseFlash.none.upload.erase_cmd= +cezerio_dev_esp32c6.menu.EraseFlash.all=Enabled +cezerio_dev_esp32c6.menu.EraseFlash.all.upload.erase_cmd=-e + +cezerio_dev_esp32c6.menu.ZigbeeMode.default=Disabled +cezerio_dev_esp32c6.menu.ZigbeeMode.default.build.zigbee_mode= +cezerio_dev_esp32c6.menu.ZigbeeMode.default.build.zigbee_libs= +cezerio_dev_esp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) +cezerio_dev_esp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED +cezerio_dev_esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +cezerio_dev_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +cezerio_dev_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +cezerio_dev_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native + +############################################################## + +cezerio_mini_dev_esp32c6.name=cezerio mini dev ESP32C6 + +cezerio_mini_dev_esp32c6.bootloader.tool=esptool_py +cezerio_mini_dev_esp32c6.bootloader.tool.default=esptool_py + +cezerio_mini_dev_esp32c6.upload.tool=esptool_py +cezerio_mini_dev_esp32c6.upload.tool.default=esptool_py +cezerio_mini_dev_esp32c6.upload.tool.network=esp_ota + +cezerio_mini_dev_esp32c6.upload.maximum_size=1310720 +cezerio_mini_dev_esp32c6.upload.maximum_data_size=327680 +cezerio_mini_dev_esp32c6.upload.flags= +cezerio_mini_dev_esp32c6.upload.extra_flags= +cezerio_mini_dev_esp32c6.upload.use_1200bps_touch=false +cezerio_mini_dev_esp32c6.upload.wait_for_upload_port=false + +cezerio_mini_dev_esp32c6.serial.disableDTR=false +cezerio_mini_dev_esp32c6.serial.disableRTS=false + +cezerio_mini_dev_esp32c6.build.tarch=riscv32 +cezerio_mini_dev_esp32c6.build.target=esp +cezerio_mini_dev_esp32c6.build.mcu=esp32c6 +cezerio_mini_dev_esp32c6.build.core=esp32 +cezerio_mini_dev_esp32c6.build.variant=cezerio_mini_dev_esp32c6 +cezerio_mini_dev_esp32c6.build.board=CEZERIO_MINI_DEV_ESP32C6 +cezerio_mini_dev_esp32c6.build.bootloader_addr=0x0 + +cezerio_mini_dev_esp32c6.build.cdc_on_boot=0 +cezerio_mini_dev_esp32c6.build.f_cpu=160000000L +cezerio_mini_dev_esp32c6.build.flash_size=4MB +cezerio_mini_dev_esp32c6.build.flash_freq=80m +cezerio_mini_dev_esp32c6.build.flash_mode=qio +cezerio_mini_dev_esp32c6.build.boot=qio +cezerio_mini_dev_esp32c6.build.partitions=default +cezerio_mini_dev_esp32c6.build.defines= + +## IDE 2.0 Seems to not update the value +cezerio_mini_dev_esp32c6.menu.JTAGAdapter.default=Disabled +cezerio_mini_dev_esp32c6.menu.JTAGAdapter.default.build.copy_jtag_files=0 +cezerio_mini_dev_esp32c6.menu.JTAGAdapter.builtin=Integrated USB JTAG +cezerio_mini_dev_esp32c6.menu.JTAGAdapter.builtin.build.openocdscript=esp32c6-builtin.cfg +cezerio_mini_dev_esp32c6.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +cezerio_mini_dev_esp32c6.menu.JTAGAdapter.external=FTDI Adapter +cezerio_mini_dev_esp32c6.menu.JTAGAdapter.external.build.openocdscript=esp32c6-ftdi.cfg +cezerio_mini_dev_esp32c6.menu.JTAGAdapter.external.build.copy_jtag_files=1 +cezerio_mini_dev_esp32c6.menu.JTAGAdapter.bridge=ESP USB Bridge +cezerio_mini_dev_esp32c6.menu.JTAGAdapter.bridge.build.openocdscript=esp32c6-bridge.cfg +cezerio_mini_dev_esp32c6.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +cezerio_mini_dev_esp32c6.menu.CDCOnBoot.default=Enabled +cezerio_mini_dev_esp32c6.menu.CDCOnBoot.default.build.cdc_on_boot=1 +cezerio_mini_dev_esp32c6.menu.CDCOnBoot.cdc=Disabled +cezerio_mini_dev_esp32c6.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +cezerio_mini_dev_esp32c6.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +cezerio_mini_dev_esp32c6.menu.PartitionScheme.default.build.partitions=default +cezerio_mini_dev_esp32c6.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +cezerio_mini_dev_esp32c6.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +cezerio_mini_dev_esp32c6.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +cezerio_mini_dev_esp32c6.menu.PartitionScheme.minimal.build.partitions=minimal +cezerio_mini_dev_esp32c6.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +cezerio_mini_dev_esp32c6.menu.PartitionScheme.no_fs.build.partitions=no_fs +cezerio_mini_dev_esp32c6.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +cezerio_mini_dev_esp32c6.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +cezerio_mini_dev_esp32c6.menu.PartitionScheme.no_ota.build.partitions=no_ota +cezerio_mini_dev_esp32c6.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +cezerio_mini_dev_esp32c6.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +cezerio_mini_dev_esp32c6.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +cezerio_mini_dev_esp32c6.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +cezerio_mini_dev_esp32c6.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +cezerio_mini_dev_esp32c6.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +cezerio_mini_dev_esp32c6.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +cezerio_mini_dev_esp32c6.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +cezerio_mini_dev_esp32c6.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +cezerio_mini_dev_esp32c6.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +cezerio_mini_dev_esp32c6.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +cezerio_mini_dev_esp32c6.menu.PartitionScheme.huge_app.build.partitions=huge_app +cezerio_mini_dev_esp32c6.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +cezerio_mini_dev_esp32c6.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +cezerio_mini_dev_esp32c6.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +cezerio_mini_dev_esp32c6.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +cezerio_mini_dev_esp32c6.menu.PartitionScheme.rainmaker=RainMaker 4MB +cezerio_mini_dev_esp32c6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +cezerio_mini_dev_esp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +cezerio_mini_dev_esp32c6.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +cezerio_mini_dev_esp32c6.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +cezerio_mini_dev_esp32c6.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +cezerio_mini_dev_esp32c6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs +cezerio_mini_dev_esp32c6.menu.PartitionScheme.zigbee.build.partitions=zigbee +cezerio_mini_dev_esp32c6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 +cezerio_mini_dev_esp32c6.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +cezerio_mini_dev_esp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +cezerio_mini_dev_esp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +cezerio_mini_dev_esp32c6.menu.PartitionScheme.custom=Custom +cezerio_mini_dev_esp32c6.menu.PartitionScheme.custom.build.partitions= +cezerio_mini_dev_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +cezerio_mini_dev_esp32c6.menu.CPUFreq.160=160MHz (WiFi) +cezerio_mini_dev_esp32c6.menu.CPUFreq.160.build.f_cpu=160000000L +cezerio_mini_dev_esp32c6.menu.CPUFreq.120=120MHz (WiFi) +cezerio_mini_dev_esp32c6.menu.CPUFreq.120.build.f_cpu=120000000L +cezerio_mini_dev_esp32c6.menu.CPUFreq.80=80MHz (WiFi) +cezerio_mini_dev_esp32c6.menu.CPUFreq.80.build.f_cpu=80000000L +cezerio_mini_dev_esp32c6.menu.CPUFreq.40=40MHz +cezerio_mini_dev_esp32c6.menu.CPUFreq.40.build.f_cpu=40000000L +cezerio_mini_dev_esp32c6.menu.CPUFreq.20=20MHz +cezerio_mini_dev_esp32c6.menu.CPUFreq.20.build.f_cpu=20000000L +cezerio_mini_dev_esp32c6.menu.CPUFreq.10=10MHz +cezerio_mini_dev_esp32c6.menu.CPUFreq.10.build.f_cpu=10000000L + +cezerio_mini_dev_esp32c6.menu.FlashMode.qio=QIO +cezerio_mini_dev_esp32c6.menu.FlashMode.qio.build.flash_mode=dio +cezerio_mini_dev_esp32c6.menu.FlashMode.qio.build.boot=qio +cezerio_mini_dev_esp32c6.menu.FlashMode.dio=DIO +cezerio_mini_dev_esp32c6.menu.FlashMode.dio.build.flash_mode=dio +cezerio_mini_dev_esp32c6.menu.FlashMode.dio.build.boot=dio + +cezerio_mini_dev_esp32c6.menu.FlashFreq.80=80MHz +cezerio_mini_dev_esp32c6.menu.FlashFreq.80.build.flash_freq=80m +cezerio_mini_dev_esp32c6.menu.FlashFreq.40=40MHz +cezerio_mini_dev_esp32c6.menu.FlashFreq.40.build.flash_freq=40m + +cezerio_mini_dev_esp32c6.menu.FlashSize.4M=4MB (32Mb) +cezerio_mini_dev_esp32c6.menu.FlashSize.4M.build.flash_size=4MB + +cezerio_mini_dev_esp32c6.menu.UploadSpeed.921600=921600 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.921600.upload.speed=921600 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.115200=115200 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.115200.upload.speed=115200 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.256000.windows=256000 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.256000.upload.speed=256000 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.230400.windows.upload.speed=256000 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.230400=230400 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.230400.upload.speed=230400 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.460800.linux=460800 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.460800.macosx=460800 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.460800.upload.speed=460800 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.512000.windows=512000 +cezerio_mini_dev_esp32c6.menu.UploadSpeed.512000.upload.speed=512000 + +cezerio_mini_dev_esp32c6.menu.DebugLevel.none=None +cezerio_mini_dev_esp32c6.menu.DebugLevel.none.build.code_debug=0 +cezerio_mini_dev_esp32c6.menu.DebugLevel.error=Error +cezerio_mini_dev_esp32c6.menu.DebugLevel.error.build.code_debug=1 +cezerio_mini_dev_esp32c6.menu.DebugLevel.warn=Warn +cezerio_mini_dev_esp32c6.menu.DebugLevel.warn.build.code_debug=2 +cezerio_mini_dev_esp32c6.menu.DebugLevel.info=Info +cezerio_mini_dev_esp32c6.menu.DebugLevel.info.build.code_debug=3 +cezerio_mini_dev_esp32c6.menu.DebugLevel.debug=Debug +cezerio_mini_dev_esp32c6.menu.DebugLevel.debug.build.code_debug=4 +cezerio_mini_dev_esp32c6.menu.DebugLevel.verbose=Verbose +cezerio_mini_dev_esp32c6.menu.DebugLevel.verbose.build.code_debug=5 + +cezerio_mini_dev_esp32c6.menu.EraseFlash.none=Disabled +cezerio_mini_dev_esp32c6.menu.EraseFlash.none.upload.erase_cmd= +cezerio_mini_dev_esp32c6.menu.EraseFlash.all=Enabled +cezerio_mini_dev_esp32c6.menu.EraseFlash.all.upload.erase_cmd=-e + +cezerio_mini_dev_esp32c6.menu.ZigbeeMode.default=Disabled +cezerio_mini_dev_esp32c6.menu.ZigbeeMode.default.build.zigbee_mode= +cezerio_mini_dev_esp32c6.menu.ZigbeeMode.default.build.zigbee_libs= +cezerio_mini_dev_esp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) +cezerio_mini_dev_esp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED +cezerio_mini_dev_esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +cezerio_mini_dev_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +cezerio_mini_dev_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +cezerio_mini_dev_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native + +############################################################## + +waveshare_esp32_s3_lcd_185.name=Waveshare ESP32-S3-LCD-1.85 +waveshare_esp32_s3_lcd_185.vid.0=0x303a +waveshare_esp32_s3_lcd_185.pid.0=0x8242 +waveshare_esp32_s3_lcd_185.upload_port.0.vid=0x303a +waveshare_esp32_s3_lcd_185.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_lcd_185.bootloader.tool=esptool_py +waveshare_esp32_s3_lcd_185.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_lcd_185.upload.tool=esptool_py +waveshare_esp32_s3_lcd_185.upload.tool.default=esptool_py +waveshare_esp32_s3_lcd_185.upload.tool.network=esp_ota + +waveshare_esp32_s3_lcd_185.upload.maximum_size=1310720 +waveshare_esp32_s3_lcd_185.upload.maximum_data_size=327680 +waveshare_esp32_s3_lcd_185.upload.flags= +waveshare_esp32_s3_lcd_185.upload.extra_flags= +waveshare_esp32_s3_lcd_185.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_185.upload.wait_for_upload_port=false + +waveshare_esp32_s3_lcd_185.serial.disableDTR=false +waveshare_esp32_s3_lcd_185.serial.disableRTS=false + +waveshare_esp32_s3_lcd_185.build.tarch=xtensa +waveshare_esp32_s3_lcd_185.build.bootloader_addr=0x0 +waveshare_esp32_s3_lcd_185.build.target=esp32s3 +waveshare_esp32_s3_lcd_185.build.mcu=esp32s3 +waveshare_esp32_s3_lcd_185.build.core=esp32 +waveshare_esp32_s3_lcd_185.build.variant=waveshare_esp32_s3_lcd_185 +waveshare_esp32_s3_lcd_185.build.board=WAVESHARE_ESP32_S3_LCD_185 + +waveshare_esp32_s3_lcd_185.build.usb_mode=1 +waveshare_esp32_s3_lcd_185.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_185.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_185.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_185.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_185.build.flash_size=16MB +waveshare_esp32_s3_lcd_185.build.flash_freq=120m +waveshare_esp32_s3_lcd_185.build.flash_mode=qio +waveshare_esp32_s3_lcd_185.build.boot=qio +waveshare_esp32_s3_lcd_185.build.boot_freq=80m +waveshare_esp32_s3_lcd_185.build.partitions=default +waveshare_esp32_s3_lcd_185.build.defines= +waveshare_esp32_s3_lcd_185.build.loop_core= +waveshare_esp32_s3_lcd_185.build.event_core= +waveshare_esp32_s3_lcd_185.build.psram_type=opi +waveshare_esp32_s3_lcd_185.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_lcd_185.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_lcd_185.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_lcd_185.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_lcd_185.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_lcd_185.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_lcd_185.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_lcd_185.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_lcd_185.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_lcd_185.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_lcd_185.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_lcd_185.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_lcd_185.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_lcd_185.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_lcd_185.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_lcd_185.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_lcd_185.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_lcd_185.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_lcd_185.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_lcd_185.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_lcd_185.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_lcd_185.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_lcd_185.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_lcd_185.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_lcd_185.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 +waveshare_esp32_s3_lcd_185.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_lcd_185.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +waveshare_esp32_s3_lcd_185.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_lcd_185.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_lcd_185.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_lcd_185.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_lcd_185.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_185.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_185.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_lcd_185.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_lcd_185.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_185.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_185.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_185.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_lcd_185.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_lcd_185.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_185.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_185.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_lcd_185.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_lcd_185.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_185.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_lcd_185.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_lcd_185.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_lcd_185.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_lcd_185.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_lcd_185.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_lcd_185.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_185.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_lcd_185.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_lcd_185.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_lcd_185.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_lcd_185.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_lcd_185.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_lcd_185.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_lcd_185.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_lcd_185.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_lcd_185.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_lcd_185.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_lcd_185.menu.DebugLevel.none=None +waveshare_esp32_s3_lcd_185.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_lcd_185.menu.DebugLevel.error=Error +waveshare_esp32_s3_lcd_185.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_lcd_185.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_lcd_185.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_lcd_185.menu.DebugLevel.info=Info +waveshare_esp32_s3_lcd_185.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_lcd_185.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_lcd_185.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_lcd_185.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_lcd_185.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_lcd_185.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_lcd_185.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_lcd_185.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_lcd_185.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_lcd_185.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_lcd_185.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_lcd_185.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_lcd_185.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_lcd_185.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_lcd_185.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native + +############################################################## + +waveshare_esp32_s3_touch_lcd_146.name=Waveshare ESP32-S3-Touch-LCD-1.46 +waveshare_esp32_s3_touch_lcd_146.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_146.pid.0=0x8242 +waveshare_esp32_s3_touch_lcd_146.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_146.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_touch_lcd_146.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_146.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_146.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_146.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_146.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_146.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_146.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_146.upload.flags= +waveshare_esp32_s3_touch_lcd_146.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_146.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_146.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_146.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_146.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_146.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_146.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_146.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_146.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_146.build.core=esp32 +waveshare_esp32_s3_touch_lcd_146.build.variant=waveshare_esp32_s3_touch_lcd_146 +waveshare_esp32_s3_touch_lcd_146.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_146 + +waveshare_esp32_s3_touch_lcd_146.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_146.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_146.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_146.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_146.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_146.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_146.build.flash_freq=120m +waveshare_esp32_s3_touch_lcd_146.build.flash_mode=qio +waveshare_esp32_s3_touch_lcd_146.build.boot=qio +waveshare_esp32_s3_touch_lcd_146.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_146.build.partitions=default +waveshare_esp32_s3_touch_lcd_146.build.defines= +waveshare_esp32_s3_touch_lcd_146.build.loop_core= +waveshare_esp32_s3_touch_lcd_146.build.event_core= +waveshare_esp32_s3_touch_lcd_146.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_146.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_touch_lcd_146.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_touch_lcd_146.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_146.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_146.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_146.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_146.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_146.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_146.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_146.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_146.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_146.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_146.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_146.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 +waveshare_esp32_s3_touch_lcd_146.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_146.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +waveshare_esp32_s3_touch_lcd_146.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_146.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_146.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_146.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_146.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_146.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_146.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_146.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_146.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_146.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_146.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_146.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_146.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_146.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_146.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_146.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_146.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_146.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_146.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_146.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_146.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_146.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_146.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_146.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_146.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_146.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_touch_lcd_146.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_touch_lcd_146.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_touch_lcd_146.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_touch_lcd_146.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_touch_lcd_146.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_touch_lcd_146.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################################################## + +waveshare_esp32_s3_lcd_146.name=Waveshare ESP32-S3-LCD-1.46 +waveshare_esp32_s3_lcd_146.vid.0=0x303a +waveshare_esp32_s3_lcd_146.pid.0=0x8242 +waveshare_esp32_s3_lcd_146.upload_port.0.vid=0x303a +waveshare_esp32_s3_lcd_146.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_lcd_146.bootloader.tool=esptool_py +waveshare_esp32_s3_lcd_146.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_lcd_146.upload.tool=esptool_py +waveshare_esp32_s3_lcd_146.upload.tool.default=esptool_py +waveshare_esp32_s3_lcd_146.upload.tool.network=esp_ota + +waveshare_esp32_s3_lcd_146.upload.maximum_size=1310720 +waveshare_esp32_s3_lcd_146.upload.maximum_data_size=327680 +waveshare_esp32_s3_lcd_146.upload.flags= +waveshare_esp32_s3_lcd_146.upload.extra_flags= +waveshare_esp32_s3_lcd_146.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_146.upload.wait_for_upload_port=false + +waveshare_esp32_s3_lcd_146.serial.disableDTR=false +waveshare_esp32_s3_lcd_146.serial.disableRTS=false + +waveshare_esp32_s3_lcd_146.build.tarch=xtensa +waveshare_esp32_s3_lcd_146.build.bootloader_addr=0x0 +waveshare_esp32_s3_lcd_146.build.target=esp32s3 +waveshare_esp32_s3_lcd_146.build.mcu=esp32s3 +waveshare_esp32_s3_lcd_146.build.core=esp32 +waveshare_esp32_s3_lcd_146.build.variant=waveshare_esp32_s3_lcd_146 +waveshare_esp32_s3_lcd_146.build.board=WAVESHARE_ESP32_S3_LCD_146 + +waveshare_esp32_s3_lcd_146.build.usb_mode=1 +waveshare_esp32_s3_lcd_146.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_146.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_146.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_146.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_146.build.flash_size=16MB +waveshare_esp32_s3_lcd_146.build.flash_freq=120m +waveshare_esp32_s3_lcd_146.build.flash_mode=qio +waveshare_esp32_s3_lcd_146.build.boot=qio +waveshare_esp32_s3_lcd_146.build.boot_freq=80m +waveshare_esp32_s3_lcd_146.build.partitions=default +waveshare_esp32_s3_lcd_146.build.defines= +waveshare_esp32_s3_lcd_146.build.loop_core= +waveshare_esp32_s3_lcd_146.build.event_core= +waveshare_esp32_s3_lcd_146.build.psram_type=opi +waveshare_esp32_s3_lcd_146.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_lcd_146.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_lcd_146.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_lcd_146.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_lcd_146.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_lcd_146.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_lcd_146.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_lcd_146.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_lcd_146.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_lcd_146.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_lcd_146.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_lcd_146.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_lcd_146.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_lcd_146.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_lcd_146.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_lcd_146.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_lcd_146.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_lcd_146.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_lcd_146.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_lcd_146.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_lcd_146.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_lcd_146.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_lcd_146.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_lcd_146.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_lcd_146.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 +waveshare_esp32_s3_lcd_146.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_lcd_146.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +waveshare_esp32_s3_lcd_146.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_lcd_146.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_lcd_146.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_lcd_146.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_lcd_146.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_146.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_146.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_lcd_146.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_lcd_146.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_146.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_146.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_146.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_lcd_146.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_lcd_146.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_146.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_146.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_lcd_146.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_lcd_146.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_146.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_lcd_146.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_lcd_146.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_lcd_146.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_lcd_146.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_lcd_146.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_lcd_146.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_146.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_lcd_146.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_lcd_146.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_lcd_146.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_lcd_146.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_lcd_146.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_lcd_146.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_lcd_146.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_lcd_146.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_lcd_146.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_lcd_146.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_lcd_146.menu.DebugLevel.none=None +waveshare_esp32_s3_lcd_146.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_lcd_146.menu.DebugLevel.error=Error +waveshare_esp32_s3_lcd_146.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_lcd_146.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_lcd_146.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_lcd_146.menu.DebugLevel.info=Info +waveshare_esp32_s3_lcd_146.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_lcd_146.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_lcd_146.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_lcd_146.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_lcd_146.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_lcd_146.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_lcd_146.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_lcd_146.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_lcd_146.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_lcd_146.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_lcd_146.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_lcd_146.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_lcd_146.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_lcd_146.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_lcd_146.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################################################## + +waveshare_esp32_s3_touch_lcd_185_box.name=Waveshare ESP32-S3-Touch-LCD-1.85-BOX +waveshare_esp32_s3_touch_lcd_185_box.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_185_box.pid.0=0x8242 +waveshare_esp32_s3_touch_lcd_185_box.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_185_box.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_touch_lcd_185_box.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_185_box.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_185_box.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_185_box.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_185_box.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_185_box.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_185_box.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_185_box.upload.flags= +waveshare_esp32_s3_touch_lcd_185_box.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_185_box.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_185_box.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_185_box.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_185_box.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_185_box.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_185_box.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_185_box.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_185_box.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_185_box.build.core=esp32 +waveshare_esp32_s3_touch_lcd_185_box.build.variant=waveshare_esp32_s3_touch_lcd_185_box +waveshare_esp32_s3_touch_lcd_185_box.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_185_BOX + +waveshare_esp32_s3_touch_lcd_185_box.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_185_box.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185_box.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185_box.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_185_box.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_185_box.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_185_box.build.flash_freq=120m +waveshare_esp32_s3_touch_lcd_185_box.build.flash_mode=qio +waveshare_esp32_s3_touch_lcd_185_box.build.boot=qio +waveshare_esp32_s3_touch_lcd_185_box.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.build.partitions=default +waveshare_esp32_s3_touch_lcd_185_box.build.defines= +waveshare_esp32_s3_touch_lcd_185_box.build.loop_core= +waveshare_esp32_s3_touch_lcd_185_box.build.event_core= +waveshare_esp32_s3_touch_lcd_185_box.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_185_box.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_touch_lcd_185_box.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_touch_lcd_185_box.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_185_box.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_185_box.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_185_box.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_185_box.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_185_box.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_185_box.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_185_box.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_185_box.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_185_box.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_185_box.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_185_box.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 +waveshare_esp32_s3_touch_lcd_185_box.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_185_box.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +waveshare_esp32_s3_touch_lcd_185_box.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_185_box.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_185_box.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_185_box.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_185_box.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185_box.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_185_box.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_185_box.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_185_box.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_185_box.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_185_box.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_185_box.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_185_box.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_185_box.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_185_box.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_185_box.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_185_box.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_185_box.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_185_box.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_185_box.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_touch_lcd_185_box.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_touch_lcd_185_box.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_touch_lcd_185_box.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_touch_lcd_185_box.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_touch_lcd_185_box.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_touch_lcd_185_box.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################################################## + +waveshare_esp32_s3_lcd_147.name=Waveshare ESP32-S3-LCD-1.47 +waveshare_esp32_s3_lcd_147.vid.0=0x303a +waveshare_esp32_s3_lcd_147.pid.0=0x8242 +waveshare_esp32_s3_lcd_147.upload_port.0.vid=0x303a +waveshare_esp32_s3_lcd_147.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_lcd_147.bootloader.tool=esptool_py +waveshare_esp32_s3_lcd_147.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_lcd_147.upload.tool=esptool_py +waveshare_esp32_s3_lcd_147.upload.tool.default=esptool_py +waveshare_esp32_s3_lcd_147.upload.tool.network=esp_ota + +waveshare_esp32_s3_lcd_147.upload.maximum_size=1310720 +waveshare_esp32_s3_lcd_147.upload.maximum_data_size=327680 +waveshare_esp32_s3_lcd_147.upload.flags= +waveshare_esp32_s3_lcd_147.upload.extra_flags= +waveshare_esp32_s3_lcd_147.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_147.upload.wait_for_upload_port=false + +waveshare_esp32_s3_lcd_147.serial.disableDTR=false +waveshare_esp32_s3_lcd_147.serial.disableRTS=false + +waveshare_esp32_s3_lcd_147.build.tarch=xtensa +waveshare_esp32_s3_lcd_147.build.bootloader_addr=0x0 +waveshare_esp32_s3_lcd_147.build.target=esp32s3 +waveshare_esp32_s3_lcd_147.build.mcu=esp32s3 +waveshare_esp32_s3_lcd_147.build.core=esp32 +waveshare_esp32_s3_lcd_147.build.variant=waveshare_esp32_s3_lcd_147 +waveshare_esp32_s3_lcd_147.build.board=WAVESHARE_ESP32_S3_LCD_147 + +waveshare_esp32_s3_lcd_147.build.usb_mode=1 +waveshare_esp32_s3_lcd_147.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_147.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_147.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_147.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_147.build.flash_size=16MB +waveshare_esp32_s3_lcd_147.build.flash_freq=80m +waveshare_esp32_s3_lcd_147.build.flash_mode=qio +waveshare_esp32_s3_lcd_147.build.boot=qio +waveshare_esp32_s3_lcd_147.build.boot_freq=80m +waveshare_esp32_s3_lcd_147.build.partitions=default +waveshare_esp32_s3_lcd_147.build.defines= +waveshare_esp32_s3_lcd_147.build.loop_core= +waveshare_esp32_s3_lcd_147.build.event_core= +waveshare_esp32_s3_lcd_147.build.psram_type=opi +waveshare_esp32_s3_lcd_147.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_lcd_147.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_lcd_147.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_lcd_147.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_lcd_147.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_lcd_147.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_lcd_147.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_lcd_147.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_lcd_147.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_lcd_147.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_lcd_147.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_lcd_147.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_lcd_147.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_lcd_147.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_lcd_147.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_lcd_147.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_lcd_147.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_lcd_147.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_lcd_147.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_lcd_147.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_lcd_147.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_lcd_147.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_lcd_147.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_lcd_147.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_lcd_147.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_lcd_147.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_lcd_147.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_lcd_147.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_lcd_147.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_lcd_147.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_lcd_147.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_lcd_147.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_147.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_lcd_147.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_lcd_147.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_lcd_147.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_lcd_147.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_lcd_147.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_147.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_lcd_147.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_lcd_147.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_lcd_147.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_lcd_147.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_lcd_147.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_lcd_147.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_lcd_147.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_lcd_147.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_lcd_147.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_lcd_147.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_lcd_147.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_lcd_147.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_lcd_147.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_lcd_147.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_lcd_147.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_lcd_147.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_lcd_147.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_lcd_147.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_lcd_147.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_lcd_147.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_lcd_147.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_lcd_147.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_lcd_147.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_lcd_147.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_lcd_147.menu.DebugLevel.none=None +waveshare_esp32_s3_lcd_147.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_lcd_147.menu.DebugLevel.error=Error +waveshare_esp32_s3_lcd_147.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_lcd_147.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_lcd_147.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_lcd_147.menu.DebugLevel.info=Info +waveshare_esp32_s3_lcd_147.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_lcd_147.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_lcd_147.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_lcd_147.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_lcd_147.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_lcd_147.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_lcd_147.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_lcd_147.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_lcd_147.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_lcd_147.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_lcd_147.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_lcd_147.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_lcd_147.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_lcd_147.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_lcd_147.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################################################## + +waveshare_esp32_s3_touch_lcd_21.name=Waveshare ESP32-S3-Touch-LCD-2.1 +waveshare_esp32_s3_touch_lcd_21.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_21.pid.0=0x8242 +waveshare_esp32_s3_touch_lcd_21.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_21.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_touch_lcd_21.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_21.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_21.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_21.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_21.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_21.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_21.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_21.upload.flags= +waveshare_esp32_s3_touch_lcd_21.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_21.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_21.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_21.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_21.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_21.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_21.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_21.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_21.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_21.build.core=esp32 +waveshare_esp32_s3_touch_lcd_21.build.variant=waveshare_esp32_s3_touch_lcd_21 +waveshare_esp32_s3_touch_lcd_21.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_21 + +waveshare_esp32_s3_touch_lcd_21.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_21.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_21.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_21.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_21.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_21.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_21.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_21.build.flash_mode=qio +waveshare_esp32_s3_touch_lcd_21.build.boot=qio +waveshare_esp32_s3_touch_lcd_21.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_21.build.partitions=default +waveshare_esp32_s3_touch_lcd_21.build.defines= +waveshare_esp32_s3_touch_lcd_21.build.loop_core= +waveshare_esp32_s3_touch_lcd_21.build.event_core= +waveshare_esp32_s3_touch_lcd_21.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_21.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_touch_lcd_21.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_touch_lcd_21.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_21.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_21.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_21.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_21.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_21.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_21.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_21.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_21.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_21.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_21.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_21.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_21.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_21.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_21.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_21.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_21.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_21.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_21.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_21.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_21.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_21.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_21.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_21.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_21.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_21.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_21.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_21.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_21.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_21.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_21.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_21.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_21.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_21.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_21.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_21.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_21.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_21.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_21.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_21.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_touch_lcd_21.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_touch_lcd_21.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_touch_lcd_21.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_touch_lcd_21.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_touch_lcd_21.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_touch_lcd_21.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################################################## + +waveshare_esp32_s3_touch_lcd_28.name=Waveshare ESP32-S3-Touch-LCD-2.8 +waveshare_esp32_s3_touch_lcd_28.vid.0=0x303a +waveshare_esp32_s3_touch_lcd_28.pid.0=0x8242 +waveshare_esp32_s3_touch_lcd_28.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_lcd_28.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_touch_lcd_28.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_lcd_28.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_lcd_28.upload.tool=esptool_py +waveshare_esp32_s3_touch_lcd_28.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_lcd_28.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_lcd_28.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_28.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_lcd_28.upload.flags= +waveshare_esp32_s3_touch_lcd_28.upload.extra_flags= +waveshare_esp32_s3_touch_lcd_28.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_28.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_lcd_28.serial.disableDTR=false +waveshare_esp32_s3_touch_lcd_28.serial.disableRTS=false + +waveshare_esp32_s3_touch_lcd_28.build.tarch=xtensa +waveshare_esp32_s3_touch_lcd_28.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_lcd_28.build.target=esp32s3 +waveshare_esp32_s3_touch_lcd_28.build.mcu=esp32s3 +waveshare_esp32_s3_touch_lcd_28.build.core=esp32 +waveshare_esp32_s3_touch_lcd_28.build.variant=waveshare_esp32_s3_touch_lcd_28 +waveshare_esp32_s3_touch_lcd_28.build.board=WAVESHARE_ESP32_S3_TOUCH_LCD_28 + +waveshare_esp32_s3_touch_lcd_28.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_28.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_28.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_28.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_28.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_28.build.flash_size=16MB +waveshare_esp32_s3_touch_lcd_28.build.flash_freq=120m +waveshare_esp32_s3_touch_lcd_28.build.flash_mode=qio +waveshare_esp32_s3_touch_lcd_28.build.boot=qio +waveshare_esp32_s3_touch_lcd_28.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_28.build.partitions=default +waveshare_esp32_s3_touch_lcd_28.build.defines= +waveshare_esp32_s3_touch_lcd_28.build.loop_core= +waveshare_esp32_s3_touch_lcd_28.build.event_core= +waveshare_esp32_s3_touch_lcd_28.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_28.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_touch_lcd_28.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_touch_lcd_28.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_lcd_28.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_lcd_28.menu.PSRAM.enabled.build.psram_type=opi +waveshare_esp32_s3_touch_lcd_28.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_lcd_28.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_touch_lcd_28.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_touch_lcd_28.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_28.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_lcd_28.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_28.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_lcd_28.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_lcd_28.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 +waveshare_esp32_s3_touch_lcd_28.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_lcd_28.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 + +waveshare_esp32_s3_touch_lcd_28.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_lcd_28.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_lcd_28.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_lcd_28.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_lcd_28.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_lcd_28.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_lcd_28.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_28.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_lcd_28.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_28.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_lcd_28.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_lcd_28.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_lcd_28.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_lcd_28.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_lcd_28.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_lcd_28.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_lcd_28.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_lcd_28.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_lcd_28.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_lcd_28.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_lcd_28.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_lcd_28.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_lcd_28.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_lcd_28.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_lcd_28.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_lcd_28.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_touch_lcd_28.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_touch_lcd_28.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_touch_lcd_28.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_touch_lcd_28.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_touch_lcd_28.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_touch_lcd_28.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################################################## + +waveshare_esp32_s3_relay_6ch.name=Waveshare ESP32-S3-Relay-6CH +waveshare_esp32_s3_relay_6ch.vid.0=0x303a +waveshare_esp32_s3_relay_6ch.pid.0=0x8242 +waveshare_esp32_s3_relay_6ch.upload_port.0.vid=0x303a +waveshare_esp32_s3_relay_6ch.upload_port.0.pid=0x8242 + +waveshare_esp32_s3_relay_6ch.bootloader.tool=esptool_py +waveshare_esp32_s3_relay_6ch.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_relay_6ch.upload.tool=esptool_py +waveshare_esp32_s3_relay_6ch.upload.tool.default=esptool_py +waveshare_esp32_s3_relay_6ch.upload.tool.network=esp_ota + +waveshare_esp32_s3_relay_6ch.upload.maximum_size=1310720 +waveshare_esp32_s3_relay_6ch.upload.maximum_data_size=327680 +waveshare_esp32_s3_relay_6ch.upload.flags= +waveshare_esp32_s3_relay_6ch.upload.extra_flags= +waveshare_esp32_s3_relay_6ch.upload.use_1200bps_touch=false +waveshare_esp32_s3_relay_6ch.upload.wait_for_upload_port=false + +waveshare_esp32_s3_relay_6ch.serial.disableDTR=false +waveshare_esp32_s3_relay_6ch.serial.disableRTS=false + +waveshare_esp32_s3_relay_6ch.build.tarch=xtensa +waveshare_esp32_s3_relay_6ch.build.bootloader_addr=0x0 +waveshare_esp32_s3_relay_6ch.build.target=esp32s3 +waveshare_esp32_s3_relay_6ch.build.mcu=esp32s3 +waveshare_esp32_s3_relay_6ch.build.core=esp32 +waveshare_esp32_s3_relay_6ch.build.variant=waveshare_esp32_s3_relay_6ch +waveshare_esp32_s3_relay_6ch.build.board=WAVESHARE_ESP32_S3_RELAY_6CH + +waveshare_esp32_s3_relay_6ch.build.usb_mode=1 +waveshare_esp32_s3_relay_6ch.build.cdc_on_boot=0 +waveshare_esp32_s3_relay_6ch.build.msc_on_boot=0 +waveshare_esp32_s3_relay_6ch.build.dfu_on_boot=0 +waveshare_esp32_s3_relay_6ch.build.f_cpu=240000000L +waveshare_esp32_s3_relay_6ch.build.flash_size=8MB +waveshare_esp32_s3_relay_6ch.build.flash_freq=80m +waveshare_esp32_s3_relay_6ch.build.flash_mode=qio +waveshare_esp32_s3_relay_6ch.build.boot=qio +waveshare_esp32_s3_relay_6ch.build.boot_freq=80m +waveshare_esp32_s3_relay_6ch.build.partitions=default +waveshare_esp32_s3_relay_6ch.build.defines= +waveshare_esp32_s3_relay_6ch.build.loop_core= +waveshare_esp32_s3_relay_6ch.build.event_core= +waveshare_esp32_s3_relay_6ch.build.psram_type= +waveshare_esp32_s3_relay_6ch.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.default=Disabled +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.default.build.copy_jtag_files=0 +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.builtin=Integrated USB JTAG +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.external=FTDI Adapter +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.external.build.copy_jtag_files=1 +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.bridge=ESP USB Bridge +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +waveshare_esp32_s3_relay_6ch.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +waveshare_esp32_s3_relay_6ch.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_relay_6ch.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_relay_6ch.menu.PSRAM.disabled.build.psram_type=qspi + +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.qio120.build.flash_freq=80m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.dio=DIO 80MHz +waveshare_esp32_s3_relay_6ch.menu.FlashMode.dio.build.flash_mode=dio +waveshare_esp32_s3_relay_6ch.menu.FlashMode.dio.build.boot=dio +waveshare_esp32_s3_relay_6ch.menu.FlashMode.dio.build.boot_freq=80m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.dio.build.flash_freq=80m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.opi=OPI 80MHz +waveshare_esp32_s3_relay_6ch.menu.FlashMode.opi.build.flash_mode=dout +waveshare_esp32_s3_relay_6ch.menu.FlashMode.opi.build.boot=opi +waveshare_esp32_s3_relay_6ch.menu.FlashMode.opi.build.boot_freq=80m +waveshare_esp32_s3_relay_6ch.menu.FlashMode.opi.build.flash_freq=80m + +waveshare_esp32_s3_relay_6ch.menu.FlashSize.8M=8MB (64Mb) +waveshare_esp32_s3_relay_6ch.menu.FlashSize.8M.build.flash_size=8MB +waveshare_esp32_s3_relay_6ch.menu.FlashSize.8M.build.partitions=default_8MB +waveshare_esp32_s3_relay_6ch.menu.FlashSize.16M=16MB (128Mb) +waveshare_esp32_s3_relay_6ch.menu.FlashSize.16M.build.flash_size=16MB + +waveshare_esp32_s3_relay_6ch.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_relay_6ch.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_relay_6ch.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_relay_6ch.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_relay_6ch.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_relay_6ch.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_relay_6ch.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_relay_6ch.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_relay_6ch.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_relay_6ch.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_relay_6ch.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_relay_6ch.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_relay_6ch.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_relay_6ch.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_relay_6ch.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_relay_6ch.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_relay_6ch.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_relay_6ch.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_relay_6ch.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_relay_6ch.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_relay_6ch.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_relay_6ch.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_relay_6ch.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_relay_6ch.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_relay_6ch.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_relay_6ch.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_relay_6ch.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_relay_6ch.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_relay_6ch.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_relay_6ch.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.minimal.build.partitions=minimal +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.no_fs.build.partitions=no_fs +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_relay_6ch.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_relay_6ch.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_relay_6ch.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.none=None +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.error=Error +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.info=Info +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_relay_6ch.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_relay_6ch.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_relay_6ch.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_relay_6ch.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_relay_6ch.menu.EraseFlash.all.upload.erase_cmd=-e + +waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.default=Disabled +waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.default.build.zigbee_mode= +waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.default.build.zigbee_libs= +waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +waveshare_esp32_s3_relay_6ch.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################################################## + +waveshare_esp32_s3_touch_amoled_164.name=Waveshare ESP32-S3-Touch-AMOLED-1.64 +waveshare_esp32_s3_touch_amoled_164.vid.0=0x303a +waveshare_esp32_s3_touch_amoled_164.pid.0=0x8249 +waveshare_esp32_s3_touch_amoled_164.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_amoled_164.upload_port.0.pid=0x8249 + +waveshare_esp32_s3_touch_amoled_164.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_amoled_164.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_amoled_164.upload.tool=esptool_py +waveshare_esp32_s3_touch_amoled_164.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_amoled_164.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_amoled_164.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_amoled_164.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_amoled_164.upload.flags= +waveshare_esp32_s3_touch_amoled_164.upload.extra_flags= +waveshare_esp32_s3_touch_amoled_164.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_164.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_amoled_164.serial.disableDTR=false +waveshare_esp32_s3_touch_amoled_164.serial.disableRTS=false + +waveshare_esp32_s3_touch_amoled_164.build.tarch=xtensa +waveshare_esp32_s3_touch_amoled_164.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_amoled_164.build.target=esp32s3 +waveshare_esp32_s3_touch_amoled_164.build.mcu=esp32s3 +waveshare_esp32_s3_touch_amoled_164.build.core=esp32 +waveshare_esp32_s3_touch_amoled_164.build.variant=waveshare_esp32_s3_touch_amoled_164 +waveshare_esp32_s3_touch_amoled_164.build.board=WAVESHARE_ESP32_S3_TOUCH_AMOLED_164 + +waveshare_esp32_s3_touch_amoled_164.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_164.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_164.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_164.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_164.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_164.build.flash_size=16MB + +waveshare_esp32_s3_touch_amoled_164.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_164.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_164.build.boot=qio +waveshare_esp32_s3_touch_amoled_164.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_164.build.partitions=default +waveshare_esp32_s3_touch_amoled_164.build.defines= +waveshare_esp32_s3_touch_amoled_164.build.loop_core= +waveshare_esp32_s3_touch_amoled_164.build.event_core= +waveshare_esp32_s3_touch_amoled_164.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_164.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_amoled_164.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_amoled_164.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_amoled_164.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_164.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_amoled_164.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_amoled_164.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_amoled_164.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_amoled_164.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_164.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_164.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_164.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_164.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_164.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_164.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_164.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_164.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_amoled_164.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_164.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_amoled_164.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_amoled_164.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_164.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_164.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_amoled_164.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_164.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_164.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_164.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_164.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_164.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_164.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_164.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_164.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) + +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 + +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_amoled_164.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_amoled_164.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_amoled_164.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_amoled_164.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_amoled_164.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_amoled_164.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_amoled_164.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_amoled_143.name=Waveshare ESP32-S3-Touch-AMOLED-1.43 +waveshare_esp32_s3_touch_amoled_143.vid.0=0x303a +waveshare_esp32_s3_touch_amoled_143.pid.0=0x824a +waveshare_esp32_s3_touch_amoled_143.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_amoled_143.upload_port.0.pid=0x824a + +waveshare_esp32_s3_touch_amoled_143.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_amoled_143.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_amoled_143.upload.tool=esptool_py +waveshare_esp32_s3_touch_amoled_143.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_amoled_143.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_amoled_143.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_amoled_143.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_amoled_143.upload.flags= +waveshare_esp32_s3_touch_amoled_143.upload.extra_flags= +waveshare_esp32_s3_touch_amoled_143.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_143.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_amoled_143.serial.disableDTR=false +waveshare_esp32_s3_touch_amoled_143.serial.disableRTS=false + +waveshare_esp32_s3_touch_amoled_143.build.tarch=xtensa +waveshare_esp32_s3_touch_amoled_143.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_amoled_143.build.target=esp32s3 +waveshare_esp32_s3_touch_amoled_143.build.mcu=esp32s3 +waveshare_esp32_s3_touch_amoled_143.build.core=esp32 +waveshare_esp32_s3_touch_amoled_143.build.variant=waveshare_esp32_s3_touch_amoled_143 +waveshare_esp32_s3_touch_amoled_143.build.board=WAVESHARE_ESP32_S3_TOUCH_AMOLED_143 + +waveshare_esp32_s3_touch_amoled_143.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_143.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_143.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_143.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_143.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_143.build.flash_size=16MB + +waveshare_esp32_s3_touch_amoled_143.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_143.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_143.build.boot=qio +waveshare_esp32_s3_touch_amoled_143.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_143.build.partitions=default +waveshare_esp32_s3_touch_amoled_143.build.defines= +waveshare_esp32_s3_touch_amoled_143.build.loop_core= +waveshare_esp32_s3_touch_amoled_143.build.event_core= +waveshare_esp32_s3_touch_amoled_143.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_143.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_amoled_143.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_amoled_143.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_amoled_143.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_143.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_amoled_143.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_amoled_143.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_amoled_143.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_amoled_143.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_143.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_143.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_143.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_143.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_143.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_143.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_143.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_143.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_amoled_143.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_143.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_amoled_143.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_amoled_143.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_143.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_143.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_amoled_143.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_143.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_143.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_143.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_143.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_143.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_143.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_143.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_143.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) + +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 + +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_amoled_143.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_amoled_143.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_amoled_143.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_amoled_143.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_amoled_143.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_amoled_143.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_amoled_143.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +waveshare_esp32_s3_touch_amoled_191.name=Waveshare ESP32-S3-Touch-AMOLED-1.91 +waveshare_esp32_s3_touch_amoled_191.vid.0=0x303a +waveshare_esp32_s3_touch_amoled_191.pid.0=0x824b +waveshare_esp32_s3_touch_amoled_191.upload_port.0.vid=0x303a +waveshare_esp32_s3_touch_amoled_191.upload_port.0.pid=0x824b + +waveshare_esp32_s3_touch_amoled_191.bootloader.tool=esptool_py +waveshare_esp32_s3_touch_amoled_191.bootloader.tool.default=esptool_py + +waveshare_esp32_s3_touch_amoled_191.upload.tool=esptool_py +waveshare_esp32_s3_touch_amoled_191.upload.tool.default=esptool_py +waveshare_esp32_s3_touch_amoled_191.upload.tool.network=esp_ota + +waveshare_esp32_s3_touch_amoled_191.upload.maximum_size=1310720 + +waveshare_esp32_s3_touch_amoled_191.upload.maximum_data_size=327680 +waveshare_esp32_s3_touch_amoled_191.upload.flags= +waveshare_esp32_s3_touch_amoled_191.upload.extra_flags= +waveshare_esp32_s3_touch_amoled_191.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_191.upload.wait_for_upload_port=false + +waveshare_esp32_s3_touch_amoled_191.serial.disableDTR=false +waveshare_esp32_s3_touch_amoled_191.serial.disableRTS=false + +waveshare_esp32_s3_touch_amoled_191.build.tarch=xtensa +waveshare_esp32_s3_touch_amoled_191.build.bootloader_addr=0x0 +waveshare_esp32_s3_touch_amoled_191.build.target=esp32s3 +waveshare_esp32_s3_touch_amoled_191.build.mcu=esp32s3 +waveshare_esp32_s3_touch_amoled_191.build.core=esp32 +waveshare_esp32_s3_touch_amoled_191.build.variant=waveshare_esp32_s3_touch_amoled_191 +waveshare_esp32_s3_touch_amoled_191.build.board=WAVESHARE_ESP32_S3_TOUCH_AMOLED_191 + +waveshare_esp32_s3_touch_amoled_191.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_191.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_191.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_191.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_191.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_191.build.flash_size=16MB + +waveshare_esp32_s3_touch_amoled_191.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_191.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_191.build.boot=qio +waveshare_esp32_s3_touch_amoled_191.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_191.build.partitions=default +waveshare_esp32_s3_touch_amoled_191.build.defines= +waveshare_esp32_s3_touch_amoled_191.build.loop_core= +waveshare_esp32_s3_touch_amoled_191.build.event_core= +waveshare_esp32_s3_touch_amoled_191.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_191.build.memory_type={build.boot}_{build.psram_type} + +waveshare_esp32_s3_touch_amoled_191.menu.PSRAM.disabled=Disabled +waveshare_esp32_s3_touch_amoled_191.menu.PSRAM.disabled.build.defines= +waveshare_esp32_s3_touch_amoled_191.menu.PSRAM.disabled.build.psram_type=qspi +waveshare_esp32_s3_touch_amoled_191.menu.PSRAM.enabled=Enabled +waveshare_esp32_s3_touch_amoled_191.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +waveshare_esp32_s3_touch_amoled_191.menu.PSRAM.enabled.build.psram_type=opi + +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio=QIO 80MHz +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio.build.boot=qio +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio.build.boot_freq=80m +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio.build.flash_freq=80m +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio120=QIO 120MHz +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio120.build.flash_mode=dio +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio120.build.boot=qio +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio120.build.boot_freq=120m +waveshare_esp32_s3_touch_amoled_191.menu.FlashMode.qio120.build.flash_freq=80m + +waveshare_esp32_s3_touch_amoled_191.menu.LoopCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_191.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_191.menu.LoopCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_191.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_191.menu.EventsCore.1=Core 1 +waveshare_esp32_s3_touch_amoled_191.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +waveshare_esp32_s3_touch_amoled_191.menu.EventsCore.0=Core 0 +waveshare_esp32_s3_touch_amoled_191.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +waveshare_esp32_s3_touch_amoled_191.menu.USBMode.hwcdc=Hardware CDC and JTAG +waveshare_esp32_s3_touch_amoled_191.menu.USBMode.hwcdc.build.usb_mode=1 +waveshare_esp32_s3_touch_amoled_191.menu.USBMode.default=USB-OTG (TinyUSB) +waveshare_esp32_s3_touch_amoled_191.menu.USBMode.default.build.usb_mode=0 + +waveshare_esp32_s3_touch_amoled_191.menu.CDCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_191.menu.CDCOnBoot.default.build.cdc_on_boot=0 +waveshare_esp32_s3_touch_amoled_191.menu.CDCOnBoot.cdc=Enabled +waveshare_esp32_s3_touch_amoled_191.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_191.menu.MSCOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_191.menu.MSCOnBoot.default.build.msc_on_boot=0 +waveshare_esp32_s3_touch_amoled_191.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_191.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +waveshare_esp32_s3_touch_amoled_191.menu.DFUOnBoot.default=Disabled +waveshare_esp32_s3_touch_amoled_191.menu.DFUOnBoot.default.build.dfu_on_boot=0 +waveshare_esp32_s3_touch_amoled_191.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +waveshare_esp32_s3_touch_amoled_191.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.default=UART0 / Hardware CDC +waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.default.upload.use_1200bps_touch=false +waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.default.upload.wait_for_upload_port=false +waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.cdc.upload.use_1200bps_touch=true +waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.default.build.partitions=default +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) + +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.no_ota.build.partitions=no_ota +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.huge_app.build.partitions=huge_app +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker=RainMaker 4MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.fatflash.build.partitions=ffat +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 + +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 + +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.all_app.upload.maximum_size=4128768 + +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.custom=Custom +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.custom.build.partitions= +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.240=240MHz (WiFi) +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.240.build.f_cpu=240000000L +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.160=160MHz (WiFi) +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.160.build.f_cpu=160000000L +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.80=80MHz (WiFi) +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.80.build.f_cpu=80000000L +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.40=40MHz +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.40.build.f_cpu=40000000L +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.20=20MHz +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.20.build.f_cpu=20000000L +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.10=10MHz +waveshare_esp32_s3_touch_amoled_191.menu.CPUFreq.10.build.f_cpu=10000000L + +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.921600=921600 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.921600.upload.speed=921600 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.115200=115200 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.115200.upload.speed=115200 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.256000.windows=256000 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.256000.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.230400.windows.upload.speed=256000 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.230400=230400 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.230400.upload.speed=230400 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.460800.linux=460800 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.460800.macosx=460800 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.460800.upload.speed=460800 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.512000.windows=512000 +waveshare_esp32_s3_touch_amoled_191.menu.UploadSpeed.512000.upload.speed=512000 + +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.none=None +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.none.build.code_debug=0 +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.error=Error +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.error.build.code_debug=1 +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.warn=Warn +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.warn.build.code_debug=2 +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.info=Info +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.info.build.code_debug=3 +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.debug=Debug +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.debug.build.code_debug=4 +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.verbose=Verbose +waveshare_esp32_s3_touch_amoled_191.menu.DebugLevel.verbose.build.code_debug=5 + +waveshare_esp32_s3_touch_amoled_191.menu.EraseFlash.none=Disabled +waveshare_esp32_s3_touch_amoled_191.menu.EraseFlash.none.upload.erase_cmd= +waveshare_esp32_s3_touch_amoled_191.menu.EraseFlash.all=Enabled +waveshare_esp32_s3_touch_amoled_191.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + + +Pcbcupid_GLYPH_C3.name=Pcbcupid GLYPH C3 +Pcbcupid_GLYPH_C3.vid.0=0x2886 +Pcbcupid_GLYPH_C3.pid.0=0x0046 + +Pcbcupid_GLYPH_C3.bootloader.tool=esptool_py +Pcbcupid_GLYPH_C3.bootloader.tool.default=esptool_py + +Pcbcupid_GLYPH_C3.upload.tool=esptool_py +Pcbcupid_GLYPH_C3.upload.tool.default=esptool_py +Pcbcupid_GLYPH_C3.upload.tool.network=esp_ota + +Pcbcupid_GLYPH_C3.upload.maximum_size=1310720 +Pcbcupid_GLYPH_C3.upload.maximum_data_size=327680 +Pcbcupid_GLYPH_C3.upload.flags= +Pcbcupid_GLYPH_C3.upload.extra_flags= +Pcbcupid_GLYPH_C3.upload.use_1200bps_touch=false +Pcbcupid_GLYPH_C3.upload.wait_for_upload_port=false + +Pcbcupid_GLYPH_C3.serial.disableDTR=false +Pcbcupid_GLYPH_C3.serial.disableRTS=false + +Pcbcupid_GLYPH_C3.build.tarch=riscv32 +Pcbcupid_GLYPH_C3.build.target=esp +Pcbcupid_GLYPH_C3.build.mcu=esp32c3 +Pcbcupid_GLYPH_C3.build.core=esp32 +Pcbcupid_GLYPH_C3.build.variant=Pcbcupid_GLYPH_C3 +Pcbcupid_GLYPH_C3.build.board=PCBCUPID_GLYPHC3 +Pcbcupid_GLYPH_C3.build.bootloader_addr=0x0 + +Pcbcupid_GLYPH_C3.build.cdc_on_boot=1 +Pcbcupid_GLYPH_C3.build.f_cpu=160000000L +Pcbcupid_GLYPH_C3.build.flash_size=4MB +Pcbcupid_GLYPH_C3.build.flash_freq=80m +Pcbcupid_GLYPH_C3.build.flash_mode=qio +Pcbcupid_GLYPH_C3.build.boot=qio +Pcbcupid_GLYPH_C3.build.partitions=default +Pcbcupid_GLYPH_C3.build.defines= + +Pcbcupid_GLYPH_C3.menu.CDCOnBoot.default=Enabled +Pcbcupid_GLYPH_C3.menu.CDCOnBoot.default.build.cdc_on_boot=1 +Pcbcupid_GLYPH_C3.menu.CDCOnBoot.cdc=Disabled +Pcbcupid_GLYPH_C3.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +Pcbcupid_GLYPH_C3.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +Pcbcupid_GLYPH_C3.menu.PartitionScheme.default.build.partitions=default +Pcbcupid_GLYPH_C3.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +Pcbcupid_GLYPH_C3.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +Pcbcupid_GLYPH_C3.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +Pcbcupid_GLYPH_C3.menu.PartitionScheme.minimal.build.partitions=minimal +Pcbcupid_GLYPH_C3.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +Pcbcupid_GLYPH_C3.menu.PartitionScheme.no_ota.build.partitions=no_ota +Pcbcupid_GLYPH_C3.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +Pcbcupid_GLYPH_C3.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +Pcbcupid_GLYPH_C3.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +Pcbcupid_GLYPH_C3.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +Pcbcupid_GLYPH_C3.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +Pcbcupid_GLYPH_C3.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +Pcbcupid_GLYPH_C3.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +Pcbcupid_GLYPH_C3.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +Pcbcupid_GLYPH_C3.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +Pcbcupid_GLYPH_C3.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +Pcbcupid_GLYPH_C3.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +Pcbcupid_GLYPH_C3.menu.PartitionScheme.huge_app.build.partitions=huge_app +Pcbcupid_GLYPH_C3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +Pcbcupid_GLYPH_C3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +Pcbcupid_GLYPH_C3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +Pcbcupid_GLYPH_C3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +Pcbcupid_GLYPH_C3.menu.PartitionScheme.rainmaker=RainMaker 4MB +Pcbcupid_GLYPH_C3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +Pcbcupid_GLYPH_C3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +Pcbcupid_GLYPH_C3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +Pcbcupid_GLYPH_C3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +Pcbcupid_GLYPH_C3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 + +Pcbcupid_GLYPH_C3.menu.CPUFreq.160=160MHz (WiFi) +Pcbcupid_GLYPH_C3.menu.CPUFreq.160.build.f_cpu=160000000L +Pcbcupid_GLYPH_C3.menu.CPUFreq.80=80MHz (WiFi) +Pcbcupid_GLYPH_C3.menu.CPUFreq.80.build.f_cpu=80000000L +Pcbcupid_GLYPH_C3.menu.CPUFreq.40=40MHz +Pcbcupid_GLYPH_C3.menu.CPUFreq.40.build.f_cpu=40000000L +Pcbcupid_GLYPH_C3.menu.CPUFreq.20=20MHz +Pcbcupid_GLYPH_C3.menu.CPUFreq.20.build.f_cpu=20000000L +Pcbcupid_GLYPH_C3.menu.CPUFreq.10=10MHz +Pcbcupid_GLYPH_C3.menu.CPUFreq.10.build.f_cpu=10000000L + +Pcbcupid_GLYPH_C3.menu.FlashMode.qio=QIO +Pcbcupid_GLYPH_C3.menu.FlashMode.qio.build.flash_mode=dio +Pcbcupid_GLYPH_C3.menu.FlashMode.qio.build.boot=qio +Pcbcupid_GLYPH_C3.menu.FlashMode.dio=DIO +Pcbcupid_GLYPH_C3.menu.FlashMode.dio.build.flash_mode=dio +Pcbcupid_GLYPH_C3.menu.FlashMode.dio.build.boot=dio + +Pcbcupid_GLYPH_C3.menu.FlashFreq.80=80MHz +Pcbcupid_GLYPH_C3.menu.FlashFreq.80.build.flash_freq=80m +Pcbcupid_GLYPH_C3.menu.FlashFreq.40=40MHz +Pcbcupid_GLYPH_C3.menu.FlashFreq.40.build.flash_freq=40m + +Pcbcupid_GLYPH_C3.menu.FlashSize.4M=4MB (32Mb) +Pcbcupid_GLYPH_C3.menu.FlashSize.4M.build.flash_size=4MB + +Pcbcupid_GLYPH_C3.menu.UploadSpeed.921600=921600 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.921600.upload.speed=921600 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.115200=115200 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.115200.upload.speed=115200 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.256000.windows=256000 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.256000.upload.speed=256000 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.230400.windows.upload.speed=256000 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.230400=230400 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.230400.upload.speed=230400 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.460800.linux=460800 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.460800.macosx=460800 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.460800.upload.speed=460800 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.512000.windows=512000 +Pcbcupid_GLYPH_C3.menu.UploadSpeed.512000.upload.speed=512000 + +Pcbcupid_GLYPH_C3.menu.DebugLevel.none=None +Pcbcupid_GLYPH_C3.menu.DebugLevel.none.build.code_debug=0 +Pcbcupid_GLYPH_C3.menu.DebugLevel.error=Error +Pcbcupid_GLYPH_C3.menu.DebugLevel.error.build.code_debug=1 +Pcbcupid_GLYPH_C3.menu.DebugLevel.warn=Warn +Pcbcupid_GLYPH_C3.menu.DebugLevel.warn.build.code_debug=2 +Pcbcupid_GLYPH_C3.menu.DebugLevel.info=Info +Pcbcupid_GLYPH_C3.menu.DebugLevel.info.build.code_debug=3 +Pcbcupid_GLYPH_C3.menu.DebugLevel.debug=Debug +Pcbcupid_GLYPH_C3.menu.DebugLevel.debug.build.code_debug=4 +Pcbcupid_GLYPH_C3.menu.DebugLevel.verbose=Verbose +Pcbcupid_GLYPH_C3.menu.DebugLevel.verbose.build.code_debug=5 + +Pcbcupid_GLYPH_C3.menu.EraseFlash.none=Disabled +Pcbcupid_GLYPH_C3.menu.EraseFlash.none.upload.erase_cmd= +Pcbcupid_GLYPH_C3.menu.EraseFlash.all=Enabled +Pcbcupid_GLYPH_C3.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + + +Pcbcupid_GLYPH_H2.name=Pcbcupid GLYPH H2 + +Pcbcupid_GLYPH_H2.bootloader.tool=esptool_py +Pcbcupid_GLYPH_H2.bootloader.tool.default=esptool_py + +Pcbcupid_GLYPH_H2.upload.tool=esptool_py +Pcbcupid_GLYPH_H2.upload.tool.default=esptool_py +Pcbcupid_GLYPH_H2.upload.tool.network=esp_ota + +Pcbcupid_GLYPH_H2.upload.maximum_size=1310720 +Pcbcupid_GLYPH_H2.upload.maximum_data_size=327680 +Pcbcupid_GLYPH_H2.upload.flags= +Pcbcupid_GLYPH_H2.upload.extra_flags= +Pcbcupid_GLYPH_H2.upload.use_1200bps_touch=false +Pcbcupid_GLYPH_H2.upload.wait_for_upload_port=false + +Pcbcupid_GLYPH_H2.serial.disableDTR=false +Pcbcupid_GLYPH_H2.serial.disableRTS=false + +Pcbcupid_GLYPH_H2.build.tarch=riscv32 +Pcbcupid_GLYPH_H2.build.target=esp +Pcbcupid_GLYPH_H2.build.mcu=esp32h2 +Pcbcupid_GLYPH_H2.build.core=esp32 +Pcbcupid_GLYPH_H2.build.variant=Pcbcupid_GLYPH_H2 +Pcbcupid_GLYPH_H2.build.board=PCBCUPID_GLYPHH2 +Pcbcupid_GLYPH_H2.build.bootloader_addr=0x0 + +Pcbcupid_GLYPH_H2.build.cdc_on_boot=1 +Pcbcupid_GLYPH_H2.build.f_cpu=96000000L +Pcbcupid_GLYPH_H2.build.flash_size=4MB +Pcbcupid_GLYPH_H2.build.flash_freq=64m +Pcbcupid_GLYPH_H2.build.img_freq=48m +Pcbcupid_GLYPH_H2.build.flash_mode=qio +Pcbcupid_GLYPH_H2.build.boot=qio +Pcbcupid_GLYPH_H2.build.partitions=default +Pcbcupid_GLYPH_H2.build.defines= + +## IDE 2.0 Seems to not update the value +Pcbcupid_GLYPH_H2.menu.JTAGAdapter.default=Disabled +Pcbcupid_GLYPH_H2.menu.JTAGAdapter.default.build.copy_jtag_files=0 +Pcbcupid_GLYPH_H2.menu.JTAGAdapter.builtin=Integrated USB JTAG +Pcbcupid_GLYPH_H2.menu.JTAGAdapter.builtin.build.openocdscript=esp32h2-builtin.cfg +Pcbcupid_GLYPH_H2.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +Pcbcupid_GLYPH_H2.menu.JTAGAdapter.external=FTDI Adapter +Pcbcupid_GLYPH_H2.menu.JTAGAdapter.external.build.openocdscript=esp32h2-ftdi.cfg +Pcbcupid_GLYPH_H2.menu.JTAGAdapter.external.build.copy_jtag_files=1 +Pcbcupid_GLYPH_H2.menu.JTAGAdapter.bridge=ESP USB Bridge +Pcbcupid_GLYPH_H2.menu.JTAGAdapter.bridge.build.openocdscript=esp32h2-bridge.cfg +Pcbcupid_GLYPH_H2.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +Pcbcupid_GLYPH_H2.menu.CDCOnBoot.default=Enabled +Pcbcupid_GLYPH_H2.menu.CDCOnBoot.default.build.cdc_on_boot=1 +Pcbcupid_GLYPH_H2.menu.CDCOnBoot.cdc=Disabled +Pcbcupid_GLYPH_H2.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +Pcbcupid_GLYPH_H2.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +Pcbcupid_GLYPH_H2.menu.PartitionScheme.default.build.partitions=default +Pcbcupid_GLYPH_H2.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +Pcbcupid_GLYPH_H2.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +Pcbcupid_GLYPH_H2.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +Pcbcupid_GLYPH_H2.menu.PartitionScheme.minimal.build.partitions=minimal +Pcbcupid_GLYPH_H2.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +Pcbcupid_GLYPH_H2.menu.PartitionScheme.no_fs.build.partitions=no_fs +Pcbcupid_GLYPH_H2.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +Pcbcupid_GLYPH_H2.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +Pcbcupid_GLYPH_H2.menu.PartitionScheme.no_ota.build.partitions=no_ota +Pcbcupid_GLYPH_H2.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +Pcbcupid_GLYPH_H2.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +Pcbcupid_GLYPH_H2.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +Pcbcupid_GLYPH_H2.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +Pcbcupid_GLYPH_H2.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +Pcbcupid_GLYPH_H2.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +Pcbcupid_GLYPH_H2.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +Pcbcupid_GLYPH_H2.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +Pcbcupid_GLYPH_H2.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +Pcbcupid_GLYPH_H2.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +Pcbcupid_GLYPH_H2.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +Pcbcupid_GLYPH_H2.menu.PartitionScheme.huge_app.build.partitions=huge_app +Pcbcupid_GLYPH_H2.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +Pcbcupid_GLYPH_H2.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +Pcbcupid_GLYPH_H2.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +Pcbcupid_GLYPH_H2.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +Pcbcupid_GLYPH_H2.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs +Pcbcupid_GLYPH_H2.menu.PartitionScheme.zigbee.build.partitions=zigbee +Pcbcupid_GLYPH_H2.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 +Pcbcupid_GLYPH_H2.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +Pcbcupid_GLYPH_H2.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +Pcbcupid_GLYPH_H2.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +Pcbcupid_GLYPH_H2.menu.PartitionScheme.custom=Custom +Pcbcupid_GLYPH_H2.menu.PartitionScheme.custom.build.partitions= +Pcbcupid_GLYPH_H2.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +Pcbcupid_GLYPH_H2.menu.FlashMode.qio=QIO +Pcbcupid_GLYPH_H2.menu.FlashMode.qio.build.flash_mode=dio +Pcbcupid_GLYPH_H2.menu.FlashMode.qio.build.boot=qio +Pcbcupid_GLYPH_H2.menu.FlashMode.dio=DIO +Pcbcupid_GLYPH_H2.menu.FlashMode.dio.build.flash_mode=dio +Pcbcupid_GLYPH_H2.menu.FlashMode.dio.build.boot=dio + +Pcbcupid_GLYPH_H2.menu.FlashFreq.64=64MHz +Pcbcupid_GLYPH_H2.menu.FlashFreq.64.build.flash_freq=64m +Pcbcupid_GLYPH_H2.menu.FlashFreq.64.build.img_freq=48m +#Pcbcupid_GLYPH_H2.menu.FlashFreq.32=32MHz +#Pcbcupid_GLYPH_H2.menu.FlashFreq.32.build.flash_freq=32m +#Pcbcupid_GLYPH_H2.menu.FlashFreq.32.build.img_freq=24m +Pcbcupid_GLYPH_H2.menu.FlashFreq.16=16MHz +Pcbcupid_GLYPH_H2.menu.FlashFreq.16.build.flash_freq=16m +Pcbcupid_GLYPH_H2.menu.FlashFreq.16.build.img_freq=12m + +Pcbcupid_GLYPH_H2.menu.FlashSize.2M=2MB (16Mb) +Pcbcupid_GLYPH_H2.menu.FlashSize.2M.build.flash_size=2MB +Pcbcupid_GLYPH_H2.menu.FlashSize.4M=4MB (32Mb) +Pcbcupid_GLYPH_H2.menu.FlashSize.4M.build.flash_size=4MB + +Pcbcupid_GLYPH_H2.menu.UploadSpeed.921600=921600 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.921600.upload.speed=921600 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.115200=115200 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.115200.upload.speed=115200 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.256000.windows=256000 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.256000.upload.speed=256000 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.230400.windows.upload.speed=256000 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.230400=230400 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.230400.upload.speed=230400 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.460800.linux=460800 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.460800.macosx=460800 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.460800.upload.speed=460800 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.512000.windows=512000 +Pcbcupid_GLYPH_H2.menu.UploadSpeed.512000.upload.speed=512000 + +Pcbcupid_GLYPH_H2.menu.DebugLevel.none=None +Pcbcupid_GLYPH_H2.menu.DebugLevel.none.build.code_debug=0 +Pcbcupid_GLYPH_H2.menu.DebugLevel.error=Error +Pcbcupid_GLYPH_H2.menu.DebugLevel.error.build.code_debug=1 +Pcbcupid_GLYPH_H2.menu.DebugLevel.warn=Warn +Pcbcupid_GLYPH_H2.menu.DebugLevel.warn.build.code_debug=2 +Pcbcupid_GLYPH_H2.menu.DebugLevel.info=Info +Pcbcupid_GLYPH_H2.menu.DebugLevel.info.build.code_debug=3 +Pcbcupid_GLYPH_H2.menu.DebugLevel.debug=Debug +Pcbcupid_GLYPH_H2.menu.DebugLevel.debug.build.code_debug=4 +Pcbcupid_GLYPH_H2.menu.DebugLevel.verbose=Verbose +Pcbcupid_GLYPH_H2.menu.DebugLevel.verbose.build.code_debug=5 + +Pcbcupid_GLYPH_H2.menu.EraseFlash.none=Disabled +Pcbcupid_GLYPH_H2.menu.EraseFlash.none.upload.erase_cmd= +Pcbcupid_GLYPH_H2.menu.EraseFlash.all=Enabled +Pcbcupid_GLYPH_H2.menu.EraseFlash.all.upload.erase_cmd=-e + +Pcbcupid_GLYPH_H2.menu.ZigbeeMode.default=Disabled +Pcbcupid_GLYPH_H2.menu.ZigbeeMode.default.build.zigbee_mode= +Pcbcupid_GLYPH_H2.menu.ZigbeeMode.default.build.zigbee_libs= +Pcbcupid_GLYPH_H2.menu.ZigbeeMode.ed=Zigbee ED (end device) +Pcbcupid_GLYPH_H2.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED +Pcbcupid_GLYPH_H2.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +Pcbcupid_GLYPH_H2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +Pcbcupid_GLYPH_H2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +Pcbcupid_GLYPH_H2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native + +############################################################## + +Pcbcupid_GLYPH_C6.name=Pcbcupid GLYPH C6 + +Pcbcupid_GLYPH_C6.bootloader.tool=esptool_py +Pcbcupid_GLYPH_C6.bootloader.tool.default=esptool_py + +Pcbcupid_GLYPH_C6.upload.tool=esptool_py +Pcbcupid_GLYPH_C6.upload.tool.default=esptool_py +Pcbcupid_GLYPH_C6.upload.tool.network=esp_ota + +Pcbcupid_GLYPH_C6.upload.maximum_size=1310720 +Pcbcupid_GLYPH_C6.upload.maximum_data_size=327680 +Pcbcupid_GLYPH_C6.upload.flags= +Pcbcupid_GLYPH_C6.upload.extra_flags= +Pcbcupid_GLYPH_C6.upload.use_1200bps_touch=false +Pcbcupid_GLYPH_C6.upload.wait_for_upload_port=false + +Pcbcupid_GLYPH_C6.serial.disableDTR=false +Pcbcupid_GLYPH_C6.serial.disableRTS=false + +Pcbcupid_GLYPH_C6.build.tarch=riscv32 +Pcbcupid_GLYPH_C6.build.target=esp +Pcbcupid_GLYPH_C6.build.mcu=esp32c6 +Pcbcupid_GLYPH_C6.build.core=esp32 +Pcbcupid_GLYPH_C6.build.variant=Pcbcupid_GLYPH_C6 +Pcbcupid_GLYPH_C6.build.board=PCBCUPID_GLYPHC6 +Pcbcupid_GLYPH_C6.build.bootloader_addr=0x0 + +Pcbcupid_GLYPH_C6.build.cdc_on_boot=1 +Pcbcupid_GLYPH_C6.build.f_cpu=160000000L +Pcbcupid_GLYPH_C6.build.flash_size=4MB +Pcbcupid_GLYPH_C6.build.flash_freq=80m +Pcbcupid_GLYPH_C6.build.flash_mode=qio +Pcbcupid_GLYPH_C6.build.boot=qio +Pcbcupid_GLYPH_C6.build.partitions=default +Pcbcupid_GLYPH_C6.build.defines= + +## IDE 2.0 Seems to not update the value +Pcbcupid_GLYPH_C6.menu.JTAGAdapter.default=Disabled +Pcbcupid_GLYPH_C6.menu.JTAGAdapter.default.build.copy_jtag_files=0 +Pcbcupid_GLYPH_C6.menu.JTAGAdapter.builtin=Integrated USB JTAG +Pcbcupid_GLYPH_C6.menu.JTAGAdapter.builtin.build.openocdscript=esp32c6-builtin.cfg +Pcbcupid_GLYPH_C6.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +Pcbcupid_GLYPH_C6.menu.JTAGAdapter.external=FTDI Adapter +Pcbcupid_GLYPH_C6.menu.JTAGAdapter.external.build.openocdscript=esp32c6-ftdi.cfg +Pcbcupid_GLYPH_C6.menu.JTAGAdapter.external.build.copy_jtag_files=1 +Pcbcupid_GLYPH_C6.menu.JTAGAdapter.bridge=ESP USB Bridge +Pcbcupid_GLYPH_C6.menu.JTAGAdapter.bridge.build.openocdscript=esp32c6-bridge.cfg +Pcbcupid_GLYPH_C6.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +Pcbcupid_GLYPH_C6.menu.CDCOnBoot.cdc=Enabled +Pcbcupid_GLYPH_C6.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 +Pcbcupid_GLYPH_C6.menu.CDCOnBoot.default=Disabled +Pcbcupid_GLYPH_C6.menu.CDCOnBoot.default.build.cdc_on_boot=0 + +Pcbcupid_GLYPH_C6.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +Pcbcupid_GLYPH_C6.menu.PartitionScheme.default.build.partitions=default +Pcbcupid_GLYPH_C6.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +Pcbcupid_GLYPH_C6.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +Pcbcupid_GLYPH_C6.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +Pcbcupid_GLYPH_C6.menu.PartitionScheme.no_ota.build.partitions=no_ota +Pcbcupid_GLYPH_C6.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +Pcbcupid_GLYPH_C6.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +Pcbcupid_GLYPH_C6.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +Pcbcupid_GLYPH_C6.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +Pcbcupid_GLYPH_C6.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +Pcbcupid_GLYPH_C6.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +Pcbcupid_GLYPH_C6.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +Pcbcupid_GLYPH_C6.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +Pcbcupid_GLYPH_C6.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +Pcbcupid_GLYPH_C6.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +Pcbcupid_GLYPH_C6.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +Pcbcupid_GLYPH_C6.menu.PartitionScheme.huge_app.build.partitions=huge_app +Pcbcupid_GLYPH_C6.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +Pcbcupid_GLYPH_C6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs +Pcbcupid_GLYPH_C6.menu.PartitionScheme.zigbee.build.partitions=zigbee +Pcbcupid_GLYPH_C6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 +Pcbcupid_GLYPH_C6.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +Pcbcupid_GLYPH_C6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +Pcbcupid_GLYPH_C6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 + +Pcbcupid_GLYPH_C6.menu.CPUFreq.160=160MHz (WiFi) +Pcbcupid_GLYPH_C6.menu.CPUFreq.160.build.f_cpu=160000000L +Pcbcupid_GLYPH_C6.menu.CPUFreq.80=80MHz (WiFi) +Pcbcupid_GLYPH_C6.menu.CPUFreq.80.build.f_cpu=80000000L +Pcbcupid_GLYPH_C6.menu.CPUFreq.40=40MHz +Pcbcupid_GLYPH_C6.menu.CPUFreq.40.build.f_cpu=40000000L +Pcbcupid_GLYPH_C6.menu.CPUFreq.20=20MHz +Pcbcupid_GLYPH_C6.menu.CPUFreq.20.build.f_cpu=20000000L +Pcbcupid_GLYPH_C6.menu.CPUFreq.10=10MHz +Pcbcupid_GLYPH_C6.menu.CPUFreq.10.build.f_cpu=10000000L + +Pcbcupid_GLYPH_C6.menu.FlashMode.qio=QIO +Pcbcupid_GLYPH_C6.menu.FlashMode.qio.build.flash_mode=dio +Pcbcupid_GLYPH_C6.menu.FlashMode.qio.build.boot=qio +Pcbcupid_GLYPH_C6.menu.FlashMode.dio=DIO +Pcbcupid_GLYPH_C6.menu.FlashMode.dio.build.flash_mode=dio +Pcbcupid_GLYPH_C6.menu.FlashMode.dio.build.boot=dio + +Pcbcupid_GLYPH_C6.menu.FlashFreq.80=80MHz +Pcbcupid_GLYPH_C6.menu.FlashFreq.80.build.flash_freq=80m +Pcbcupid_GLYPH_C6.menu.FlashFreq.40=40MHz +Pcbcupid_GLYPH_C6.menu.FlashFreq.40.build.flash_freq=40m + +Pcbcupid_GLYPH_C6.menu.FlashSize.4M=4MB (32Mb) +Pcbcupid_GLYPH_C6.menu.FlashSize.4M.build.flash_size=4MB + +Pcbcupid_GLYPH_C6.menu.UploadSpeed.921600=921600 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.921600.upload.speed=921600 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.115200=115200 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.115200.upload.speed=115200 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.256000.windows=256000 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.256000.upload.speed=256000 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.230400.windows.upload.speed=256000 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.230400=230400 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.230400.upload.speed=230400 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.460800.linux=460800 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.460800.macosx=460800 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.460800.upload.speed=460800 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.512000.windows=512000 +Pcbcupid_GLYPH_C6.menu.UploadSpeed.512000.upload.speed=512000 + +Pcbcupid_GLYPH_C6.menu.DebugLevel.none=None +Pcbcupid_GLYPH_C6.menu.DebugLevel.none.build.code_debug=0 +Pcbcupid_GLYPH_C6.menu.DebugLevel.error=Error +Pcbcupid_GLYPH_C6.menu.DebugLevel.error.build.code_debug=1 +Pcbcupid_GLYPH_C6.menu.DebugLevel.warn=Warn +Pcbcupid_GLYPH_C6.menu.DebugLevel.warn.build.code_debug=2 +Pcbcupid_GLYPH_C6.menu.DebugLevel.info=Info +Pcbcupid_GLYPH_C6.menu.DebugLevel.info.build.code_debug=3 +Pcbcupid_GLYPH_C6.menu.DebugLevel.debug=Debug +Pcbcupid_GLYPH_C6.menu.DebugLevel.debug.build.code_debug=4 +Pcbcupid_GLYPH_C6.menu.DebugLevel.verbose=Verbose +Pcbcupid_GLYPH_C6.menu.DebugLevel.verbose.build.code_debug=5 + +Pcbcupid_GLYPH_C6.menu.EraseFlash.none=Disabled +Pcbcupid_GLYPH_C6.menu.EraseFlash.none.upload.erase_cmd= +Pcbcupid_GLYPH_C6.menu.EraseFlash.all=Enabled +Pcbcupid_GLYPH_C6.menu.EraseFlash.all.upload.erase_cmd=-e + +Pcbcupid_GLYPH_C6.menu.ZigbeeMode.default=Disabled +Pcbcupid_GLYPH_C6.menu.ZigbeeMode.default.build.zigbee_mode= +Pcbcupid_GLYPH_C6.menu.ZigbeeMode.default.build.zigbee_libs= +Pcbcupid_GLYPH_C6.menu.ZigbeeMode.ed=Zigbee ED (end device) +Pcbcupid_GLYPH_C6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED +Pcbcupid_GLYPH_C6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +Pcbcupid_GLYPH_C6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +Pcbcupid_GLYPH_C6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +Pcbcupid_GLYPH_C6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native + +############################################################## + +yb_esp32s3_amp_v2.name=YelloByte YB-ESP32-S3-AMP (Rev.2) + +yb_esp32s3_amp_v2.bootloader.tool=esptool_py +yb_esp32s3_amp_v2.bootloader.tool.default=esptool_py + +yb_esp32s3_amp_v2.upload.tool=esptool_py +yb_esp32s3_amp_v2.upload.tool.default=esptool_py +yb_esp32s3_amp_v2.upload.tool.network=esp_ota + +yb_esp32s3_amp_v2.upload.maximum_size=1310720 +yb_esp32s3_amp_v2.upload.maximum_data_size=327680 +yb_esp32s3_amp_v2.upload.flags= +yb_esp32s3_amp_v2.upload.extra_flags= +yb_esp32s3_amp_v2.upload.use_1200bps_touch=false +yb_esp32s3_amp_v2.upload.wait_for_upload_port=false + +yb_esp32s3_amp_v2.serial.disableDTR=false +yb_esp32s3_amp_v2.serial.disableRTS=false + +yb_esp32s3_amp_v2.build.tarch=xtensa +yb_esp32s3_amp_v2.build.bootloader_addr=0x0 +yb_esp32s3_amp_v2.build.target=esp32s3 +yb_esp32s3_amp_v2.build.mcu=esp32s3 +yb_esp32s3_amp_v2.build.core=esp32 +yb_esp32s3_amp_v2.build.variant=yb_esp32s3_amp_v2 +yb_esp32s3_amp_v2.build.board=YB_ESP32S3_AMP_V2 + +yb_esp32s3_amp_v2.build.usb_mode=1 +yb_esp32s3_amp_v2.build.cdc_on_boot=0 +yb_esp32s3_amp_v2.build.msc_on_boot=0 +yb_esp32s3_amp_v2.build.dfu_on_boot=0 +yb_esp32s3_amp_v2.build.f_cpu=240000000L +yb_esp32s3_amp_v2.build.flash_size=8MB +yb_esp32s3_amp_v2.build.flash_freq=80m +yb_esp32s3_amp_v2.build.flash_mode=dio +yb_esp32s3_amp_v2.build.boot=qio +yb_esp32s3_amp_v2.build.partitions=default +yb_esp32s3_amp_v2.build.defines= +yb_esp32s3_amp_v2.build.loop_core= +yb_esp32s3_amp_v2.build.event_core= +yb_esp32s3_amp_v2.build.flash_type=qio +yb_esp32s3_amp_v2.build.psram_type=qspi +yb_esp32s3_amp_v2.build.memory_type={build.flash_type}_{build.psram_type} + +yb_esp32s3_amp_v2.menu.JTAGAdapter.default=Disabled +yb_esp32s3_amp_v2.menu.JTAGAdapter.default.build.copy_jtag_files=0 +yb_esp32s3_amp_v2.menu.JTAGAdapter.external=FTDI Adapter +yb_esp32s3_amp_v2.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +yb_esp32s3_amp_v2.menu.JTAGAdapter.external.build.copy_jtag_files=1 +yb_esp32s3_amp_v2.menu.JTAGAdapter.bridge=ESP USB Bridge +yb_esp32s3_amp_v2.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +yb_esp32s3_amp_v2.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +yb_esp32s3_amp_v2.menu.LoopCore.1=Core 1 +yb_esp32s3_amp_v2.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +yb_esp32s3_amp_v2.menu.LoopCore.0=Core 0 +yb_esp32s3_amp_v2.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +yb_esp32s3_amp_v2.menu.EventsCore.1=Core 1 +yb_esp32s3_amp_v2.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +yb_esp32s3_amp_v2.menu.EventsCore.0=Core 0 +yb_esp32s3_amp_v2.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +yb_esp32s3_amp_v2.menu.USBMode.hwcdc=Hardware CDC and JTAG +yb_esp32s3_amp_v2.menu.USBMode.hwcdc.build.usb_mode=1 +yb_esp32s3_amp_v2.menu.USBMode.default=USB-OTG (TinyUSB) +yb_esp32s3_amp_v2.menu.USBMode.default.build.usb_mode=0 + +yb_esp32s3_amp_v2.menu.CDCOnBoot.default=Disabled +yb_esp32s3_amp_v2.menu.CDCOnBoot.default.build.cdc_on_boot=0 +yb_esp32s3_amp_v2.menu.CDCOnBoot.cdc=Enabled +yb_esp32s3_amp_v2.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +yb_esp32s3_amp_v2.menu.MSCOnBoot.default=Disabled +yb_esp32s3_amp_v2.menu.MSCOnBoot.default.build.msc_on_boot=0 +yb_esp32s3_amp_v2.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +yb_esp32s3_amp_v2.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +yb_esp32s3_amp_v2.menu.DFUOnBoot.default=Disabled +yb_esp32s3_amp_v2.menu.DFUOnBoot.default.build.dfu_on_boot=0 +yb_esp32s3_amp_v2.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +yb_esp32s3_amp_v2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +yb_esp32s3_amp_v2.menu.UploadMode.default=UART0 / Hardware CDC +yb_esp32s3_amp_v2.menu.UploadMode.default.upload.use_1200bps_touch=false +yb_esp32s3_amp_v2.menu.UploadMode.default.upload.wait_for_upload_port=false +yb_esp32s3_amp_v2.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +yb_esp32s3_amp_v2.menu.UploadMode.cdc.upload.use_1200bps_touch=true +yb_esp32s3_amp_v2.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +yb_esp32s3_amp_v2.menu.PSRAM.enabled=QSPI PSRAM +yb_esp32s3_amp_v2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +yb_esp32s3_amp_v2.menu.PSRAM.enabled.build.psram_type=qspi +yb_esp32s3_amp_v2.menu.PSRAM.disabled=Disabled +yb_esp32s3_amp_v2.menu.PSRAM.disabled.build.defines= +yb_esp32s3_amp_v2.menu.PSRAM.disabled.build.psram_type=qspi +yb_esp32s3_amp_v2.menu.PSRAM.opi=OPI PSRAM +yb_esp32s3_amp_v2.menu.PSRAM.opi.build.defines=-DBOARD_HAS_PSRAM +yb_esp32s3_amp_v2.menu.PSRAM.opi.build.psram_type=opi + +yb_esp32s3_amp_v2.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +yb_esp32s3_amp_v2.menu.PartitionScheme.default.build.partitions=default +yb_esp32s3_amp_v2.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +yb_esp32s3_amp_v2.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +yb_esp32s3_amp_v2.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +yb_esp32s3_amp_v2.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +yb_esp32s3_amp_v2.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +yb_esp32s3_amp_v2.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +yb_esp32s3_amp_v2.menu.PartitionScheme.minimal.build.partitions=minimal +yb_esp32s3_amp_v2.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +yb_esp32s3_amp_v2.menu.PartitionScheme.no_ota.build.partitions=no_ota +yb_esp32s3_amp_v2.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +yb_esp32s3_amp_v2.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +yb_esp32s3_amp_v2.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +yb_esp32s3_amp_v2.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +yb_esp32s3_amp_v2.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +yb_esp32s3_amp_v2.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +yb_esp32s3_amp_v2.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +yb_esp32s3_amp_v2.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +yb_esp32s3_amp_v2.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +yb_esp32s3_amp_v2.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +yb_esp32s3_amp_v2.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +yb_esp32s3_amp_v2.menu.PartitionScheme.huge_app.build.partitions=huge_app +yb_esp32s3_amp_v2.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +yb_esp32s3_amp_v2.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +yb_esp32s3_amp_v2.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +yb_esp32s3_amp_v2.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +yb_esp32s3_amp_v2.menu.PartitionScheme.max_app_8MB=Maximum APP (7.9MB APP No OTA/No FS) +yb_esp32s3_amp_v2.menu.PartitionScheme.max_app_8MB.build.partitions=max_app_8MB +yb_esp32s3_amp_v2.menu.PartitionScheme.max_app_8MB.upload.maximum_size=8257536 + +yb_esp32s3_amp_v2.menu.CPUFreq.240=240MHz (WiFi) +yb_esp32s3_amp_v2.menu.CPUFreq.240.build.f_cpu=240000000L +yb_esp32s3_amp_v2.menu.CPUFreq.160=160MHz (WiFi) +yb_esp32s3_amp_v2.menu.CPUFreq.160.build.f_cpu=160000000L +yb_esp32s3_amp_v2.menu.CPUFreq.80=80MHz (WiFi) +yb_esp32s3_amp_v2.menu.CPUFreq.80.build.f_cpu=80000000L +yb_esp32s3_amp_v2.menu.CPUFreq.40=40MHz +yb_esp32s3_amp_v2.menu.CPUFreq.40.build.f_cpu=40000000L +yb_esp32s3_amp_v2.menu.CPUFreq.20=20MHz +yb_esp32s3_amp_v2.menu.CPUFreq.20.build.f_cpu=20000000L +yb_esp32s3_amp_v2.menu.CPUFreq.10=10MHz +yb_esp32s3_amp_v2.menu.CPUFreq.10.build.f_cpu=10000000L + +yb_esp32s3_amp_v2.menu.FlashMode.qio=QIO 80MHz +yb_esp32s3_amp_v2.menu.FlashMode.qio.build.flash_mode=dio +yb_esp32s3_amp_v2.menu.FlashMode.qio.build.boot=qio +yb_esp32s3_amp_v2.menu.FlashMode.qio.build.boot_freq=80m +yb_esp32s3_amp_v2.menu.FlashMode.qio.build.flash_freq=80m +yb_esp32s3_amp_v2.menu.FlashMode.qio120=QIO 120MHz +yb_esp32s3_amp_v2.menu.FlashMode.qio120.build.flash_mode=dio +yb_esp32s3_amp_v2.menu.FlashMode.qio120.build.boot=qio +yb_esp32s3_amp_v2.menu.FlashMode.qio120.build.boot_freq=120m +yb_esp32s3_amp_v2.menu.FlashMode.qio120.build.flash_freq=80m +yb_esp32s3_amp_v2.menu.FlashMode.dio=DIO 80MHz +yb_esp32s3_amp_v2.menu.FlashMode.dio.build.flash_mode=dio +yb_esp32s3_amp_v2.menu.FlashMode.dio.build.boot=dio +yb_esp32s3_amp_v2.menu.FlashMode.dio.build.boot_freq=80m +yb_esp32s3_amp_v2.menu.FlashMode.dio.build.flash_freq=80m +yb_esp32s3_amp_v2.menu.FlashMode.opi=OPI 80MHz +yb_esp32s3_amp_v2.menu.FlashMode.opi.build.flash_mode=dout +yb_esp32s3_amp_v2.menu.FlashMode.opi.build.boot=opi +yb_esp32s3_amp_v2.menu.FlashMode.opi.build.boot_freq=80m +yb_esp32s3_amp_v2.menu.FlashMode.opi.build.flash_freq=80m + +yb_esp32s3_amp_v2.menu.FlashSize.4M=4MB (32Mb) +yb_esp32s3_amp_v2.menu.FlashSize.4M.build.flash_size=4MB +yb_esp32s3_amp_v2.menu.FlashSize.8M=8MB (64Mb) +yb_esp32s3_amp_v2.menu.FlashSize.8M.build.flash_size=8MB +yb_esp32s3_amp_v2.menu.FlashSize.16M=16MB (128Mb) +yb_esp32s3_amp_v2.menu.FlashSize.16M.build.flash_size=16MB + +yb_esp32s3_amp_v2.menu.UploadSpeed.921600=921600 +yb_esp32s3_amp_v2.menu.UploadSpeed.921600.upload.speed=921600 +yb_esp32s3_amp_v2.menu.UploadSpeed.115200=115200 +yb_esp32s3_amp_v2.menu.UploadSpeed.115200.upload.speed=115200 +yb_esp32s3_amp_v2.menu.UploadSpeed.256000.windows=256000 +yb_esp32s3_amp_v2.menu.UploadSpeed.256000.upload.speed=256000 +yb_esp32s3_amp_v2.menu.UploadSpeed.230400.windows.upload.speed=256000 +yb_esp32s3_amp_v2.menu.UploadSpeed.230400=230400 +yb_esp32s3_amp_v2.menu.UploadSpeed.230400.upload.speed=230400 +yb_esp32s3_amp_v2.menu.UploadSpeed.460800.linux=460800 +yb_esp32s3_amp_v2.menu.UploadSpeed.460800.macosx=460800 +yb_esp32s3_amp_v2.menu.UploadSpeed.460800.upload.speed=460800 +yb_esp32s3_amp_v2.menu.UploadSpeed.512000.windows=512000 +yb_esp32s3_amp_v2.menu.UploadSpeed.512000.upload.speed=512000 + +yb_esp32s3_amp_v2.menu.DebugLevel.none=None +yb_esp32s3_amp_v2.menu.DebugLevel.none.build.code_debug=0 +yb_esp32s3_amp_v2.menu.DebugLevel.error=Error +yb_esp32s3_amp_v2.menu.DebugLevel.error.build.code_debug=1 +yb_esp32s3_amp_v2.menu.DebugLevel.warn=Warn +yb_esp32s3_amp_v2.menu.DebugLevel.warn.build.code_debug=2 +yb_esp32s3_amp_v2.menu.DebugLevel.info=Info +yb_esp32s3_amp_v2.menu.DebugLevel.info.build.code_debug=3 +yb_esp32s3_amp_v2.menu.DebugLevel.debug=Debug +yb_esp32s3_amp_v2.menu.DebugLevel.debug.build.code_debug=4 +yb_esp32s3_amp_v2.menu.DebugLevel.verbose=Verbose +yb_esp32s3_amp_v2.menu.DebugLevel.verbose.build.code_debug=5 + +yb_esp32s3_amp_v2.menu.EraseFlash.none=Disabled +yb_esp32s3_amp_v2.menu.EraseFlash.none.upload.erase_cmd= +yb_esp32s3_amp_v2.menu.EraseFlash.all=Enabled +yb_esp32s3_amp_v2.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +yb_esp32s3_amp_v3.name=YelloByte YB-ESP32-S3-AMP (Rev.3) + +yb_esp32s3_amp_v3.bootloader.tool=esptool_py +yb_esp32s3_amp_v3.bootloader.tool.default=esptool_py + +yb_esp32s3_amp_v3.upload.tool=esptool_py +yb_esp32s3_amp_v3.upload.tool.default=esptool_py +yb_esp32s3_amp_v3.upload.tool.network=esp_ota + +yb_esp32s3_amp_v3.upload.maximum_size=1310720 +yb_esp32s3_amp_v3.upload.maximum_data_size=327680 +yb_esp32s3_amp_v3.upload.flags= +yb_esp32s3_amp_v3.upload.extra_flags= +yb_esp32s3_amp_v3.upload.use_1200bps_touch=false +yb_esp32s3_amp_v3.upload.wait_for_upload_port=false + +yb_esp32s3_amp_v3.serial.disableDTR=false +yb_esp32s3_amp_v3.serial.disableRTS=false + +yb_esp32s3_amp_v3.build.tarch=xtensa +yb_esp32s3_amp_v3.build.bootloader_addr=0x0 +yb_esp32s3_amp_v3.build.target=esp32s3 +yb_esp32s3_amp_v3.build.mcu=esp32s3 +yb_esp32s3_amp_v3.build.core=esp32 +yb_esp32s3_amp_v3.build.variant=yb_esp32s3_amp_v3 +yb_esp32s3_amp_v3.build.board=YB_ESP32S3_AMP_V3 + +yb_esp32s3_amp_v3.build.usb_mode=1 +yb_esp32s3_amp_v3.build.cdc_on_boot=1 +yb_esp32s3_amp_v3.build.msc_on_boot=0 +yb_esp32s3_amp_v3.build.dfu_on_boot=0 +yb_esp32s3_amp_v3.build.f_cpu=240000000L +yb_esp32s3_amp_v3.build.flash_size=8MB +yb_esp32s3_amp_v3.build.flash_freq=80m +yb_esp32s3_amp_v3.build.flash_mode=dio +yb_esp32s3_amp_v3.build.boot=qio +yb_esp32s3_amp_v3.build.partitions=default +yb_esp32s3_amp_v3.build.defines= +yb_esp32s3_amp_v3.build.loop_core= +yb_esp32s3_amp_v3.build.event_core= +yb_esp32s3_amp_v3.build.flash_type=qio +yb_esp32s3_amp_v3.build.psram_type=qspi +yb_esp32s3_amp_v3.build.memory_type={build.flash_type}_{build.psram_type} + +yb_esp32s3_amp_v3.menu.JTAGAdapter.default=Disabled +yb_esp32s3_amp_v3.menu.JTAGAdapter.default.build.copy_jtag_files=0 +yb_esp32s3_amp_v3.menu.JTAGAdapter.builtin=Integrated USB JTAG +yb_esp32s3_amp_v3.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +yb_esp32s3_amp_v3.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +yb_esp32s3_amp_v3.menu.JTAGAdapter.external=FTDI Adapter +yb_esp32s3_amp_v3.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +yb_esp32s3_amp_v3.menu.JTAGAdapter.external.build.copy_jtag_files=1 +yb_esp32s3_amp_v3.menu.JTAGAdapter.bridge=ESP USB Bridge +yb_esp32s3_amp_v3.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +yb_esp32s3_amp_v3.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +yb_esp32s3_amp_v3.menu.LoopCore.1=Core 1 +yb_esp32s3_amp_v3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +yb_esp32s3_amp_v3.menu.LoopCore.0=Core 0 +yb_esp32s3_amp_v3.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +yb_esp32s3_amp_v3.menu.EventsCore.1=Core 1 +yb_esp32s3_amp_v3.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +yb_esp32s3_amp_v3.menu.EventsCore.0=Core 0 +yb_esp32s3_amp_v3.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +yb_esp32s3_amp_v3.menu.USBMode.hwcdc=Hardware CDC and JTAG +yb_esp32s3_amp_v3.menu.USBMode.hwcdc.build.usb_mode=1 +yb_esp32s3_amp_v3.menu.USBMode.default=USB-OTG (TinyUSB) +yb_esp32s3_amp_v3.menu.USBMode.default.build.usb_mode=0 + +yb_esp32s3_amp_v3.menu.CDCOnBoot.cdc=Enabled +yb_esp32s3_amp_v3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 +yb_esp32s3_amp_v3.menu.CDCOnBoot.default=Disabled +yb_esp32s3_amp_v3.menu.CDCOnBoot.default.build.cdc_on_boot=0 + +yb_esp32s3_amp_v3.menu.MSCOnBoot.default=Disabled +yb_esp32s3_amp_v3.menu.MSCOnBoot.default.build.msc_on_boot=0 +yb_esp32s3_amp_v3.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +yb_esp32s3_amp_v3.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +yb_esp32s3_amp_v3.menu.DFUOnBoot.default=Disabled +yb_esp32s3_amp_v3.menu.DFUOnBoot.default.build.dfu_on_boot=0 +yb_esp32s3_amp_v3.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +yb_esp32s3_amp_v3.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +yb_esp32s3_amp_v3.menu.UploadMode.default=UART0 / Hardware CDC +yb_esp32s3_amp_v3.menu.UploadMode.default.upload.use_1200bps_touch=false +yb_esp32s3_amp_v3.menu.UploadMode.default.upload.wait_for_upload_port=false +yb_esp32s3_amp_v3.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +yb_esp32s3_amp_v3.menu.UploadMode.cdc.upload.use_1200bps_touch=true +yb_esp32s3_amp_v3.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +yb_esp32s3_amp_v3.menu.PSRAM.enabled=QSPI PSRAM +yb_esp32s3_amp_v3.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +yb_esp32s3_amp_v3.menu.PSRAM.enabled.build.psram_type=qspi +yb_esp32s3_amp_v3.menu.PSRAM.disabled=Disabled +yb_esp32s3_amp_v3.menu.PSRAM.disabled.build.defines= +yb_esp32s3_amp_v3.menu.PSRAM.disabled.build.psram_type=qspi +yb_esp32s3_amp_v3.menu.PSRAM.opi=OPI PSRAM +yb_esp32s3_amp_v3.menu.PSRAM.opi.build.defines=-DBOARD_HAS_PSRAM +yb_esp32s3_amp_v3.menu.PSRAM.opi.build.psram_type=opi + +yb_esp32s3_amp_v3.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +yb_esp32s3_amp_v3.menu.PartitionScheme.default.build.partitions=default +yb_esp32s3_amp_v3.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +yb_esp32s3_amp_v3.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +yb_esp32s3_amp_v3.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +yb_esp32s3_amp_v3.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +yb_esp32s3_amp_v3.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +yb_esp32s3_amp_v3.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +yb_esp32s3_amp_v3.menu.PartitionScheme.minimal.build.partitions=minimal +yb_esp32s3_amp_v3.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +yb_esp32s3_amp_v3.menu.PartitionScheme.no_ota.build.partitions=no_ota +yb_esp32s3_amp_v3.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +yb_esp32s3_amp_v3.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +yb_esp32s3_amp_v3.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +yb_esp32s3_amp_v3.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +yb_esp32s3_amp_v3.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +yb_esp32s3_amp_v3.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +yb_esp32s3_amp_v3.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +yb_esp32s3_amp_v3.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +yb_esp32s3_amp_v3.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +yb_esp32s3_amp_v3.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +yb_esp32s3_amp_v3.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +yb_esp32s3_amp_v3.menu.PartitionScheme.huge_app.build.partitions=huge_app +yb_esp32s3_amp_v3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +yb_esp32s3_amp_v3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +yb_esp32s3_amp_v3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +yb_esp32s3_amp_v3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +yb_esp32s3_amp_v3.menu.PartitionScheme.max_app_8MB=Maximum APP (7.9MB APP No OTA/No FS) +yb_esp32s3_amp_v3.menu.PartitionScheme.max_app_8MB.build.partitions=max_app_8MB +yb_esp32s3_amp_v3.menu.PartitionScheme.max_app_8MB.upload.maximum_size=8257536 + +yb_esp32s3_amp_v3.menu.CPUFreq.240=240MHz (WiFi) +yb_esp32s3_amp_v3.menu.CPUFreq.240.build.f_cpu=240000000L +yb_esp32s3_amp_v3.menu.CPUFreq.160=160MHz (WiFi) +yb_esp32s3_amp_v3.menu.CPUFreq.160.build.f_cpu=160000000L +yb_esp32s3_amp_v3.menu.CPUFreq.80=80MHz (WiFi) +yb_esp32s3_amp_v3.menu.CPUFreq.80.build.f_cpu=80000000L +yb_esp32s3_amp_v3.menu.CPUFreq.40=40MHz +yb_esp32s3_amp_v3.menu.CPUFreq.40.build.f_cpu=40000000L +yb_esp32s3_amp_v3.menu.CPUFreq.20=20MHz +yb_esp32s3_amp_v3.menu.CPUFreq.20.build.f_cpu=20000000L +yb_esp32s3_amp_v3.menu.CPUFreq.10=10MHz +yb_esp32s3_amp_v3.menu.CPUFreq.10.build.f_cpu=10000000L + +yb_esp32s3_amp_v3.menu.FlashMode.qio=QIO 80MHz +yb_esp32s3_amp_v3.menu.FlashMode.qio.build.flash_mode=dio +yb_esp32s3_amp_v3.menu.FlashMode.qio.build.boot=qio +yb_esp32s3_amp_v3.menu.FlashMode.qio.build.boot_freq=80m +yb_esp32s3_amp_v3.menu.FlashMode.qio.build.flash_freq=80m +yb_esp32s3_amp_v3.menu.FlashMode.qio120=QIO 120MHz +yb_esp32s3_amp_v3.menu.FlashMode.qio120.build.flash_mode=dio +yb_esp32s3_amp_v3.menu.FlashMode.qio120.build.boot=qio +yb_esp32s3_amp_v3.menu.FlashMode.qio120.build.boot_freq=120m +yb_esp32s3_amp_v3.menu.FlashMode.qio120.build.flash_freq=80m +yb_esp32s3_amp_v3.menu.FlashMode.dio=DIO 80MHz +yb_esp32s3_amp_v3.menu.FlashMode.dio.build.flash_mode=dio +yb_esp32s3_amp_v3.menu.FlashMode.dio.build.boot=dio +yb_esp32s3_amp_v3.menu.FlashMode.dio.build.boot_freq=80m +yb_esp32s3_amp_v3.menu.FlashMode.dio.build.flash_freq=80m +yb_esp32s3_amp_v3.menu.FlashMode.opi=OPI 80MHz +yb_esp32s3_amp_v3.menu.FlashMode.opi.build.flash_mode=dout +yb_esp32s3_amp_v3.menu.FlashMode.opi.build.boot=opi +yb_esp32s3_amp_v3.menu.FlashMode.opi.build.boot_freq=80m +yb_esp32s3_amp_v3.menu.FlashMode.opi.build.flash_freq=80m + +yb_esp32s3_amp_v3.menu.FlashSize.4M=4MB (32Mb) +yb_esp32s3_amp_v3.menu.FlashSize.4M.build.flash_size=4MB +yb_esp32s3_amp_v3.menu.FlashSize.8M=8MB (64Mb) +yb_esp32s3_amp_v3.menu.FlashSize.8M.build.flash_size=8MB +yb_esp32s3_amp_v3.menu.FlashSize.16M=16MB (128Mb) +yb_esp32s3_amp_v3.menu.FlashSize.16M.build.flash_size=16MB + +yb_esp32s3_amp_v3.menu.UploadSpeed.921600=921600 +yb_esp32s3_amp_v3.menu.UploadSpeed.921600.upload.speed=921600 +yb_esp32s3_amp_v3.menu.UploadSpeed.115200=115200 +yb_esp32s3_amp_v3.menu.UploadSpeed.115200.upload.speed=115200 +yb_esp32s3_amp_v3.menu.UploadSpeed.256000.windows=256000 +yb_esp32s3_amp_v3.menu.UploadSpeed.256000.upload.speed=256000 +yb_esp32s3_amp_v3.menu.UploadSpeed.230400.windows.upload.speed=256000 +yb_esp32s3_amp_v3.menu.UploadSpeed.230400=230400 +yb_esp32s3_amp_v3.menu.UploadSpeed.230400.upload.speed=230400 +yb_esp32s3_amp_v3.menu.UploadSpeed.460800.linux=460800 +yb_esp32s3_amp_v3.menu.UploadSpeed.460800.macosx=460800 +yb_esp32s3_amp_v3.menu.UploadSpeed.460800.upload.speed=460800 +yb_esp32s3_amp_v3.menu.UploadSpeed.512000.windows=512000 +yb_esp32s3_amp_v3.menu.UploadSpeed.512000.upload.speed=512000 + +yb_esp32s3_amp_v3.menu.DebugLevel.none=None +yb_esp32s3_amp_v3.menu.DebugLevel.none.build.code_debug=0 +yb_esp32s3_amp_v3.menu.DebugLevel.error=Error +yb_esp32s3_amp_v3.menu.DebugLevel.error.build.code_debug=1 +yb_esp32s3_amp_v3.menu.DebugLevel.warn=Warn +yb_esp32s3_amp_v3.menu.DebugLevel.warn.build.code_debug=2 +yb_esp32s3_amp_v3.menu.DebugLevel.info=Info +yb_esp32s3_amp_v3.menu.DebugLevel.info.build.code_debug=3 +yb_esp32s3_amp_v3.menu.DebugLevel.debug=Debug +yb_esp32s3_amp_v3.menu.DebugLevel.debug.build.code_debug=4 +yb_esp32s3_amp_v3.menu.DebugLevel.verbose=Verbose +yb_esp32s3_amp_v3.menu.DebugLevel.verbose.build.code_debug=5 + +yb_esp32s3_amp_v3.menu.EraseFlash.none=Disabled +yb_esp32s3_amp_v3.menu.EraseFlash.none.upload.erase_cmd= +yb_esp32s3_amp_v3.menu.EraseFlash.all=Enabled +yb_esp32s3_amp_v3.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +yb_esp32s3_eth.name=YelloByte YB-ESP32-S3-ETH + +yb_esp32s3_eth.bootloader.tool=esptool_py +yb_esp32s3_eth.bootloader.tool.default=esptool_py + +yb_esp32s3_eth.upload.tool=esptool_py +yb_esp32s3_eth.upload.tool.default=esptool_py +yb_esp32s3_eth.upload.tool.network=esp_ota + +yb_esp32s3_eth.upload.maximum_size=1310720 +yb_esp32s3_eth.upload.maximum_data_size=327680 +yb_esp32s3_eth.upload.flags= +yb_esp32s3_eth.upload.extra_flags= +yb_esp32s3_eth.upload.use_1200bps_touch=false +yb_esp32s3_eth.upload.wait_for_upload_port=false + +yb_esp32s3_eth.serial.disableDTR=false +yb_esp32s3_eth.serial.disableRTS=false + +yb_esp32s3_eth.build.tarch=xtensa +yb_esp32s3_eth.build.bootloader_addr=0x0 +yb_esp32s3_eth.build.target=esp32s3 +yb_esp32s3_eth.build.mcu=esp32s3 +yb_esp32s3_eth.build.core=esp32 +yb_esp32s3_eth.build.variant=yb_esp32s3_eth +yb_esp32s3_eth.build.board=YB_ESP32S3_ETH + +yb_esp32s3_eth.build.usb_mode=1 +yb_esp32s3_eth.build.cdc_on_boot=0 +yb_esp32s3_eth.build.msc_on_boot=0 +yb_esp32s3_eth.build.dfu_on_boot=0 +yb_esp32s3_eth.build.f_cpu=240000000L +yb_esp32s3_eth.build.flash_size=4MB +yb_esp32s3_eth.build.flash_freq=80m +yb_esp32s3_eth.build.flash_mode=dio +yb_esp32s3_eth.build.boot=qio +yb_esp32s3_eth.build.boot_freq=80m +yb_esp32s3_eth.build.partitions=default +yb_esp32s3_eth.build.defines= +yb_esp32s3_eth.build.loop_core= +yb_esp32s3_eth.build.event_core= +yb_esp32s3_eth.build.psram_type=qspi +yb_esp32s3_eth.build.memory_type={build.boot}_{build.psram_type} + +yb_esp32s3_eth.menu.JTAGAdapter.default=Disabled +yb_esp32s3_eth.menu.JTAGAdapter.default.build.copy_jtag_files=0 +yb_esp32s3_eth.menu.JTAGAdapter.builtin=Integrated USB JTAG +yb_esp32s3_eth.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +yb_esp32s3_eth.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +yb_esp32s3_eth.menu.JTAGAdapter.external=FTDI Adapter +yb_esp32s3_eth.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +yb_esp32s3_eth.menu.JTAGAdapter.external.build.copy_jtag_files=1 +yb_esp32s3_eth.menu.JTAGAdapter.bridge=ESP USB Bridge +yb_esp32s3_eth.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +yb_esp32s3_eth.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +yb_esp32s3_eth.menu.LoopCore.1=Core 1 +yb_esp32s3_eth.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +yb_esp32s3_eth.menu.LoopCore.0=Core 0 +yb_esp32s3_eth.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +yb_esp32s3_eth.menu.EventsCore.1=Core 1 +yb_esp32s3_eth.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +yb_esp32s3_eth.menu.EventsCore.0=Core 0 +yb_esp32s3_eth.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +yb_esp32s3_eth.menu.USBMode.hwcdc=Hardware CDC and JTAG +yb_esp32s3_eth.menu.USBMode.hwcdc.build.usb_mode=1 +yb_esp32s3_eth.menu.USBMode.default=USB-OTG (TinyUSB) +yb_esp32s3_eth.menu.USBMode.default.build.usb_mode=0 + +yb_esp32s3_eth.menu.CDCOnBoot.default=Disabled +yb_esp32s3_eth.menu.CDCOnBoot.default.build.cdc_on_boot=0 +yb_esp32s3_eth.menu.CDCOnBoot.cdc=Enabled +yb_esp32s3_eth.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +yb_esp32s3_eth.menu.MSCOnBoot.default=Disabled +yb_esp32s3_eth.menu.MSCOnBoot.default.build.msc_on_boot=0 +yb_esp32s3_eth.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +yb_esp32s3_eth.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +yb_esp32s3_eth.menu.DFUOnBoot.default=Disabled +yb_esp32s3_eth.menu.DFUOnBoot.default.build.dfu_on_boot=0 +yb_esp32s3_eth.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +yb_esp32s3_eth.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +yb_esp32s3_eth.menu.UploadMode.default=UART0 / Hardware CDC +yb_esp32s3_eth.menu.UploadMode.default.upload.use_1200bps_touch=false +yb_esp32s3_eth.menu.UploadMode.default.upload.wait_for_upload_port=false +yb_esp32s3_eth.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +yb_esp32s3_eth.menu.UploadMode.cdc.upload.use_1200bps_touch=true +yb_esp32s3_eth.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +yb_esp32s3_eth.menu.PSRAM.disabled=Disabled +yb_esp32s3_eth.menu.PSRAM.disabled.build.defines= +yb_esp32s3_eth.menu.PSRAM.disabled.build.psram_type=qspi +yb_esp32s3_eth.menu.PSRAM.enabled=QSPI PSRAM +yb_esp32s3_eth.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +yb_esp32s3_eth.menu.PSRAM.enabled.build.psram_type=qspi +yb_esp32s3_eth.menu.PSRAM.opi=OPI PSRAM +yb_esp32s3_eth.menu.PSRAM.opi.build.defines=-DBOARD_HAS_PSRAM +yb_esp32s3_eth.menu.PSRAM.opi.build.psram_type=opi + +yb_esp32s3_eth.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.default.build.partitions=default +yb_esp32s3_eth.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +yb_esp32s3_eth.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +yb_esp32s3_eth.menu.PartitionScheme.default_16MB=16M with spiffs (6.25MB APP/3.43MB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.default_16MB.build.partitions=default_16MB +yb_esp32s3_eth.menu.PartitionScheme.default_16MB.upload.maximum_size=6553600 +yb_esp32s3_eth.menu.PartitionScheme.max_app_8MB=Maximum APP (7.9MB APP No OTA/No FS) +yb_esp32s3_eth.menu.PartitionScheme.max_app_8MB.build.partitions=max_app_8MB +yb_esp32s3_eth.menu.PartitionScheme.max_app_8MB.upload.maximum_size=8257536 +yb_esp32s3_eth.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +yb_esp32s3_eth.menu.PartitionScheme.fatflash.build.partitions=ffat +yb_esp32s3_eth.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +yb_esp32s3_eth.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +yb_esp32s3_eth.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +yb_esp32s3_eth.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.minimal.build.partitions=minimal +yb_esp32s3_eth.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.no_ota.build.partitions=no_ota +yb_esp32s3_eth.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +yb_esp32s3_eth.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +yb_esp32s3_eth.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +yb_esp32s3_eth.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +yb_esp32s3_eth.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +yb_esp32s3_eth.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +yb_esp32s3_eth.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +yb_esp32s3_eth.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +yb_esp32s3_eth.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +yb_esp32s3_eth.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.huge_app.build.partitions=huge_app +yb_esp32s3_eth.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +yb_esp32s3_eth.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +yb_esp32s3_eth.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +yb_esp32s3_eth.menu.PartitionScheme.custom=Custom +yb_esp32s3_eth.menu.PartitionScheme.custom.build.partitions= +yb_esp32s3_eth.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +yb_esp32s3_eth.menu.CPUFreq.240=240MHz (WiFi) +yb_esp32s3_eth.menu.CPUFreq.240.build.f_cpu=240000000L +yb_esp32s3_eth.menu.CPUFreq.160=160MHz (WiFi) +yb_esp32s3_eth.menu.CPUFreq.160.build.f_cpu=160000000L +yb_esp32s3_eth.menu.CPUFreq.80=80MHz (WiFi) +yb_esp32s3_eth.menu.CPUFreq.80.build.f_cpu=80000000L +yb_esp32s3_eth.menu.CPUFreq.40=40MHz +yb_esp32s3_eth.menu.CPUFreq.40.build.f_cpu=40000000L +yb_esp32s3_eth.menu.CPUFreq.20=20MHz +yb_esp32s3_eth.menu.CPUFreq.20.build.f_cpu=20000000L +yb_esp32s3_eth.menu.CPUFreq.10=10MHz +yb_esp32s3_eth.menu.CPUFreq.10.build.f_cpu=10000000L + +yb_esp32s3_eth.menu.FlashMode.qio=QIO 80MHz +yb_esp32s3_eth.menu.FlashMode.qio.build.flash_mode=dio +yb_esp32s3_eth.menu.FlashMode.qio.build.boot=qio +yb_esp32s3_eth.menu.FlashMode.qio.build.boot_freq=80m +yb_esp32s3_eth.menu.FlashMode.qio.build.flash_freq=80m +yb_esp32s3_eth.menu.FlashMode.qio120=QIO 120MHz +yb_esp32s3_eth.menu.FlashMode.qio120.build.flash_mode=dio +yb_esp32s3_eth.menu.FlashMode.qio120.build.boot=qio +yb_esp32s3_eth.menu.FlashMode.qio120.build.boot_freq=120m +yb_esp32s3_eth.menu.FlashMode.qio120.build.flash_freq=80m +yb_esp32s3_eth.menu.FlashMode.dio=DIO 80MHz +yb_esp32s3_eth.menu.FlashMode.dio.build.flash_mode=dio +yb_esp32s3_eth.menu.FlashMode.dio.build.boot=dio +yb_esp32s3_eth.menu.FlashMode.dio.build.boot_freq=80m +yb_esp32s3_eth.menu.FlashMode.dio.build.flash_freq=80m +yb_esp32s3_eth.menu.FlashMode.opi=OPI 80MHz +yb_esp32s3_eth.menu.FlashMode.opi.build.flash_mode=dout +yb_esp32s3_eth.menu.FlashMode.opi.build.boot=opi +yb_esp32s3_eth.menu.FlashMode.opi.build.boot_freq=80m +yb_esp32s3_eth.menu.FlashMode.opi.build.flash_freq=80m + +yb_esp32s3_eth.menu.FlashSize.4M=4MB (32Mb) +yb_esp32s3_eth.menu.FlashSize.4M.build.flash_size=4MB +yb_esp32s3_eth.menu.FlashSize.8M=8MB (64Mb) +yb_esp32s3_eth.menu.FlashSize.8M.build.flash_size=8MB +yb_esp32s3_eth.menu.FlashSize.16M=16MB (128Mb) +yb_esp32s3_eth.menu.FlashSize.16M.build.flash_size=16MB + +yb_esp32s3_eth.menu.UploadSpeed.921600=921600 +yb_esp32s3_eth.menu.UploadSpeed.921600.upload.speed=921600 +yb_esp32s3_eth.menu.UploadSpeed.115200=115200 +yb_esp32s3_eth.menu.UploadSpeed.115200.upload.speed=115200 +yb_esp32s3_eth.menu.UploadSpeed.256000.windows=256000 +yb_esp32s3_eth.menu.UploadSpeed.256000.upload.speed=256000 +yb_esp32s3_eth.menu.UploadSpeed.230400.windows.upload.speed=256000 +yb_esp32s3_eth.menu.UploadSpeed.230400=230400 +yb_esp32s3_eth.menu.UploadSpeed.230400.upload.speed=230400 +yb_esp32s3_eth.menu.UploadSpeed.460800.linux=460800 +yb_esp32s3_eth.menu.UploadSpeed.460800.macosx=460800 +yb_esp32s3_eth.menu.UploadSpeed.460800.upload.speed=460800 +yb_esp32s3_eth.menu.UploadSpeed.512000.windows=512000 +yb_esp32s3_eth.menu.UploadSpeed.512000.upload.speed=512000 + +yb_esp32s3_eth.menu.DebugLevel.none=None +yb_esp32s3_eth.menu.DebugLevel.none.build.code_debug=0 +yb_esp32s3_eth.menu.DebugLevel.error=Error +yb_esp32s3_eth.menu.DebugLevel.error.build.code_debug=1 +yb_esp32s3_eth.menu.DebugLevel.warn=Warn +yb_esp32s3_eth.menu.DebugLevel.warn.build.code_debug=2 +yb_esp32s3_eth.menu.DebugLevel.info=Info +yb_esp32s3_eth.menu.DebugLevel.info.build.code_debug=3 +yb_esp32s3_eth.menu.DebugLevel.debug=Debug +yb_esp32s3_eth.menu.DebugLevel.debug.build.code_debug=4 +yb_esp32s3_eth.menu.DebugLevel.verbose=Verbose +yb_esp32s3_eth.menu.DebugLevel.verbose.build.code_debug=5 + +yb_esp32s3_eth.menu.EraseFlash.none=Disabled +yb_esp32s3_eth.menu.EraseFlash.none.upload.erase_cmd= +yb_esp32s3_eth.menu.EraseFlash.all=Enabled +yb_esp32s3_eth.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## +# Huidu HD-WF2 - esp32-s3 HUB75 driver board +# https://www.hdwell.com/Product/index46.html + +huidu_hd_wf2.name=Huidu HD-WF2 + +huidu_hd_wf2.bootloader.tool=esptool_py +huidu_hd_wf2.bootloader.tool.default=esptool_py + +huidu_hd_wf2.upload.tool=esptool_py +huidu_hd_wf2.upload.tool.default=esptool_py +huidu_hd_wf2.upload.tool.network=esp_ota + +huidu_hd_wf2.upload.maximum_size=1310720 +huidu_hd_wf2.upload.maximum_data_size=327680 +huidu_hd_wf2.upload.flags= +huidu_hd_wf2.upload.extra_flags= +huidu_hd_wf2.upload.use_1200bps_touch=true +huidu_hd_wf2.upload.wait_for_upload_port=true + +huidu_hd_wf2.serial.disableDTR=false +huidu_hd_wf2.serial.disableRTS=false + +huidu_hd_wf2.build.tarch=xtensa +huidu_hd_wf2.build.bootloader_addr=0x0 +huidu_hd_wf2.build.target=esp32s3 +huidu_hd_wf2.build.mcu=esp32s3 +huidu_hd_wf2.build.core=esp32 +huidu_hd_wf2.build.variant=huidu_hd_wf2 +huidu_hd_wf2.build.board=HUIDU_HD_WF2 + +huidu_hd_wf2.build.usb_mode=0 +huidu_hd_wf2.build.cdc_on_boot=1 +huidu_hd_wf2.build.msc_on_boot=0 +huidu_hd_wf2.build.dfu_on_boot=0 +huidu_hd_wf2.build.f_cpu=240000000L +huidu_hd_wf2.build.flash_size=8MB +huidu_hd_wf2.build.flash_freq=80m +huidu_hd_wf2.build.flash_mode=qio +huidu_hd_wf2.build.boot=qio +huidu_hd_wf2.build.partitions=default +huidu_hd_wf2.build.defines= +huidu_hd_wf2.build.loop_core= +huidu_hd_wf2.build.event_core= +huidu_hd_wf2.build.flash_type=qio +huidu_hd_wf2.build.psram_type=qspi +huidu_hd_wf2.build.memory_type={build.flash_type}_{build.psram_type} + +huidu_hd_wf2.menu.FlashSize.8M=8MB (64Mb) +huidu_hd_wf2.menu.FlashSize.8M.build.flash_size=8MB + +huidu_hd_wf2.menu.LoopCore.1=Core 1 +huidu_hd_wf2.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +huidu_hd_wf2.menu.LoopCore.0=Core 0 +huidu_hd_wf2.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +huidu_hd_wf2.menu.EventsCore.1=Core 1 +huidu_hd_wf2.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +huidu_hd_wf2.menu.EventsCore.0=Core 0 +huidu_hd_wf2.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +huidu_hd_wf2.menu.USBMode.hwcdc=Hardware CDC and JTAG +huidu_hd_wf2.menu.USBMode.hwcdc.build.usb_mode=1 +huidu_hd_wf2.menu.USBMode.default=USB-OTG (TinyUSB) +huidu_hd_wf2.menu.USBMode.default.build.usb_mode=0 + +huidu_hd_wf2.menu.CDCOnBoot.default=Enabled +huidu_hd_wf2.menu.CDCOnBoot.default.build.cdc_on_boot=1 +huidu_hd_wf2.menu.CDCOnBoot.cdc=Disabled +huidu_hd_wf2.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +huidu_hd_wf2.menu.MSCOnBoot.default=Disabled +huidu_hd_wf2.menu.MSCOnBoot.default.build.msc_on_boot=0 +huidu_hd_wf2.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +huidu_hd_wf2.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +huidu_hd_wf2.menu.DFUOnBoot.default=Disabled +huidu_hd_wf2.menu.DFUOnBoot.default.build.dfu_on_boot=0 +huidu_hd_wf2.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +huidu_hd_wf2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +huidu_hd_wf2.menu.UploadMode.default=UART0 / Hardware CDC +huidu_hd_wf2.menu.UploadMode.default.upload.use_1200bps_touch=false +huidu_hd_wf2.menu.UploadMode.default.upload.wait_for_upload_port=false +huidu_hd_wf2.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +huidu_hd_wf2.menu.UploadMode.cdc.upload.use_1200bps_touch=true +huidu_hd_wf2.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +huidu_hd_wf2.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +huidu_hd_wf2.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +huidu_hd_wf2.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +huidu_hd_wf2.menu.PartitionScheme.large_spiffs_8MB=Large SPIFFS (1.3MB APP/5.5MiB SPIFFS) +huidu_hd_wf2.menu.PartitionScheme.large_spiffs_8MB.build.partitions=large_spiffs_8MB +huidu_hd_wf2.menu.PartitionScheme.large_spiffs_8MB.upload.maximum_size=1310720 +huidu_hd_wf2.menu.PartitionScheme.default_ffat_8MB=8MiB fatfs (3MB APP/1.5MB FATFS) +huidu_hd_wf2.menu.PartitionScheme.default_ffat_8MB.build.partitions=default_ffat_8MB +huidu_hd_wf2.menu.PartitionScheme.default_ffat_8MB.upload.maximum_size=3342336 + +huidu_hd_wf2.menu.CPUFreq.240=240MHz (WiFi) +huidu_hd_wf2.menu.CPUFreq.240.build.f_cpu=240000000L +huidu_hd_wf2.menu.CPUFreq.160=160MHz (WiFi) +huidu_hd_wf2.menu.CPUFreq.160.build.f_cpu=160000000L +huidu_hd_wf2.menu.CPUFreq.80=80MHz (WiFi) +huidu_hd_wf2.menu.CPUFreq.80.build.f_cpu=80000000L +huidu_hd_wf2.menu.CPUFreq.40=40MHz +huidu_hd_wf2.menu.CPUFreq.40.build.f_cpu=40000000L + +huidu_hd_wf2.menu.FlashMode.dio=DIO 80MHz +huidu_hd_wf2.menu.FlashMode.dio.build.flash_mode=dio +huidu_hd_wf2.menu.FlashMode.dio.build.boot=dio +huidu_hd_wf2.menu.FlashMode.dio.build.boot_freq=80m +huidu_hd_wf2.menu.FlashMode.dio.build.flash_freq=80m + +huidu_hd_wf2.menu.UploadSpeed.921600=921600 +huidu_hd_wf2.menu.UploadSpeed.921600.upload.speed=921600 +huidu_hd_wf2.menu.UploadSpeed.115200=115200 +huidu_hd_wf2.menu.UploadSpeed.115200.upload.speed=115200 +huidu_hd_wf2.menu.UploadSpeed.460800.linux=460800 +huidu_hd_wf2.menu.UploadSpeed.460800.macosx=460800 +huidu_hd_wf2.menu.UploadSpeed.460800.upload.speed=460800 + +huidu_hd_wf2.menu.DebugLevel.none=None +huidu_hd_wf2.menu.DebugLevel.none.build.code_debug=0 +huidu_hd_wf2.menu.DebugLevel.error=Error +huidu_hd_wf2.menu.DebugLevel.error.build.code_debug=1 +huidu_hd_wf2.menu.DebugLevel.warn=Warn +huidu_hd_wf2.menu.DebugLevel.warn.build.code_debug=2 +huidu_hd_wf2.menu.DebugLevel.info=Info +huidu_hd_wf2.menu.DebugLevel.info.build.code_debug=3 +huidu_hd_wf2.menu.DebugLevel.debug=Debug +huidu_hd_wf2.menu.DebugLevel.debug.build.code_debug=4 +huidu_hd_wf2.menu.DebugLevel.verbose=Verbose +huidu_hd_wf2.menu.DebugLevel.verbose.build.code_debug=5 + +huidu_hd_wf2.menu.EraseFlash.none=Disabled +huidu_hd_wf2.menu.EraseFlash.none.upload.erase_cmd= +huidu_hd_wf2.menu.EraseFlash.all=Enabled +huidu_hd_wf2.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## +# Huidu HD-WF4 - esp32-s3 HUB75 driver board +# https://www.hdwell.com/Product/index46.html + +huidu_hd_wf4.name=Huidu HD-WF4 + +huidu_hd_wf4.bootloader.tool=esptool_py +huidu_hd_wf4.bootloader.tool.default=esptool_py + +huidu_hd_wf4.upload.tool=esptool_py +huidu_hd_wf4.upload.tool.default=esptool_py +huidu_hd_wf4.upload.tool.network=esp_ota + +huidu_hd_wf4.upload.maximum_size=1310720 +huidu_hd_wf4.upload.maximum_data_size=327680 +huidu_hd_wf4.upload.flags= +huidu_hd_wf4.upload.extra_flags= +huidu_hd_wf4.upload.use_1200bps_touch=true +huidu_hd_wf4.upload.wait_for_upload_port=true + +huidu_hd_wf4.serial.disableDTR=false +huidu_hd_wf4.serial.disableRTS=false + +huidu_hd_wf4.build.tarch=xtensa +huidu_hd_wf4.build.bootloader_addr=0x0 +huidu_hd_wf4.build.target=esp32s3 +huidu_hd_wf4.build.mcu=esp32s3 +huidu_hd_wf4.build.core=esp32 +huidu_hd_wf4.build.variant=huidu_hd_wf4 +huidu_hd_wf4.build.board=HUIDU_HD_WF4 + +huidu_hd_wf4.build.usb_mode=0 +huidu_hd_wf4.build.cdc_on_boot=1 +huidu_hd_wf4.build.msc_on_boot=0 +huidu_hd_wf4.build.dfu_on_boot=0 +huidu_hd_wf4.build.f_cpu=240000000L +huidu_hd_wf4.build.flash_size=8MB +huidu_hd_wf4.build.flash_freq=80m +huidu_hd_wf4.build.flash_mode=qio +huidu_hd_wf4.build.boot=qio +huidu_hd_wf4.build.partitions=default +huidu_hd_wf4.build.defines= +huidu_hd_wf4.build.loop_core= +huidu_hd_wf4.build.event_core= +huidu_hd_wf4.build.flash_type=qio +huidu_hd_wf4.build.psram_type=qspi +huidu_hd_wf4.build.memory_type={build.flash_type}_{build.psram_type} + +huidu_hd_wf4.menu.FlashSize.8M=8MB (64Mb) +huidu_hd_wf4.menu.FlashSize.8M.build.flash_size=8MB + +huidu_hd_wf4.menu.LoopCore.1=Core 1 +huidu_hd_wf4.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +huidu_hd_wf4.menu.LoopCore.0=Core 0 +huidu_hd_wf4.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +huidu_hd_wf4.menu.EventsCore.1=Core 1 +huidu_hd_wf4.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +huidu_hd_wf4.menu.EventsCore.0=Core 0 +huidu_hd_wf4.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +huidu_hd_wf4.menu.USBMode.hwcdc=Hardware CDC and JTAG +huidu_hd_wf4.menu.USBMode.hwcdc.build.usb_mode=1 +huidu_hd_wf4.menu.USBMode.default=USB-OTG (TinyUSB) +huidu_hd_wf4.menu.USBMode.default.build.usb_mode=0 + +huidu_hd_wf4.menu.CDCOnBoot.default=Enabled +huidu_hd_wf4.menu.CDCOnBoot.default.build.cdc_on_boot=1 +huidu_hd_wf4.menu.CDCOnBoot.cdc=Disabled +huidu_hd_wf4.menu.CDCOnBoot.cdc.build.cdc_on_boot=0 + +huidu_hd_wf4.menu.MSCOnBoot.default=Disabled +huidu_hd_wf4.menu.MSCOnBoot.default.build.msc_on_boot=0 +huidu_hd_wf4.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +huidu_hd_wf4.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +huidu_hd_wf4.menu.DFUOnBoot.default=Disabled +huidu_hd_wf4.menu.DFUOnBoot.default.build.dfu_on_boot=0 +huidu_hd_wf4.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +huidu_hd_wf4.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +huidu_hd_wf4.menu.UploadMode.default=UART0 / Hardware CDC +huidu_hd_wf4.menu.UploadMode.default.upload.use_1200bps_touch=false +huidu_hd_wf4.menu.UploadMode.default.upload.wait_for_upload_port=false +huidu_hd_wf4.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +huidu_hd_wf4.menu.UploadMode.cdc.upload.use_1200bps_touch=true +huidu_hd_wf4.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +huidu_hd_wf4.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +huidu_hd_wf4.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +huidu_hd_wf4.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +huidu_hd_wf4.menu.PartitionScheme.large_spiffs_8MB=Large SPIFFS (1.3MB APP/5.5MiB SPIFFS) +huidu_hd_wf4.menu.PartitionScheme.large_spiffs_8MB.build.partitions=large_spiffs_8MB +huidu_hd_wf4.menu.PartitionScheme.large_spiffs_8MB.upload.maximum_size=1310720 +huidu_hd_wf4.menu.PartitionScheme.default_ffat_8MB=8MiB fatfs (3MB APP/1.5MB FATFS) +huidu_hd_wf4.menu.PartitionScheme.default_ffat_8MB.build.partitions=default_ffat_8MB +huidu_hd_wf4.menu.PartitionScheme.default_ffat_8MB.upload.maximum_size=3342336 + +huidu_hd_wf4.menu.CPUFreq.240=240MHz (WiFi) +huidu_hd_wf4.menu.CPUFreq.240.build.f_cpu=240000000L +huidu_hd_wf4.menu.CPUFreq.160=160MHz (WiFi) +huidu_hd_wf4.menu.CPUFreq.160.build.f_cpu=160000000L +huidu_hd_wf4.menu.CPUFreq.80=80MHz (WiFi) +huidu_hd_wf4.menu.CPUFreq.80.build.f_cpu=80000000L +huidu_hd_wf4.menu.CPUFreq.40=40MHz +huidu_hd_wf4.menu.CPUFreq.40.build.f_cpu=40000000L + +huidu_hd_wf4.menu.FlashMode.dio=DIO 80MHz +huidu_hd_wf4.menu.FlashMode.dio.build.flash_mode=dio +huidu_hd_wf4.menu.FlashMode.dio.build.boot=dio +huidu_hd_wf4.menu.FlashMode.dio.build.boot_freq=80m +huidu_hd_wf4.menu.FlashMode.dio.build.flash_freq=80m + +huidu_hd_wf4.menu.UploadSpeed.921600=921600 +huidu_hd_wf4.menu.UploadSpeed.921600.upload.speed=921600 +huidu_hd_wf4.menu.UploadSpeed.115200=115200 +huidu_hd_wf4.menu.UploadSpeed.115200.upload.speed=115200 +huidu_hd_wf4.menu.UploadSpeed.460800.linux=460800 +huidu_hd_wf4.menu.UploadSpeed.460800.macosx=460800 +huidu_hd_wf4.menu.UploadSpeed.460800.upload.speed=460800 + +huidu_hd_wf4.menu.DebugLevel.none=None +huidu_hd_wf4.menu.DebugLevel.none.build.code_debug=0 +huidu_hd_wf4.menu.DebugLevel.error=Error +huidu_hd_wf4.menu.DebugLevel.error.build.code_debug=1 +huidu_hd_wf4.menu.DebugLevel.warn=Warn +huidu_hd_wf4.menu.DebugLevel.warn.build.code_debug=2 +huidu_hd_wf4.menu.DebugLevel.info=Info +huidu_hd_wf4.menu.DebugLevel.info.build.code_debug=3 +huidu_hd_wf4.menu.DebugLevel.debug=Debug +huidu_hd_wf4.menu.DebugLevel.debug.build.code_debug=4 +huidu_hd_wf4.menu.DebugLevel.verbose=Verbose +huidu_hd_wf4.menu.DebugLevel.verbose.build.code_debug=5 + +huidu_hd_wf4.menu.EraseFlash.none=Disabled +huidu_hd_wf4.menu.EraseFlash.none.upload.erase_cmd= +huidu_hd_wf4.menu.EraseFlash.all=Enabled +huidu_hd_wf4.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## + +# CYOBot (CYOBrain V2 ESP32S3) Board +cyobot_v2_esp32s3.name=CYOBOT V2 ESP32S3 + +cyobot_v2_esp32s3.bootloader.tool=esptool_py +cyobot_v2_esp32s3.bootloader.tool.default=esptool_py + +cyobot_v2_esp32s3.upload.tool=esptool_py +cyobot_v2_esp32s3.upload.tool.default=esptool_py +cyobot_v2_esp32s3.upload.tool.network=esp_ota + +cyobot_v2_esp32s3.upload.maximum_size=1310720 +cyobot_v2_esp32s3.upload.maximum_data_size=327680 +cyobot_v2_esp32s3.upload.flags= +cyobot_v2_esp32s3.upload.extra_flags= +cyobot_v2_esp32s3.upload.use_1200bps_touch=false +cyobot_v2_esp32s3.upload.wait_for_upload_port=false + +cyobot_v2_esp32s3.serial.disableDTR=false +cyobot_v2_esp32s3.serial.disableRTS=false + +cyobot_v2_esp32s3.build.tarch=xtensa +cyobot_v2_esp32s3.build.bootloader_addr=0x0 +cyobot_v2_esp32s3.build.target=esp32s3 +cyobot_v2_esp32s3.build.mcu=esp32s3 +cyobot_v2_esp32s3.build.core=esp32 +cyobot_v2_esp32s3.build.variant=cyobot_v2_esp32s3 +cyobot_v2_esp32s3.build.board=CYOBOT_V2_ESP32S3 + +cyobot_v2_esp32s3.build.usb_mode=1 +cyobot_v2_esp32s3.build.cdc_on_boot=0 +cyobot_v2_esp32s3.build.msc_on_boot=0 +cyobot_v2_esp32s3.build.dfu_on_boot=0 +cyobot_v2_esp32s3.build.f_cpu=240000000L +cyobot_v2_esp32s3.build.flash_size=4MB +cyobot_v2_esp32s3.build.flash_freq=80m +cyobot_v2_esp32s3.build.flash_mode=dio +cyobot_v2_esp32s3.build.boot=qio +cyobot_v2_esp32s3.build.boot_freq=80m +cyobot_v2_esp32s3.build.partitions=default +cyobot_v2_esp32s3.build.defines= +cyobot_v2_esp32s3.build.loop_core= +cyobot_v2_esp32s3.build.event_core= +cyobot_v2_esp32s3.build.psram_type=qspi +cyobot_v2_esp32s3.build.memory_type={build.boot}_{build.psram_type} + +## IDE 2.0 Seems to not update the value +cyobot_v2_esp32s3.menu.JTAGAdapter.default=Disabled +cyobot_v2_esp32s3.menu.JTAGAdapter.default.build.copy_jtag_files=0 +cyobot_v2_esp32s3.menu.JTAGAdapter.builtin=Integrated USB JTAG +cyobot_v2_esp32s3.menu.JTAGAdapter.builtin.build.openocdscript=cyobot_v2_esp32s3-builtin.cfg +cyobot_v2_esp32s3.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +cyobot_v2_esp32s3.menu.JTAGAdapter.external=FTDI Adapter +cyobot_v2_esp32s3.menu.JTAGAdapter.external.build.openocdscript=cyobot_v2_esp32s3-ftdi.cfg +cyobot_v2_esp32s3.menu.JTAGAdapter.external.build.copy_jtag_files=1 +cyobot_v2_esp32s3.menu.JTAGAdapter.bridge=ESP USB Bridge +cyobot_v2_esp32s3.menu.JTAGAdapter.bridge.build.openocdscript=cyobot_v2_esp32s3-bridge.cfg +cyobot_v2_esp32s3.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +cyobot_v2_esp32s3.menu.PSRAM.disabled=Disabled +cyobot_v2_esp32s3.menu.PSRAM.disabled.build.defines= +cyobot_v2_esp32s3.menu.PSRAM.disabled.build.psram_type=qspi +cyobot_v2_esp32s3.menu.PSRAM.enabled=QSPI PSRAM +cyobot_v2_esp32s3.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +cyobot_v2_esp32s3.menu.PSRAM.enabled.build.psram_type=qspi +cyobot_v2_esp32s3.menu.PSRAM.opi=OPI PSRAM +cyobot_v2_esp32s3.menu.PSRAM.opi.build.defines=-DBOARD_HAS_PSRAM +cyobot_v2_esp32s3.menu.PSRAM.opi.build.psram_type=opi + +cyobot_v2_esp32s3.menu.FlashMode.qio=QIO 80MHz +cyobot_v2_esp32s3.menu.FlashMode.qio.build.flash_mode=dio +cyobot_v2_esp32s3.menu.FlashMode.qio.build.boot=qio +cyobot_v2_esp32s3.menu.FlashMode.qio.build.boot_freq=80m +cyobot_v2_esp32s3.menu.FlashMode.qio.build.flash_freq=80m +cyobot_v2_esp32s3.menu.FlashMode.qio120=QIO 120MHz +cyobot_v2_esp32s3.menu.FlashMode.qio120.build.flash_mode=dio +cyobot_v2_esp32s3.menu.FlashMode.qio120.build.boot=qio +cyobot_v2_esp32s3.menu.FlashMode.qio120.build.boot_freq=120m +cyobot_v2_esp32s3.menu.FlashMode.qio120.build.flash_freq=80m +cyobot_v2_esp32s3.menu.FlashMode.dio=DIO 80MHz +cyobot_v2_esp32s3.menu.FlashMode.dio.build.flash_mode=dio +cyobot_v2_esp32s3.menu.FlashMode.dio.build.boot=dio +cyobot_v2_esp32s3.menu.FlashMode.dio.build.boot_freq=80m +cyobot_v2_esp32s3.menu.FlashMode.dio.build.flash_freq=80m +cyobot_v2_esp32s3.menu.FlashMode.opi=OPI 80MHz +cyobot_v2_esp32s3.menu.FlashMode.opi.build.flash_mode=dout +cyobot_v2_esp32s3.menu.FlashMode.opi.build.boot=opi +cyobot_v2_esp32s3.menu.FlashMode.opi.build.boot_freq=80m +cyobot_v2_esp32s3.menu.FlashMode.opi.build.flash_freq=80m + +cyobot_v2_esp32s3.menu.FlashSize.4M=4MB (32Mb) +cyobot_v2_esp32s3.menu.FlashSize.4M.build.flash_size=4MB +cyobot_v2_esp32s3.menu.FlashSize.8M=8MB (64Mb) +cyobot_v2_esp32s3.menu.FlashSize.8M.build.flash_size=8MB +cyobot_v2_esp32s3.menu.FlashSize.16M=16MB (128Mb) +cyobot_v2_esp32s3.menu.FlashSize.16M.build.flash_size=16MB +cyobot_v2_esp32s3.menu.FlashSize.32M=32MB (256Mb) +cyobot_v2_esp32s3.menu.FlashSize.32M.build.flash_size=32MB + +cyobot_v2_esp32s3.menu.LoopCore.1=Core 1 +cyobot_v2_esp32s3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +cyobot_v2_esp32s3.menu.LoopCore.0=Core 0 +cyobot_v2_esp32s3.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +cyobot_v2_esp32s3.menu.EventsCore.1=Core 1 +cyobot_v2_esp32s3.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +cyobot_v2_esp32s3.menu.EventsCore.0=Core 0 +cyobot_v2_esp32s3.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +cyobot_v2_esp32s3.menu.USBMode.hwcdc=Hardware CDC and JTAG +cyobot_v2_esp32s3.menu.USBMode.hwcdc.build.usb_mode=1 +cyobot_v2_esp32s3.menu.USBMode.default=USB-OTG (TinyUSB) +cyobot_v2_esp32s3.menu.USBMode.default.build.usb_mode=0 + +cyobot_v2_esp32s3.menu.CDCOnBoot.default=Disabled +cyobot_v2_esp32s3.menu.CDCOnBoot.default.build.cdc_on_boot=0 +cyobot_v2_esp32s3.menu.CDCOnBoot.cdc=Enabled +cyobot_v2_esp32s3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +cyobot_v2_esp32s3.menu.MSCOnBoot.default=Disabled +cyobot_v2_esp32s3.menu.MSCOnBoot.default.build.msc_on_boot=0 +cyobot_v2_esp32s3.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +cyobot_v2_esp32s3.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +cyobot_v2_esp32s3.menu.DFUOnBoot.default=Disabled +cyobot_v2_esp32s3.menu.DFUOnBoot.default.build.dfu_on_boot=0 +cyobot_v2_esp32s3.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +cyobot_v2_esp32s3.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +cyobot_v2_esp32s3.menu.UploadMode.default=UART0 / Hardware CDC +cyobot_v2_esp32s3.menu.UploadMode.default.upload.use_1200bps_touch=false +cyobot_v2_esp32s3.menu.UploadMode.default.upload.wait_for_upload_port=false +cyobot_v2_esp32s3.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +cyobot_v2_esp32s3.menu.UploadMode.cdc.upload.use_1200bps_touch=true +cyobot_v2_esp32s3.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +cyobot_v2_esp32s3.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +cyobot_v2_esp32s3.menu.PartitionScheme.default.build.partitions=default +cyobot_v2_esp32s3.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +cyobot_v2_esp32s3.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +cyobot_v2_esp32s3.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +cyobot_v2_esp32s3.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +cyobot_v2_esp32s3.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +cyobot_v2_esp32s3.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +cyobot_v2_esp32s3.menu.PartitionScheme.minimal.build.partitions=minimal +cyobot_v2_esp32s3.menu.PartitionScheme.no_fs=No FS 4MB (2MB APP x2) +cyobot_v2_esp32s3.menu.PartitionScheme.no_fs.build.partitions=no_fs +cyobot_v2_esp32s3.menu.PartitionScheme.no_fs.upload.maximum_size=2031616 +cyobot_v2_esp32s3.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +cyobot_v2_esp32s3.menu.PartitionScheme.no_ota.build.partitions=no_ota +cyobot_v2_esp32s3.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +cyobot_v2_esp32s3.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +cyobot_v2_esp32s3.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +cyobot_v2_esp32s3.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +cyobot_v2_esp32s3.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +cyobot_v2_esp32s3.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +cyobot_v2_esp32s3.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +cyobot_v2_esp32s3.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +cyobot_v2_esp32s3.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +cyobot_v2_esp32s3.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +cyobot_v2_esp32s3.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +cyobot_v2_esp32s3.menu.PartitionScheme.huge_app.build.partitions=huge_app +cyobot_v2_esp32s3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +cyobot_v2_esp32s3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +cyobot_v2_esp32s3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +cyobot_v2_esp32s3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +cyobot_v2_esp32s3.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +cyobot_v2_esp32s3.menu.PartitionScheme.fatflash.build.partitions=ffat +cyobot_v2_esp32s3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +cyobot_v2_esp32s3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +cyobot_v2_esp32s3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +cyobot_v2_esp32s3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 +cyobot_v2_esp32s3.menu.PartitionScheme.rainmaker=RainMaker 4MB +cyobot_v2_esp32s3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +cyobot_v2_esp32s3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +cyobot_v2_esp32s3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +cyobot_v2_esp32s3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +cyobot_v2_esp32s3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +cyobot_v2_esp32s3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB +cyobot_v2_esp32s3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB +cyobot_v2_esp32s3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480 +cyobot_v2_esp32s3.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) +cyobot_v2_esp32s3.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB +cyobot_v2_esp32s3.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 +cyobot_v2_esp32s3.menu.PartitionScheme.app5M_little24M_32MB=32M Flash (4.8MB APP/22MB LittleFS) +cyobot_v2_esp32s3.menu.PartitionScheme.app5M_little24M_32MB.build.partitions=large_littlefs_32MB +cyobot_v2_esp32s3.menu.PartitionScheme.app5M_little24M_32MB.upload.maximum_size=4718592 +cyobot_v2_esp32s3.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) +cyobot_v2_esp32s3.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 +cyobot_v2_esp32s3.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin +cyobot_v2_esp32s3.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 +cyobot_v2_esp32s3.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +cyobot_v2_esp32s3.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +cyobot_v2_esp32s3.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +cyobot_v2_esp32s3.menu.PartitionScheme.custom=Custom +cyobot_v2_esp32s3.menu.PartitionScheme.custom.build.partitions= +cyobot_v2_esp32s3.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +cyobot_v2_esp32s3.menu.CPUFreq.240=240MHz (WiFi) +cyobot_v2_esp32s3.menu.CPUFreq.240.build.f_cpu=240000000L +cyobot_v2_esp32s3.menu.CPUFreq.160=160MHz (WiFi) +cyobot_v2_esp32s3.menu.CPUFreq.160.build.f_cpu=160000000L +cyobot_v2_esp32s3.menu.CPUFreq.80=80MHz (WiFi) +cyobot_v2_esp32s3.menu.CPUFreq.80.build.f_cpu=80000000L +cyobot_v2_esp32s3.menu.CPUFreq.40=40MHz +cyobot_v2_esp32s3.menu.CPUFreq.40.build.f_cpu=40000000L +cyobot_v2_esp32s3.menu.CPUFreq.20=20MHz +cyobot_v2_esp32s3.menu.CPUFreq.20.build.f_cpu=20000000L +cyobot_v2_esp32s3.menu.CPUFreq.10=10MHz +cyobot_v2_esp32s3.menu.CPUFreq.10.build.f_cpu=10000000L + +cyobot_v2_esp32s3.menu.UploadSpeed.921600=921600 +cyobot_v2_esp32s3.menu.UploadSpeed.921600.upload.speed=921600 +cyobot_v2_esp32s3.menu.UploadSpeed.115200=115200 +cyobot_v2_esp32s3.menu.UploadSpeed.115200.upload.speed=115200 +cyobot_v2_esp32s3.menu.UploadSpeed.256000.windows=256000 +cyobot_v2_esp32s3.menu.UploadSpeed.256000.upload.speed=256000 +cyobot_v2_esp32s3.menu.UploadSpeed.230400.windows.upload.speed=256000 +cyobot_v2_esp32s3.menu.UploadSpeed.230400=230400 +cyobot_v2_esp32s3.menu.UploadSpeed.230400.upload.speed=230400 +cyobot_v2_esp32s3.menu.UploadSpeed.460800.linux=460800 +cyobot_v2_esp32s3.menu.UploadSpeed.460800.macosx=460800 +cyobot_v2_esp32s3.menu.UploadSpeed.460800.upload.speed=460800 +cyobot_v2_esp32s3.menu.UploadSpeed.512000.windows=512000 +cyobot_v2_esp32s3.menu.UploadSpeed.512000.upload.speed=512000 + +cyobot_v2_esp32s3.menu.DebugLevel.none=None +cyobot_v2_esp32s3.menu.DebugLevel.none.build.code_debug=0 +cyobot_v2_esp32s3.menu.DebugLevel.error=Error +cyobot_v2_esp32s3.menu.DebugLevel.error.build.code_debug=1 +cyobot_v2_esp32s3.menu.DebugLevel.warn=Warn +cyobot_v2_esp32s3.menu.DebugLevel.warn.build.code_debug=2 +cyobot_v2_esp32s3.menu.DebugLevel.info=Info +cyobot_v2_esp32s3.menu.DebugLevel.info.build.code_debug=3 +cyobot_v2_esp32s3.menu.DebugLevel.debug=Debug +cyobot_v2_esp32s3.menu.DebugLevel.debug.build.code_debug=4 +cyobot_v2_esp32s3.menu.DebugLevel.verbose=Verbose +cyobot_v2_esp32s3.menu.DebugLevel.verbose.build.code_debug=5 + +cyobot_v2_esp32s3.menu.EraseFlash.none=Disabled +cyobot_v2_esp32s3.menu.EraseFlash.none.upload.erase_cmd= +cyobot_v2_esp32s3.menu.EraseFlash.all=Enabled +cyobot_v2_esp32s3.menu.EraseFlash.all.upload.erase_cmd=-e + +cyobot_v2_esp32s3.menu.ZigbeeMode.default=Disabled +cyobot_v2_esp32s3.menu.ZigbeeMode.default.build.zigbee_mode= +cyobot_v2_esp32s3.menu.ZigbeeMode.default.build.zigbee_libs= +cyobot_v2_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +cyobot_v2_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +cyobot_v2_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote + +############################################################## diff --git a/cores/esp32/Arduino.h b/cores/esp32/Arduino.h index 2f2c53af4b9..9048249a873 100644 --- a/cores/esp32/Arduino.h +++ b/cores/esp32/Arduino.h @@ -33,7 +33,6 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" -#include "esp32-hal.h" #include "esp8266-compat.h" #include "soc/gpio_reg.h" @@ -41,6 +40,9 @@ #include "binary.h" #include "extra_attr.h" +#include "pins_arduino.h" +#include "esp32-hal.h" + #define PI 3.1415926535897932384626433832795 #define HALF_PI 1.5707963267948966192313216916398 #define TWO_PI 6.283185307179586476925286766559 @@ -142,7 +144,7 @@ #endif #define EXTERNAL_NUM_INTERRUPTS NUM_DIGITAL_PINS // All GPIOs #define analogInputToDigitalPin(p) (((p) < NUM_ANALOG_INPUTS) ? (analogChannelToDigitalPin(p)) : -1) -#define digitalPinToInterrupt(p) ((((uint8_t)digitalPinToGPIONumber(p)) < NUM_DIGITAL_PINS) ? digitalPinToGPIONumber(p) : NOT_AN_INTERRUPT) +#define digitalPinToInterrupt(p) ((((uint8_t)digitalPinToGPIONumber(p)) < NUM_DIGITAL_PINS) ? (p) : NOT_AN_INTERRUPT) #define digitalPinHasPWM(p) (((uint8_t)digitalPinToGPIONumber(p)) < NUM_DIGITAL_PINS) typedef bool boolean; @@ -179,7 +181,7 @@ void initArduino(void); unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout); -uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); // codespell:ignore shiftin void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); #ifdef __cplusplus @@ -199,6 +201,7 @@ void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); #include "Udp.h" #include "HardwareSerial.h" #include "Esp.h" +#include "freertos_stats.h" // Use float-compatible stl abs() and round(), we don't use Arduino macros to avoid issues with the C++ libraries using std::abs; @@ -248,7 +251,7 @@ void noTone(uint8_t _pin); #endif /* __cplusplus */ -#include "pins_arduino.h" +// must be applied last as it overrides some of the above #include "io_pin_remap.h" #endif /* _ESP32_CORE_ARDUINO_H_ */ diff --git a/cores/esp32/ColorFormat.c b/cores/esp32/ColorFormat.c new file mode 100644 index 00000000000..a01123545b3 --- /dev/null +++ b/cores/esp32/ColorFormat.c @@ -0,0 +1,279 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ColorFormat.h" + +#include + +// define a clamp macro to substitute the std::clamp macro which is available from C++17 onwards +#define clamp(a, min, max) ((a) < (min) ? (min) : ((a) > (max) ? (max) : (a))) + +const espHsvColor_t HSV_BLACK = {0, 0, 0}; +const espHsvColor_t HSV_WHITE = {0, 0, 254}; +const espHsvColor_t HSV_RED = {0, 254, 254}; +const espHsvColor_t HSV_YELLOW = {42, 254, 254}; +const espHsvColor_t HSV_GREEN = {84, 254, 254}; +const espHsvColor_t HSV_CYAN = {127, 254, 254}; +const espHsvColor_t HSV_BLUE = {169, 254, 254}; +const espHsvColor_t HSV_MAGENTA = {211, 254, 254}; + +const espRgbColor_t RGB_BLACK = {0, 0, 0}; +const espRgbColor_t RGB_WHITE = {255, 255, 255}; +const espRgbColor_t RGB_RED = {255, 0, 0}; +const espRgbColor_t RGB_YELLOW = {255, 255, 0}; +const espRgbColor_t RGB_GREEN = {0, 255, 0}; +const espRgbColor_t RGB_CYAN = {0, 255, 255}; +const espRgbColor_t RGB_BLUE = {0, 0, 255}; +const espRgbColor_t RGB_MAGENTA = {255, 0, 255}; + +// main color temperature values +const espCtColor_t COOL_WHITE_COLOR_TEMPERATURE = {142}; +const espCtColor_t DAYLIGHT_WHITE_COLOR_TEMPERATURE = {181}; +const espCtColor_t WHITE_COLOR_TEMPERATURE = {250}; +const espCtColor_t SOFT_WHITE_COLOR_TEMPERATURE = {370}; +const espCtColor_t WARM_WHITE_COLOR_TEMPERATURE = {454}; + +espRgbColor_t espHsvToRgbColor(uint16_t h, uint8_t s, uint8_t v) { + espHsvColor_t hsv = {h, s, v}; + return espHsvColorToRgbColor(hsv); +} + +espRgbColor_t espHsvColorToRgbColor(espHsvColor_t hsv) { + espRgbColor_t rgb; + + uint8_t region, p, q, t; + uint32_t h, s, v, remainder; + + if (hsv.s == 0) { + rgb.r = rgb.g = rgb.b = hsv.v; + } else { + h = hsv.h; + s = hsv.s; + v = hsv.v; + + region = h / 43; + remainder = (h - (region * 43)) * 6; + p = (v * (255 - s)) >> 8; + q = (v * (255 - ((s * remainder) >> 8))) >> 8; + t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8; + switch (region) { + case 0: rgb.r = v, rgb.g = t, rgb.b = p; break; + case 1: rgb.r = q, rgb.g = v, rgb.b = p; break; + case 2: rgb.r = p, rgb.g = v, rgb.b = t; break; + case 3: rgb.r = p, rgb.g = q, rgb.b = v; break; + case 4: rgb.r = t, rgb.g = p, rgb.b = v; break; + case 5: + default: rgb.r = v, rgb.g = p, rgb.b = q; break; + } + } + return rgb; +} + +espHsvColor_t espRgbToHsvColor(uint8_t r, uint8_t g, uint8_t b) { + espRgbColor_t rgb = {r, g, b}; + return espRgbColorToHsvColor(rgb); +} + +espHsvColor_t espRgbColorToHsvColor(espRgbColor_t rgb) { + espHsvColor_t hsv; + uint8_t rgbMin, rgbMax; + + rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b); + rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b); + + hsv.v = rgbMax; + if (hsv.v == 0) { + hsv.h = 0; + hsv.s = 0; + return hsv; + } + + hsv.s = 255 * (rgbMax - rgbMin) / hsv.v; + if (hsv.s == 0) { + hsv.h = 0; + return hsv; + } + if (rgbMax == rgb.r) { + hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin); + } else if (rgbMax == rgb.g) { + hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin); + } else { + hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin); + } + return hsv; +} + +espRgbColor_t espXYColorToRgbColor(uint8_t Level, espXyColor_t xy) { + return espXYToRgbColor(Level, xy.x, xy.y); +} + +espRgbColor_t espXYToRgbColor(uint8_t Level, uint16_t current_X, uint16_t current_Y) { + // convert xyY color space to RGB + + // https://www.easyrgb.com/en/math.php + // https://en.wikipedia.org/wiki/SRGB + // refer https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space + + // The current_X/current_Y attribute contains the current value of the normalized chromaticity value of x/y. + // The value of x/y shall be related to the current_X/current_Y attribute by the relationship + // x = current_X/65536 + // y = current_Y/65536 + // z = 1-x-y + + espRgbColor_t rgb; + + float x, y, z; + float X, Y, Z; + float r, g, b; + + x = ((float)current_X) / 65535.0f; + y = ((float)current_Y) / 65535.0f; + + z = 1.0f - x - y; + + // Calculate XYZ values + + // Y - given brightness in 0 - 1 range + Y = ((float)Level) / 254.0f; + X = (Y / y) * x; + Z = (Y / y) * z; + + // X, Y and Z input refer to a D65/2° standard illuminant. + // sR, sG and sB (standard RGB) output range = 0 ÷ 255 + // convert XYZ to RGB - CIE XYZ to sRGB + X = X / 100.0f; + Y = Y / 100.0f; + Z = Z / 100.0f; + + r = (X * 3.2406f) - (Y * 1.5372f) - (Z * 0.4986f); + g = -(X * 0.9689f) + (Y * 1.8758f) + (Z * 0.0415f); + b = (X * 0.0557f) - (Y * 0.2040f) + (Z * 1.0570f); + + // apply gamma 2.2 correction + r = (r <= 0.0031308f ? 12.92f * r : (1.055f) * pow(r, (1.0f / 2.4f)) - 0.055f); + g = (g <= 0.0031308f ? 12.92f * g : (1.055f) * pow(g, (1.0f / 2.4f)) - 0.055f); + b = (b <= 0.0031308f ? 12.92f * b : (1.055f) * pow(b, (1.0f / 2.4f)) - 0.055f); + + // Round off + r = clamp(r, 0, 1); + g = clamp(g, 0, 1); + b = clamp(b, 0, 1); + + // these rgb values are in the range of 0 to 1, convert to limit of HW specific LED + rgb.r = (uint8_t)(r * 255); + rgb.g = (uint8_t)(g * 255); + rgb.b = (uint8_t)(b * 255); + + return rgb; +} + +espXyColor_t espRgbToXYColor(uint8_t r, uint8_t g, uint8_t b) { + espRgbColor_t rgb = {r, g, b}; + return espRgbColorToXYColor(rgb); +} + +espXyColor_t espRgbColorToXYColor(espRgbColor_t rgb) { + // convert RGB to xy color space + + // https://www.easyrgb.com/en/math.php + // https://en.wikipedia.org/wiki/SRGB + // refer https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space + + espXyColor_t xy; + + float r, g, b; + float X, Y, Z; + float x, y; + + r = ((float)rgb.r) / 255.0f; + g = ((float)rgb.g) / 255.0f; + b = ((float)rgb.b) / 255.0f; + + // convert RGB to XYZ - sRGB to CIE XYZ + r = (r <= 0.04045f ? r / 12.92f : pow((r + 0.055f) / 1.055f, 2.4f)); + g = (g <= 0.04045f ? g / 12.92f : pow((g + 0.055f) / 1.055f, 2.4f)); + b = (b <= 0.04045f ? b / 12.92f : pow((b + 0.055f) / 1.055f, 2.4f)); + + // https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d + X = r * 0.649926f + g * 0.103455f + b * 0.197109f; + Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; + Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f; + + // sR, sG and sB (standard RGB) input range = 0 ÷ 255 + // X, Y and Z output refer to a D65/2° standard illuminant. + X = r * 0.4124564f + g * 0.3575761f + b * 0.1804375f; + Y = r * 0.2126729f + g * 0.7151522f + b * 0.0721750f; + Z = r * 0.0193339f + g * 0.1191920f + b * 0.9503041f; + + // Calculate xy values + x = X / (X + Y + Z); + y = Y / (X + Y + Z); + + // convert to 0-65535 range + xy.x = (uint16_t)(x * 65535); + xy.y = (uint16_t)(y * 65535); + return xy; +} + +espRgbColor_t espCTToRgbColor(uint16_t ct) { + espCtColor_t ctColor = {ct}; + return espCTColorToRgbColor(ctColor); +} + +espRgbColor_t espCTColorToRgbColor(espCtColor_t ct) { + espRgbColor_t rgb = {0, 0, 0}; + float r, g, b; + + if (ct.ctMireds == 0) { + return rgb; + } + // Algorithm credits to Tanner Helland: https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html + + // Convert Mireds to centiKelvins. k = 1,000,000/mired + float ctCentiKelvin = 10000 / ct.ctMireds; + + // Red + if (ctCentiKelvin <= 66) { + r = 255; + } else { + r = 329.698727446f * pow(ctCentiKelvin - 60, -0.1332047592f); + } + + // Green + if (ctCentiKelvin <= 66) { + g = 99.4708025861f * log(ctCentiKelvin) - 161.1195681661f; + } else { + g = 288.1221695283f * pow(ctCentiKelvin - 60, -0.0755148492f); + } + + // Blue + if (ctCentiKelvin >= 66) { + b = 255; + } else { + if (ctCentiKelvin <= 19) { + b = 0; + } else { + b = 138.5177312231 * log(ctCentiKelvin - 10) - 305.0447927307; + } + } + rgb.r = (uint8_t)clamp(r, 0, 255); + rgb.g = (uint8_t)clamp(g, 0, 255); + rgb.b = (uint8_t)clamp(b, 0, 255); + + return rgb; +} diff --git a/cores/esp32/ColorFormat.h b/cores/esp32/ColorFormat.h new file mode 100644 index 00000000000..0bb87145d16 --- /dev/null +++ b/cores/esp32/ColorFormat.h @@ -0,0 +1,70 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#ifdef __cplusplus +extern "C" { +#endif + +struct RgbColor_t { + uint8_t r; + uint8_t g; + uint8_t b; +}; + +struct HsvColor_t { + uint16_t h; + uint8_t s; + uint8_t v; +}; + +struct XyColor_t { + uint16_t x; + uint16_t y; +}; + +struct CtColor_t { + uint16_t ctMireds; +}; + +typedef struct RgbColor_t espRgbColor_t; +typedef struct HsvColor_t espHsvColor_t; +typedef struct XyColor_t espXyColor_t; +typedef struct CtColor_t espCtColor_t; + +espRgbColor_t espXYToRgbColor(uint8_t Level, uint16_t current_X, uint16_t current_Y); +espRgbColor_t espXYColorToRgb(uint8_t Level, espXyColor_t xy); +espXyColor_t espRgbColorToXYColor(espRgbColor_t rgb); +espXyColor_t espRgbToXYColor(uint8_t r, uint8_t g, uint8_t b); +espRgbColor_t espHsvColorToRgbColor(espHsvColor_t hsv); +espRgbColor_t espHsvToRgbColor(uint16_t h, uint8_t s, uint8_t v); +espRgbColor_t espCTColorToRgbColor(espCtColor_t ct); +espRgbColor_t espCTToRgbColor(uint16_t ct); +espHsvColor_t espRgbColorToHsvColor(espRgbColor_t rgb); +espHsvColor_t espRgbToHsvColor(uint8_t r, uint8_t g, uint8_t b); + +extern const espHsvColor_t HSV_BLACK, HSV_WHITE, HSV_RED, HSV_YELLOW, HSV_GREEN, HSV_CYAN, HSV_BLUE, HSV_MAGENTA; +extern const espCtColor_t COOL_WHITE_COLOR_TEMPERATURE, DAYLIGHT_WHITE_COLOR_TEMPERATURE, WHITE_COLOR_TEMPERATURE, SOFT_WHITE_COLOR_TEMPERATURE, + WARM_WHITE_COLOR_TEMPERATURE; +extern const espRgbColor_t RGB_BLACK, RGB_WHITE, RGB_RED, RGB_YELLOW, RGB_GREEN, RGB_CYAN, RGB_BLUE, RGB_MAGENTA; + +#ifdef __cplusplus +} +#endif diff --git a/cores/esp32/Esp.cpp b/cores/esp32/Esp.cpp index a463fc16ba0..9f90a828b25 100644 --- a/cores/esp32/Esp.cpp +++ b/cores/esp32/Esp.cpp @@ -60,6 +60,9 @@ extern "C" { #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/spi_flash.h" #define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32h2 is located at 0x0000 +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/spi_flash.h" +#define ESP_FLASH_IMAGE_BASE 0x2000 // Esp32p4 is located at 0x2000 #else #error Target CONFIG_IDF_TARGET is not supported #endif @@ -262,19 +265,19 @@ const char *EspClass::getChipModel(void) { uint32_t pkg_ver = chip_ver & 0x7; switch (pkg_ver) { case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6: - if (getChipRevision() == 3) { + if ((getChipRevision() / 100) == 3) { return "ESP32-D0WDQ6-V3"; } else { return "ESP32-D0WDQ6"; } case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5: - if (getChipRevision() == 3) { + if ((getChipRevision() / 100) == 3) { return "ESP32-D0WD-V3"; } else { return "ESP32-D0WD"; } case EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5: return "ESP32-D2WD"; - case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2: return "ESP32-PICO-D2"; + case EFUSE_RD_CHIP_VER_PKG_ESP32U4WDH: return "ESP32-U4WDH"; case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4: return "ESP32-PICO-D4"; case EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302: return "ESP32-PICO-V3-02"; case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDR2V3: return "ESP32-D0WDR2-V3"; @@ -297,6 +300,7 @@ const char *EspClass::getChipModel(void) { case CHIP_ESP32C2: return "ESP32-C2"; case CHIP_ESP32C6: return "ESP32-C6"; case CHIP_ESP32H2: return "ESP32-H2"; + case CHIP_ESP32P4: return "ESP32-P4"; default: return "UNKNOWN"; } #endif @@ -335,6 +339,8 @@ uint32_t EspClass::getFlashChipSpeed(void) { return magicFlashChipSpeed(fhdr.spi_speed); } +// FIXME for P4 +#if !defined(CONFIG_IDF_TARGET_ESP32P4) FlashMode_t EspClass::getFlashChipMode(void) { #if CONFIG_IDF_TARGET_ESP32S2 uint32_t spi_ctrl = REG_READ(PERIPHS_SPI_FLASH_CTRL); @@ -361,6 +367,7 @@ FlashMode_t EspClass::getFlashChipMode(void) { } return (FM_DOUT); } +#endif // if !defined(CONFIG_IDF_TARGET_ESP32P4) uint32_t EspClass::magicFlashChipSize(uint8_t byte) { /* diff --git a/cores/esp32/FirmwareMSC.cpp b/cores/esp32/FirmwareMSC.cpp index c408f52fcdb..2e944ad4df3 100644 --- a/cores/esp32/FirmwareMSC.cpp +++ b/cores/esp32/FirmwareMSC.cpp @@ -19,8 +19,8 @@ #include "esp_partition.h" #include "esp_ota_ops.h" #include "esp_image_format.h" -#include "esp32-hal.h" #include "pins_arduino.h" +#include "esp32-hal.h" #include "firmware_msc_fat.h" #include "spi_flash_mmap.h" diff --git a/cores/esp32/HWCDC.cpp b/cores/esp32/HWCDC.cpp index b0f653e889e..062317d9f53 100644 --- a/cores/esp32/HWCDC.cpp +++ b/cores/esp32/HWCDC.cpp @@ -286,14 +286,14 @@ bool HWCDC::deinit(void *busptr) { running = true; // Setting USB D+ D- pins bool retCode = true; - retCode &= perimanClearPinBus(USB_DM_GPIO_NUM); - retCode &= perimanClearPinBus(USB_DP_GPIO_NUM); + retCode &= perimanClearPinBus(USB_INT_PHY0_DM_GPIO_NUM); + retCode &= perimanClearPinBus(USB_INT_PHY0_DP_GPIO_NUM); if (retCode) { // Force the host to re-enumerate (BUS_RESET) - pinMode(USB_DM_GPIO_NUM, OUTPUT_OPEN_DRAIN); - pinMode(USB_DP_GPIO_NUM, OUTPUT_OPEN_DRAIN); - digitalWrite(USB_DM_GPIO_NUM, LOW); - digitalWrite(USB_DP_GPIO_NUM, LOW); + pinMode(USB_INT_PHY0_DM_GPIO_NUM, OUTPUT_OPEN_DRAIN); + pinMode(USB_INT_PHY0_DP_GPIO_NUM, OUTPUT_OPEN_DRAIN); + digitalWrite(USB_INT_PHY0_DM_GPIO_NUM, LOW); + digitalWrite(USB_INT_PHY0_DP_GPIO_NUM, LOW); } // release the flag running = false; @@ -323,11 +323,11 @@ void HWCDC::begin(unsigned long baud) { // delay(10); // USB Host has to enumerate it again // Peripheral Manager setting for USB D+ D- pins - uint8_t pin = USB_DM_GPIO_NUM; + uint8_t pin = USB_INT_PHY0_DM_GPIO_NUM; if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_USB_DM, (void *)this, -1, -1)) { goto err; } - pin = USB_DP_GPIO_NUM; + pin = USB_INT_PHY0_DP_GPIO_NUM; if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_USB_DP, (void *)this, -1, -1)) { goto err; } @@ -443,7 +443,7 @@ size_t HWCDC::write(const uint8_t *buffer, size_t size) { if (connected) { usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY); } - // tracks CDC trasmission progress to avoid hanging if CDC is unplugged while still sending data + // tracks CDC transmission progress to avoid hanging if CDC is unplugged while still sending data size_t last_toSend = to_send; uint32_t tries = tx_timeout_ms; // waits 1ms per sending data attempt, in case CDC is unplugged while (connected && to_send) { @@ -479,7 +479,7 @@ size_t HWCDC::write(const uint8_t *buffer, size_t size) { } } } - // CDC was diconnected while sending data ==> flush the TX buffer keeping the last data + // CDC was disconnected while sending data ==> flush the TX buffer keeping the last data if (to_send && !usb_serial_jtag_ll_txfifo_writable()) { connected = false; flushTXBuffer(buffer + so_far, to_send); @@ -603,6 +603,7 @@ void HWCDC::setDebugOutput(bool en) { } else { ets_install_putc2(NULL); } + ets_install_putc1(NULL); // closes UART log output } #if ARDUINO_USB_MODE && ARDUINO_USB_CDC_ON_BOOT // Hardware JTAG CDC selected diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index 3d7c7068728..6d762da21fb 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -11,31 +11,34 @@ #include "driver/uart.h" #include "freertos/queue.h" -#ifndef ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE -#define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE 2048 -#endif - -#ifndef ARDUINO_SERIAL_EVENT_TASK_PRIORITY -#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY (configMAX_PRIORITIES - 1) -#endif - -#ifndef ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1 +#if (SOC_UART_LP_NUM >= 1) +#define UART_HW_FIFO_LEN(uart_num) ((uart_num < SOC_UART_HP_NUM) ? SOC_UART_FIFO_LEN : SOC_LP_UART_FIFO_LEN) +#else +#define UART_HW_FIFO_LEN(uart_num) SOC_UART_FIFO_LEN #endif void serialEvent(void) __attribute__((weak)); -void serialEvent(void) {} #if SOC_UART_NUM > 1 void serialEvent1(void) __attribute__((weak)); -void serialEvent1(void) {} #endif /* SOC_UART_NUM > 1 */ #if SOC_UART_NUM > 2 void serialEvent2(void) __attribute__((weak)); -void serialEvent2(void) {} #endif /* SOC_UART_NUM > 2 */ +#if SOC_UART_NUM > 3 +void serialEvent3(void) __attribute__((weak)); +#endif /* SOC_UART_NUM > 3 */ + +#if SOC_UART_NUM > 4 +void serialEvent4(void) __attribute__((weak)); +#endif /* SOC_UART_NUM > 4 */ + +#if SOC_UART_NUM > 5 +void serialEvent5(void) __attribute__((weak)); +#endif /* SOC_UART_NUM > 5 */ + #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) // There is always Seria0 for UART0 HardwareSerial Serial0(0); @@ -45,43 +48,64 @@ HardwareSerial Serial1(1); #if SOC_UART_NUM > 2 HardwareSerial Serial2(2); #endif - +#if SOC_UART_NUM > 3 +HardwareSerial Serial3(3); +#endif +#if SOC_UART_NUM > 4 +HardwareSerial Serial4(4); +#endif +#if (SOC_UART_NUM > 5) +HardwareSerial Serial5(5); +#endif #if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event extern void HWCDCSerialEvent(void) __attribute__((weak)); -void HWCDCSerialEvent(void) {} #endif #if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event // Used by Hardware Serial for USB CDC events extern void USBSerialEvent(void) __attribute__((weak)); -void USBSerialEvent(void) {} #endif void serialEventRun(void) { #if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event - if (HWCDCSerial.available()) { + if (HWCDCSerialEvent && HWCDCSerial.available()) { HWCDCSerialEvent(); } #endif #if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event - if (USBSerial.available()) { + if (USBSerialEvent && USBSerial.available()) { USBSerialEvent(); } #endif // UART0 is default serialEvent() - if (Serial0.available()) { + if (serialEvent && Serial0.available()) { serialEvent(); } #if SOC_UART_NUM > 1 - if (Serial1.available()) { + if (serialEvent1 && Serial1.available()) { serialEvent1(); } #endif #if SOC_UART_NUM > 2 - if (Serial2.available()) { + if (serialEvent2 && Serial2.available()) { serialEvent2(); } #endif +#if SOC_UART_NUM > 3 + if (serialEvent3 && Serial3.available()) { + serialEvent3(); + } +#endif +#if SOC_UART_NUM > 4 + if (serialEvent4 && Serial4.available()) { + serialEvent4(); + } +#endif +#if SOC_UART_NUM > 5 + if (serialEvent5 && Serial5.available()) { + serialEvent5(); + } +#endif } #endif @@ -96,7 +120,7 @@ void serialEventRun(void) { #endif HardwareSerial::HardwareSerial(uint8_t uart_nr) - : _uart_nr(uart_nr), _uart(NULL), _rxBufferSize(256), _txBufferSize(0), _onReceiveCB(NULL), _onReceiveErrorCB(NULL), _onReceiveTimeout(false), _rxTimeout(2), + : _uart_nr(uart_nr), _uart(NULL), _rxBufferSize(256), _txBufferSize(0), _onReceiveCB(NULL), _onReceiveErrorCB(NULL), _onReceiveTimeout(false), _rxTimeout(1), _rxFIFOFull(0), _eventTask(NULL) #if !CONFIG_DISABLE_HAL_LOCKS , @@ -166,7 +190,8 @@ void HardwareSerial::onReceive(OnReceiveCb function, bool onlyOnTimeout) { // in case that onReceive() shall work only with RX Timeout, FIFO shall be high // this is a work around for an IDF issue with events and low FIFO Full value (< 3) - if (_onReceiveTimeout) { + // Not valid for the LP UART + if (_onReceiveTimeout && _uart_nr < SOC_UART_HP_NUM) { uartSetRxFIFOFull(_uart, 120); log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes."); } @@ -188,12 +213,13 @@ bool HardwareSerial::setRxFIFOFull(uint8_t fifoBytes) { HSERIAL_MUTEX_LOCK(); // in case that onReceive() shall work only with RX Timeout, FIFO shall be high // this is a work around for an IDF issue with events and low FIFO Full value (< 3) - if (_onReceiveCB != NULL && _onReceiveTimeout) { + // Not valid for the LP UART + if (_onReceiveCB != NULL && _onReceiveTimeout && _uart_nr < SOC_UART_HP_NUM) { fifoBytes = 120; log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes."); } bool retCode = uartSetRxFIFOFull(_uart, fifoBytes); // Set new timeout - if (fifoBytes > 0 && fifoBytes < SOC_UART_FIFO_LEN - 1) { + if (fifoBytes > 0 && fifoBytes < UART_HW_FIFO_LEN(_uart_nr) - 1) { _rxFIFOFull = fifoBytes; } HSERIAL_MUTEX_UNLOCK(); @@ -291,6 +317,15 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in } #endif + // map logical pins to GPIO numbers + rxPin = digitalPinToGPIONumber(rxPin); + txPin = digitalPinToGPIONumber(txPin); + int8_t _rxPin = uart_get_RxPin(_uart_nr); + int8_t _txPin = uart_get_TxPin(_uart_nr); + + rxPin = rxPin < 0 ? _rxPin : rxPin; + txPin = txPin < 0 ? _txPin : txPin; + HSERIAL_MUTEX_LOCK(); // First Time or after end() --> set default Pins if (!uartIsDriverInstalled(_uart)) { @@ -305,7 +340,7 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in txPin = _txPin < 0 ? (int8_t)SOC_TX0 : _txPin; } break; -#if SOC_UART_NUM > 1 // may save some flash bytes... +#if SOC_UART_HP_NUM > 1 case UART_NUM_1: if (rxPin < 0 && txPin < 0) { // do not change RX1/TX1 if it has already been set before @@ -313,22 +348,69 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in txPin = _txPin < 0 ? (int8_t)TX1 : _txPin; } break; -#endif -#if SOC_UART_NUM > 2 // may save some flash bytes... +#endif // UART_NUM_1 +#if SOC_UART_HP_NUM > 2 case UART_NUM_2: if (rxPin < 0 && txPin < 0) { // do not change RX2/TX2 if it has already been set before +#ifdef RX2 rxPin = _rxPin < 0 ? (int8_t)RX2 : _rxPin; +#endif +#ifdef TX2 txPin = _txPin < 0 ? (int8_t)TX2 : _txPin; +#endif } break; +#endif // UART_NUM_2 +#if SOC_UART_HP_NUM > 3 + case UART_NUM_3: + if (rxPin < 0 && txPin < 0) { + // do not change RX3/TX3 if it has already been set before +#ifdef RX3 + rxPin = _rxPin < 0 ? (int8_t)RX3 : _rxPin; +#endif +#ifdef TX3 + txPin = _txPin < 0 ? (int8_t)TX3 : _txPin; #endif + } + break; +#endif // UART_NUM_3 +#if SOC_UART_HP_NUM > 4 + case UART_NUM_4: + if (rxPin < 0 && txPin < 0) { + // do not change RX4/TX4 if it has already been set before +#ifdef RX4 + rxPin = _rxPin < 0 ? (int8_t)RX4 : _rxPin; +#endif +#ifdef TX4 + txPin = _txPin < 0 ? (int8_t)TX4 : _txPin; +#endif + } + break; +#endif // UART_NUM_4 +#if (SOC_UART_LP_NUM >= 1) + case LP_UART_NUM_0: + if (rxPin < 0 && txPin < 0) { + // do not change RX0_LP/TX0_LP if it has already been set before +#ifdef LP_RX0 + rxPin = _rxPin < 0 ? (int8_t)LP_RX0 : _rxPin; +#endif +#ifdef LP_TX0 + txPin = _txPin < 0 ? (int8_t)LP_TX0 : _txPin; +#endif + } + break; +#endif // LP_UART_NUM_0 } } - // map logical pins to GPIO numbers - rxPin = digitalPinToGPIONumber(rxPin); - txPin = digitalPinToGPIONumber(txPin); + // if no RX/TX pins are defined, it will not start the UART driver + if (rxPin < 0 && txPin < 0) { + log_e("No RX/TX pins defined. Please set RX/TX pins."); + HSERIAL_MUTEX_UNLOCK(); + return; + } + // IDF UART driver keeps Pin setting on restarting. Negative Pin number will keep it unmodified. // it will detach previous UART attached pins @@ -383,7 +465,8 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in if (!_rxFIFOFull) { // it has not being changed before calling begin() // set a default FIFO Full value for the IDF driver uint8_t fifoFull = 1; - if (baud > 57600 || (_onReceiveCB != NULL && _onReceiveTimeout)) { + // if baud rate is higher than 57600 or onReceive() is set, it will set FIFO Full to 120 bytes, except for LP UART + if (_uart_nr < SOC_UART_HP_NUM && (baud > 57600 || (_onReceiveCB != NULL && _onReceiveTimeout))) { fifoFull = 120; } uartSetRxFIFOFull(_uart, fifoFull); @@ -415,6 +498,12 @@ void HardwareSerial::setDebugOutput(bool en) { if (_uart == 0) { return; } +#if (SOC_UART_LP_NUM >= 1) + if (_uart_nr >= SOC_UART_HP_NUM) { + log_e("LP UART does not support Debug Output."); + return; + } +#endif if (en) { uartSetDebug(_uart); } else { @@ -518,35 +607,56 @@ bool HardwareSerial::setMode(SerialMode mode) { return uartSetMode(_uart, mode); } +// Sets the UART Clock Source based on the compatible SoC options +// This method must be called before starting UART using begin(), otherwise it won't have any effect. +// Clock Source Options are: +// UART_CLK_SRC_DEFAULT :: any SoC - it will set whatever IDF defines as the default UART Clock Source +// UART_CLK_SRC_APB :: ESP32, ESP32-S2, ESP32-C3 and ESP32-S3 +// UART_CLK_SRC_PLL :: ESP32-C2, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2 and ESP32-P4 +// UART_CLK_SRC_XTAL :: ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, ESP32-S3 and ESP32-P4 +// UART_CLK_SRC_RTC :: ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, ESP32-S3 and ESP32-P4 +// UART_CLK_SRC_REF_TICK :: ESP32 and ESP32-S2 +// Note: CLK_SRC_PLL Freq depends on the SoC - ESP32-C2 has 40MHz, ESP32-H2 has 48MHz and ESP32-C5, C6, C61 and P4 has 80MHz +// Note: ESP32-C6, C61, ESP32-P4 and ESP32-C5 have LP UART that will use only RTC_FAST or XTAL/2 as Clock Source +bool HardwareSerial::setClockSource(SerialClkSrc clkSrc) { + if (_uart) { + log_e("No Clock Source change was done. This function must be called before beginning UART%d.", _uart_nr); + return false; + } + return uartSetClockSource(_uart_nr, (uart_sclk_t)clkSrc); +} // minimum total RX Buffer size is the UART FIFO space (128 bytes for most SoC) + 1. IDF imposition. +// LP UART has FIFO of 16 bytes size_t HardwareSerial::setRxBufferSize(size_t new_size) { if (_uart) { log_e("RX Buffer can't be resized when Serial is already running. Set it before calling begin()."); return 0; } - - if (new_size <= SOC_UART_FIFO_LEN) { - log_w("RX Buffer set to minimum value: %d.", SOC_UART_FIFO_LEN + 1); // ESP32, S2, S3 and C3 means higher than 128 - new_size = SOC_UART_FIFO_LEN + 1; + uint8_t FIFOLen = UART_HW_FIFO_LEN(_uart_nr); + // Valid value is higher than the FIFO length + if (new_size <= FIFOLen) { + new_size = FIFOLen + 1; + log_w("RX Buffer set to minimum value: %d.", new_size); } _rxBufferSize = new_size; return _rxBufferSize; } -// minimum total TX Buffer size is the UART FIFO space (128 bytes for most SoC). +// minimum total TX Buffer size is the UART FIFO space (128 bytes for most SoC) + 1. +// LP UART has FIFO of 16 bytes size_t HardwareSerial::setTxBufferSize(size_t new_size) { if (_uart) { log_e("TX Buffer can't be resized when Serial is already running. Set it before calling begin()."); return 0; } - - if (new_size <= SOC_UART_FIFO_LEN) { - log_w("TX Buffer set to minimum value: %d.", SOC_UART_FIFO_LEN); // ESP32, S2, S3 and C3 means higher than 128 - _txBufferSize = 0; // it will use just UART FIFO with SOC_UART_FIFO_LEN bytes (128 for most SoC) - return SOC_UART_FIFO_LEN; + uint8_t FIFOLen = UART_HW_FIFO_LEN(_uart_nr); + // Valid values are zero or higher than the FIFO length + if (new_size > 0 && new_size <= FIFOLen) { + new_size = FIFOLen + 1; + log_w("TX Buffer set to minimum value: %d.", new_size); } // if new_size is higher than SOC_UART_FIFO_LEN, TX Ringbuffer will be active and it will be used to report back "availableToWrite()" _txBufferSize = new_size; diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index 3fd5e7dc99b..e974f112701 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -96,16 +96,51 @@ typedef enum { UART_PARITY_ERROR } hardwareSerial_error_t; +typedef enum { + UART_CLK_SRC_DEFAULT = UART_SCLK_DEFAULT, +#if SOC_UART_SUPPORT_APB_CLK + UART_CLK_SRC_APB = UART_SCLK_APB, +#endif +#if SOC_UART_SUPPORT_PLL_F40M_CLK + UART_CLK_SRC_PLL = UART_SCLK_PLL_F40M, +#elif SOC_UART_SUPPORT_PLL_F80M_CLK + UART_CLK_SRC_PLL = UART_SCLK_PLL_F80M, +#elif CONFIG_IDF_TARGET_ESP32H2 + UART_CLK_SRC_PLL = UART_SCLK_PLL_F48M, +#endif +#if SOC_UART_SUPPORT_XTAL_CLK + UART_CLK_SRC_XTAL = UART_SCLK_XTAL, +#endif +#if SOC_UART_SUPPORT_RTC_CLK + UART_CLK_SRC_RTC = UART_SCLK_RTC, +#endif +#if SOC_UART_SUPPORT_REF_TICK + UART_CLK_SRC_REF_TICK = UART_SCLK_REF_TICK, +#endif +} SerialClkSrc; + #ifndef ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE +#ifndef CONFIG_ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE #define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE 2048 +#else +#define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE CONFIG_ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE +#endif #endif #ifndef ARDUINO_SERIAL_EVENT_TASK_PRIORITY +#ifndef CONFIG_ARDUINO_SERIAL_EVENT_TASK_PRIORITY #define ARDUINO_SERIAL_EVENT_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#else +#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY CONFIG_ARDUINO_SERIAL_EVENT_TASK_PRIORITY +#endif #endif #ifndef ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE +#ifndef CONFIG_ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE #define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1 +#else +#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE CONFIG_ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE +#endif #endif // UART0 pins are defined by default by the bootloader. @@ -125,6 +160,8 @@ typedef enum { #define SOC_RX0 (gpio_num_t)17 #elif CONFIG_IDF_TARGET_ESP32H2 #define SOC_RX0 (gpio_num_t)23 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define SOC_RX0 (gpio_num_t)38 #endif #endif @@ -141,12 +178,14 @@ typedef enum { #define SOC_TX0 (gpio_num_t)16 #elif CONFIG_IDF_TARGET_ESP32H2 #define SOC_TX0 (gpio_num_t)24 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define SOC_TX0 (gpio_num_t)37 #endif #endif // Default pins for UART1 are arbitrary, and defined here for convenience. -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 #ifndef RX1 #if CONFIG_IDF_TARGET_ESP32 #define RX1 (gpio_num_t)26 @@ -162,6 +201,8 @@ typedef enum { #define RX1 (gpio_num_t)4 #elif CONFIG_IDF_TARGET_ESP32H2 #define RX1 (gpio_num_t)0 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define RX1 (gpio_num_t)11 #endif #endif @@ -180,13 +221,15 @@ typedef enum { #define TX1 (gpio_num_t)5 #elif CONFIG_IDF_TARGET_ESP32H2 #define TX1 (gpio_num_t)1 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define TX1 (gpio_num_t)10 #endif #endif -#endif /* SOC_UART_NUM > 1 */ +#endif /* SOC_UART_HP_NUM > 1 */ // Default pins for UART2 are arbitrary, and defined here for convenience. -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 #ifndef RX2 #if CONFIG_IDF_TARGET_ESP32 #define RX2 (gpio_num_t)4 @@ -202,7 +245,17 @@ typedef enum { #define TX2 (gpio_num_t)20 #endif #endif -#endif /* SOC_UART_NUM > 2 */ +#endif /* SOC_UART_HP_NUM > 2 */ + +#if SOC_UART_LP_NUM >= 1 +#ifndef LP_RX0 +#define LP_RX0 (gpio_num_t) LP_U0RXD_GPIO_NUM +#endif + +#ifndef LP_TX0 +#define LP_TX0 (gpio_num_t) LP_U0TXD_GPIO_NUM +#endif +#endif /* SOC_UART_LP_NUM >= 1 */ typedef std::function OnReceiveCb; typedef std::function OnReceiveErrorCb; @@ -228,7 +281,7 @@ class HardwareSerial : public Stream { // onReceive will setup a callback that will be called whenever an UART interruption occurs (UART_INTR_RXFIFO_FULL or UART_INTR_RXFIFO_TOUT) // UART_INTR_RXFIFO_FULL interrupt triggers at UART_FULL_THRESH_DEFAULT bytes received (defined as 120 bytes by default in IDF) - // UART_INTR_RXFIFO_TOUT interrupt triggers at UART_TOUT_THRESH_DEFAULT symbols passed without any reception (defined as 10 symbos by default in IDF) + // UART_INTR_RXFIFO_TOUT interrupt triggers at UART_TOUT_THRESH_DEFAULT symbols passed without any reception (defined as 10 symbols by default in IDF) // onlyOnTimeout parameter will define how onReceive will behave: // Default: true -- The callback will only be called when RX Timeout happens. // Whole stream of bytes will be ready for being read on the callback function at once. @@ -251,7 +304,7 @@ class HardwareSerial : public Stream { // rxfifo_full_thrhd if the UART Flow Control Threshold in the UART FIFO (max 127) void begin( unsigned long baud, uint32_t config = SERIAL_8N1, int8_t rxPin = -1, int8_t txPin = -1, bool invert = false, unsigned long timeout_ms = 20000UL, - uint8_t rxfifo_full_thrhd = 112 + uint8_t rxfifo_full_thrhd = 120 ); void end(void); void updateBaudRate(unsigned long baud); @@ -314,6 +367,17 @@ class HardwareSerial : public Stream { // UART_MODE_RS485_COLLISION_DETECT = 0x03 mode: RS485 collision detection UART mode (used for test purposes) // UART_MODE_RS485_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes) bool setMode(SerialMode mode); + // Used to set the UART clock source mode. It must be set before calling begin(), otherwise it won't have any effect. + // Not all clock source are available to every SoC. The compatible option are listed here: + // UART_CLK_SRC_DEFAULT :: any SoC - it will set whatever IDF defines as the default UART Clock Source + // UART_CLK_SRC_APB :: ESP32, ESP32-S2, ESP32-C3 and ESP32-S3 + // UART_CLK_SRC_PLL :: ESP32-C2, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2 and ESP32-P4 + // UART_CLK_SRC_XTAL :: ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, ESP32-S3 and ESP32-P4 + // UART_CLK_SRC_RTC :: ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, ESP32-S3 and ESP32-P4 + // UART_CLK_SRC_REF_TICK :: ESP32 and ESP32-S2 + // Note: CLK_SRC_PLL Freq depends on the SoC - ESP32-C2 has 40MHz, ESP32-H2 has 48MHz and ESP32-C5, C6, C61 and P4 has 80MHz + // Note: ESP32-C6, C61, ESP32-P4 and ESP32-C5 have LP UART that will use only RTC_FAST or XTAL/2 as Clock Source + bool setClockSource(SerialClkSrc clkSrc); size_t setRxBufferSize(size_t new_size); size_t setTxBufferSize(size_t new_size); @@ -363,6 +427,15 @@ extern HardwareSerial Serial1; #if SOC_UART_NUM > 2 extern HardwareSerial Serial2; #endif +#if SOC_UART_NUM > 3 +extern HardwareSerial Serial3; +#endif +#if SOC_UART_NUM > 4 +extern HardwareSerial Serial4; +#endif +#if SOC_UART_NUM > 5 +extern HardwareSerial Serial5; +#endif #endif //!defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) #endif // HardwareSerial_h diff --git a/cores/esp32/IPAddress.cpp b/cores/esp32/IPAddress.cpp index b4fc4c3f7e0..299a625ff27 100644 --- a/cores/esp32/IPAddress.cpp +++ b/cores/esp32/IPAddress.cpp @@ -22,6 +22,10 @@ #include "lwip/netif.h" #include "StreamString.h" +#ifndef CONFIG_LWIP_IPV6 +#define IP6_NO_ZONE 0 +#endif + IPAddress::IPAddress() : IPAddress(IPv4) {} IPAddress::IPAddress(IPType ip_type) { @@ -201,7 +205,13 @@ bool IPAddress::fromString6(const char *address) { colons++; acc = 0; } else if (c == '%') { - _zone = netif_name_to_index(address); + // netif_index_to_name crashes on latest esp-idf + // _zone = netif_name_to_index(address); + // in the interim, we parse the suffix as a zone number + while ((*address != '\0') && (!isdigit(*address))) { // skip all non-digit after '%' + address++; + } + _zone = atol(address) + 1; // increase by one by convention, so we can have zone '0' while (*address != '\0') { address++; } @@ -344,12 +354,25 @@ size_t IPAddress::printTo(Print &p, bool includeZone) const { n += p.print(':'); } } - // add a zone if zone-id is non-zero + // add a zone if zone-id is non-zero (causes exception on recent IDF builds) + // if (_zone > 0 && includeZone) { + // n += p.print('%'); + // char if_name[NETIF_NAMESIZE]; + // netif_index_to_name(_zone, if_name); + // n += p.print(if_name); + // } + // In the interim, we just output the index number if (_zone > 0 && includeZone) { n += p.print('%'); - char if_name[NETIF_NAMESIZE]; - netif_index_to_name(_zone, if_name); - n += p.print(if_name); + // look for the interface name + for (netif *intf = netif_list; intf != nullptr; intf = intf->next) { + if (_zone - 1 == intf->num) { + n += p.print(intf->name[0]); + n += p.print(intf->name[1]); + break; + } + } + n += p.print(_zone - 1); } return n; } @@ -368,6 +391,7 @@ IPAddress::IPAddress(const ip_addr_t *addr) { } void IPAddress::to_ip_addr_t(ip_addr_t *addr) const { +#if CONFIG_LWIP_IPV6 if (_type == IPv6) { addr->type = IPADDR_TYPE_V6; addr->u_addr.ip6.addr[0] = _address.dword[0]; @@ -381,9 +405,13 @@ void IPAddress::to_ip_addr_t(ip_addr_t *addr) const { addr->type = IPADDR_TYPE_V4; addr->u_addr.ip4.addr = _address.dword[IPADDRESS_V4_DWORD_INDEX]; } +#else + addr->addr = _address.dword[IPADDRESS_V4_DWORD_INDEX]; +#endif } IPAddress &IPAddress::from_ip_addr_t(const ip_addr_t *addr) { +#if CONFIG_LWIP_IPV6 if (addr->type == IPADDR_TYPE_V6) { _type = IPv6; _address.dword[0] = addr->u_addr.ip6.addr[0]; @@ -394,13 +422,21 @@ IPAddress &IPAddress::from_ip_addr_t(const ip_addr_t *addr) { _zone = addr->u_addr.ip6.zone; #endif /* LWIP_IPV6_SCOPES */ } else { +#endif _type = IPv4; memset(_address.bytes, 0, sizeof(_address.bytes)); +#if CONFIG_LWIP_IPV6 _address.dword[IPADDRESS_V4_DWORD_INDEX] = addr->u_addr.ip4.addr; +#else + _address.dword[IPADDRESS_V4_DWORD_INDEX] = addr->addr; +#endif +#if CONFIG_LWIP_IPV6 } +#endif return *this; } +#if CONFIG_LWIP_IPV6 esp_ip6_addr_type_t IPAddress::addr_type() const { if (_type != IPv6) { return ESP_IP6_ADDR_IS_UNKNOWN; @@ -409,6 +445,9 @@ esp_ip6_addr_type_t IPAddress::addr_type() const { to_ip_addr_t(&addr); return esp_netif_ip6_get_addr_type((esp_ip6_addr_t *)(&(addr.u_addr.ip6))); } +#endif +#if CONFIG_LWIP_IPV6 const IPAddress IN6ADDR_ANY(IPv6); +#endif const IPAddress INADDR_NONE(0, 0, 0, 0); diff --git a/cores/esp32/IPAddress.h b/cores/esp32/IPAddress.h index b88aeed3026..923f4dd5ca6 100644 --- a/cores/esp32/IPAddress.h +++ b/cores/esp32/IPAddress.h @@ -24,6 +24,7 @@ #include "WString.h" #include "lwip/ip_addr.h" #include "esp_netif_ip_addr.h" +#include "sdkconfig.h" #define IPADDRESS_V4_BYTES_INDEX 12 #define IPADDRESS_V4_DWORD_INDEX 3 @@ -115,7 +116,9 @@ class IPAddress : public Printable { IPAddress(const ip_addr_t *addr); void to_ip_addr_t(ip_addr_t *addr) const; IPAddress &from_ip_addr_t(const ip_addr_t *addr); +#if CONFIG_LWIP_IPV6 esp_ip6_addr_type_t addr_type() const; +#endif uint8_t zone() const { return (type() == IPv6) ? _zone : 0; } diff --git a/cores/esp32/Stream.cpp b/cores/esp32/Stream.cpp index 1eb8e512a32..5c2060eaa35 100644 --- a/cores/esp32/Stream.cpp +++ b/cores/esp32/Stream.cpp @@ -18,14 +18,14 @@ Created July 2011 parsing functions based on TextFinder library by Michael Margolis + + findMulti/findUntil routines written by Jim Leonard/Xuth */ #include "Arduino.h" #include "Stream.h" -#include "esp32-hal.h" #define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait -#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field // private method to read stream with timeout int Stream::timedRead() { @@ -55,18 +55,26 @@ int Stream::timedPeek() { // returns peek of the next digit in the stream or -1 if timeout // discards non-numeric characters -int Stream::peekNextDigit() { +int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal) { int c; while (1) { c = timedPeek(); - if (c < 0) { - return c; // timeout - } - if (c == '-') { + + if (c < 0 || c == '-' || (c >= '0' && c <= '9') || (detectDecimal && c == '.')) { return c; } - if (c >= '0' && c <= '9') { - return c; + + switch (lookahead) { + case SKIP_NONE: return -1; // Fail code. + case SKIP_WHITESPACE: + switch (c) { + case ' ': + case '\t': + case '\r': + case '\n': break; + default: return -1; // Fail code. + } + case SKIP_ALL: break; } read(); // discard non-numeric } @@ -79,9 +87,6 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi { _timeout = timeout; } -unsigned long Stream::getTimeout(void) { - return _timeout; -} // find returns true if the target string is found bool Stream::find(const char *target) { @@ -105,107 +110,32 @@ bool Stream::findUntil(const char *target, const char *terminator) { bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen) { if (terminator == NULL) { MultiTarget t[1] = {{target, targetLen, 0}}; - return findMulti(t, 1) == 0 ? true : false; + return findMulti(t, 1) == 0; } else { MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}}; - return findMulti(t, 2) == 0 ? true : false; + return findMulti(t, 2) == 0; } } -int Stream::findMulti(struct Stream::MultiTarget *targets, int tCount) { - // any zero length target string automatically matches and would make - // a mess of the rest of the algorithm. - for (struct MultiTarget *t = targets; t < targets + tCount; ++t) { - if (t->len <= 0) { - return t - targets; - } - } - - while (1) { - int c = timedRead(); - if (c < 0) { - return -1; - } - - for (struct MultiTarget *t = targets; t < targets + tCount; ++t) { - // the simple case is if we match, deal with that first. - if (c == t->str[t->index]) { - if (++t->index == t->len) { - return t - targets; - } else { - continue; - } - } - - // if not we need to walk back and see if we could have matched further - // down the stream (ie '1112' doesn't match the first position in '11112' - // but it will match the second position so we can't just reset the current - // index to 0 when we find a mismatch. - if (t->index == 0) { - continue; - } - - int origIndex = t->index; - do { - --t->index; - // first check if current char works against the new current index - if (c != t->str[t->index]) { - continue; - } - - // if it's the only char then we're good, nothing more to check - if (t->index == 0) { - t->index++; - break; - } - - // otherwise we need to check the rest of the found string - int diff = origIndex - t->index; - size_t i; - for (i = 0; i < t->index; ++i) { - if (t->str[i] != t->str[i + diff]) { - break; - } - } - - // if we successfully got through the previous loop then our current - // index is good. - if (i == t->index) { - t->index++; - break; - } - - // otherwise we just try the next index - } while (t->index); - } - } - // unreachable - return -1; -} - // returns the first valid (long) integer value from the current position. -// initial characters that are not digits (or the minus sign) are skipped -// function is terminated by the first character that is not a digit. -long Stream::parseInt() { - return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) -} - -// as above but a given skipChar is ignored -// this allows format characters (typically commas) in values to be ignored -long Stream::parseInt(char skipChar) { - boolean isNegative = false; +// lookahead determines how parseInt looks ahead in the stream. +// See LookaheadMode enumeration at the top of the file. +// Lookahead is terminated by the first character that is not a valid part of an integer. +// Once parsing commences, 'ignore' will be skipped in the stream. +long Stream::parseInt(LookaheadMode lookahead, char ignore) { + bool isNegative = false; long value = 0; int c; - c = peekNextDigit(); + c = peekNextDigit(lookahead, false); // ignore non numeric leading characters if (c < 0) { return 0; // zero returned if timeout } do { - if (c == skipChar) { - } // ignore this character + if ((char)c == ignore) + ; // ignore this character else if (c == '-') { isNegative = true; } else if (c >= '0' && c <= '9') { // is c a digit? @@ -213,7 +143,7 @@ long Stream::parseInt(char skipChar) { } read(); // consume the character we got with peek c = timedPeek(); - } while ((c >= '0' && c <= '9') || c == skipChar); + } while ((c >= '0' && c <= '9') || (char)c == ignore); if (isNegative) { value = -value; @@ -222,50 +152,43 @@ long Stream::parseInt(char skipChar) { } // as parseInt but returns a floating point value -float Stream::parseFloat() { - return parseFloat(NO_SKIP_CHAR); -} - -// as above but the given skipChar is ignored -// this allows format characters (typically commas) in values to be ignored -float Stream::parseFloat(char skipChar) { - boolean isNegative = false; - boolean isFraction = false; - long value = 0; +float Stream::parseFloat(LookaheadMode lookahead, char ignore) { + bool isNegative = false; + bool isFraction = false; + double value = 0.0; int c; - float fraction = 1.0; + double fraction = 1.0; - c = peekNextDigit(); + c = peekNextDigit(lookahead, true); // ignore non numeric leading characters if (c < 0) { return 0; // zero returned if timeout } do { - if (c == skipChar) { - } // ignore + if ((char)c == ignore) + ; // ignore else if (c == '-') { isNegative = true; } else if (c == '.') { isFraction = true; } else if (c >= '0' && c <= '9') { // is c a digit? - value = value * 10 + c - '0'; if (isFraction) { - fraction *= 0.1f; + fraction *= 0.1; + value = value + fraction * (c - '0'); + } else { + value = value * 10 + c - '0'; } } read(); // consume the character we got with peek c = timedPeek(); - } while ((c >= '0' && c <= '9') || c == '.' || c == skipChar); + } while ((c >= '0' && c <= '9') || (c == '.' && !isFraction) || (char)c == ignore); if (isNegative) { value = -value; } - if (isFraction) { - return value * fraction; - } else { - return value; - } + + return value; } // read characters from stream into buffer @@ -291,13 +214,10 @@ size_t Stream::readBytes(char *buffer, size_t length) { // returns the number of characters placed in the buffer (0 means no valid data found) size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) { - if (length < 1) { - return 0; - } size_t index = 0; while (index < length) { int c = timedRead(); - if (c < 0 || c == terminator) { + if (c < 0 || (char)c == terminator) { break; } *buffer++ = (char)c; @@ -319,9 +239,80 @@ String Stream::readString() { String Stream::readStringUntil(char terminator) { String ret; int c = timedRead(); - while (c >= 0 && c != terminator) { + while (c >= 0 && (char)c != terminator) { ret += (char)c; c = timedRead(); } return ret; } + +int Stream::findMulti(struct Stream::MultiTarget *targets, int tCount) { + // any zero length target string automatically matches and would make + // a mess of the rest of the algorithm. + for (struct MultiTarget *t = targets; t < targets + tCount; ++t) { + if (t->len <= 0) { + return t - targets; + } + } + + while (1) { + int c = timedRead(); + if (c < 0) { + return -1; + } + + for (struct MultiTarget *t = targets; t < targets + tCount; ++t) { + // the simple case is if we match, deal with that first. + if ((char)c == t->str[t->index]) { + if (++t->index == t->len) { + return t - targets; + } else { + continue; + } + } + + // if not we need to walk back and see if we could have matched further + // down the stream (ie '1112' doesn't match the first position in '11112' + // but it will match the second position so we can't just reset the current + // index to 0 when we find a mismatch. + if (t->index == 0) { + continue; + } + + int origIndex = t->index; + do { + --t->index; + // first check if current char works against the new current index + if ((char)c != t->str[t->index]) { + continue; + } + + // if it's the only char then we're good, nothing more to check + if (t->index == 0) { + t->index++; + break; + } + + // otherwise we need to check the rest of the found string + int diff = origIndex - t->index; + size_t i; + for (i = 0; i < t->index; ++i) { + if (t->str[i] != t->str[i + diff]) { + break; + } + } + + // if we successfully got through the previous loop then our current + // index is good. + if (i == t->index) { + t->index++; + break; + } + + // otherwise we just try the next index + } while (t->index); + } + } + // unreachable + return -1; +} diff --git a/cores/esp32/Stream.h b/cores/esp32/Stream.h index 5a83747a55f..37346cdb99f 100644 --- a/cores/esp32/Stream.h +++ b/cores/esp32/Stream.h @@ -1,72 +1,83 @@ /* - Stream.h - base class for character-based streams. - Copyright (c) 2010 David A. Mellis. All right reserved. + Stream.h - base class for character-based streams. + Copyright (c) 2010 David A. Mellis. All right reserved. - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - parsing functions based on TextFinder library by Michael Margolis - */ + parsing functions based on TextFinder library by Michael Margolis +*/ -#ifndef Stream_h -#define Stream_h +#pragma once #include #include "Print.h" // compatibility macros for testing /* - #define getInt() parseInt() - #define getInt(skipChar) parseInt(skipchar) - #define getFloat() parseFloat() - #define getFloat(skipChar) parseFloat(skipChar) - #define getString( pre_string, post_string, buffer, length) - readBytesBetween( pre_string, terminator, buffer, length) - */ +#define getInt() parseInt() +#define getInt(ignore) parseInt(ignore) +#define getFloat() parseFloat() +#define getFloat(ignore) parseFloat(ignore) +#define getString( pre_string, post_string, buffer, length) +readBytesBetween( pre_string, terminator, buffer, length) +*/ + +// This enumeration provides the lookahead options for parseInt(), parseFloat() +// The rules set out here are used until either the first valid character is found +// or a time out occurs due to lack of input. +enum LookaheadMode { + SKIP_ALL, // All invalid characters are ignored. + SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid. + SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped. +}; + +#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field class Stream : public Print { protected: - unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read - unsigned long _startMillis; // used for timeout measurement - int timedRead(); // private method to read stream with timeout - int timedPeek(); // private method to peek stream with timeout - int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout + unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read + unsigned long _startMillis; // used for timeout measurement + int timedRead(); // private method to read stream with timeout + int timedPeek(); // private method to peek stream with timeout + int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout public: virtual int available() = 0; virtual int read() = 0; virtual int peek() = 0; - Stream() : _startMillis(0) { + Stream() { _timeout = 1000; } - virtual ~Stream() {} // parsing methods void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second - unsigned long getTimeout(void); + unsigned long getTimeout(void) { + return _timeout; + } bool find(const char *target); // reads data from the stream until the target string is found - bool find(uint8_t *target) { - return find((char *)target); + bool find(const uint8_t *target) { + return find((const char *)target); } // returns true if target string is found, false if timed out (see setTimeout) bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found bool find(const uint8_t *target, size_t length) { - return find((char *)target, length); + return find((const char *)target, length); } // returns true if target string is found, false if timed out @@ -76,19 +87,23 @@ class Stream : public Print { bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found bool findUntil(const uint8_t *target, const char *terminator) { - return findUntil((char *)target, terminator); + return findUntil((const char *)target, terminator); } bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) { - return findUntil((char *)target, targetLen, terminate, termLen); + return findUntil((const char *)target, targetLen, terminate, termLen); } - long parseInt(); // returns the first valid (long) integer value from the current position. - // initial characters that are not digits (or the minus sign) are skipped - // integer is terminated by the first character that is not a digit. + long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); + // returns the first valid (long) integer value from the current position. + // lookahead determines how parseInt looks ahead in the stream. + // See LookaheadMode enumeration at the top of the file. + // Lookahead is terminated by the first character that is not a valid part of an integer. + // Once parsing commences, 'ignore' will be skipped in the stream. - float parseFloat(); // float version of parseInt + float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); + // float version of parseInt virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer virtual size_t readBytes(uint8_t *buffer, size_t length) { @@ -109,11 +124,15 @@ class Stream : public Print { String readStringUntil(char terminator); protected: - long parseInt(char skipChar); // as above but the given skipChar is ignored - // as above but the given skipChar is ignored - // this allows format characters (typically commas) in values to be ignored - - float parseFloat(char skipChar); // as above but the given skipChar is ignored + long parseInt(char ignore) { + return parseInt(SKIP_ALL, ignore); + } + float parseFloat(char ignore) { + return parseFloat(SKIP_ALL, ignore); + } + // These overload exists for compatibility with any class that has derived + // Stream and used parseFloat/Int with a custom ignore character. To keep + // the public API simple, these overload remains protected. struct MultiTarget { const char *str; // string you're searching for @@ -126,4 +145,4 @@ class Stream : public Print { int findMulti(struct MultiTarget *targets, int tCount); }; -#endif +#undef NO_IGNORE_CHAR diff --git a/cores/esp32/Tone.cpp b/cores/esp32/Tone.cpp index bb1e8d745c0..ec8587d8de3 100644 --- a/cores/esp32/Tone.cpp +++ b/cores/esp32/Tone.cpp @@ -4,9 +4,11 @@ #include "freertos/queue.h" #include "freertos/semphr.h" +#if SOC_LEDC_SUPPORTED static TaskHandle_t _tone_task = NULL; static QueueHandle_t _tone_queue = NULL; static int8_t _pin = -1; +static uint8_t _channel = 255; typedef enum { TONE_START, @@ -20,6 +22,12 @@ typedef struct { unsigned long duration; } tone_msg_t; +#ifdef SOC_LEDC_SUPPORT_HS_MODE +#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM << 1) +#else +#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM) +#endif + static void tone_task(void *) { tone_msg_t tone_msg; while (1) { @@ -29,7 +37,13 @@ static void tone_task(void *) { log_d("Task received from queue TONE_START: pin=%d, frequency=%u Hz, duration=%lu ms", tone_msg.pin, tone_msg.frequency, tone_msg.duration); if (_pin == -1) { - if (ledcAttach(tone_msg.pin, tone_msg.frequency, 10) == 0) { + bool ret = true; + if (_channel == 255) { + ret = ledcAttach(tone_msg.pin, tone_msg.frequency, 10); + } else { + ret = ledcAttachChannel(tone_msg.pin, tone_msg.frequency, 10, _channel); + } + if (!ret) { log_e("Tone start failed"); break; } @@ -73,7 +87,7 @@ static int tone_init() { "toneTask", // Name of the task 3500, // Stack size in words NULL, // Task input parameter - 1, // Priority of the task + 10, // Priority of the task must be higher than Arduino task &_tone_task // Task handle. ); if (_tone_task == NULL) { @@ -126,3 +140,13 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) { return; } } + +void setToneChannel(uint8_t channel) { + if (channel >= LEDC_CHANNELS) { + log_e("Channel %u is not available (maximum %u)!", channel, LEDC_CHANNELS); + return; + } + _channel = channel; +} + +#endif /* SOC_LEDC_SUPPORTED */ diff --git a/cores/esp32/USB.cpp b/cores/esp32/USB.cpp index 8fdd7a3ab71..269e9a76cb3 100644 --- a/cores/esp32/USB.cpp +++ b/cores/esp32/USB.cpp @@ -100,6 +100,7 @@ static bool tinyusb_device_suspended = false; void tud_mount_cb(void) { tinyusb_device_mounted = true; arduino_usb_event_data_t p; + p.suspend.remote_wakeup_en = 0; arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STARTED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY); } @@ -107,6 +108,7 @@ void tud_mount_cb(void) { void tud_umount_cb(void) { tinyusb_device_mounted = false; arduino_usb_event_data_t p; + p.suspend.remote_wakeup_en = 0; arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY); } @@ -123,6 +125,7 @@ void tud_suspend_cb(bool remote_wakeup_en) { void tud_resume_cb(void) { tinyusb_device_suspended = false; arduino_usb_event_data_t p; + p.suspend.remote_wakeup_en = 0; arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_RESUME_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY); } diff --git a/cores/esp32/USBCDC.cpp b/cores/esp32/USBCDC.cpp index 2689086013a..c7bb4582d4f 100644 --- a/cores/esp32/USBCDC.cpp +++ b/cores/esp32/USBCDC.cpp @@ -25,13 +25,29 @@ ESP_EVENT_DEFINE_BASE(ARDUINO_USB_CDC_EVENTS); esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait); esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg); -#define MAX_USB_CDC_DEVICES 2 -USBCDC *devices[MAX_USB_CDC_DEVICES] = {NULL, NULL}; +USBCDC *devices[CFG_TUD_CDC]; static uint16_t load_cdc_descriptor(uint8_t *dst, uint8_t *itf) { uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC"); uint8_t descriptor[TUD_CDC_DESC_LEN] = {// Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, 64, 0x03, 0x84, 64) + TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, CFG_TUD_ENDOINT_SIZE, 0x03, 0x84, CFG_TUD_ENDOINT_SIZE) + }; + *itf += 2; + memcpy(dst, descriptor, TUD_CDC_DESC_LEN); + return TUD_CDC_DESC_LEN; +} + +static uint16_t load_cdc_descriptor2(uint8_t *dst, uint8_t *itf) { + uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC2"); + uint8_t ep_ntfy = tinyusb_get_free_in_endpoint(); + TU_VERIFY(ep_ntfy != 0); + uint8_t ep_in = tinyusb_get_free_in_endpoint(); + TU_VERIFY(ep_in != 0); + uint8_t ep_out = tinyusb_get_free_out_endpoint(); + TU_VERIFY(ep_out != 0); + uint8_t descriptor[TUD_CDC_DESC_LEN] = { + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(*itf, str_index, (uint8_t)(0x80 | ep_ntfy), CFG_TUD_ENDOINT_SIZE, ep_out, (uint8_t)(0x80 | ep_in), CFG_TUD_ENDOINT_SIZE) }; *itf += 2; memcpy(dst, descriptor, TUD_CDC_DESC_LEN); @@ -40,21 +56,24 @@ static uint16_t load_cdc_descriptor(uint8_t *dst, uint8_t *itf) { // Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { - if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) { + //log_v("ITF: %u, DTR: %u, RTS: %u", itf, dtr, rts); + if (itf < CFG_TUD_CDC && devices[itf] != NULL) { devices[itf]->_onLineState(dtr, rts); } } // Invoked when line coding is change via SET_LINE_CODING void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding) { - if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) { + //log_v("ITF: %u, BITRATE: %lu, STOP_BITS: %u, PARITY: %u, DATA_BITS: %u", itf, p_line_coding->bit_rate, p_line_coding->stop_bits, p_line_coding->parity, p_line_coding->data_bits); + if (itf < CFG_TUD_CDC && devices[itf] != NULL) { devices[itf]->_onLineCoding(p_line_coding->bit_rate, p_line_coding->stop_bits, p_line_coding->parity, p_line_coding->data_bits); } } // Invoked when received new data void tud_cdc_rx_cb(uint8_t itf) { - if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) { + //log_v("ITF: %u", itf); + if (itf < CFG_TUD_CDC && devices[itf] != NULL) { devices[itf]->_onRX(); } } @@ -66,13 +85,13 @@ void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms) { // Invoked when space becomes available in TX buffer void tud_cdc_tx_complete_cb(uint8_t itf) { - if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) { + if (itf < CFG_TUD_CDC && devices[itf] != NULL) { devices[itf]->_onTX(); } } static void ARDUINO_ISR_ATTR cdc0_write_char(char c) { - if (devices[0] != NULL) { + if (CFG_TUD_CDC && devices[0] != NULL) { tud_cdc_n_write_char(0, c); } } @@ -84,9 +103,15 @@ static void usb_unplugged_cb(void *arg, esp_event_base_t event_base, int32_t eve USBCDC::USBCDC(uint8_t itfn) : itf(itfn), bit_rate(0), stop_bits(0), parity(0), data_bits(0), dtr(false), rts(false), connected(false), reboot_enable(true), rx_queue(NULL), tx_lock(NULL), tx_timeout_ms(250) { - tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor); - if (itf < MAX_USB_CDC_DEVICES) { + if (itf < CFG_TUD_CDC) { + if (itf == 0) { + tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor); + } else { + tinyusb_enable_interface(USB_INTERFACE_CDC2, TUD_CDC_DESC_LEN, load_cdc_descriptor2); + } arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this); + } else { + log_e("Maximum of %u CDC devices are supported", CFG_TUD_CDC); } } @@ -142,6 +167,9 @@ size_t USBCDC::setRxBufferSize(size_t rx_queue_len) { } void USBCDC::begin(unsigned long baud) { + if (itf >= CFG_TUD_CDC) { + return; + } if (tx_lock == NULL) { tx_lock = xSemaphoreCreateMutex(); } @@ -153,6 +181,9 @@ void USBCDC::begin(unsigned long baud) { } void USBCDC::end() { + if (itf >= CFG_TUD_CDC) { + return; + } connected = false; devices[itf] = NULL; setRxBufferSize(0); @@ -298,14 +329,14 @@ bool USBCDC::rebootEnabled(void) { } int USBCDC::available(void) { - if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) { + if (itf >= CFG_TUD_CDC || rx_queue == NULL) { return -1; } return uxQueueMessagesWaiting(rx_queue); } int USBCDC::peek(void) { - if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) { + if (itf >= CFG_TUD_CDC || rx_queue == NULL) { return -1; } uint8_t c; @@ -316,7 +347,7 @@ int USBCDC::peek(void) { } int USBCDC::read(void) { - if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) { + if (itf >= CFG_TUD_CDC || rx_queue == NULL) { return -1; } uint8_t c = 0; @@ -327,7 +358,7 @@ int USBCDC::read(void) { } size_t USBCDC::read(uint8_t *buffer, size_t size) { - if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) { + if (itf >= CFG_TUD_CDC || rx_queue == NULL) { return -1; } uint8_t c = 0; @@ -339,7 +370,7 @@ size_t USBCDC::read(uint8_t *buffer, size_t size) { } void USBCDC::flush(void) { - if (itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || !tud_cdc_n_connected(itf)) { + if (itf >= CFG_TUD_CDC || tx_lock == NULL || !tud_cdc_n_connected(itf)) { return; } if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) { @@ -350,7 +381,7 @@ void USBCDC::flush(void) { } int USBCDC::availableForWrite(void) { - if (itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || !tud_cdc_n_connected(itf)) { + if (itf >= CFG_TUD_CDC || tx_lock == NULL || !tud_cdc_n_connected(itf)) { return 0; } if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) { @@ -362,7 +393,7 @@ int USBCDC::availableForWrite(void) { } size_t USBCDC::write(const uint8_t *buffer, size_t size) { - if (itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || buffer == NULL || size == 0 || !tud_cdc_n_connected(itf)) { + if (itf >= CFG_TUD_CDC || tx_lock == NULL || buffer == NULL || size == 0 || !tud_cdc_n_connected(itf)) { return 0; } if (xPortInIsrContext()) { @@ -415,16 +446,20 @@ uint32_t USBCDC::baudRate() { } void USBCDC::setDebugOutput(bool en) { + if (itf) { + return; + } if (en) { uartSetDebug(NULL); ets_install_putc2((void (*)(char)) & cdc0_write_char); } else { ets_install_putc2(NULL); } + ets_install_putc1(NULL); // closes UART log output } USBCDC::operator bool() const { - if (itf >= MAX_USB_CDC_DEVICES) { + if (itf >= CFG_TUD_CDC) { return false; } return connected; diff --git a/cores/esp32/USBMSC.cpp b/cores/esp32/USBMSC.cpp index eeaf3026535..aeb79883f0d 100644 --- a/cores/esp32/USBMSC.cpp +++ b/cores/esp32/USBMSC.cpp @@ -24,7 +24,7 @@ extern "C" uint16_t tusb_msc_load_descriptor(uint8_t *dst, uint8_t *itf) { uint8_t ep_num = tinyusb_get_free_duplex_endpoint(); TU_VERIFY(ep_num != 0); uint8_t descriptor[TUD_MSC_DESC_LEN] = {// Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(*itf, str_index, ep_num, (uint8_t)(0x80 | ep_num), 64) + TUD_MSC_DESCRIPTOR(*itf, str_index, ep_num, (uint8_t)(0x80 | ep_num), CFG_TUD_ENDOINT_SIZE) }; *itf += 1; memcpy(dst, descriptor, TUD_MSC_DESC_LEN); diff --git a/cores/esp32/WString.cpp b/cores/esp32/WString.cpp index 71183213ac2..18e64767545 100644 --- a/cores/esp32/WString.cpp +++ b/cores/esp32/WString.cpp @@ -226,11 +226,11 @@ bool String::changeBuffer(unsigned int maxStrLen) { /*********************************************/ String &String::copy(const char *cstr, unsigned int length) { - if (!reserve(length)) { + if (cstr == nullptr || !reserve(length)) { invalidate(); return *this; } - memmove(wbuffer(), cstr, length + 1); + memmove(wbuffer(), cstr, length); setLen(length); return *this; } @@ -239,15 +239,18 @@ String &String::copy(const char *cstr, unsigned int length) { void String::move(String &rhs) { if (buffer()) { if (capacity() >= rhs.len()) { - memmove(wbuffer(), rhs.buffer(), rhs.length() + 1); + // Use case: When 'reserve()' was called and the first + // assignment/append is the return value of a function. + if (rhs.len() && rhs.buffer()) { + memmove(wbuffer(), rhs.buffer(), rhs.length()); + } setLen(rhs.len()); rhs.invalidate(); return; - } else { - if (!isSSO()) { - free(wbuffer()); - setBuffer(nullptr); - } + } + if (!isSSO()) { + free(wbuffer()); + setBuffer(nullptr); } } if (rhs.isSSO()) { @@ -259,10 +262,7 @@ void String::move(String &rhs) { } setCapacity(rhs.capacity()); setLen(rhs.len()); - rhs.setSSO(false); - rhs.setCapacity(0); - rhs.setBuffer(nullptr); - rhs.setLen(0); + rhs.init(); } #endif @@ -270,12 +270,7 @@ String &String::operator=(const String &rhs) { if (this == &rhs) { return *this; } - if (rhs.buffer()) { - copy(rhs.buffer(), rhs.len()); - } else { - invalidate(); - } - return *this; + return copy(rhs.buffer(), rhs.len()); } #ifdef __GXX_EXPERIMENTAL_CXX0X__ @@ -295,12 +290,8 @@ String &String::operator=(StringSumHelper &&rval) { #endif String &String::operator=(const char *cstr) { - if (cstr) { - copy(cstr, strlen(cstr)); - } else { - invalidate(); - } - return *this; + const uint32_t length = cstr ? strlen(cstr) : 0u; + return copy(cstr, length); } /*********************************************/ @@ -311,23 +302,21 @@ bool String::concat(const String &s) { // Special case if we're concatting ourself (s += s;) since we may end up // realloc'ing the buffer and moving s.buffer in the method called if (&s == this) { - unsigned int newlen = 2 * len(); - if (!s.buffer()) { - return false; - } if (s.len() == 0) { return true; } + if (!s.buffer()) { + return false; + } + unsigned int newlen = 2 * len(); if (!reserve(newlen)) { return false; } memmove(wbuffer() + len(), buffer(), len()); setLen(newlen); - wbuffer()[len()] = 0; return true; - } else { - return concat(s.buffer(), s.len()); } + return concat(s.buffer(), s.len()); } bool String::concat(const char *cstr, unsigned int length) { @@ -343,10 +332,10 @@ bool String::concat(const char *cstr, unsigned int length) { } if (cstr >= wbuffer() && cstr < wbuffer() + len()) { // compatible with SSO in ram #6155 (case "x += x.c_str()") - memmove(wbuffer() + len(), cstr, length + 1); + memmove(wbuffer() + len(), cstr, length); } else { // compatible with source in flash #6367 - memcpy_P(wbuffer() + len(), cstr, length + 1); + memcpy_P(wbuffer() + len(), cstr, length); } setLen(newlen); return true; diff --git a/cores/esp32/chip-debug-report.cpp b/cores/esp32/chip-debug-report.cpp index c5b9866e3cc..daafef3cab9 100644 --- a/cores/esp32/chip-debug-report.cpp +++ b/cores/esp32/chip-debug-report.cpp @@ -64,6 +64,9 @@ static void printPkgVersion(void) { #elif CONFIG_IDF_TARGET_ESP32H2 uint32_t pkg_ver = REG_GET_FIELD(EFUSE_RD_MAC_SYS_4_REG, EFUSE_PKG_VERSION); chip_report_printf("%lu", pkg_ver); +#elif CONFIG_IDF_TARGET_ESP32P4 + uint32_t pkg_ver = REG_GET_FIELD(EFUSE_RD_MAC_SYS_2_REG, EFUSE_PKG_VERSION); + chip_report_printf("%lu", pkg_ver); #else chip_report_printf("Unknown"); #endif @@ -84,20 +87,17 @@ static void printChipInfo(void) { case CHIP_ESP32C3: chip_report_printf("ESP32-C3\n"); break; case CHIP_ESP32C6: chip_report_printf("ESP32-C6\n"); break; case CHIP_ESP32H2: chip_report_printf("ESP32-H2\n"); break; + case CHIP_ESP32P4: chip_report_printf("ESP32-P4\n"); break; default: chip_report_printf("Unknown %d\n", info.model); break; } printPkgVersion(); - chip_report_printf(" Revision : "); - if (info.revision > 0xFF) { - chip_report_printf("%d.%d\n", info.revision >> 8, info.revision & 0xFF); - } else { - chip_report_printf("%d\n", info.revision); - } + chip_report_printf(" Revision : %.2f\n", (float)(info.revision) / 100.0); chip_report_printf(" Cores : %d\n", info.cores); rtc_cpu_freq_config_t conf; rtc_clk_cpu_freq_get_config(&conf); chip_report_printf(" CPU Frequency : %lu MHz\n", conf.freq_mhz); chip_report_printf(" XTAL Frequency : %d MHz\n", rtc_clk_xtal_freq_get()); + chip_report_printf(" Features Bitfield : %#010x\n", info.features); chip_report_printf(" Embedded Flash : %s\n", (info.features & CHIP_FEATURE_EMB_FLASH) ? "Yes" : "No"); chip_report_printf(" Embedded PSRAM : %s\n", (info.features & CHIP_FEATURE_EMB_PSRAM) ? "Yes" : "No"); chip_report_printf(" 2.4GHz WiFi : %s\n", (info.features & CHIP_FEATURE_WIFI_BGN) ? "Yes" : "No"); @@ -109,6 +109,8 @@ static void printChipInfo(void) { static void printFlashInfo(void) { #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 #define ESP_FLASH_IMAGE_BASE 0x1000 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define ESP_FLASH_IMAGE_BASE 0x2000 #else #define ESP_FLASH_IMAGE_BASE 0x0000 #endif diff --git a/cores/esp32/esp32-hal-adc.c b/cores/esp32/esp32-hal-adc.c index 6788f2eb123..c7cc1f5d556 100644 --- a/cores/esp32/esp32-hal-adc.c +++ b/cores/esp32/esp32-hal-adc.c @@ -75,7 +75,7 @@ static bool adcDetachBus(void *pin) { if (err != ESP_OK) { return false; } -#elif !defined(CONFIG_IDF_TARGET_ESP32H2) +#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle); if (err != ESP_OK) { return false; @@ -127,7 +127,7 @@ esp_err_t __analogChannelConfig(adc_bitwidth_t width, adc_attenuation_t atten, i log_e("adc_cali_create_scheme_curve_fitting failed with error: %d", err); return err; } -#elif !defined(CONFIG_IDF_TARGET_ESP32H2) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED +#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED log_d("Deleting ADC_UNIT_%d line cali handle", adc_unit); err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle); if (err != ESP_OK) { @@ -310,7 +310,7 @@ uint32_t __analogReadMilliVolts(uint8_t pin) { .bitwidth = __analogWidth, }; err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_handle[adc_unit].adc_cali_handle); -#elif !defined(CONFIG_IDF_TARGET_ESP32H2) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED +#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED adc_cali_line_fitting_config_t cali_config = { .unit_id = adc_unit, .bitwidth = __analogWidth, @@ -379,7 +379,7 @@ static bool adcContinuousDetachBus(void *adc_unit_number) { if (err != ESP_OK) { return false; } -#elif !defined(CONFIG_IDF_TARGET_ESP32H2) +#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle); if (err != ESP_OK) { return false; @@ -456,7 +456,7 @@ esp_err_t __analogContinuousInit(adc_channel_t *channel, uint8_t channel_num, ad return ESP_OK; } -bool analogContinuous(uint8_t pins[], size_t pins_count, uint32_t conversions_per_pin, uint32_t sampling_freq_hz, void (*userFunc)(void)) { +bool analogContinuous(const uint8_t pins[], size_t pins_count, uint32_t conversions_per_pin, uint32_t sampling_freq_hz, void (*userFunc)(void)) { adc_channel_t channel[pins_count]; adc_unit_t adc_unit = ADC_UNIT_1; esp_err_t err = ESP_OK; @@ -552,7 +552,7 @@ bool analogContinuous(uint8_t pins[], size_t pins_count, uint32_t conversions_pe .bitwidth = __adcContinuousWidth, }; err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_handle[adc_unit].adc_cali_handle); -#elif !defined(CONFIG_IDF_TARGET_ESP32H2) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED +#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED adc_cali_line_fitting_config_t cali_config = { .unit_id = adc_unit, .bitwidth = __adcContinuousWidth, diff --git a/cores/esp32/esp32-hal-adc.h b/cores/esp32/esp32-hal-adc.h index 636057b4f18..6ab5c920cfc 100644 --- a/cores/esp32/esp32-hal-adc.h +++ b/cores/esp32/esp32-hal-adc.h @@ -91,7 +91,7 @@ typedef struct { /* * Setup ADC continuous peripheral * */ -bool analogContinuous(uint8_t pins[], size_t pins_count, uint32_t conversions_per_pin, uint32_t sampling_freq_hz, void (*userFunc)(void)); +bool analogContinuous(const uint8_t pins[], size_t pins_count, uint32_t conversions_per_pin, uint32_t sampling_freq_hz, void (*userFunc)(void)); /* * Read ADC continuous conversion data diff --git a/cores/esp32/esp32-hal-bt.c b/cores/esp32/esp32-hal-bt.c index 5f1148bd492..1e5f73e324c 100644 --- a/cores/esp32/esp32-hal-bt.c +++ b/cores/esp32/esp32-hal-bt.c @@ -15,7 +15,7 @@ #include "esp32-hal-bt.h" #if SOC_BT_SUPPORTED -#ifdef CONFIG_BT_ENABLED +#ifdef CONFIG_BT_BLUEDROID_ENABLED #if CONFIG_IDF_TARGET_ESP32 bool btInUse() { diff --git a/cores/esp32/esp32-hal-cpu.c b/cores/esp32/esp32-hal-cpu.c index 7027c7cad9d..1ffde860792 100644 --- a/cores/esp32/esp32-hal-cpu.c +++ b/cores/esp32/esp32-hal-cpu.c @@ -19,9 +19,9 @@ #include "esp_attr.h" #include "esp_log.h" #include "soc/rtc.h" -#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) +#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4) #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #endif #include "soc/efuse_reg.h" #include "esp32-hal.h" @@ -30,13 +30,13 @@ #include "esp_system.h" #ifdef ESP_IDF_VERSION_MAJOR // IDF 4+ #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 -#include "freertos/xtensa_timer.h" +#include "xtensa_timer.h" #include "esp32/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32S2 -#include "freertos/xtensa_timer.h" +#include "xtensa_timer.h" #include "esp32s2/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32S3 -#include "freertos/xtensa_timer.h" +#include "xtensa_timer.h" #include "esp32s3/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32C2 #include "esp32c2/rom/rtc.h" @@ -46,6 +46,8 @@ #include "esp32c6/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/rtc.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif @@ -161,13 +163,13 @@ bool removeApbChangeCallback(void *arg, apb_change_cb_t cb) { } static uint32_t calculateApb(rtc_cpu_freq_config_t *conf) { -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 - return APB_CLK_FREQ; -#else +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 if (conf->freq_mhz >= 80) { return 80 * MHZ; } return (conf->source_freq_mhz * MHZ) / conf->div; +#else + return APB_CLK_FREQ; #endif } @@ -177,7 +179,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { rtc_cpu_freq_config_t conf, cconf; uint32_t capb, apb; //Get XTAL Frequency and calculate min CPU MHz -#ifndef CONFIG_IDF_TARGET_ESP32H2 +#if (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) rtc_xtal_freq_t xtal = rtc_clk_xtal_freq_get(); #endif #if CONFIG_IDF_TARGET_ESP32 @@ -193,7 +195,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { } } #endif -#ifndef CONFIG_IDF_TARGET_ESP32H2 +#if (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) if (cpu_freq_mhz > xtal && cpu_freq_mhz != 240 && cpu_freq_mhz != 160 && cpu_freq_mhz != 120 && cpu_freq_mhz != 80) { if (xtal >= RTC_XTAL_FREQ_40M) { log_e("Bad frequency: %u MHz! Options are: 240, 160, 120, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal / 2, xtal / 4); @@ -235,7 +237,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { } //Make the frequency change rtc_clk_cpu_freq_set_config_fast(&conf); -#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) +#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) if (capb != apb) { //Update REF_TICK (uncomment if REF_TICK is different than 1MHz) //if(conf.freq_mhz < 80){ @@ -248,11 +250,8 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { } #endif //Update FreeRTOS Tick Divisor -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 -#elif CONFIG_IDF_TARGET_ESP32S3 - -#else +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 uint32_t fcpu = (conf.freq_mhz >= 80) ? (conf.freq_mhz * MHZ) : (apb); _xt_tick_divisor = fcpu / XT_TICK_PER_SEC; #endif @@ -260,16 +259,15 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { if (apb_change_callbacks) { triggerApbChangeCallback(APB_AFTER_CHANGE, capb, apb); } -#ifdef SOC_CLK_APLL_SUPPORTED +#if defined(SOC_CLK_APLL_SUPPORTED) && !defined(CONFIG_IDF_TARGET_ESP32P4) // APLL not yet supported in ESP32-P4 log_d( "%s: %u / %u = %u Mhz, APB: %u Hz", - (conf.source == RTC_CPU_FREQ_SRC_PLL) ? "PLL" - : ((conf.source == RTC_CPU_FREQ_SRC_APLL) ? "APLL" : ((conf.source == RTC_CPU_FREQ_SRC_XTAL) ? "XTAL" : "8M")), + (conf.source == SOC_CPU_CLK_SRC_PLL) ? "PLL" : ((conf.source == SOC_CPU_CLK_SRC_APLL) ? "APLL" : ((conf.source == SOC_CPU_CLK_SRC_XTAL) ? "XTAL" : "8M")), conf.source_freq_mhz, conf.div, conf.freq_mhz, apb ); #else log_d( - "%s: %u / %u = %u Mhz, APB: %u Hz", (conf.source == RTC_CPU_FREQ_SRC_PLL) ? "PLL" : ((conf.source == RTC_CPU_FREQ_SRC_XTAL) ? "XTAL" : "17.5M"), + "%s: %u / %u = %u Mhz, APB: %u Hz", (conf.source == SOC_CPU_CLK_SRC_PLL) ? "PLL" : ((conf.source == SOC_CPU_CLK_SRC_XTAL) ? "XTAL" : "17.5M"), conf.source_freq_mhz, conf.div, conf.freq_mhz, apb ); #endif diff --git a/cores/esp32/esp32-hal-gpio.c b/cores/esp32/esp32-hal-gpio.c index b433adcc7fc..90ad1e7f36d 100644 --- a/cores/esp32/esp32-hal-gpio.c +++ b/cores/esp32/esp32-hal-gpio.c @@ -17,6 +17,16 @@ #include "hal/gpio_hal.h" #include "soc/soc_caps.h" +// RGB_BUILTIN is defined in pins_arduino.h +// If RGB_BUILTIN is defined, it will be used as a pin number for the RGB LED +// If RGB_BUILTIN has a side effect that prevents using RMT Legacy driver in IDF 5.1 +// Define ESP32_ARDUINO_NO_RGB_BUILTIN in build_opt.h or through CLI to disable RGB_BUILTIN +#ifdef ESP32_ARDUINO_NO_RGB_BUILTIN +#ifdef RGB_BUILTIN +#undef RGB_BUILTIN +#endif +#endif + // It fixes lack of pin definition for S3 and for any future SoC // this function works for ESP32, ESP32-S2 and ESP32-S3 - including the C3, it will return -1 for any pin #if SOC_TOUCH_SENSOR_NUM > 0 @@ -156,14 +166,14 @@ extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val) { //use RMT to set all channels on/off RGB_BUILTIN_storage = val; const uint8_t comm_val = val != 0 ? RGB_BRIGHTNESS : 0; - neopixelWrite(RGB_BUILTIN, comm_val, comm_val, comm_val); + rgbLedWrite(RGB_BUILTIN, comm_val, comm_val, comm_val); return; } -#endif +#endif // RGB_BUILTIN if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) != NULL) { gpio_set_level((gpio_num_t)pin, val); } else { - log_e("IO %i is not set as GPIO.", pin); + log_e("IO %i is not set as GPIO. Execute digitalMode(%i, OUTPUT) first.", pin, pin); } } @@ -172,14 +182,12 @@ extern int ARDUINO_ISR_ATTR __digitalRead(uint8_t pin) { if (pin == RGB_BUILTIN) { return RGB_BUILTIN_storage; } -#endif - - if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) != NULL) { - return gpio_get_level((gpio_num_t)pin); - } else { - log_e("IO %i is not set as GPIO.", pin); - return 0; +#endif // RGB_BUILTIN + // This work when the pin is set as GPIO and in INPUT mode. For all other pin functions, it may return inconsistent response + if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) == NULL) { + log_w("IO %i is not set as GPIO. digitalRead() may return an inconsistent value.", pin); } + return gpio_get_level((gpio_num_t)pin); } static void ARDUINO_ISR_ATTR __onPinInterrupt(void *arg) { diff --git a/cores/esp32/esp32-hal-gpio.h b/cores/esp32/esp32-hal-gpio.h index f92209cc29e..9fce4368c22 100644 --- a/cores/esp32/esp32-hal-gpio.h +++ b/cores/esp32/esp32-hal-gpio.h @@ -24,9 +24,10 @@ extern "C" { #endif +#include "pins_arduino.h" #include "esp32-hal.h" #include "soc/soc_caps.h" -#include "pins_arduino.h" +#include "driver/gpio.h" #if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3) #define NUM_OUPUT_PINS 46 diff --git a/cores/esp32/esp32-hal-i2c-ng.c b/cores/esp32/esp32-hal-i2c-ng.c new file mode 100644 index 00000000000..8e48d0e0397 --- /dev/null +++ b/cores/esp32/esp32-hal-i2c-ng.c @@ -0,0 +1,445 @@ +// Copyright 2015-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp32-hal-i2c.h" + +#if SOC_I2C_SUPPORTED +#include "esp_idf_version.h" +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0) +#include "esp32-hal.h" +#if !CONFIG_DISABLE_HAL_LOCKS +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#endif +#include "esp_attr.h" +#include "esp_system.h" +#include "soc/soc_caps.h" +#include "driver/i2c_master.h" +#include "esp32-hal-periman.h" + +typedef volatile struct { + bool initialized; + uint32_t frequency; +#if !CONFIG_DISABLE_HAL_LOCKS + SemaphoreHandle_t lock; +#endif + int8_t scl; + int8_t sda; + i2c_master_bus_handle_t bus_handle; + i2c_master_dev_handle_t dev_handles[128]; +} i2c_bus_t; + +static i2c_bus_t bus[SOC_I2C_NUM]; + +static bool i2cDetachBus(void *bus_i2c_num) { + uint8_t i2c_num = (int)bus_i2c_num - 1; + if (!bus[i2c_num].initialized) { + return true; + } + esp_err_t err = i2cDeinit(i2c_num); + if (err != ESP_OK) { + log_e("i2cDeinit failed with error: %d", err); + return false; + } + return true; +} + +bool i2cIsInit(uint8_t i2c_num) { + if (i2c_num >= SOC_I2C_NUM) { + return false; + } + return bus[i2c_num].initialized; +} + +esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) { + esp_err_t ret = ESP_OK; + if (i2c_num >= SOC_I2C_NUM) { + return ESP_ERR_INVALID_ARG; + } +#if !CONFIG_DISABLE_HAL_LOCKS + if (bus[i2c_num].lock == NULL) { + bus[i2c_num].lock = xSemaphoreCreateMutex(); + if (bus[i2c_num].lock == NULL) { + log_e("xSemaphoreCreateMutex failed"); + return ESP_ERR_NO_MEM; + } + } + //acquire lock + if (xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) { + log_e("could not acquire lock"); + return ESP_FAIL; + } +#endif + if (bus[i2c_num].initialized) { + log_e("bus is already initialized"); + ret = ESP_FAIL; + goto init_fail; + } + + if (!frequency) { + frequency = 100000UL; + } else if (frequency > 1000000UL) { + frequency = 1000000UL; + } + + perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER_SDA, i2cDetachBus); + perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER_SCL, i2cDetachBus); + + if (!perimanClearPinBus(sda) || !perimanClearPinBus(scl)) { + ret = ESP_FAIL; + goto init_fail; + } + + log_i("Initializing I2C Master: num=%u sda=%d scl=%d freq=%lu", i2c_num, sda, scl, frequency); + + i2c_master_bus_handle_t bus_handle = NULL; + i2c_master_bus_config_t bus_config; + memset(&bus_config, 0, sizeof(i2c_master_bus_config_t)); + bus_config.i2c_port = (i2c_port_num_t)i2c_num; + bus_config.sda_io_num = (gpio_num_t)sda; + bus_config.scl_io_num = (gpio_num_t)scl; +#if SOC_LP_I2C_SUPPORTED + if (i2c_num >= SOC_HP_I2C_NUM) { + bus_config.lp_source_clk = LP_I2C_SCLK_DEFAULT; + } else +#endif + { + bus_config.clk_source = I2C_CLK_SRC_DEFAULT; + } + bus_config.glitch_ignore_cnt = 7; + bus_config.intr_priority = 0; // auto + bus_config.trans_queue_depth = 0; // only valid in asynchronous transaction, which Arduino does not use + bus_config.flags.enable_internal_pullup = 1; +#if SOC_I2C_SUPPORT_SLEEP_RETENTION + bus_config.flags.allow_pd = 1; // backup/restore the I2C registers before/after entering/exist sleep mode +#endif + + ret = i2c_new_master_bus(&bus_config, &bus_handle); + if (ret != ESP_OK) { + log_e("i2c_new_master_bus failed: [%d] %s", ret, esp_err_to_name(ret)); + } else { + bus[i2c_num].initialized = true; + bus[i2c_num].frequency = frequency; + bus[i2c_num].scl = scl; + bus[i2c_num].sda = sda; + bus[i2c_num].bus_handle = bus_handle; + for (uint8_t i = 0; i < 128; i++) { + bus[i2c_num].dev_handles[i] = NULL; + } + if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_MASTER_SDA, (void *)(i2c_num + 1), i2c_num, -1) + || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_MASTER_SCL, (void *)(i2c_num + 1), i2c_num, -1)) { +#if !CONFIG_DISABLE_HAL_LOCKS + //release lock so that i2cDetachBus can execute i2cDeinit + xSemaphoreGive(bus[i2c_num].lock); +#endif + i2cDetachBus((void *)(i2c_num + 1)); + return ESP_FAIL; + } + } + +init_fail: +#if !CONFIG_DISABLE_HAL_LOCKS + //release lock + xSemaphoreGive(bus[i2c_num].lock); +#endif + return ret; +} + +esp_err_t i2cDeinit(uint8_t i2c_num) { + esp_err_t err = ESP_FAIL; + if (i2c_num >= SOC_I2C_NUM) { + return ESP_ERR_INVALID_ARG; + } +#if !CONFIG_DISABLE_HAL_LOCKS + //acquire lock + if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) { + log_e("could not acquire lock"); + return err; + } +#endif + if (!bus[i2c_num].initialized) { + log_e("bus is not initialized"); + } else { + // remove devices from the bus + for (uint8_t i = 0; i < 128; i++) { + if (bus[i2c_num].dev_handles[i] != NULL) { + err = i2c_master_bus_rm_device(bus[i2c_num].dev_handles[i]); + bus[i2c_num].dev_handles[i] = NULL; + if (err != ESP_OK) { + log_e("i2c_master_bus_rm_device failed: [%d] %s", err, esp_err_to_name(err)); + } + } + } + err = i2c_del_master_bus(bus[i2c_num].bus_handle); + if (err != ESP_OK) { + log_e("i2c_del_master_bus failed: [%d] %s", err, esp_err_to_name(err)); + } else { + bus[i2c_num].initialized = false; + perimanClearPinBus(bus[i2c_num].scl); + perimanClearPinBus(bus[i2c_num].sda); + bus[i2c_num].scl = -1; + bus[i2c_num].sda = -1; + bus[i2c_num].bus_handle = NULL; + } + } +#if !CONFIG_DISABLE_HAL_LOCKS + //release lock + xSemaphoreGive(bus[i2c_num].lock); +#endif + return err; +} + +static esp_err_t i2cAddDeviceIfNeeded(uint8_t i2c_num, uint16_t address) { + esp_err_t ret = ESP_OK; + if (bus[i2c_num].dev_handles[address] == NULL) { + i2c_master_dev_handle_t dev_handle = NULL; + i2c_device_config_t dev_config; + memset(&dev_config, 0, sizeof(i2c_device_config_t)); + dev_config.dev_addr_length = I2C_ADDR_BIT_LEN_7; // Arduino supports only 7bit addresses + dev_config.device_address = address; + dev_config.scl_speed_hz = bus[i2c_num].frequency; + dev_config.scl_wait_us = 0; + dev_config.flags.disable_ack_check = 0; + + ret = i2c_master_bus_add_device(bus[i2c_num].bus_handle, &dev_config, &dev_handle); + if (ret != ESP_OK) { + log_e("i2c_master_bus_add_device failed: [%d] %s", ret, esp_err_to_name(ret)); + } else { + bus[i2c_num].dev_handles[address] = dev_handle; + log_v("added device: bus=%u addr=0x%x handle=0x%08x", i2c_num, address, dev_handle); + } + } + return ret; +} + +esp_err_t i2cWrite(uint8_t i2c_num, uint16_t address, const uint8_t *buff, size_t size, uint32_t timeOutMillis) { + esp_err_t ret = ESP_FAIL; + // i2c_cmd_handle_t cmd = NULL; + if (i2c_num >= SOC_I2C_NUM) { + return ESP_ERR_INVALID_ARG; + } + if (address >= 128) { + log_e("Only 7bit I2C addresses are supported"); + return ESP_ERR_INVALID_ARG; + } +#if !CONFIG_DISABLE_HAL_LOCKS + //acquire lock + if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) { + log_e("could not acquire lock"); + return ret; + } +#endif + if (!bus[i2c_num].initialized) { + log_e("bus is not initialized"); + goto end; + } + + if (size == 0) { + // Probe device + ret = i2c_master_probe(bus[i2c_num].bus_handle, address, timeOutMillis); + if (ret != ESP_OK) { + log_v("i2c_master_probe failed: [%d] %s", ret, esp_err_to_name(ret)); + } + } else { + // writing data to device + ret = i2cAddDeviceIfNeeded(i2c_num, address); + if (ret != ESP_OK) { + goto end; + } + + log_v("i2c_master_transmit: bus=%u addr=0x%x handle=0x%08x size=%u", i2c_num, address, bus[i2c_num].dev_handles[address], size); + ret = i2c_master_transmit(bus[i2c_num].dev_handles[address], buff, size, timeOutMillis); + if (ret != ESP_OK) { + log_e("i2c_master_transmit failed: [%d] %s", ret, esp_err_to_name(ret)); + goto end; + } + + // wait for transactions to finish (is it needed with sync transactions?) + // ret = i2c_master_bus_wait_all_done(bus[i2c_num].bus_handle, timeOutMillis); + // if (ret != ESP_OK) { + // log_e("i2c_master_bus_wait_all_done failed: [%d] %s", ret, esp_err_to_name(ret)); + // goto end; + // } + } + +end: +#if !CONFIG_DISABLE_HAL_LOCKS + //release lock + xSemaphoreGive(bus[i2c_num].lock); +#endif + return ret; +} + +esp_err_t i2cRead(uint8_t i2c_num, uint16_t address, uint8_t *buff, size_t size, uint32_t timeOutMillis, size_t *readCount) { + esp_err_t ret = ESP_FAIL; + *readCount = 0; + if (i2c_num >= SOC_I2C_NUM) { + return ESP_ERR_INVALID_ARG; + } +#if !CONFIG_DISABLE_HAL_LOCKS + //acquire lock + if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) { + log_e("could not acquire lock"); + return ret; + } +#endif + if (!bus[i2c_num].initialized) { + log_e("bus is not initialized"); + goto end; + } + + ret = i2cAddDeviceIfNeeded(i2c_num, address); + if (ret != ESP_OK) { + goto end; + } + + log_v("i2c_master_receive: bus=%u addr=0x%x handle=0x%08x size=%u", i2c_num, address, bus[i2c_num].dev_handles[address], size); + ret = i2c_master_receive(bus[i2c_num].dev_handles[address], buff, size, timeOutMillis); + if (ret != ESP_OK) { + log_e("i2c_master_receive failed: [%d] %s", ret, esp_err_to_name(ret)); + goto end; + } + + // wait for transactions to finish (is it needed with sync transactions?) + // ret = i2c_master_bus_wait_all_done(bus[i2c_num].bus_handle, timeOutMillis); + // if (ret != ESP_OK) { + // log_e("i2c_master_bus_wait_all_done failed: [%d] %s", ret, esp_err_to_name(ret)); + // goto end; + // } + *readCount = size; + +end: +#if !CONFIG_DISABLE_HAL_LOCKS + //release lock + xSemaphoreGive(bus[i2c_num].lock); +#endif + return ret; +} + +esp_err_t i2cWriteReadNonStop( + uint8_t i2c_num, uint16_t address, const uint8_t *wbuff, size_t wsize, uint8_t *rbuff, size_t rsize, uint32_t timeOutMillis, size_t *readCount +) { + esp_err_t ret = ESP_FAIL; + *readCount = 0; + if (i2c_num >= SOC_I2C_NUM) { + return ESP_ERR_INVALID_ARG; + } +#if !CONFIG_DISABLE_HAL_LOCKS + //acquire lock + if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) { + log_e("could not acquire lock"); + return ret; + } +#endif + if (!bus[i2c_num].initialized) { + log_e("bus is not initialized"); + goto end; + } + + ret = i2cAddDeviceIfNeeded(i2c_num, address); + if (ret != ESP_OK) { + goto end; + } + + log_v("i2c_master_transmit_receive: bus=%u addr=0x%x handle=0x%08x write=%u read=%u", i2c_num, address, bus[i2c_num].dev_handles[address], wsize, rsize); + ret = i2c_master_transmit_receive(bus[i2c_num].dev_handles[address], wbuff, wsize, rbuff, rsize, timeOutMillis); + if (ret != ESP_OK) { + log_e("i2c_master_transmit_receive failed: [%d] %s", ret, esp_err_to_name(ret)); + goto end; + } + + // wait for transactions to finish (is it needed with sync transactions?) + // ret = i2c_master_bus_wait_all_done(bus[i2c_num].bus_handle, timeOutMillis); + // if (ret != ESP_OK) { + // log_e("i2c_master_bus_wait_all_done failed: [%d] %s", ret, esp_err_to_name(ret)); + // goto end; + // } + *readCount = rsize; + +end: +#if !CONFIG_DISABLE_HAL_LOCKS + //release lock + xSemaphoreGive(bus[i2c_num].lock); +#endif + return ret; +} + +esp_err_t i2cSetClock(uint8_t i2c_num, uint32_t frequency) { + esp_err_t ret = ESP_FAIL; + if (i2c_num >= SOC_I2C_NUM) { + return ESP_ERR_INVALID_ARG; + } +#if !CONFIG_DISABLE_HAL_LOCKS + //acquire lock + if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) { + log_e("could not acquire lock"); + return ret; + } +#endif + if (!bus[i2c_num].initialized) { + log_e("bus is not initialized"); + goto end; + } + if (bus[i2c_num].frequency == frequency) { + ret = ESP_OK; + goto end; + } + if (!frequency) { + frequency = 100000UL; + } else if (frequency > 1000000UL) { + frequency = 1000000UL; + } + + bus[i2c_num].frequency = frequency; + + // loop through devices, remove them and then re-add them with the new frequency + for (uint8_t i = 0; i < 128; i++) { + if (bus[i2c_num].dev_handles[i] != NULL) { + ret = i2c_master_bus_rm_device(bus[i2c_num].dev_handles[i]); + if (ret != ESP_OK) { + log_e("i2c_master_bus_rm_device failed: [%d] %s", ret, esp_err_to_name(ret)); + goto end; + } else { + bus[i2c_num].dev_handles[i] = NULL; + ret = i2cAddDeviceIfNeeded(i2c_num, i); + if (ret != ESP_OK) { + goto end; + } + } + } + } + +end: +#if !CONFIG_DISABLE_HAL_LOCKS + //release lock + xSemaphoreGive(bus[i2c_num].lock); +#endif + return ret; +} + +esp_err_t i2cGetClock(uint8_t i2c_num, uint32_t *frequency) { + if (i2c_num >= SOC_I2C_NUM) { + return ESP_ERR_INVALID_ARG; + } + if (!bus[i2c_num].initialized) { + log_e("bus is not initialized"); + return ESP_FAIL; + } + *frequency = bus[i2c_num].frequency; + return ESP_OK; +} + +#endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0) */ +#endif /* SOC_I2C_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-i2c-slave.c b/cores/esp32/esp32-hal-i2c-slave.c index edae1e57c92..46c3a4d58c2 100644 --- a/cores/esp32/esp32-hal-i2c-slave.c +++ b/cores/esp32/esp32-hal-i2c-slave.c @@ -41,21 +41,40 @@ #include "esp_intr_alloc.h" #include "soc/i2c_reg.h" #include "soc/i2c_struct.h" +#include "soc/periph_defs.h" #include "hal/i2c_ll.h" #include "hal/clk_gate_ll.h" #include "esp32-hal-log.h" #include "esp32-hal-i2c-slave.h" #include "esp32-hal-periman.h" +#include "esp_private/periph_ctrl.h" + +#if SOC_PERIPH_CLK_CTRL_SHARED +#define I2C_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define I2C_CLOCK_SRC_ATOMIC() +#endif + +#if !SOC_RCC_IS_INDEPENDENT +#define I2C_RCC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define I2C_RCC_ATOMIC() +#endif #define I2C_SLAVE_USE_RX_QUEUE 0 // 1: Queue, 0: RingBuffer -#if SOC_I2C_NUM > 1 +#ifdef CONFIG_IDF_TARGET_ESP32P4 +#define I2C_SCL_IDX(p) ((p == 0) ? I2C0_SCL_PAD_OUT_IDX : ((p == 1) ? I2C1_SCL_PAD_OUT_IDX : 0)) +#define I2C_SDA_IDX(p) ((p == 0) ? I2C0_SDA_PAD_OUT_IDX : ((p == 1) ? I2C1_SDA_PAD_OUT_IDX : 0)) +#else +#if SOC_HP_I2C_NUM > 1 #define I2C_SCL_IDX(p) ((p == 0) ? I2CEXT0_SCL_OUT_IDX : ((p == 1) ? I2CEXT1_SCL_OUT_IDX : 0)) #define I2C_SDA_IDX(p) ((p == 0) ? I2CEXT0_SDA_OUT_IDX : ((p == 1) ? I2CEXT1_SDA_OUT_IDX : 0)) #else #define I2C_SCL_IDX(p) I2CEXT0_SCL_OUT_IDX #define I2C_SDA_IDX(p) I2CEXT0_SDA_OUT_IDX #endif +#endif // ifdef CONFIG_IDF_TARGET_ESP32P4 #if CONFIG_IDF_TARGET_ESP32 #define I2C_TXFIFO_WM_INT_ENA I2C_TXFIFO_EMPTY_INT_ENA @@ -99,14 +118,14 @@ typedef union { uint32_t val; } i2c_slave_queue_event_t; -static i2c_slave_struct_t _i2c_bus_array[SOC_I2C_NUM] = { +static i2c_slave_struct_t _i2c_bus_array[SOC_HP_I2C_NUM] = { {&I2C0, 0, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 #if !CONFIG_DISABLE_HAL_LOCKS , NULL #endif }, -#if SOC_I2C_NUM > 1 +#if SOC_HP_I2C_NUM > 1 {&I2C1, 1, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 #if !CONFIG_DISABLE_HAL_LOCKS , @@ -173,19 +192,19 @@ static inline void i2c_ll_stretch_clr(i2c_dev_t *hw) { } static inline bool i2c_ll_slave_addressed(i2c_dev_t *hw) { -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 - return hw->sr.slave_addressed; -#else +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 return hw->status_reg.slave_addressed; +#else + return hw->sr.slave_addressed; #endif } static inline bool i2c_ll_slave_rw(i2c_dev_t *hw) //not exposed by hal_ll { -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 - return hw->sr.slave_rw; -#else +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 return hw->status_reg.slave_rw; +#else + return hw->sr.slave_rw; #endif } @@ -210,7 +229,7 @@ static bool i2cSlaveDetachBus(void *bus_i2c_num); //===================================================================================================================== esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_callback, i2c_slave_receive_cb_t receive_callback, void *arg) { - if (num >= SOC_I2C_NUM) { + if (num >= SOC_HP_I2C_NUM) { log_e("Invalid port num: %u", num); return ESP_ERR_INVALID_ARG; } @@ -224,7 +243,7 @@ esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_ca } esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency, size_t rx_len, size_t tx_len) { - if (num >= SOC_I2C_NUM) { + if (num >= SOC_HP_I2C_NUM) { log_e("Invalid port num: %u", num); return ESP_ERR_INVALID_ARG; } @@ -306,17 +325,22 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency = 100000L; } frequency = (frequency * 5) / 4; - +#if !defined(CONFIG_IDF_TARGET_ESP32P4) if (i2c->num == 0) { periph_ll_enable_clk_clear_rst(PERIPH_I2C0_MODULE); -#if SOC_I2C_NUM > 1 +#if SOC_HP_I2C_NUM > 1 } else { periph_ll_enable_clk_clear_rst(PERIPH_I2C1_MODULE); #endif } +#endif // !defined(CONFIG_IDF_TARGET_ESP32P4) i2c_ll_slave_init(i2c->dev); - i2c_ll_set_fifo_mode(i2c->dev, true); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0) + i2c_ll_enable_fifo_mode(i2c->dev, true); +#else + i2c_ll_slave_set_fifo_mode(i2c->dev, true); +#endif i2c_ll_set_slave_addr(i2c->dev, slaveID, false); i2c_ll_set_tout(i2c->dev, I2C_LL_MAX_TIMEOUT); i2c_slave_set_frequency(i2c, frequency); @@ -337,15 +361,27 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK); i2c_ll_clear_intr_mask(i2c->dev, I2C_LL_INTR_MASK); - i2c_ll_set_fifo_mode(i2c->dev, true); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0) + i2c_ll_enable_fifo_mode(i2c->dev, true); +#else + i2c_ll_slave_set_fifo_mode(i2c->dev, true); +#endif if (!i2c->intr_handle) { uint32_t flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED; if (i2c->num == 0) { +#if !defined(CONFIG_IDF_TARGET_ESP32P4) ret = esp_intr_alloc(ETS_I2C_EXT0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); -#if SOC_I2C_NUM > 1 +#else + ret = esp_intr_alloc(ETS_I2C0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); +#endif +#if SOC_HP_I2C_NUM > 1 } else { +#if !defined(CONFIG_IDF_TARGET_ESP32P4) ret = esp_intr_alloc(ETS_I2C_EXT1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); +#else + ret = esp_intr_alloc(ETS_I2C1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); +#endif #endif } @@ -375,7 +411,7 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t } esp_err_t i2cSlaveDeinit(uint8_t num) { - if (num >= SOC_I2C_NUM) { + if (num >= SOC_HP_I2C_NUM) { log_e("Invalid port num: %u", num); return ESP_ERR_INVALID_ARG; } @@ -398,7 +434,7 @@ esp_err_t i2cSlaveDeinit(uint8_t num) { } size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms) { - if (num >= SOC_I2C_NUM) { + if (num >= SOC_HP_I2C_NUM) { log_e("Invalid port num: %u", num); return 0; } @@ -515,16 +551,20 @@ static bool i2c_slave_set_frequency(i2c_slave_struct_t *i2c, uint32_t clk_speed) i2c_hal_clk_config_t clk_cal; #if SOC_I2C_SUPPORT_APB - i2c_ll_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal); - i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_APB); /*!< I2C source clock from APB, 80M*/ + i2c_ll_master_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal); + I2C_CLOCK_SRC_ATOMIC() { + i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_APB); /*!< I2C source clock from APB, 80M*/ + } #elif SOC_I2C_SUPPORT_XTAL - i2c_ll_cal_bus_clk(XTAL_CLK_FREQ, clk_speed, &clk_cal); - i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_XTAL); /*!< I2C source clock from XTAL, 40M */ + i2c_ll_master_cal_bus_clk(XTAL_CLK_FREQ, clk_speed, &clk_cal); + I2C_CLOCK_SRC_ATOMIC() { + i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_XTAL); /*!< I2C source clock from XTAL, 40M */ + } #endif i2c_ll_set_txfifo_empty_thr(i2c->dev, a); i2c_ll_set_rxfifo_full_thr(i2c->dev, SOC_I2C_FIFO_LEN - a); - i2c_ll_set_bus_timing(i2c->dev, &clk_cal); - i2c_ll_set_filter(i2c->dev, 3); + i2c_ll_master_set_bus_timing(i2c->dev, &clk_cal); + i2c_ll_master_set_filter(i2c->dev, 3); return true; } diff --git a/cores/esp32/esp32-hal-i2c.c b/cores/esp32/esp32-hal-i2c.c index 1ecef5bfb0d..71c8ae1c428 100644 --- a/cores/esp32/esp32-hal-i2c.c +++ b/cores/esp32/esp32-hal-i2c.c @@ -15,6 +15,8 @@ #include "esp32-hal-i2c.h" #if SOC_I2C_SUPPORTED +#include "esp_idf_version.h" +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 0) #include "esp32-hal.h" #if !CONFIG_DISABLE_HAL_LOCKS #include "freertos/FreeRTOS.h" @@ -29,6 +31,19 @@ #include "hal/i2c_ll.h" #include "driver/i2c.h" #include "esp32-hal-periman.h" +#include "esp_private/periph_ctrl.h" + +#if SOC_PERIPH_CLK_CTRL_SHARED +#define I2C_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define I2C_CLOCK_SRC_ATOMIC() +#endif + +#if !SOC_RCC_IS_INDEPENDENT +#define I2C_RCC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define I2C_RCC_ATOMIC() +#endif #if SOC_I2C_SUPPORT_APB || SOC_I2C_SUPPORT_XTAL #include "esp_private/esp_clk.h" @@ -71,6 +86,7 @@ bool i2cIsInit(uint8_t i2c_num) { } esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) { + esp_err_t ret = ESP_OK; if (i2c_num >= SOC_I2C_NUM) { return ESP_ERR_INVALID_ARG; } @@ -90,7 +106,8 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) { #endif if (bus[i2c_num].initialized) { log_e("bus is already initialized"); - return ESP_FAIL; + ret = ESP_FAIL; + goto init_fail; } if (!frequency) { @@ -103,7 +120,8 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) { perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER_SCL, i2cDetachBus); if (!perimanClearPinBus(sda) || !perimanClearPinBus(scl)) { - return false; + ret = ESP_FAIL; + goto init_fail; } log_i("Initializing I2C Master: sda=%d scl=%d freq=%d", sda, scl, frequency); @@ -117,7 +135,7 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) { conf.master.clk_speed = frequency; conf.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL; //Any one clock source that is available for the specified frequency may be chosen - esp_err_t ret = i2c_param_config((i2c_port_t)i2c_num, &conf); + ret = i2c_param_config((i2c_port_t)i2c_num, &conf); if (ret != ESP_OK) { log_e("i2c_param_config failed"); } else { @@ -133,11 +151,16 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) { i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT); if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_MASTER_SDA, (void *)(i2c_num + 1), i2c_num, -1) || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_MASTER_SCL, (void *)(i2c_num + 1), i2c_num, -1)) { +#if !CONFIG_DISABLE_HAL_LOCKS + //release lock so that i2cDetachBus can execute i2cDeinit + xSemaphoreGive(bus[i2c_num].lock); +#endif i2cDetachBus((void *)(i2c_num + 1)); - return false; + return ESP_FAIL; } } } +init_fail: #if !CONFIG_DISABLE_HAL_LOCKS //release lock xSemaphoreGive(bus[i2c_num].lock); @@ -380,7 +403,9 @@ esp_err_t i2cSetClock(uint8_t i2c_num, uint32_t frequency) { periph_rtc_dig_clk8m_enable(); } #endif - i2c_hal_set_bus_timing(&(hal), frequency, i2c_clk_alloc[src_clk].clk, i2c_clk_alloc[src_clk].clk_freq); + I2C_CLOCK_SRC_ATOMIC() { + i2c_hal_set_bus_timing(&(hal), frequency, i2c_clk_alloc[src_clk].clk, i2c_clk_alloc[src_clk].clk_freq); + } bus[i2c_num].frequency = frequency; //Clock Stretching Timeout: 20b:esp32, 5b:esp32-c3, 24b:esp32-s2 i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT); @@ -406,4 +431,5 @@ esp_err_t i2cGetClock(uint8_t i2c_num, uint32_t *frequency) { return ESP_OK; } +#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 0) */ #endif /* SOC_I2C_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-ledc.c b/cores/esp32/esp32-hal-ledc.c index 8c9454c996f..039fa1312f1 100644 --- a/cores/esp32/esp32-hal-ledc.c +++ b/cores/esp32/esp32-hal-ledc.c @@ -21,6 +21,7 @@ #include "esp32-hal-periman.h" #include "soc/gpio_sig_map.h" #include "esp_rom_gpio.h" +#include "hal/ledc_ll.h" #ifdef SOC_LEDC_SUPPORT_HS_MODE #define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM << 1) @@ -46,10 +47,42 @@ ledc_periph_t ledc_handle = {0}; static bool fade_initialized = false; +static ledc_clk_cfg_t clock_source = LEDC_DEFAULT_CLK; + +ledc_clk_cfg_t ledcGetClockSource(void) { + return clock_source; +} + +bool ledcSetClockSource(ledc_clk_cfg_t source) { + if (ledc_handle.used_channels) { + log_e("Cannot change LEDC clock source! LEDC channels in use."); + return false; + } + clock_source = source; + return true; +} + static bool ledcDetachBus(void *bus) { ledc_channel_handle_t *handle = (ledc_channel_handle_t *)bus; - ledc_handle.used_channels &= ~(1UL << handle->channel); + bool channel_found = false; + // Check if more pins are attached to the same ledc channel + for (uint8_t i = 0; i < SOC_GPIO_PIN_COUNT; i++) { + if (!perimanPinIsValid(i) || i == handle->pin) { + continue; //invalid pin or same pin + } + peripheral_bus_type_t type = perimanGetPinBusType(i); + if (type == ESP32_BUS_TYPE_LEDC) { + ledc_channel_handle_t *bus_check = (ledc_channel_handle_t *)perimanGetPinBus(i, ESP32_BUS_TYPE_LEDC); + if (bus_check->channel == handle->channel) { + channel_found = true; + break; + } + } + } pinMatrixOutDetach(handle->pin, false, false); + if (!channel_found) { + ledc_handle.used_channels &= ~(1UL << handle->channel); + } free(handle); if (ledc_handle.used_channels == 0) { ledc_fade_func_uninstall(); @@ -59,8 +92,8 @@ static bool ledcDetachBus(void *bus) { } bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t channel) { - if (channel >= LEDC_CHANNELS || ledc_handle.used_channels & (1UL << channel)) { - log_e("Channel %u is not available (maximum %u) or already used!", channel, LEDC_CHANNELS); + if (channel >= LEDC_CHANNELS) { + log_e("Channel %u is not available (maximum %u)!", channel, LEDC_CHANNELS); return false; } if (freq == 0) { @@ -85,29 +118,59 @@ bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t c } uint8_t group = (channel / 8), timer = ((channel / 2) % 4); + bool channel_used = ledc_handle.used_channels & (1UL << channel); + if (channel_used) { + log_i("Channel %u is already set up, given frequency and resolution will be ignored", channel); + if (ledc_set_pin(pin, group, channel % 8) != ESP_OK) { + log_e("Attaching pin to already used channel failed!"); + return false; + } + } else { + ledc_timer_config_t ledc_timer; + memset((void *)&ledc_timer, 0, sizeof(ledc_timer_config_t)); + ledc_timer.speed_mode = group; + ledc_timer.timer_num = timer; + ledc_timer.duty_resolution = resolution; + ledc_timer.freq_hz = freq; + ledc_timer.clk_cfg = clock_source; - ledc_timer_config_t ledc_timer = {.speed_mode = group, .timer_num = timer, .duty_resolution = resolution, .freq_hz = freq, .clk_cfg = LEDC_DEFAULT_CLK}; - if (ledc_timer_config(&ledc_timer) != ESP_OK) { - log_e("ledc setup failed!"); - return false; - } + if (ledc_timer_config(&ledc_timer) != ESP_OK) { + log_e("ledc setup failed!"); + return false; + } - uint32_t duty = ledc_get_duty(group, (channel % 8)); + uint32_t duty = ledc_get_duty(group, (channel % 8)); - ledc_channel_config_t ledc_channel = { - .speed_mode = group, .channel = (channel % 8), .timer_sel = timer, .intr_type = LEDC_INTR_DISABLE, .gpio_num = pin, .duty = duty, .hpoint = 0 - }; - ledc_channel_config(&ledc_channel); + ledc_channel_config_t ledc_channel; + memset((void *)&ledc_channel, 0, sizeof(ledc_channel_config_t)); + ledc_channel.speed_mode = group; + ledc_channel.channel = (channel % 8); + ledc_channel.timer_sel = timer; + ledc_channel.intr_type = LEDC_INTR_DISABLE; + ledc_channel.gpio_num = pin; + ledc_channel.duty = duty; + ledc_channel.hpoint = 0; - ledc_channel_handle_t *handle = (ledc_channel_handle_t *)malloc(sizeof(ledc_channel_handle_t)); + ledc_channel_config(&ledc_channel); + } + ledc_channel_handle_t *handle = (ledc_channel_handle_t *)malloc(sizeof(ledc_channel_handle_t)); handle->pin = pin; handle->channel = channel; - handle->channel_resolution = resolution; #ifndef SOC_LEDC_SUPPORT_FADE_STOP handle->lock = NULL; #endif - ledc_handle.used_channels |= 1UL << channel; + + //get resolution of selected channel when used + if (channel_used) { + uint32_t channel_resolution = 0; + ledc_ll_get_duty_resolution(LEDC_LL_GET_HW(), group, timer, &channel_resolution); + log_i("Channel %u frequency: %u, resolution: %u", channel, ledc_get_freq(group, timer), channel_resolution); + handle->channel_resolution = (uint8_t)channel_resolution; + } else { + handle->channel_resolution = resolution; + ledc_handle.used_channels |= 1UL << channel; + } if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_LEDC, (void *)handle, group, channel)) { ledcDetachBus((void *)handle); @@ -150,6 +213,30 @@ bool ledcWrite(uint8_t pin, uint32_t duty) { return false; } +bool ledcWriteChannel(uint8_t channel, uint32_t duty) { + //check if channel is valid and used + if (channel >= LEDC_CHANNELS || !(ledc_handle.used_channels & (1UL << channel))) { + log_e("Channel %u is not available (maximum %u) or not used!", channel, LEDC_CHANNELS); + return false; + } + uint8_t group = (channel / 8), timer = ((channel / 2) % 4); + + //Fixing if all bits in resolution is set = LEDC FULL ON + uint32_t resolution = 0; + ledc_ll_get_duty_resolution(LEDC_LL_GET_HW(), group, timer, &resolution); + + uint32_t max_duty = (1 << resolution) - 1; + + if ((duty == max_duty) && (max_duty != 1)) { + duty = max_duty + 1; + } + + ledc_set_duty(group, channel, duty); + ledc_update_duty(group, channel); + + return true; +} + uint32_t ledcRead(uint8_t pin) { ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC); if (bus != NULL) { @@ -183,7 +270,13 @@ uint32_t ledcWriteTone(uint8_t pin, uint32_t freq) { uint8_t group = (bus->channel / 8), timer = ((bus->channel / 2) % 4); - ledc_timer_config_t ledc_timer = {.speed_mode = group, .timer_num = timer, .duty_resolution = 10, .freq_hz = freq, .clk_cfg = LEDC_DEFAULT_CLK}; + ledc_timer_config_t ledc_timer; + memset((void *)&ledc_timer, 0, sizeof(ledc_timer_config_t)); + ledc_timer.speed_mode = group; + ledc_timer.timer_num = timer; + ledc_timer.duty_resolution = 10; + ledc_timer.freq_hz = freq; + ledc_timer.clk_cfg = clock_source; if (ledc_timer_config(&ledc_timer) != ESP_OK) { log_e("ledcWriteTone configuration failed!"); @@ -234,7 +327,13 @@ uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution) { } uint8_t group = (bus->channel / 8), timer = ((bus->channel / 2) % 4); - ledc_timer_config_t ledc_timer = {.speed_mode = group, .timer_num = timer, .duty_resolution = resolution, .freq_hz = freq, .clk_cfg = LEDC_DEFAULT_CLK}; + ledc_timer_config_t ledc_timer; + memset((void *)&ledc_timer, 0, sizeof(ledc_timer_config_t)); + ledc_timer.speed_mode = group; + ledc_timer.timer_num = timer; + ledc_timer.duty_resolution = resolution; + ledc_timer.freq_hz = freq; + ledc_timer.clk_cfg = clock_source; if (ledc_timer_config(&ledc_timer) != ESP_OK) { log_e("ledcChangeFrequency failed!"); @@ -250,11 +349,16 @@ bool ledcOutputInvert(uint8_t pin, bool out_invert) { ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC); if (bus != NULL) { gpio_set_level(pin, out_invert); + +#ifdef CONFIG_IDF_TARGET_ESP32P4 + esp_rom_gpio_connect_out_signal(pin, LEDC_LS_SIG_OUT_PAD_OUT0_IDX + ((bus->channel) % 8), out_invert, 0); +#else #ifdef SOC_LEDC_SUPPORT_HS_MODE esp_rom_gpio_connect_out_signal(pin, ((bus->channel / 8 == 0) ? LEDC_HS_SIG_OUT0_IDX : LEDC_LS_SIG_OUT0_IDX) + ((bus->channel) % 8), out_invert, 0); #else esp_rom_gpio_connect_out_signal(pin, LEDC_LS_SIG_OUT0_IDX + ((bus->channel) % 8), out_invert, 0); #endif +#endif // ifdef CONFIG_IDF_TARGET_ESP32P4 return true; } return false; diff --git a/cores/esp32/esp32-hal-ledc.h b/cores/esp32/esp32-hal-ledc.h index 2cff8dc0a8f..5b44aaad452 100644 --- a/cores/esp32/esp32-hal-ledc.h +++ b/cores/esp32/esp32-hal-ledc.h @@ -26,6 +26,7 @@ extern "C" { #include #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" +#include "hal/ledc_types.h" typedef enum { NOTE_C, @@ -57,6 +58,22 @@ typedef struct { #endif } ledc_channel_handle_t; +/** + * @brief Get the LEDC clock source. + * + * @return LEDC clock source. + */ +ledc_clk_cfg_t ledcGetClockSource(void); + +/** + * @brief Set the LEDC clock source. + * + * @param source LEDC clock source to set. + * + * @return true if LEDC clock source was successfully set, false otherwise. + */ +bool ledcSetClockSource(ledc_clk_cfg_t source); + /** * @brief Attach a pin to the LEDC driver, with a given frequency and resolution. * Channel is automatically assigned. @@ -91,6 +108,16 @@ bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t c */ bool ledcWrite(uint8_t pin, uint32_t duty); +/** + * @brief Set the duty cycle of a given channel. + * + * @param channel LEDC channel + * @param duty duty cycle to set + * + * @return true if duty cycle was successfully set, false otherwise. + */ +bool ledcWriteChannel(uint8_t channel, uint32_t duty); + /** * @brief Sets the duty to 50 % PWM tone on selected frequency. * diff --git a/cores/esp32/esp32-hal-log.h b/cores/esp32/esp32-hal-log.h index b8810c8bba9..da63c6dea94 100644 --- a/cores/esp32/esp32-hal-log.h +++ b/cores/esp32/esp32-hal-log.h @@ -20,6 +20,7 @@ extern "C" { #include "sdkconfig.h" #include "esp_timer.h" +#include "rom/ets_sys.h" #define ARDUHAL_LOG_LEVEL_NONE (0) #define ARDUHAL_LOG_LEVEL_ERROR (1) diff --git a/cores/esp32/esp32-hal-matrix.c b/cores/esp32/esp32-hal-matrix.c index fba044d0c85..7cddb4e04db 100644 --- a/cores/esp32/esp32-hal-matrix.c +++ b/cores/esp32/esp32-hal-matrix.c @@ -32,6 +32,8 @@ #include "esp32c6/rom/gpio.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/gpio.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/gpio.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif diff --git a/cores/esp32/esp32-hal-misc.c b/cores/esp32/esp32-hal-misc.c index 82363b97bd0..594acd38153 100644 --- a/cores/esp32/esp32-hal-misc.c +++ b/cores/esp32/esp32-hal-misc.c @@ -24,14 +24,15 @@ #ifdef CONFIG_APP_ROLLBACK_ENABLE #include "esp_ota_ops.h" #endif //CONFIG_APP_ROLLBACK_ENABLE -#ifdef CONFIG_BT_ENABLED +#include "esp_private/startup_internal.h" +#if defined(CONFIG_BT_BLUEDROID_ENABLED) && SOC_BT_SUPPORTED #include "esp_bt.h" -#endif //CONFIG_BT_ENABLED +#endif //CONFIG_BT_BLUEDROID_ENABLED #include #include "soc/rtc.h" -#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) +#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4) #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #endif #include "esp_task_wdt.h" #include "esp32-hal.h" @@ -53,6 +54,8 @@ #include "esp32c6/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/rtc.h" #else #error Target CONFIG_IDF_TARGET is not supported @@ -147,32 +150,36 @@ void feedLoopWDT() { #endif void enableCore0WDT() { - TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0); + TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCore(0); if (idle_0 == NULL || esp_task_wdt_add(idle_0) != ESP_OK) { log_e("Failed to add Core 0 IDLE task to WDT"); } } -void disableCore0WDT() { - TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0); - if (idle_0 == NULL || esp_task_wdt_delete(idle_0) != ESP_OK) { +bool disableCore0WDT() { + TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCore(0); + if (idle_0 == NULL || esp_task_wdt_status(idle_0) || esp_task_wdt_delete(idle_0) != ESP_OK) { log_e("Failed to remove Core 0 IDLE task from WDT"); + return false; } + return true; } #ifndef CONFIG_FREERTOS_UNICORE void enableCore1WDT() { - TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1); + TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCore(1); if (idle_1 == NULL || esp_task_wdt_add(idle_1) != ESP_OK) { log_e("Failed to add Core 1 IDLE task to WDT"); } } -void disableCore1WDT() { - TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1); - if (idle_1 == NULL || esp_task_wdt_delete(idle_1) != ESP_OK) { +bool disableCore1WDT() { + TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCore(1); + if (idle_1 == NULL || esp_task_wdt_status(idle_1) || esp_task_wdt_delete(idle_1) != ESP_OK) { log_e("Failed to remove Core 1 IDLE task from WDT"); + return false; } + return true; } #endif @@ -236,7 +243,7 @@ bool verifyRollbackLater() { } #endif -#ifdef CONFIG_BT_ENABLED +#ifdef CONFIG_BT_BLUEDROID_ENABLED #if CONFIG_IDF_TARGET_ESP32 //overwritten in esp32-hal-bt.c bool btInUse() __attribute__((weak)); @@ -249,11 +256,20 @@ extern bool btInUse(); #endif #endif +#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM +ESP_SYSTEM_INIT_FN(init_psram_new, CORE, BIT(0), 99) { + psramInit(); + return ESP_OK; +} +#endif + void initArduino() { //init proper ref tick value for PLL (uncomment if REF_TICK is different than 1MHz) //ESP_REG(APB_CTRL_PLL_TICK_CONF_REG) = APB_CLK_FREQ / REF_CLK_FREQ - 1; #if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM - psramInit(); +#ifndef CONFIG_SPIRAM_BOOT_INIT + psramAddToHeap(); +#endif #endif #ifdef CONFIG_APP_ROLLBACK_ENABLE if (!verifyRollbackLater()) { @@ -289,7 +305,7 @@ void initArduino() { if (err) { log_e("Failed to initialize NVS! Error: %u", err); } -#ifdef CONFIG_BT_ENABLED +#if defined(CONFIG_BT_BLUEDROID_ENABLED) && SOC_BT_SUPPORTED if (!btInUse()) { esp_bt_controller_mem_release(ESP_BT_MODE_BTDM); } diff --git a/cores/esp32/esp32-hal-psram.c b/cores/esp32/esp32-hal-psram.c index 5a741908f07..3c7a51c3343 100644 --- a/cores/esp32/esp32-hal-psram.c +++ b/cores/esp32/esp32-hal-psram.c @@ -27,10 +27,14 @@ #include "esp32s2/rom/cache.h" #elif CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/rom/cache.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/cache.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif +#define TAG "arduino-psram" + static volatile bool spiramDetected = false; static volatile bool spiramFailed = false; @@ -52,7 +56,7 @@ bool psramInit() { uint32_t pkg_ver = chip_ver & 0x7; if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) { spiramFailed = true; - log_w("PSRAM not supported!"); + ESP_EARLY_LOGW(TAG, "PSRAM not supported!"); return false; } #elif CONFIG_IDF_TARGET_ESP32S2 @@ -62,7 +66,7 @@ bool psramInit() { #endif if (esp_psram_init() != ESP_OK) { spiramFailed = true; - log_w("PSRAM init failed!"); + ESP_EARLY_LOGW(TAG, "PSRAM init failed!"); #if CONFIG_IDF_TARGET_ESP32 if (pkg_ver != EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) { pinMatrixOutDetach(16, false, false); @@ -71,24 +75,31 @@ bool psramInit() { #endif return false; } - //testSPIRAM() allows user to bypass SPI RAM test routine if (!testSPIRAM()) { spiramFailed = true; - log_e("PSRAM test failed!"); + ESP_EARLY_LOGE(TAG, "PSRAM test failed!"); + return false; + } + //ESP_EARLY_LOGI(TAG, "PSRAM enabled"); +#endif /* CONFIG_SPIRAM_BOOT_INIT */ + spiramDetected = true; + return true; +} + +bool psramAddToHeap() { + if (!spiramDetected) { + log_e("PSRAM not initialized!"); return false; } if (esp_psram_extram_add_to_heap_allocator() != ESP_OK) { - spiramFailed = true; log_e("PSRAM could not be added to the heap!"); return false; } #if CONFIG_SPIRAM_USE_MALLOC && !CONFIG_ARDUINO_ISR_IRAM heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL); #endif -#endif /* CONFIG_SPIRAM_BOOT_INIT */ - log_i("PSRAM enabled"); - spiramDetected = true; + log_i("PSRAM added to the heap."); return true; } diff --git a/cores/esp32/esp32-hal-psram.h b/cores/esp32/esp32-hal-psram.h index 0ba6763c69f..69c1c625157 100644 --- a/cores/esp32/esp32-hal-psram.h +++ b/cores/esp32/esp32-hal-psram.h @@ -21,7 +21,8 @@ extern "C" { #include "sdkconfig.h" -#ifndef BOARD_HAS_PSRAM +// Clear flags in Arduino IDE when PSRAM is disabled +#if defined(ESP32_ARDUINO_LIB_BUILDER) && !defined(BOARD_HAS_PSRAM) #ifdef CONFIG_SPIRAM_SUPPORT #undef CONFIG_SPIRAM_SUPPORT #endif @@ -31,6 +32,7 @@ extern "C" { #endif bool psramInit(); +bool psramAddToHeap(); bool psramFound(); void *ps_malloc(size_t size); diff --git a/cores/esp32/esp32-hal-rgb-led.c b/cores/esp32/esp32-hal-rgb-led.c index 99c95e1943e..d47dde53664 100644 --- a/cores/esp32/esp32-hal-rgb-led.c +++ b/cores/esp32/esp32-hal-rgb-led.c @@ -1,8 +1,32 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "soc/soc_caps.h" #include "esp32-hal-rgb-led.h" +// Backward compatibility - Deprecated. It will be removed in future releases. void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val) { + log_w("neopixelWrite() is deprecated. Use rgbLedWrite()."); + rgbLedWrite(pin, red_val, green_val, blue_val); +} + +void rgbLedWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val) { + rgbLedWriteOrdered(pin, RGB_BUILTIN_LED_COLOR_ORDER, red_val, green_val, blue_val); +} + +void rgbLedWriteOrdered(uint8_t pin, rgb_led_color_order_t order, uint8_t red_val, uint8_t green_val, uint8_t blue_val) { #if SOC_RMT_SUPPORTED rmt_data_t led_data[24]; @@ -15,7 +39,39 @@ void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue return; } - int color[] = {green_val, red_val, blue_val}; // Color coding is in order GREEN, RED, BLUE + // default WS2812B color order is G, R, B + int color[3] = {green_val, red_val, blue_val}; + + switch (order) { + case LED_COLOR_ORDER_RGB: + color[0] = red_val; + color[1] = green_val; + color[2] = blue_val; + break; + case LED_COLOR_ORDER_BGR: + color[0] = blue_val; + color[1] = green_val; + color[2] = red_val; + break; + case LED_COLOR_ORDER_BRG: + color[0] = blue_val; + color[1] = red_val; + color[2] = green_val; + break; + case LED_COLOR_ORDER_RBG: + color[0] = red_val; + color[1] = blue_val; + color[2] = green_val; + break; + case LED_COLOR_ORDER_GBR: + color[0] = green_val; + color[1] = blue_val; + color[2] = red_val; + break; + default: // GRB + break; + } + int i = 0; for (int col = 0; col < 3; col++) { for (int bit = 0; bit < 8; bit++) { diff --git a/cores/esp32/esp32-hal-rgb-led.h b/cores/esp32/esp32-hal-rgb-led.h index 33f37c849b6..b151732e565 100644 --- a/cores/esp32/esp32-hal-rgb-led.h +++ b/cores/esp32/esp32-hal-rgb-led.h @@ -11,7 +11,27 @@ extern "C" { #define RGB_BRIGHTNESS 64 #endif -void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val); +#ifndef RGB_BUILTIN_LED_COLOR_ORDER +#define RGB_BUILTIN_LED_COLOR_ORDER LED_COLOR_ORDER_GRB // default WS2812B color order +#endif + +typedef enum { + LED_COLOR_ORDER_RGB, + LED_COLOR_ORDER_BGR, + LED_COLOR_ORDER_BRG, + LED_COLOR_ORDER_RBG, + LED_COLOR_ORDER_GBR, + LED_COLOR_ORDER_GRB +} rgb_led_color_order_t; + +void rgbLedWriteOrdered(uint8_t pin, rgb_led_color_order_t order, uint8_t red_val, uint8_t green_val, uint8_t blue_val); + +// Will use RGB_BUILTIN_LED_COLOR_ORDER +void rgbLedWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val); + +// Backward compatibility - Deprecated. It will be removed in future releases. +[[deprecated("Use rgbLedWrite() instead.")]] +void neopixelWrite(uint8_t p, uint8_t r, uint8_t g, uint8_t b); #ifdef __cplusplus } diff --git a/cores/esp32/esp32-hal-rmt.c b/cores/esp32/esp32-hal-rmt.c index 0ed29ea9c13..7bca1a1b529 100644 --- a/cores/esp32/esp32-hal-rmt.c +++ b/cores/esp32/esp32-hal-rmt.c @@ -1,4 +1,4 @@ -// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -58,11 +58,12 @@ struct rmt_obj_s { uint32_t signal_range_min_ns; // RX Filter data - Low Pass pulse width uint32_t signal_range_max_ns; // RX idle time that defines end of reading - EventGroupHandle_t rmt_events; // read/write done event RMT callback handle - bool rmt_ch_is_looping; // Is this RMT TX Channel in LOOPING MODE? - size_t *num_symbols_read; // Pointer to the number of RMT symbol read by IDF RMT RX Done - uint32_t frequency_Hz; // RMT Frequency - uint8_t rmt_EOT_Level; // RMT End of Transmission Level - default is LOW + EventGroupHandle_t rmt_events; // read/write done event RMT callback handle + bool rmt_ch_is_looping; // Is this RMT TX Channel in LOOPING MODE? + size_t *num_symbols_read; // Pointer to the number of RMT symbol read by IDF RMT RX Done + rmt_reserve_memsize_t mem_size; // RMT Memory size + uint32_t frequency_Hz; // RMT Frequency + uint8_t rmt_EOT_Level; // RMT End of Transmission Level - default is LOW #if !CONFIG_DISABLE_HAL_LOCKS SemaphoreHandle_t g_rmt_objlocks; // Channel Semaphore Lock @@ -205,7 +206,8 @@ bool rmtSetCarrier(int pin, bool carrier_en, bool carrier_level, uint32_t freque log_w("GPIO %d - RMT Carrier must be a float percentage from 0 to 1. Setting to 50%.", pin); duty_percent = 0.5; } - rmt_carrier_config_t carrier_cfg = {0}; + rmt_carrier_config_t carrier_cfg; + memset((void *)&carrier_cfg, 0, sizeof(rmt_carrier_config_t)); carrier_cfg.duty_cycle = duty_percent; // duty cycle carrier_cfg.frequency_hz = carrier_en ? frequency_Hz : 0; // carrier frequency in Hz carrier_cfg.flags.polarity_active_low = carrier_level; // carrier modulation polarity level @@ -312,7 +314,8 @@ static bool _rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, bool bl return false; } - rmt_transmit_config_t transmit_cfg = {0}; // loop mode disabled + rmt_transmit_config_t transmit_cfg; // loop mode disabled + memset((void *)&transmit_cfg, 0, sizeof(rmt_transmit_config_t)); bool retCode = true; RMT_MUTEX_LOCK(bus); @@ -379,6 +382,7 @@ static bool _rmtRead(int pin, rmt_data_t *data, size_t *num_rmt_symbols, bool wa // request reading RMT Channel Data rmt_receive_config_t receive_config; + memset((void *)&receive_config, 0, sizeof(rmt_receive_config_t)); receive_config.signal_range_min_ns = bus->signal_range_min_ns; receive_config.signal_range_max_ns = bus->signal_range_max_ns; @@ -464,6 +468,17 @@ bool rmtInit(int pin, rmt_ch_dir_t channel_direction, rmt_reserve_memsize_t mem_ } } + // check if the RMT peripheral is already initialized with the same parameters + rmt_bus_handle_t bus = NULL; + peripheral_bus_type_t rmt_bus_type = perimanGetPinBusType(pin); + if (rmt_bus_type == ESP32_BUS_TYPE_RMT_TX || rmt_bus_type == ESP32_BUS_TYPE_RMT_RX) { + rmt_ch_dir_t bus_rmt_dir = rmt_bus_type == ESP32_BUS_TYPE_RMT_TX ? RMT_TX_MODE : RMT_RX_MODE; + bus = (rmt_bus_handle_t)perimanGetPinBus(pin, rmt_bus_type); + if (bus->frequency_Hz == frequency_Hz && bus_rmt_dir == channel_direction && bus->mem_size == mem_size) { + return true; // already initialized with the same parameters + } + } + // set Peripheral Manager deInit Callback perimanSetBusDeinit(ESP32_BUS_TYPE_RMT_TX, _rmtDetachBus); perimanSetBusDeinit(ESP32_BUS_TYPE_RMT_RX, _rmtDetachBus); @@ -491,14 +506,15 @@ bool rmtInit(int pin, rmt_ch_dir_t channel_direction, rmt_reserve_memsize_t mem_ while (xSemaphoreTake(g_rmt_block_lock, portMAX_DELAY) != pdPASS) {} // allocate the rmt bus object and sets all fields to NULL - rmt_bus_handle_t bus = (rmt_bus_handle_t)heap_caps_calloc(1, sizeof(struct rmt_obj_s), MALLOC_CAP_DEFAULT); + bus = (rmt_bus_handle_t)heap_caps_calloc(1, sizeof(struct rmt_obj_s), MALLOC_CAP_DEFAULT); if (bus == NULL) { log_e("GPIO %d - Bus Memory allocation fault.", pin); goto Err; } - // store the RMT Freq to check Filter and Idle valid values in the RMT API + // store the RMT Freq and mem_size to check Initialization, Filter and Idle valid values in the RMT API bus->frequency_Hz = frequency_Hz; + bus->mem_size = mem_size; // pulses with width smaller than min_ns will be ignored (as a glitch) //bus->signal_range_min_ns = 0; // disabled --> not necessary CALLOC set all to ZERO. // RMT stops reading if the input stays idle for longer than max_ns @@ -517,6 +533,7 @@ bool rmtInit(int pin, rmt_ch_dir_t channel_direction, rmt_reserve_memsize_t mem_ if (channel_direction == RMT_TX_MODE) { // TX Channel rmt_tx_channel_config_t tx_cfg; + memset((void *)&tx_cfg, 0, sizeof(rmt_tx_channel_config_t)); tx_cfg.gpio_num = pin; // CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F80M for C6 -- CLK_XTAL for H2 tx_cfg.clk_src = RMT_CLK_SRC_DEFAULT; @@ -546,6 +563,7 @@ bool rmtInit(int pin, rmt_ch_dir_t channel_direction, rmt_reserve_memsize_t mem_ } else { // RX Channel rmt_rx_channel_config_t rx_cfg; + memset((void *)&rx_cfg, 0, sizeof(rmt_rx_channel_config_t)); rx_cfg.gpio_num = pin; // CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F80M for C6 -- CLK_XTAL for H2 rx_cfg.clk_src = RMT_CLK_SRC_DEFAULT; @@ -572,7 +590,8 @@ bool rmtInit(int pin, rmt_ch_dir_t channel_direction, rmt_reserve_memsize_t mem_ } // allocate memory for the RMT Copy encoder - rmt_copy_encoder_config_t copy_encoder_config = {}; + rmt_copy_encoder_config_t copy_encoder_config; + memset((void *)©_encoder_config, 0, sizeof(rmt_copy_encoder_config_t)); if (rmt_new_copy_encoder(©_encoder_config, &bus->rmt_copy_encoder_h) != ESP_OK) { log_e("GPIO %d - RMT Encoder Memory Allocation error.", pin); goto Err; diff --git a/cores/esp32/esp32-hal-spi.c b/cores/esp32/esp32-hal-spi.c index 857c3d4bb2e..6b8e3f8c013 100644 --- a/cores/esp32/esp32-hal-spi.c +++ b/cores/esp32/esp32-hal-spi.c @@ -22,11 +22,13 @@ #include "esp_attr.h" #include "soc/spi_reg.h" #include "soc/spi_struct.h" +#include "soc/periph_defs.h" #include "soc/io_mux_reg.h" #include "soc/gpio_sig_map.h" #include "soc/rtc.h" #include "hal/clk_gate_ll.h" #include "esp32-hal-periman.h" +#include "esp_private/periph_ctrl.h" #include "esp_system.h" #include "esp_intr_alloc.h" @@ -55,12 +57,15 @@ #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/ets_sys.h" #include "esp32h2/rom/gpio.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/ets_sys.h" +#include "esp32p4/rom/gpio.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif struct spi_struct_t { - spi_dev_t *dev; + volatile spi_dev_t *dev; #if !CONFIG_DISABLE_HAL_LOCKS SemaphoreHandle_t lock; #endif @@ -69,6 +74,7 @@ struct spi_struct_t { int8_t miso; int8_t mosi; int8_t ss; + bool ss_invert; }; #if CONFIG_IDF_TARGET_ESP32S2 @@ -96,6 +102,24 @@ struct spi_struct_t { #define SPI_FSPI_SS_IDX(n) ((n == 0) ? FSPICS0_OUT_IDX : ((n == 1) ? FSPICS1_OUT_IDX : 0)) #define SPI_SS_IDX(p, n) ((p == 0) ? SPI_FSPI_SS_IDX(n) : ((p == 1) ? SPI_HSPI_SS_IDX(n) : 0)) +#elif CONFIG_IDF_TARGET_ESP32P4 +// ESP32P4 +#define SPI_COUNT (2) // SPI2 and SPI3. SPI0 and SPI1 are reserved for flash and PSRAM + +#define SPI_CLK_IDX(p) ((p == 0) ? SPI2_CK_PAD_OUT_IDX : ((p == 1) ? SPI3_CK_PAD_OUT_IDX : 0)) +#define SPI_MISO_IDX(p) ((p == 0) ? SPI2_Q_PAD_OUT_IDX : ((p == 1) ? SPI3_QO_PAD_OUT_IDX : 0)) +#define SPI_MOSI_IDX(p) ((p == 0) ? SPI2_D_PAD_IN_IDX : ((p == 1) ? SPI3_D_PAD_IN_IDX : 0)) + +#define SPI_HSPI_SS_IDX(n) ((n == 0) ? SPI3_CS_PAD_OUT_IDX : ((n == 1) ? SPI3_CS1_PAD_OUT_IDX : ((n == 2) ? SPI3_CS2_PAD_OUT_IDX : 0))) + +#define SPI_FSPI_SS_IDX(n) \ + ((n == 0) ? SPI2_CS_PAD_OUT_IDX \ + : ((n == 1) ? SPI2_CS1_PAD_OUT_IDX \ + : ((n == 2) ? SPI2_CS2_PAD_OUT_IDX \ + : ((n == 3) ? SPI2_CS3_PAD_OUT_IDX : ((n == 4) ? SPI2_CS4_PAD_OUT_IDX : ((n == 5) ? SPI2_CS5_PAD_OUT_IDX : 0)))))) + +#define SPI_SS_IDX(p, n) ((p == 0) ? SPI_FSPI_SS_IDX(n) : ((p == 1) ? SPI_HSPI_SS_IDX(n) : 0)) + #elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 // ESP32C3 #define SPI_COUNT (1) @@ -125,27 +149,29 @@ struct spi_struct_t { #if CONFIG_DISABLE_HAL_LOCKS #define SPI_MUTEX_LOCK() #define SPI_MUTEX_UNLOCK() - +// clang-format off static spi_t _spi_bus_array[] = { #if CONFIG_IDF_TARGET_ESP32S2 - {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 0, -1, -1, -1, -1}, - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 1, -1, -1, -1, -1}, - {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 2, -1, -1, -1, -1} -#elif CONFIG_IDF_TARGET_ESP32S3 - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 1, -1, -1, -1, -1} + {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 0, -1, -1, -1, -1, false}, + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 1, -1, -1, -1, -1, false}, + {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 2, -1, -1, -1, -1, false} +#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1, false}, + {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 1, -1, -1, -1, -1, false} #elif CONFIG_IDF_TARGET_ESP32C2 - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1} + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1, false} #elif CONFIG_IDF_TARGET_ESP32C3 - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1} + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1, false} #elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 - {(spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1} + {(spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1, false} #else - {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), 0, -1, -1, -1, -1}, - {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 1, -1, -1, -1, -1}, - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 2, -1, -1, -1, -1}, - {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3, -1, -1, -1, -1} + {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), 0, -1, -1, -1, -1, false}, + {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 1, -1, -1, -1, -1, false}, + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 2, -1, -1, -1, -1, false}, + {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3, -1, -1, -1, -1, false} #endif }; +// clang-format on #else #define SPI_MUTEX_LOCK() \ do { \ @@ -154,22 +180,22 @@ static spi_t _spi_bus_array[] = { static spi_t _spi_bus_array[] = { #if CONFIG_IDF_TARGET_ESP32S2 - {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 0, -1, -1, -1, -1}, - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 1, -1, -1, -1, -1}, - {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 2, -1, -1, -1, -1} -#elif CONFIG_IDF_TARGET_ESP32S3 - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 1, -1, -1, -1, -1} + {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 0, -1, -1, -1, -1, false}, + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 1, -1, -1, -1, -1, false}, + {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 2, -1, -1, -1, -1, false} +#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1, false}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 1, -1, -1, -1, -1, false} #elif CONFIG_IDF_TARGET_ESP32C2 - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1} + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1, false} #elif CONFIG_IDF_TARGET_ESP32C3 - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1} + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1, false} #elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 - {(spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1} + {(spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1, false} #else - {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0, -1, -1, -1, -1}, - {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1, -1, -1, -1, -1}, - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2, -1, -1, -1, -1}, - {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3, -1, -1, -1, -1} + {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0, -1, -1, -1, -1, false}, + {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1, -1, -1, -1, -1, false}, + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2, -1, -1, -1, -1, false}, + {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3, -1, -1, -1, -1, false} #endif }; #endif @@ -340,7 +366,7 @@ bool spiAttachSS(spi_t *spi, uint8_t ss_num, int8_t ss) { return false; } pinMode(ss, OUTPUT); - pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, ss_num), false, false); + pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, ss_num), spi->ss_invert, false); spiEnableSSPins(spi, (1 << ss_num)); spi->ss = ss; if (!perimanSetPinBus(ss, ESP32_BUS_TYPE_SPI_MASTER_SS, (void *)(spi->num + 1), spi->num, -1)) { @@ -369,11 +395,10 @@ void spiEnableSSPins(spi_t *spi, uint8_t ss_mask) { return; } SPI_MUTEX_LOCK(); -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.val &= ~(ss_mask & SPI_SS_MASK_ALL); -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.val &= ~(ss_mask & SPI_SS_MASK_ALL); +#else + spi->dev->misc.val &= ~(ss_mask & SPI_SS_MASK_ALL); #endif SPI_MUTEX_UNLOCK(); } @@ -383,11 +408,10 @@ void spiDisableSSPins(spi_t *spi, uint8_t ss_mask) { return; } SPI_MUTEX_LOCK(); -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.val |= (ss_mask & SPI_SS_MASK_ALL); -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.val |= (ss_mask & SPI_SS_MASK_ALL); +#else + spi->dev->misc.val |= (ss_mask & SPI_SS_MASK_ALL); #endif SPI_MUTEX_UNLOCK(); } @@ -412,16 +436,21 @@ void spiSSDisable(spi_t *spi) { SPI_MUTEX_UNLOCK(); } +void spiSSInvert(spi_t *spi, bool invert) { + if (spi) { + spi->ss_invert = invert; + } +} + void spiSSSet(spi_t *spi) { if (!spi) { return; } SPI_MUTEX_LOCK(); -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.cs_keep_active = 1; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.cs_keep_active = 1; +#else + spi->dev->misc.cs_keep_active = 1; #endif SPI_MUTEX_UNLOCK(); } @@ -431,11 +460,10 @@ void spiSSClear(spi_t *spi) { return; } SPI_MUTEX_LOCK(); -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.cs_keep_active = 0; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.cs_keep_active = 0; +#else + spi->dev->misc.cs_keep_active = 0; #endif SPI_MUTEX_UNLOCK(); } @@ -460,11 +488,10 @@ uint8_t spiGetDataMode(spi_t *spi) { if (!spi) { return 0; } -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - bool idleEdge = spi->dev->misc.ck_idle_edge; -#else +#if CONFIG_IDF_TARGET_ESP32 bool idleEdge = spi->dev->pin.ck_idle_edge; +#else + bool idleEdge = spi->dev->misc.ck_idle_edge; #endif bool outEdge = spi->dev->user.ck_out_edge; if (idleEdge) { @@ -486,39 +513,35 @@ void spiSetDataMode(spi_t *spi, uint8_t dataMode) { SPI_MUTEX_LOCK(); switch (dataMode) { case SPI_MODE1: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 0; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 0; +#else + spi->dev->misc.ck_idle_edge = 0; #endif spi->dev->user.ck_out_edge = 1; break; case SPI_MODE2: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 1; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 1; +#else + spi->dev->misc.ck_idle_edge = 1; #endif spi->dev->user.ck_out_edge = 1; break; case SPI_MODE3: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 1; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 1; +#else + spi->dev->misc.ck_idle_edge = 1; #endif spi->dev->user.ck_out_edge = 0; break; case SPI_MODE0: default: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 0; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 0; +#else + spi->dev->misc.ck_idle_edge = 0; #endif spi->dev->user.ck_out_edge = 0; break; @@ -564,11 +587,10 @@ static void spiInitBus(spi_t *spi) { spi->dev->slave.trans_done = 0; #endif spi->dev->slave.val = 0; -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.val = 0; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.val = 0; +#else + spi->dev->misc.val = 0; #endif spi->dev->user.val = 0; spi->dev->user1.val = 0; @@ -648,18 +670,18 @@ spi_t *spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST); } -#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#elif defined(__PERIPH_CTRL_ALLOW_LEGACY_API) periph_ll_reset(PERIPH_SPI2_MODULE); periph_ll_enable_clk_clear_rst(PERIPH_SPI2_MODULE); #endif SPI_MUTEX_LOCK(); spiInitBus(spi); -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->clk_gate.clk_en = 1; spi->dev->clk_gate.mst_clk_sel = 1; spi->dev->clk_gate.mst_clk_active = 1; -#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 +#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) spi->dev->dma_conf.tx_seg_trans_clr_en = 1; spi->dev->dma_conf.rx_seg_trans_clr_en = 1; spi->dev->dma_conf.dma_seg_trans_en = 0; @@ -670,7 +692,7 @@ spi_t *spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t spi->dev->user.doutdin = 1; int i; for (i = 0; i < 16; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = 0x00000000; #else spi->dev->data_buf[i] = 0x00000000; @@ -697,7 +719,7 @@ void spiWaitReady(spi_t *spi) { #if CONFIG_IDF_TARGET_ESP32S2 #define usr_mosi_dbitlen usr_mosi_bit_len #define usr_miso_dbitlen usr_miso_bit_len -#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#elif !defined(CONFIG_IDF_TARGET_ESP32) #define usr_mosi_dbitlen ms_data_bitlen #define usr_miso_dbitlen ms_data_bitlen #define mosi_dlen ms_dlen @@ -718,13 +740,13 @@ void spiWrite(spi_t *spi, const uint32_t *data, uint8_t len) { spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif for (i = 0; i < len; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = data[i]; #else spi->dev->data_buf[i] = data[i]; #endif } -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -745,20 +767,20 @@ void spiTransfer(spi_t *spi, uint32_t *data, uint8_t len) { spi->dev->mosi_dlen.usr_mosi_dbitlen = (len * 32) - 1; spi->dev->miso_dlen.usr_miso_dbitlen = (len * 32) - 1; for (i = 0; i < len; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = data[i]; #else spi->dev->data_buf[i] = data[i]; #endif } -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); for (i = 0; i < len; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data[i] = spi->dev->data_buf[i].val; #else data[i] = spi->dev->data_buf[i]; @@ -776,13 +798,13 @@ void spiWriteByte(spi_t *spi, uint8_t data) { #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -798,18 +820,18 @@ uint8_t spiTransferByte(spi_t *spi, uint8_t data) { SPI_MUTEX_LOCK(); spi->dev->mosi_dlen.usr_mosi_dbitlen = 7; spi->dev->miso_dlen.usr_miso_dbitlen = 7; -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val & 0xFF; #else data = spi->dev->data_buf[0] & 0xFF; @@ -839,12 +861,12 @@ void spiWriteWord(spi_t *spi, uint16_t data) { #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -863,18 +885,18 @@ uint16_t spiTransferWord(spi_t *spi, uint16_t data) { SPI_MUTEX_LOCK(); spi->dev->mosi_dlen.usr_mosi_dbitlen = 15; spi->dev->miso_dlen.usr_miso_dbitlen = 15; -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val; #else data = spi->dev->data_buf[0]; @@ -898,12 +920,12 @@ void spiWriteLong(spi_t *spi, uint32_t data) { #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -922,18 +944,18 @@ uint32_t spiTransferLong(spi_t *spi, uint32_t data) { SPI_MUTEX_LOCK(); spi->dev->mosi_dlen.usr_mosi_dbitlen = 31; spi->dev->miso_dlen.usr_miso_dbitlen = 31; -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val; #else data = spi->dev->data_buf[0]; @@ -972,14 +994,14 @@ static void __spiTransferBytes(spi_t *spi, const uint8_t *data, uint8_t *out, ui spi->dev->miso_dlen.usr_miso_dbitlen = ((bytes * 8) - 1); for (i = 0; i < words; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = wordsBuf[i]; //copy buffer to spi fifo #else spi->dev->data_buf[i] = wordsBuf[i]; //copy buffer to spi fifo #endif } -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -989,7 +1011,7 @@ static void __spiTransferBytes(spi_t *spi, const uint8_t *data, uint8_t *out, ui if (out) { for (i = 0; i < words; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 wordsBuf[i] = spi->dev->data_buf[i].val; //copy spi fifo to buffer #else wordsBuf[i] = spi->dev->data_buf[i]; //copy spi fifo to buffer @@ -1061,39 +1083,35 @@ void spiTransaction(spi_t *spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bit spi->dev->clock.val = clockDiv; switch (dataMode) { case SPI_MODE1: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 0; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 0; +#else + spi->dev->misc.ck_idle_edge = 0; #endif spi->dev->user.ck_out_edge = 1; break; case SPI_MODE2: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 1; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 1; +#else + spi->dev->misc.ck_idle_edge = 1; #endif spi->dev->user.ck_out_edge = 1; break; case SPI_MODE3: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 1; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 1; +#else + spi->dev->misc.ck_idle_edge = 1; #endif spi->dev->user.ck_out_edge = 0; break; case SPI_MODE0: default: -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \ - || CONFIG_IDF_TARGET_ESP32H2 - spi->dev->misc.ck_idle_edge = 0; -#else +#if CONFIG_IDF_TARGET_ESP32 spi->dev->pin.ck_idle_edge = 0; +#else + spi->dev->misc.ck_idle_edge = 0; #endif spi->dev->user.ck_out_edge = 0; break; @@ -1105,7 +1123,7 @@ void spiTransaction(spi_t *spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bit spi->dev->ctrl.wr_bit_order = 1; spi->dev->ctrl.rd_bit_order = 1; } -#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) // Sync new config with hardware, fixes https://github.com/espressif/arduino-esp32/issues/9221 spi->dev->cmd.update = 1; while (spi->dev->cmd.update); @@ -1134,12 +1152,12 @@ void ARDUINO_ISR_ATTR spiWriteByteNL(spi_t *spi, uint8_t data) { #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -1153,18 +1171,18 @@ uint8_t spiTransferByteNL(spi_t *spi, uint8_t data) { } spi->dev->mosi_dlen.usr_mosi_dbitlen = 7; spi->dev->miso_dlen.usr_miso_dbitlen = 7; -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val & 0xFF; #else data = spi->dev->data_buf[0] & 0xFF; @@ -1183,12 +1201,12 @@ void ARDUINO_ISR_ATTR spiWriteShortNL(spi_t *spi, uint16_t data) { #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -1205,18 +1223,18 @@ uint16_t spiTransferShortNL(spi_t *spi, uint16_t data) { } spi->dev->mosi_dlen.usr_mosi_dbitlen = 15; spi->dev->miso_dlen.usr_miso_dbitlen = 15; -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val & 0xFFFF; #else data = spi->dev->data_buf[0] & 0xFFFF; @@ -1238,12 +1256,12 @@ void ARDUINO_ISR_ATTR spiWriteLongNL(spi_t *spi, uint32_t data) { #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -1260,18 +1278,18 @@ uint32_t spiTransferLongNL(spi_t *spi, uint32_t data) { } spi->dev->mosi_dlen.usr_mosi_dbitlen = 31; spi->dev->miso_dlen.usr_miso_dbitlen = 31; -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val; #else data = spi->dev->data_buf[0]; @@ -1302,13 +1320,13 @@ void spiWriteNL(spi_t *spi, const void *data_in, uint32_t len) { spi->dev->miso_dlen.usr_miso_dbitlen = 0; #endif for (size_t i = 0; i < c_longs; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = data[i]; #else spi->dev->data_buf[i] = data[i]; #endif } -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -1341,7 +1359,7 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint spi->dev->miso_dlen.usr_miso_dbitlen = (c_len * 8) - 1; if (data) { for (size_t i = 0; i < c_longs; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = data[i]; #else spi->dev->data_buf[i] = data[i]; @@ -1349,14 +1367,14 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint } } else { for (size_t i = 0; i < c_longs; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = 0xFFFFFFFF; #else spi->dev->data_buf[i] = 0xFFFFFFFF; #endif } } -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -1365,13 +1383,13 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint if (result) { if (c_len & 3) { for (size_t i = 0; i < (c_longs - 1); i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 result[i] = spi->dev->data_buf[i].val; #else result[i] = spi->dev->data_buf[i]; #endif } -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 uint32_t last_data = spi->dev->data_buf[c_longs - 1].val; #else uint32_t last_data = spi->dev->data_buf[c_longs - 1]; @@ -1383,7 +1401,7 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint } } else { for (size_t i = 0; i < c_longs; i++) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 result[i] = spi->dev->data_buf[i].val; #else result[i] = spi->dev->data_buf[i]; @@ -1425,18 +1443,18 @@ void spiTransferBitsNL(spi_t *spi, uint32_t data, uint32_t *out, uint8_t bits) { spi->dev->mosi_dlen.usr_mosi_dbitlen = (bits - 1); spi->dev->miso_dlen.usr_miso_dbitlen = (bits - 1); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[0].val = data; #else spi->dev->data_buf[0] = data; #endif -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif spi->dev->cmd.usr = 1; while (spi->dev->cmd.usr); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 data = spi->dev->data_buf[0].val; #else data = spi->dev->data_buf[0]; @@ -1477,34 +1495,34 @@ void ARDUINO_ISR_ATTR spiWritePixelsNL(spi_t *spi, const void *data_in, uint32_t if (msb) { if (l_bytes && i == (c_longs - 1)) { if (l_bytes == 2) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 MSB_16_SET(spi->dev->data_buf[i].val, data[i]); #else MSB_16_SET(spi->dev->data_buf[i], data[i]); #endif } else { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = data[i] & 0xFF; #else spi->dev->data_buf[i] = data[i] & 0xFF; #endif } } else { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 MSB_PIX_SET(spi->dev->data_buf[i].val, data[i]); #else MSB_PIX_SET(spi->dev->data_buf[i], data[i]); #endif } } else { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 spi->dev->data_buf[i].val = data[i]; #else spi->dev->data_buf[i] = data[i]; #endif } } -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) spi->dev->cmd.update = 1; while (spi->dev->cmd.update); #endif @@ -1528,7 +1546,7 @@ typedef union { uint32_t clkcnt_l : 6; /*it must be equal to spi_clkcnt_N.*/ uint32_t clkcnt_h : 6; /*it must be floor((spi_clkcnt_N+1)/2-1).*/ uint32_t clkcnt_n : 6; /*it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_N+1)*/ -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) uint32_t clkdiv_pre : 4; /*it is pre-divider of spi_clk.*/ uint32_t reserved : 9; /*reserved*/ #else @@ -1573,7 +1591,7 @@ uint32_t spiFrequencyToClockDiv(uint32_t freq) { while (calPreVari++ <= 1) { calPre = (((apb_freq / (reg.clkcnt_n + 1)) / freq) - 1) + calPreVari; -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) if (calPre > 0xF) { reg.clkdiv_pre = 0xF; #else diff --git a/cores/esp32/esp32-hal-spi.h b/cores/esp32/esp32-hal-spi.h index a238cada87d..7d56f0820d3 100644 --- a/cores/esp32/esp32-hal-spi.h +++ b/cores/esp32/esp32-hal-spi.h @@ -28,10 +28,7 @@ extern "C" { #define SPI_HAS_TRANSACTION -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32S3 -#define FSPI 0 -#define HSPI 1 -#elif CONFIG_IDF_TARGET_ESP32S2 +#ifdef CONFIG_IDF_TARGET_ESP32S2 #define FSPI 1 //SPI 1 bus. ESP32S2: for external memory only (can use the same data lines but different SS) #define HSPI 2 //SPI 2 bus. ESP32S2: external memory or device - it can be matrixed to any pins #define SPI2 2 // Another name for ESP32S2 SPI 2 @@ -40,6 +37,9 @@ extern "C" { #define FSPI 1 //SPI 1 bus attached to the flash (can use the same data lines but different SS) #define HSPI 2 //SPI 2 bus normally mapped to pins 12 - 15, but can be matrixed to any pins #define VSPI 3 //SPI 3 bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins +#else +#define FSPI 0 +#define HSPI 1 #endif // This defines are not representing the real Divider of the ESP32 @@ -97,6 +97,8 @@ void spiSSSet(spi_t *spi); void spiSSClear(spi_t *spi); void spiWaitReady(spi_t *spi); +//invert hardware SS +void spiSSInvert(spi_t *spi, bool invert); uint32_t spiGetClockDiv(spi_t *spi); uint8_t spiGetDataMode(spi_t *spi); diff --git a/cores/esp32/esp32-hal-time.c b/cores/esp32/esp32-hal-time.c index 23bd3bf9e99..074e999be71 100644 --- a/cores/esp32/esp32-hal-time.c +++ b/cores/esp32/esp32-hal-time.c @@ -17,6 +17,10 @@ //#include "tcpip_adapter.h" #include "esp_netif.h" +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING +#include "lwip/priv/tcpip_priv.h" +#endif + static void setTimeZone(long offset, int daylight) { char cst[17] = {0}; char cdt[17] = "DST"; @@ -47,14 +51,29 @@ static void setTimeZone(long offset, int daylight) { void configTime(long gmtOffset_sec, int daylightOffset_sec, const char *server1, const char *server2, const char *server3) { //tcpip_adapter_init(); // Should not hurt anything if already inited esp_netif_init(); + +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING + if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { + LOCK_TCPIP_CORE(); + } +#endif + if (sntp_enabled()) { sntp_stop(); } + sntp_setoperatingmode(SNTP_OPMODE_POLL); sntp_setservername(0, (char *)server1); sntp_setservername(1, (char *)server2); sntp_setservername(2, (char *)server3); sntp_init(); + +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING + if (sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { + UNLOCK_TCPIP_CORE(); + } +#endif + setTimeZone(-gmtOffset_sec, daylightOffset_sec); } @@ -65,14 +84,29 @@ void configTime(long gmtOffset_sec, int daylightOffset_sec, const char *server1, void configTzTime(const char *tz, const char *server1, const char *server2, const char *server3) { //tcpip_adapter_init(); // Should not hurt anything if already inited esp_netif_init(); + +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING + if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { + LOCK_TCPIP_CORE(); + } +#endif + if (sntp_enabled()) { sntp_stop(); } + sntp_setoperatingmode(SNTP_OPMODE_POLL); sntp_setservername(0, (char *)server1); sntp_setservername(1, (char *)server2); sntp_setservername(2, (char *)server3); sntp_init(); + +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING + if (sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { + UNLOCK_TCPIP_CORE(); + } +#endif + setenv("TZ", tz, 1); tzset(); } diff --git a/cores/esp32/esp32-hal-timer.c b/cores/esp32/esp32-hal-timer.c index 56f58529ec4..ec6c507358e 100644 --- a/cores/esp32/esp32-hal-timer.c +++ b/cores/esp32/esp32-hal-timer.c @@ -37,17 +37,28 @@ struct timer_struct_t { }; inline uint64_t timerRead(hw_timer_t *timer) { - + if (timer == NULL) { + log_e("Timer handle is NULL"); + return 0; + } uint64_t value; gptimer_get_raw_count(timer->timer_handle, &value); return value; } void timerWrite(hw_timer_t *timer, uint64_t val) { + if (timer == NULL) { + log_e("Timer handle is NULL"); + return; + } gptimer_set_raw_count(timer->timer_handle, val); } void timerAlarm(hw_timer_t *timer, uint64_t alarm_value, bool autoreload, uint64_t reload_count) { + if (timer == NULL) { + log_e("Timer handle is NULL"); + return; + } esp_err_t err = ESP_OK; gptimer_alarm_config_t alarm_cfg = { .alarm_count = alarm_value, @@ -61,22 +72,37 @@ void timerAlarm(hw_timer_t *timer, uint64_t alarm_value, bool autoreload, uint64 } uint32_t timerGetFrequency(hw_timer_t *timer) { + if (timer == NULL) { + return 0; + } uint32_t frequency; gptimer_get_resolution(timer->timer_handle, &frequency); return frequency; } void timerStart(hw_timer_t *timer) { + if (timer == NULL) { + log_e("Timer handle is NULL"); + return; + } gptimer_start(timer->timer_handle); timer->timer_started = true; } void timerStop(hw_timer_t *timer) { + if (timer == NULL) { + log_e("Timer handle is NULL"); + return; + } gptimer_stop(timer->timer_handle); timer->timer_started = false; } void timerRestart(hw_timer_t *timer) { + if (timer == NULL) { + log_e("Timer handle is NULL"); + return; + } gptimer_set_raw_count(timer->timer_handle, 0); } @@ -129,17 +155,19 @@ hw_timer_t *timerBegin(uint32_t frequency) { } void timerEnd(hw_timer_t *timer) { - esp_err_t err = ESP_OK; - if (timer->timer_started == true) { - gptimer_stop(timer->timer_handle); - } - gptimer_disable(timer->timer_handle); - err = gptimer_del_timer(timer->timer_handle); - if (err != ESP_OK) { - log_e("Failed to destroy GPTimer, error num=%d", err); - return; + if (timer != NULL) { + esp_err_t err = ESP_OK; + if (timer->timer_started == true) { + gptimer_stop(timer->timer_handle); + } + gptimer_disable(timer->timer_handle); + err = gptimer_del_timer(timer->timer_handle); + if (err != ESP_OK) { + log_e("Failed to destroy GPTimer, error num=%d", err); + return; + } + free(timer); } - free(timer); } bool IRAM_ATTR timerFnWrapper(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *args) { @@ -156,6 +184,10 @@ bool IRAM_ATTR timerFnWrapper(gptimer_handle_t timer, const gptimer_alarm_event_ } void timerAttachInterruptFunctionalArg(hw_timer_t *timer, void (*userFunc)(void *), void *arg) { + if (timer == NULL) { + log_e("Timer handle is NULL"); + return; + } esp_err_t err = ESP_OK; gptimer_event_callbacks_t cbs = { .on_alarm = timerFnWrapper, @@ -187,6 +219,10 @@ void timerAttachInterrupt(hw_timer_t *timer, voidFuncPtr userFunc) { } void timerDetachInterrupt(hw_timer_t *timer) { + if (timer == NULL) { + log_e("Timer handle is NULL"); + return; + } esp_err_t err = ESP_OK; err = gptimer_set_alarm_action(timer->timer_handle, NULL); timer->interrupt_handle.fn = NULL; @@ -197,18 +233,30 @@ void timerDetachInterrupt(hw_timer_t *timer) { } uint64_t timerReadMicros(hw_timer_t *timer) { + if (timer == NULL) { + log_e("Timer handle is NULL"); + return 0; + } uint64_t timer_val = timerRead(timer); uint32_t frequency = timerGetFrequency(timer); return timer_val * 1000000 / frequency; } -uint64_t timerReadMilis(hw_timer_t *timer) { +uint64_t timerReadMillis(hw_timer_t *timer) { + if (timer == NULL) { + log_e("Timer handle is NULL"); + return 0; + } uint64_t timer_val = timerRead(timer); uint32_t frequency = timerGetFrequency(timer); return timer_val * 1000 / frequency; } double timerReadSeconds(hw_timer_t *timer) { + if (timer == NULL) { + log_e("Timer handle is NULL"); + return 0; + } uint64_t timer_val = timerRead(timer); uint32_t frequency = timerGetFrequency(timer); return (double)timer_val / frequency; diff --git a/cores/esp32/esp32-hal-timer.h b/cores/esp32/esp32-hal-timer.h index 35518534783..59b88c99cba 100644 --- a/cores/esp32/esp32-hal-timer.h +++ b/cores/esp32/esp32-hal-timer.h @@ -42,7 +42,7 @@ void timerWrite(hw_timer_t *timer, uint64_t val); uint64_t timerRead(hw_timer_t *timer); uint64_t timerReadMicros(hw_timer_t *timer); -uint64_t timerReadMilis(hw_timer_t *timer); +uint64_t timerReadMillis(hw_timer_t *timer); double timerReadSeconds(hw_timer_t *timer); uint32_t timerGetFrequency(hw_timer_t *timer); diff --git a/cores/esp32/esp32-hal-tinyusb.c b/cores/esp32/esp32-hal-tinyusb.c index 4b39da82641..0991e08d27f 100644 --- a/cores/esp32/esp32-hal-tinyusb.c +++ b/cores/esp32/esp32-hal-tinyusb.c @@ -10,12 +10,15 @@ #include "soc/soc.h" #include "soc/efuse_reg.h" +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #include "soc/rtc_cntl_reg.h" #include "soc/usb_struct.h" #include "soc/usb_reg.h" #include "soc/usb_wrap_reg.h" #include "soc/usb_wrap_struct.h" #include "soc/usb_periph.h" +#endif + #include "soc/periph_defs.h" #include "soc/timer_group_struct.h" #include "soc/system_reg.h" @@ -34,8 +37,8 @@ #include "esp32-hal.h" #include "esp32-hal-periman.h" - #include "esp32-hal-tinyusb.h" + #if CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/rom/usb/usb_persist.h" #include "esp32s2/rom/usb/usb_dc.h" @@ -50,6 +53,7 @@ #include "esp32s3/rom/usb/usb_persist.h" #include "esp32s3/rom/usb/usb_dc.h" #include "esp32s3/rom/usb/chip_usb_dw_wrapper.h" +#elif CONFIG_IDF_TARGET_ESP32P4 #endif typedef enum { @@ -127,7 +131,11 @@ esp_err_t init_usb_hal(bool external_phy) { .controller = USB_PHY_CTRL_OTG, .target = USB_PHY_TARGET_INT, .otg_mode = USB_OTG_MODE_DEVICE, +#if CONFIG_IDF_TARGET_ESP32P4 + .otg_speed = USB_PHY_SPEED_HIGH, +#else .otg_speed = USB_PHY_SPEED_FULL, +#endif .ext_io_conf = NULL, .otg_io_conf = NULL, }; @@ -165,7 +173,16 @@ void deinit_usb_hal() { esp_err_t tinyusb_driver_install(const tinyusb_config_t *config) { init_usb_hal(config->external_phy); - if (!tusb_init()) { + tusb_rhport_init_t tinit; + memset(&tinit, 0, sizeof(tusb_rhport_init_t)); + tinit.role = TUSB_ROLE_DEVICE; +#if CONFIG_IDF_TARGET_ESP32P4 + tinit.speed = TUSB_SPEED_HIGH; + if (!tusb_init(1, &tinit)) { +#else + tinit.speed = TUSB_SPEED_FULL; + if (!tusb_init(0, &tinit)) { +#endif log_e("Can't initialize the TinyUSB stack."); return ESP_FAIL; } @@ -275,15 +292,14 @@ enum { VENDOR_REQUEST_MICROSOFT = 2 }; -static uint8_t const tinyusb_bos_descriptor[] = { - // total length, number of device caps - TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 2), +static uint8_t const tinyusb_bos_descriptor[] = {// total length, number of device caps + TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 2), - // Vendor Code, iLandingPage - TUD_BOS_WEBUSB_DESCRIPTOR(VENDOR_REQUEST_WEBUSB, 1), + // Vendor Code, iLandingPage + TUD_BOS_WEBUSB_DESCRIPTOR(VENDOR_REQUEST_WEBUSB, 1), - // Microsoft OS 2.0 descriptor - TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, VENDOR_REQUEST_MICROSOFT) + // Microsoft OS 2.0 descriptor + TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, VENDOR_REQUEST_MICROSOFT) }; /* @@ -453,14 +469,24 @@ __attribute__((weak)) int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cm __attribute__((weak)) bool tud_msc_is_writable_cb(uint8_t lun) { return false; } - +#endif +#if CFG_TUD_NCM +__attribute__((weak)) bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { + return false; +} +__attribute__((weak)) uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) { + return 0; +} +__attribute__((weak)) void tud_network_init_cb(void) {} #endif /* * Private API * */ +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 static bool usb_persist_enabled = false; static restart_type_t usb_persist_mode = RESTART_NO_PERSIST; +#endif #if CONFIG_IDF_TARGET_ESP32S3 @@ -541,6 +567,7 @@ static void usb_switch_to_cdc_jtag() { } #endif +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 static void IRAM_ATTR usb_persist_shutdown_handler(void) { if (usb_persist_mode != RESTART_NO_PERSIST) { if (usb_persist_enabled) { @@ -572,8 +599,10 @@ static void IRAM_ATTR usb_persist_shutdown_handler(void) { } } } +#endif void usb_persist_restart(restart_type_t mode) { +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 if (mode < RESTART_TYPE_MAX && esp_register_shutdown_handler(usb_persist_shutdown_handler) == ESP_OK) { usb_persist_mode = mode; #if CONFIG_IDF_TARGET_ESP32S3 @@ -583,10 +612,11 @@ void usb_persist_restart(restart_type_t mode) { #endif esp_restart(); } +#endif } static bool tinyusb_reserve_in_endpoint(uint8_t endpoint) { - if (endpoint > 6 || (tinyusb_endpoints.in & BIT(endpoint)) != 0) { + if (endpoint > CFG_TUD_NUM_EPS || (tinyusb_endpoints.in & BIT(endpoint)) != 0) { return false; } tinyusb_endpoints.in |= BIT(endpoint); @@ -594,7 +624,7 @@ static bool tinyusb_reserve_in_endpoint(uint8_t endpoint) { } static bool tinyusb_reserve_out_endpoint(uint8_t endpoint) { - if (endpoint > 6 || (tinyusb_endpoints.out & BIT(endpoint)) != 0) { + if (endpoint > CFG_TUD_NUM_EPS || (tinyusb_endpoints.out & BIT(endpoint)) != 0) { return false; } tinyusb_endpoints.out |= BIT(endpoint); @@ -602,11 +632,13 @@ static bool tinyusb_reserve_out_endpoint(uint8_t endpoint) { } static bool tinyusb_has_available_fifos(void) { - uint8_t max_endpoints = 4, active_endpoints = 0; + uint8_t max_endpoints = CFG_TUD_NUM_IN_EPS - 1, active_endpoints = 0; +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 if (tinyusb_loaded_interfaces_mask & BIT(USB_INTERFACE_CDC)) { - max_endpoints = 5; //CDC endpoint 0x85 is actually not linked to FIFO and not used + max_endpoints = CFG_TUD_NUM_IN_EPS; //CDC endpoint 0x85 is actually not linked to FIFO and not used } - for (uint8_t i = 1; i < 7; i++) { +#endif + for (uint8_t i = 1; i <= CFG_TUD_NUM_EPS; i++) { if ((tinyusb_endpoints.in & BIT(i)) != 0) { active_endpoints++; } @@ -666,8 +698,13 @@ static inline char nibble_to_hex_char(uint8_t b) { static void set_usb_serial_num(void) { /* Get the MAC address */ +#if CONFIG_IDF_TARGET_ESP32P4 + const uint32_t mac0 = REG_GET_FIELD(EFUSE_RD_MAC_SYS_0_REG, EFUSE_MAC_0); + const uint32_t mac1 = REG_GET_FIELD(EFUSE_RD_MAC_SYS_0_REG, EFUSE_MAC_1); +#else const uint32_t mac0 = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_0_REG, EFUSE_MAC_0); const uint32_t mac1 = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_1_REG, EFUSE_MAC_1); +#endif uint8_t mac_bytes[6]; memcpy(mac_bytes, &mac0, 4); memcpy(mac_bytes + 4, &mac1, 2); @@ -736,7 +773,7 @@ static void usb_device_task(void *param) { * PUBLIC API * */ #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR -const char *tinyusb_interface_names[USB_INTERFACE_MAX] = {"MSC", "DFU", "HID", "VENDOR", "CDC", "MIDI", "CUSTOM"}; +const char *tinyusb_interface_names[USB_INTERFACE_MAX] = {"MSC", "DFU", "HID", "VENDOR", "CDC", "CDC2", "MIDI", "CUSTOM"}; #endif static bool tinyusb_is_initialized = false; @@ -786,6 +823,7 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) { return ESP_FAIL; } +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 bool usb_did_persist = (USB_WRAP.date.val == USBDC_PERSIST_ENA); //if(usb_did_persist && usb_persist_enabled){ @@ -798,6 +836,7 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) { periph_ll_reset(PERIPH_USB_MODULE); periph_ll_enable_clk_clear_rst(PERIPH_USB_MODULE); } +#endif tinyusb_config_t tusb_cfg = { .external_phy = false // In the most cases you need to use a `false` value @@ -825,7 +864,7 @@ uint8_t tinyusb_get_free_duplex_endpoint(void) { log_e("No available IN endpoints"); return 0; } - for (uint8_t i = 1; i < 7; i++) { + for (uint8_t i = 1; i <= CFG_TUD_NUM_IN_EPS; i++) { if ((tinyusb_endpoints.in & BIT(i)) == 0 && (tinyusb_endpoints.out & BIT(i)) == 0) { tinyusb_endpoints.in |= BIT(i); tinyusb_endpoints.out |= BIT(i); @@ -841,13 +880,13 @@ uint8_t tinyusb_get_free_in_endpoint(void) { log_e("No available IN endpoints"); return 0; } - for (uint8_t i = 1; i < 7; i++) { + for (uint8_t i = 1; i <= CFG_TUD_NUM_IN_EPS; i++) { if ((tinyusb_endpoints.in & BIT(i)) == 0 && (tinyusb_endpoints.out & BIT(i)) != 0) { tinyusb_endpoints.in |= BIT(i); return i; } } - for (uint8_t i = 1; i < 7; i++) { + for (uint8_t i = 1; i <= CFG_TUD_NUM_IN_EPS; i++) { if ((tinyusb_endpoints.in & BIT(i)) == 0) { tinyusb_endpoints.in |= BIT(i); return i; @@ -857,13 +896,13 @@ uint8_t tinyusb_get_free_in_endpoint(void) { } uint8_t tinyusb_get_free_out_endpoint(void) { - for (uint8_t i = 1; i < 7; i++) { + for (uint8_t i = 1; i <= CFG_TUD_NUM_EPS; i++) { if ((tinyusb_endpoints.out & BIT(i)) == 0 && (tinyusb_endpoints.in & BIT(i)) != 0) { tinyusb_endpoints.out |= BIT(i); return i; } } - for (uint8_t i = 1; i < 7; i++) { + for (uint8_t i = 1; i <= CFG_TUD_NUM_EPS; i++) { if ((tinyusb_endpoints.out & BIT(i)) == 0) { tinyusb_endpoints.out |= BIT(i); return i; diff --git a/cores/esp32/esp32-hal-tinyusb.h b/cores/esp32/esp32-hal-tinyusb.h index 9e9d044f80e..73210c4872b 100644 --- a/cores/esp32/esp32-hal-tinyusb.h +++ b/cores/esp32/esp32-hal-tinyusb.h @@ -31,6 +31,21 @@ extern "C" { #define USB_ESPRESSIF_VID 0x303A #define USB_STRING_DESCRIPTOR_ARRAY_SIZE 10 +#ifndef CFG_TUD_ENDOINT_SIZE +#if CONFIG_IDF_TARGET_ESP32P4 +#define CFG_TUD_ENDOINT_SIZE 512 +#else +#define CFG_TUD_ENDOINT_SIZE 64 +#endif +#endif +#if CONFIG_IDF_TARGET_ESP32P4 +#define CFG_TUD_NUM_EPS 15 +#define CFG_TUD_NUM_IN_EPS 8 +#else +#define CFG_TUD_NUM_EPS 6 +#define CFG_TUD_NUM_IN_EPS 5 +#endif + typedef struct { uint16_t vid; uint16_t pid; @@ -80,6 +95,7 @@ typedef enum { USB_INTERFACE_HID, USB_INTERFACE_VENDOR, USB_INTERFACE_CDC, + USB_INTERFACE_CDC2, USB_INTERFACE_MIDI, USB_INTERFACE_CUSTOM, USB_INTERFACE_MAX diff --git a/cores/esp32/esp32-hal-touch-ng.c b/cores/esp32/esp32-hal-touch-ng.c new file mode 100644 index 00000000000..888a299ec0c --- /dev/null +++ b/cores/esp32/esp32-hal-touch-ng.c @@ -0,0 +1,453 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "soc/soc_caps.h" + +#if SOC_TOUCH_SENSOR_SUPPORTED +#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 for now + +#include "driver/touch_sens.h" +#include "esp32-hal-touch-ng.h" +#include "esp32-hal-periman.h" + +/* + Internal Private Touch Data Structure and Functions +*/ + +typedef void (*voidFuncPtr)(void); +typedef void (*voidArgFuncPtr)(void *); + +typedef struct { + voidFuncPtr fn; + bool callWithArgs; + void *arg; + bool lastStatusIsPressed; +} TouchInterruptHandle_t; + +static TouchInterruptHandle_t __touchInterruptHandlers[SOC_TOUCH_SENSOR_NUM] = { + 0, +}; + +static uint8_t _sample_num = 1; +static uint32_t _div_num = 1; +static uint8_t _coarse_freq_tune = 1; +static uint8_t _fine_freq_tune = 1; +static uint8_t used_pads = 0; + +static uint32_t __touchSleepTime = 256; +static float __touchMeasureTime = 32.0f; + +static touch_sensor_config_t sensor_config; + +static bool initialized = false; +static bool enabled = false; +static bool running = false; +static bool channels_initialized[SOC_TOUCH_SENSOR_NUM] = {false}; + +static touch_sensor_handle_t touch_sensor_handle = NULL; +static touch_channel_handle_t touch_channel_handle[SOC_TOUCH_SENSOR_NUM] = {}; + +// Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio)) +static float s_thresh2bm_ratio = 0.015f; // 1.5% for all channels + +static bool ARDUINO_ISR_ATTR __touchOnActiveISR(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx) { + uint8_t pad_num = (uint8_t)event->chan_id; + __touchInterruptHandlers[pad_num].lastStatusIsPressed = true; + if (__touchInterruptHandlers[pad_num].fn) { + // keeping backward compatibility with "void cb(void)" and with new "void cb(void *)" + if (__touchInterruptHandlers[pad_num].callWithArgs) { + ((voidArgFuncPtr)__touchInterruptHandlers[pad_num].fn)(__touchInterruptHandlers[pad_num].arg); + } else { + __touchInterruptHandlers[pad_num].fn(); + } + } + return false; +} + +static bool ARDUINO_ISR_ATTR __touchOnInactiveISR(touch_sensor_handle_t sens_handle, const touch_inactive_event_data_t *event, void *user_ctx) { + uint8_t pad_num = (uint8_t)event->chan_id; + __touchInterruptHandlers[pad_num].lastStatusIsPressed = false; + if (__touchInterruptHandlers[pad_num].fn) { + // keeping backward compatibility with "void cb(void)" and with new "void cb(void *)" + if (__touchInterruptHandlers[pad_num].callWithArgs) { + ((voidArgFuncPtr)__touchInterruptHandlers[pad_num].fn)(__touchInterruptHandlers[pad_num].arg); + } else { + __touchInterruptHandlers[pad_num].fn(); + } + } + return false; +} + +bool touchStop() { + if (!running) { // Already stopped + return true; + } + if (touch_sensor_stop_continuous_scanning(touch_sensor_handle) != ESP_OK) { + log_e("Touch sensor stop scanning failed!"); + return false; + } + running = false; + return true; +} + +bool touchDisable() { + if (!enabled) { // Already disabled + return true; + } + if (!running && (touch_sensor_disable(touch_sensor_handle) != ESP_OK)) { + log_e("Touch sensor still running or disable failed!"); + return false; + } + enabled = false; + return true; +} + +bool touchStart() { + if (running) { // Already running + return true; + } + if (enabled && (touch_sensor_start_continuous_scanning(touch_sensor_handle) != ESP_OK)) { + log_e("Touch sensor not enabled or failed to start continuous scanning failed!"); + return false; + } + running = true; + return true; +} + +bool touchEnable() { + if (enabled) { // Already enabled + return true; + } + if (touch_sensor_enable(touch_sensor_handle) != ESP_OK) { + log_e("Touch sensor enable failed!"); + return false; + } + enabled = true; + return true; +} + +bool touchBenchmarkThreshold(uint8_t pad) { + if (!touchEnable()) { + return false; + } + + /* Scan the enabled touch channels for several times, to make sure the initial channel data is stable */ + for (int i = 0; i < 3; i++) { + if (touch_sensor_trigger_oneshot_scanning(touch_sensor_handle, 2000) != ESP_OK) { + log_e("Touch sensor trigger oneshot scanning failed!"); + return false; + } + } + + /* Disable the touch channel to rollback the state */ + if (!touchDisable()) { + return false; + } + + // Reconfigure passed pad with new threshold + uint32_t benchmark[_sample_num] = {}; + if (touch_channel_read_data(touch_channel_handle[pad], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark) != ESP_OK) { + log_e("Touch channel read data failed!"); + return false; + } + /* Calculate the proper active thresholds regarding the initial benchmark */ + touch_channel_config_t chan_cfg = {}; + for (int i = 0; i < _sample_num; i++) { + chan_cfg.active_thresh[i] = (uint32_t)(benchmark[i] * s_thresh2bm_ratio); + log_v("Configured [CH %d] sample %d: benchmark = %" PRIu32 ", threshold = %" PRIu32 "\t", pad, i, benchmark[i], chan_cfg.active_thresh[i]); + } + /* Update the channel configuration */ + if (touch_sensor_reconfig_channel(touch_channel_handle[pad], &chan_cfg) != ESP_OK) { + log_e("Touch sensor threshold reconfig channel failed!"); + return false; + } + return true; +} + +static bool touchDetachBus(void *pin) { + int8_t pad = digitalPinToTouchChannel((int)(pin - 1)); + channels_initialized[pad] = false; + //disable touch pad and delete the channel + touch_sensor_del_channel(touch_channel_handle[pad]); + used_pads--; + if (used_pads == 0) { + touchStop(); + touchDisable(); + if (touch_sensor_del_controller(touch_sensor_handle) != ESP_OK) //deinit touch module, as no pads are used + { + log_e("Touch module deinit failed!"); + return false; + } + initialized = false; + } + return true; +} + +static void __touchInit() { + if (initialized) { + return; + } + // Support only one sample configuration for now + touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG(_div_num, _coarse_freq_tune, _fine_freq_tune); + touch_sensor_sample_config_t sample_cfg[_sample_num] = {}; + sample_cfg[0] = single_sample_cfg; + + /* Allocate new touch controller handle */ + touch_sensor_config_t sens_cfg = { + .power_on_wait_us = __touchSleepTime, + .meas_interval_us = __touchMeasureTime, + .max_meas_time_us = 0, + .output_mode = TOUCH_PAD_OUT_AS_CLOCK, + .sample_cfg_num = _sample_num, + .sample_cfg = sample_cfg, + }; + + // touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(_sample_num, sample_cfg); + if (touch_sensor_new_controller(&sens_cfg, &touch_sensor_handle) != ESP_OK) { + goto err; + } + + sensor_config = sens_cfg; + /* Configure the touch sensor filter */ + touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG(); + if (touch_sensor_config_filter(touch_sensor_handle, &filter_cfg) != ESP_OK) { + goto err; + } + + /* Register the touch sensor on_active and on_inactive callbacks */ + touch_event_callbacks_t callbacks = { + .on_active = __touchOnActiveISR, + .on_inactive = __touchOnInactiveISR, + .on_measure_done = NULL, + .on_scan_done = NULL, + .on_timeout = NULL, + .on_proximity_meas_done = NULL, + }; + if (touch_sensor_register_callbacks(touch_sensor_handle, &callbacks, NULL) != ESP_OK) { + goto err; + } + + initialized = true; + return; +err: + log_e(" Touch sensor initialization error."); + initialized = false; + return; +} + +static void __touchChannelInit(int pad) { + if (channels_initialized[pad]) { + return; + } + + // Initial setup with default Threshold + __touchInterruptHandlers[pad].fn = NULL; + + touch_channel_config_t chan_cfg = { + .active_thresh = {1000} // default threshold, will be updated after benchmark + }; + + if (!touchStop() || !touchDisable()) { + log_e("Touch sensor stop and disable failed!"); + return; + } + + if (touch_sensor_new_channel(touch_sensor_handle, pad, &chan_cfg, &touch_channel_handle[pad]) != ESP_OK) { + log_e("Touch sensor new channel failed!"); + return; + } + + // Benchmark active threshold and reconfigure pad + if (!touchBenchmarkThreshold(pad)) { + log_e("Touch sensor benchmark threshold failed!"); + return; + } + + channels_initialized[pad] = true; + used_pads++; + + if (!touchEnable() || !touchStart()) { + log_e("Touch sensor enable and start failed!"); + } +} + +static touch_value_t __touchRead(uint8_t pin) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + log_e(" No touch pad on selected pin!"); + return 0; + } + + if (perimanGetPinBus(pin, ESP32_BUS_TYPE_TOUCH) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_TOUCH, touchDetachBus); + if (!perimanClearPinBus(pin)) { + return 0; + } + __touchInit(); + __touchChannelInit(pad); + + if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_TOUCH, (void *)(pin + 1), -1, pad)) { + touchDetachBus((void *)(pin + 1)); + return 0; + } + } + + uint32_t touch_read[_sample_num] = {}; + touch_channel_read_data(touch_channel_handle[pad], TOUCH_CHAN_DATA_TYPE_SMOOTH, touch_read); + touch_value_t touch_value = touch_read[0]; // only one sample configuration for now + + return touch_value; +} + +static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Args, bool callWithArgs, touch_value_t threshold) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + log_e(" No touch pad on selected pin!"); + return; + } + + if (userFunc == NULL) { + // detach ISR User Call + __touchInterruptHandlers[pad].fn = NULL; + __touchInterruptHandlers[pad].callWithArgs = false; + __touchInterruptHandlers[pad].arg = NULL; + } else { + // attach ISR User Call + __touchInit(); + __touchChannelInit(pad); + __touchInterruptHandlers[pad].fn = userFunc; + __touchInterruptHandlers[pad].callWithArgs = callWithArgs; + __touchInterruptHandlers[pad].arg = Args; + } + + if (threshold != 0) { + if (!touchStop() || !touchDisable()) { + log_e("Touch sensor stop and disable failed!"); + return; + } + + touch_channel_config_t chan_cfg = {}; + for (int i = 0; i < _sample_num; i++) { + chan_cfg.active_thresh[i] = threshold; + } + + if (touch_sensor_reconfig_channel(touch_channel_handle[pad], &chan_cfg) != ESP_OK) { + log_e("Touch sensor threshold reconfig channel failed!"); + } + + if (!touchEnable() || !touchStart()) { + log_e("Touch sensor enable and start failed!"); + } + } +} + +// it keeps backwards compatibility +static void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), touch_value_t threshold) { + __touchConfigInterrupt(pin, userFunc, NULL, threshold, false); +} + +// new additional version of the API with User Args +static void __touchAttachArgsInterrupt(uint8_t pin, void (*userFunc)(void), void *args, touch_value_t threshold) { + __touchConfigInterrupt(pin, userFunc, args, threshold, true); +} + +// new additional API to detach touch ISR +static void __touchDettachInterrupt(uint8_t pin) { + __touchConfigInterrupt(pin, NULL, NULL, 0, false); // userFunc as NULL acts as detaching +} + +// /* +// External Public Touch API Functions +// */ + +bool touchInterruptGetLastStatus(uint8_t pin) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + return false; + } + + return __touchInterruptHandlers[pad].lastStatusIsPressed; +} + +void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + log_e(" No touch pad on selected pin!"); + return; + } + + if (perimanGetPinBus(pin, ESP32_BUS_TYPE_TOUCH) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_TOUCH, touchDetachBus); + __touchInit(); + __touchChannelInit(pad); + if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_TOUCH, (void *)(pin + 1), -1, pad)) { + log_e("Failed to set bus to Peripheral manager"); + touchDetachBus((void *)(pin + 1)); + return; + } + } + + log_v("Touch sensor deep sleep wake-up configuration for pad %d with threshold %d", pad, threshold); + if (!touchStop() || !touchDisable()) { + log_e("Touch sensor stop and disable failed!"); + return; + } + + touch_sleep_config_t deep_slp_cfg = { + .slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP, + .deep_slp_chan = touch_channel_handle[pad], + .deep_slp_thresh = {threshold}, + .deep_slp_sens_cfg = NULL, // Use the original touch sensor configuration + }; + + // Register the deep sleep wake-up + if (touch_sensor_config_sleep_wakeup(touch_sensor_handle, &deep_slp_cfg) != ESP_OK) { + log_e("Touch sensor deep sleep wake-up failed!"); + return; + } + + if (!touchEnable() || !touchStart()) { + log_e("Touch sensor enable and start failed!"); + } +} + +void touchSetDefaultThreshold(float percentage) { + s_thresh2bm_ratio = (float)percentage / 100.0f; +} + +void touchSetTiming(float measure, uint32_t sleep) { + if (initialized) { + log_e("Touch sensor already initialized. Cannot set cycles."); + return; + } + __touchSleepTime = sleep; + __touchMeasureTime = measure; +} + +void touchSetConfig(uint32_t div_num, uint8_t coarse_freq_tune, uint8_t fine_freq_tune) { + if (initialized) { + log_e("Touch sensor already initialized. Cannot set configuration."); + return; + } + _div_num = div_num; + _coarse_freq_tune = coarse_freq_tune; + _fine_freq_tune = fine_freq_tune; +} + +extern touch_value_t touchRead(uint8_t) __attribute__((weak, alias("__touchRead"))); +extern void touchAttachInterrupt(uint8_t, voidFuncPtr, touch_value_t) __attribute__((weak, alias("__touchAttachInterrupt"))); +extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value_t) __attribute__((weak, alias("__touchAttachArgsInterrupt"))); +extern void touchDetachInterrupt(uint8_t) __attribute__((weak, alias("__touchDettachInterrupt"))); + +#endif /* SOC_TOUCH_SENSOR_VERSION == 3 */ +#endif /* SOC_TOUCH_SENSOR_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-touch-ng.h b/cores/esp32/esp32-hal-touch-ng.h new file mode 100644 index 00000000000..0d4eb79ac58 --- /dev/null +++ b/cores/esp32/esp32-hal-touch-ng.h @@ -0,0 +1,91 @@ +/* + Arduino.h - Main include file for the Arduino SDK + Copyright (c) 2005-2013 Arduino Team. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAIN_ESP32_HAL_TOUCH_NEW_H_ +#define MAIN_ESP32_HAL_TOUCH_NEW_H_ + +#include "soc/soc_caps.h" +#if SOC_TOUCH_SENSOR_SUPPORTED +#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp32-hal.h" + +typedef uint32_t touch_value_t; + +/* + * Set time in us that measurement operation takes + * The result from touchRead, threshold and detection + * accuracy depend on these values. + * Note: must be called before setting up touch pads + **/ +void touchSetTiming(float measure, uint32_t sleep); + +/* + * Tune the touch pad frequency. + * Note: Must be called before setting up touch pads +*/ +void touchSetConfig(uint32_t _div_num, uint8_t coarse_freq_tune, uint8_t fine_freq_tune); + +/* + * Read touch pad value. + * You can use this method to chose a good threshold value + * to use as value for touchAttachInterrupt. + * */ +touch_value_t touchRead(uint8_t pin); + +/* + * Set function to be called if touch pad value rises by given increment (threshold). + * Use touchRead to determine a proper threshold between touched and untouched state. + * */ +void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), touch_value_t threshold); +void touchAttachInterruptArg(uint8_t pin, void (*userFunc)(void *), void *arg, touch_value_t threshold); +void touchDetachInterrupt(uint8_t pin); + +/* + * Returns true when the latest ISR status for the Touchpad is that it is touched (Active) + * and false when the Touchpad is untoouched (Inactive). + * This function can be used in conjunction with ISR User callback in order to take action + * as soon as the touchpad is touched and/or released. + **/ +bool touchInterruptGetLastStatus(uint8_t pin); + +/* + * Set the default threshold for touch pads. + * The threshold is a percentage of the benchmark value. + * The default value is 1.5%. + **/ +void touchSetDefaultThreshold(float percentage); + +/* + * Setup touch pad wake up from deep sleep /light sleep with given threshold. + * When light sleep is used, all used touch pads will be able to wake up the chip. + **/ +void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold); + +#ifdef __cplusplus +} +#endif + +#endif /* SOC_TOUCH_SENSOR_VERSION == 3 */ +#endif /* SOC_TOUCH_SENSOR_SUPPORTED */ +#endif /* MAIN_ESP32_HAL_TOUCH_H_ */ diff --git a/cores/esp32/esp32-hal-touch.c b/cores/esp32/esp32-hal-touch.c index d32b34d0173..701bf6d16c9 100644 --- a/cores/esp32/esp32-hal-touch.c +++ b/cores/esp32/esp32-hal-touch.c @@ -14,6 +14,8 @@ #include "soc/soc_caps.h" #if SOC_TOUCH_SENSOR_SUPPORTED +#if SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3 + #include "driver/touch_sensor.h" #include "esp32-hal-touch.h" #include "esp32-hal-periman.h" @@ -22,10 +24,10 @@ Internal Private Touch Data Structure and Functions */ -#if SOC_TOUCH_VERSION_1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 static uint16_t __touchSleepCycles = 0x1000; static uint16_t __touchMeasureCycles = 0x1000; -#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 static uint16_t __touchSleepCycles = TOUCH_PAD_SLEEP_CYCLE_DEFAULT; static uint16_t __touchMeasureCycles = TOUCH_PAD_MEASURE_CYCLE_DEFAULT; #endif @@ -37,7 +39,7 @@ typedef struct { voidFuncPtr fn; bool callWithArgs; void *arg; -#if SOC_TOUCH_VERSION_2 // Only for ESP32S2 and ESP32S3 +#if SOC_TOUCH_SENSOR_VERSION == 2 // Only for ESP32S2 and ESP32S3 bool lastStatusIsPressed; #endif } TouchInterruptHandle_t; @@ -51,7 +53,7 @@ static bool initialized = false; static bool channels_initialized[SOC_TOUCH_SENSOR_NUM] = {false}; static void ARDUINO_ISR_ATTR __touchISR(void *arg) { -#if SOC_TOUCH_VERSION_1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 uint32_t pad_intr = touch_pad_get_status(); //clear interrupt touch_pad_clear_status(); @@ -68,7 +70,7 @@ static void ARDUINO_ISR_ATTR __touchISR(void *arg) { } } } -#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 touch_pad_intr_mask_t evt = touch_pad_read_intr_status_mask(); uint8_t pad_num = touch_pad_get_current_meas_channel(); if (evt & TOUCH_PAD_INTR_MASK_ACTIVE) { @@ -93,9 +95,9 @@ static void ARDUINO_ISR_ATTR __touchISR(void *arg) { static void __touchSetCycles(uint16_t measure, uint16_t sleep) { __touchSleepCycles = sleep; __touchMeasureCycles = measure; -#if SOC_TOUCH_VERSION_1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 touch_pad_set_measurement_clock_cycles(measure); -#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 touch_pad_set_charge_discharge_times(measure); #endif touch_pad_set_measurement_interval(sleep); @@ -123,7 +125,7 @@ static void __touchInit() { esp_err_t err = ESP_OK; -#if SOC_TOUCH_VERSION_1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 err = touch_pad_init(); if (err != ESP_OK) { goto err; @@ -143,8 +145,8 @@ static void __touchInit() { if (err != ESP_OK) { goto err; } - touch_pad_intr_enable(); // returns ESP_OK -#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 + touch_pad_intr_enable(); // returns ESP_OK +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 err = touch_pad_init(); if (err != ESP_OK) { goto err; @@ -165,7 +167,6 @@ static void __touchInit() { touch_pad_fsm_start(); // returns ESP_OK //ISR setup moved to __touchChannelInit #endif - initialized = true; return; err: @@ -179,11 +180,11 @@ static void __touchChannelInit(int pad) { return; } -#if SOC_TOUCH_VERSION_1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 // Initial no Threshold and setup __touchInterruptHandlers[pad].fn = NULL; - touch_pad_config(pad, SOC_TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK -#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3 + touch_pad_config(pad, TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 // Initial no Threshold and setup __touchInterruptHandlers[pad].fn = NULL; touch_pad_config(pad); // returns ESP_OK @@ -238,7 +239,7 @@ static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Ar if (userFunc == NULL) { // detach ISR User Call __touchInterruptHandlers[pad].fn = NULL; - threshold = SOC_TOUCH_PAD_THRESHOLD_MAX; // deactivate the ISR with SOC_TOUCH_PAD_THRESHOLD_MAX + threshold = TOUCH_PAD_THRESHOLD_MAX; // deactivate the ISR with SOC_TOUCH_PAD_THRESHOLD_MAX } else { // attach ISR User Call __touchInit(); @@ -270,7 +271,7 @@ static void __touchDettachInterrupt(uint8_t pin) { External Public Touch API Functions */ -#if SOC_TOUCH_VERSION_1 // Only for ESP32 SoC +#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC void touchInterruptSetThresholdDirection(bool mustbeLower) { if (mustbeLower) { touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW); @@ -278,7 +279,7 @@ void touchInterruptSetThresholdDirection(bool mustbeLower) { touch_pad_set_trigger_mode(TOUCH_TRIGGER_ABOVE); } } -#elif SOC_TOUCH_VERSION_2 // Only for ESP32S2 and ESP32S3 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // Only for ESP32S2 and ESP32S3 // returns true if touch pad has been and continues pressed and false otherwise bool touchInterruptGetLastStatus(uint8_t pin) { int8_t pad = digitalPinToTouchChannel(pin); @@ -307,10 +308,10 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold) { return; } } -#if SOC_TOUCH_VERSION_1 // Only for ESP32 SoC +#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC touch_pad_set_thresh(pad, threshold); -#elif SOC_TOUCH_VERSION_2 +#elif SOC_TOUCH_SENSOR_VERSION == 2 touch_pad_sleep_channel_enable(pad, true); touch_pad_sleep_set_threshold(pad, threshold); @@ -324,4 +325,5 @@ extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value extern void touchDetachInterrupt(uint8_t) __attribute__((weak, alias("__touchDettachInterrupt"))); extern void touchSetCycles(uint16_t, uint16_t) __attribute__((weak, alias("__touchSetCycles"))); +#endif /* SOC_TOUCH_SENSOR_VERSION <= 2 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-touch.h b/cores/esp32/esp32-hal-touch.h index db33ce3bc6a..4b06c7db766 100644 --- a/cores/esp32/esp32-hal-touch.h +++ b/cores/esp32/esp32-hal-touch.h @@ -22,6 +22,7 @@ #include "soc/soc_caps.h" #if SOC_TOUCH_SENSOR_SUPPORTED +#if SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32 ESP32S2 ESP32S3 #ifdef __cplusplus extern "C" { @@ -29,13 +30,13 @@ extern "C" { #include "esp32-hal.h" -#if !defined(SOC_TOUCH_VERSION_1) && !defined(SOC_TOUCH_VERSION_2) +#if !SOC_TOUCH_SENSOR_SUPPORTED #error Touch IDF driver Not supported! #endif -#if SOC_TOUCH_VERSION_1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 typedef uint16_t touch_value_t; -#elif SOC_TOUCH_VERSION_2 // ESP32S2 ESP32S3 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2 ESP32S3 typedef uint32_t touch_value_t; #endif @@ -71,7 +72,7 @@ void touchDetachInterrupt(uint8_t pin); * Default if Lower. **/ -#if SOC_TOUCH_VERSION_1 // Only for ESP32 SoC +#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC void touchInterruptSetThresholdDirection(bool mustbeLower); #endif @@ -83,7 +84,7 @@ void touchInterruptSetThresholdDirection(bool mustbeLower); * as soon as the touchpad is touched and/or released **/ -#if SOC_TOUCH_VERSION_2 // Only for ESP32S2 and ESP32S3 +#if SOC_TOUCH_SENSOR_VERSION == 2 // Only for ESP32S2 and ESP32S3 // returns true if touch pad has been and continues pressed and false otherwise bool touchInterruptGetLastStatus(uint8_t pin); #endif @@ -97,5 +98,6 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold); } #endif +#endif /* SOC_TOUCH_SENSOR_VERSION <= 2 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ #endif /* MAIN_ESP32_HAL_TOUCH_H_ */ diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index 68a600b51c5..5311aff4f37 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -1,4 +1,4 @@ -// Copyright 2015-2024 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2025 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. @@ -33,7 +33,13 @@ #include "hal/gpio_hal.h" #include "esp_rom_gpio.h" -static int s_uart_debug_nr = 0; // UART number for debug output +#include "driver/rtc_io.h" +#include "driver/lp_io.h" +#include "soc/uart_periph.h" +#include "esp_private/uart_share_hw_ctrl.h" + +static int s_uart_debug_nr = 0; // UART number for debug output +#define REF_TICK_BAUDRATE_LIMIT 250000 // this is maximum UART badrate using REF_TICK as clock struct uart_struct_t { @@ -45,13 +51,14 @@ struct uart_struct_t { bool has_peek; // flag to indicate that there is a peek byte pending to be read uint8_t peek_byte; // peek byte that has been read but not consumed QueueHandle_t uart_event_queue; // export it by some uartGetEventQueue() function - // configuration data:: Arduino API tipical data + // configuration data:: Arduino API typical data int8_t _rxPin, _txPin, _ctsPin, _rtsPin; // UART GPIOs uint32_t _baudrate, _config; // UART baudrate and config // UART ESP32 specific data uint16_t _rx_buffer_size, _tx_buffer_size; // UART RX and TX buffer sizes bool _inverted; // UART inverted signal uint8_t _rxfifo_full_thrhd; // UART RX FIFO full threshold + int8_t _uart_clock_source; // UART Clock Source used when it is started using uartBegin() }; #if CONFIG_DISABLE_HAL_LOCKS @@ -60,12 +67,21 @@ struct uart_struct_t { #define UART_MUTEX_UNLOCK() static uart_t _uart_bus_array[] = { - {0, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, + {0, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0, -1}, #if SOC_UART_NUM > 1 - {1, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, + {1, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0, -1}, #endif #if SOC_UART_NUM > 2 - {2, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, + {2, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0, -1}, +#endif +#if SOC_UART_NUM > 3 + {3, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0, -1}, +#endif +#if SOC_UART_NUM > 4 + {4, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0, -1}, +#endif +#if SOC_UART_NUM > 5 + {5, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0, -1}, #endif }; @@ -80,17 +96,117 @@ static uart_t _uart_bus_array[] = { xSemaphoreGive(uart->lock) static uart_t _uart_bus_array[] = { - {NULL, 0, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, + {NULL, 0, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0, -1}, #if SOC_UART_NUM > 1 - {NULL, 1, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, + {NULL, 1, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0, -1}, #endif #if SOC_UART_NUM > 2 - {NULL, 2, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0}, + {NULL, 2, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0, -1}, +#endif +#if SOC_UART_NUM > 3 + {NULL, 3, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0, -1}, +#endif +#if SOC_UART_NUM > 4 + {NULL, 4, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0, -1}, +#endif +#if SOC_UART_NUM > 5 + {NULL, 5, false, 0, NULL, -1, -1, -1, -1, 0, 0, 0, 0, false, 0, -1}, #endif }; #endif +#if SOC_UART_LP_NUM >= 1 +// LP UART enable pins routine +static bool lp_uart_config_io(uint8_t uart_num, int8_t pin, rtc_gpio_mode_t direction, uint32_t idx) { + /* Skip configuration if the LP_IO is -1 */ + if (pin < 0) { + return true; + } + + // Initialize LP_IO + if (rtc_gpio_init(pin) != ESP_OK) { + log_e("Failed to initialize LP_IO %d", pin); + return false; + } + + // Set LP_IO direction + if (rtc_gpio_set_direction(pin, direction) != ESP_OK) { + log_e("Failed to set LP_IO %d direction", pin); + return false; + } + + // Connect pins + const uart_periph_sig_t *upin = &uart_periph_signal[uart_num].pins[idx]; +#if !SOC_LP_GPIO_MATRIX_SUPPORTED // ESP32-C6/C61/C5 + // When LP_IO Matrix is not support, LP_IO Mux must be connected to the pins + if (rtc_gpio_iomux_func_sel(pin, upin->iomux_func) != ESP_OK) { + log_e("Failed to set LP_IO pin %d into Mux function", pin); + return false; + } +#else // So far, only ESP32-P4 + // If the configured pin is the default LP_IO Mux pin for LP UART, then set the LP_IO MUX function + if (upin->default_gpio == pin) { + if (rtc_gpio_iomux_func_sel(pin, upin->iomux_func) != ESP_OK) { + log_e("Failed to set LP_IO pin %d into Mux function", pin); + return false; + } + } else { + // Otherwise, set the LP_IO Matrix and select FUNC1 + if (rtc_gpio_iomux_func_sel(pin, 1) != ESP_OK) { + log_e("Failed to set LP_IO pin %d into Mux function GPIO", pin); + return false; + } + // Connect the LP_IO to the LP UART peripheral signal + esp_err_t ret; + if (direction == RTC_GPIO_MODE_OUTPUT_ONLY) { + ret = lp_gpio_connect_out_signal(pin, UART_PERIPH_SIGNAL(uart_num, idx), 0, 0); + } else { + ret = lp_gpio_connect_in_signal(pin, UART_PERIPH_SIGNAL(uart_num, idx), 0); + } + if (ret != ESP_OK) { + log_e("Failed to connect LP_IO pin %d to UART%d signal", pin, uart_num); + return false; + } + } +#endif // SOC_LP_GPIO_MATRIX_SUPPORTED + + return true; +} + +// When LP UART needs the RTC IO MUX to set the pin, it will always have fixed pins for RX, TX, CTS and RTS +static bool lpuartCheckPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin, uint8_t uart_nr) { +// check if LP UART is being used and if the pins are valid +#if !SOC_LP_GPIO_MATRIX_SUPPORTED // ESP32-C6/C61/C5 + uint16_t lp_uart_fixed_pin = uart_periph_signal[uart_nr].pins[SOC_UART_RX_PIN_IDX].default_gpio; + if (uart_nr >= SOC_UART_HP_NUM) { // it is a LP UART NUM + if (rxPin > 0 && rxPin != lp_uart_fixed_pin) { + log_e("UART%d LP UART requires RX pin to be set to %d.", uart_nr, lp_uart_fixed_pin); + return false; + } + lp_uart_fixed_pin = uart_periph_signal[uart_nr].pins[SOC_UART_TX_PIN_IDX].default_gpio; + if (txPin > 0 && txPin != lp_uart_fixed_pin) { + log_e("UART%d LP UART requires TX pin to be set to %d.", uart_nr, lp_uart_fixed_pin); + return false; + } + lp_uart_fixed_pin = uart_periph_signal[uart_nr].pins[SOC_UART_CTS_PIN_IDX].default_gpio; + if (ctsPin > 0 && ctsPin != lp_uart_fixed_pin) { + log_e("UART%d LP UART requires CTS pin to be set to %d.", uart_nr, lp_uart_fixed_pin); + return false; + } + lp_uart_fixed_pin = uart_periph_signal[uart_nr].pins[SOC_UART_RTS_PIN_IDX].default_gpio; + if (rtsPin > 0 && rtsPin != lp_uart_fixed_pin) { + log_e("UART%d LP UART requires RTS pin to be set to %d.", uart_nr, lp_uart_fixed_pin); + return false; + } + } + return true; +#else // ESP32-P4 can set any pin for LP UART + return true; +#endif // SOC_LP_GPIO_MATRIX_SUPPORTED +} +#endif // SOC_UART_LP_NUM >= 1 + // Negative Pin Number will keep it unmodified, thus this function can detach individual pins // This function will also unset the pins in the Peripheral Manager and set the pin to -1 after detaching static bool _uartDetachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) { @@ -104,7 +220,7 @@ static bool _uartDetachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t //log_v("detaching UART%d pins: prev,pin RX(%d,%d) TX(%d,%d) CTS(%d,%d) RTS(%d,%d)", uart_num, // uart->_rxPin, rxPin, uart->_txPin, txPin, uart->_ctsPin, ctsPin, uart->_rtsPin, rtsPin); vTaskDelay(10); - // detaches pins and sets Peripheral Manager and UART information + // detaches HP and LP pins and sets Peripheral Manager and UART information if (rxPin >= 0 && uart->_rxPin == rxPin && perimanGetPinBusType(rxPin) == ESP32_BUS_TYPE_UART_RX) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rxPin], PIN_FUNC_GPIO); // avoids causing BREAK in the UART line @@ -190,6 +306,8 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t //log_v("attaching UART%d pins: prev,new RX(%d,%d) TX(%d,%d) CTS(%d,%d) RTS(%d,%d)", uart_num, // uart->_rxPin, rxPin, uart->_txPin, txPin, uart->_ctsPin, ctsPin, uart->_rtsPin, rtsPin); vTaskDelay(10); + // IDF uart_set_pin() checks if the pin is used within LP UART and if it is a valid RTC IO pin + // No need for Arduino Layer to check it again bool retCode = true; if (rxPin >= 0) { // forces a clean detaching from a previous peripheral @@ -198,6 +316,11 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t } // connect RX Pad bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); +#if SOC_UART_LP_NUM >= 1 + if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM + ret &= lp_uart_config_io(uart->num, rxPin, RTC_GPIO_MODE_INPUT_ONLY, SOC_UART_RX_PIN_IDX); + } +#endif if (ret) { ret &= perimanSetPinBus(rxPin, ESP32_BUS_TYPE_UART_RX, (void *)uart, uart_num, -1); if (ret) { @@ -216,6 +339,11 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t } // connect TX Pad bool ret = ESP_OK == uart_set_pin(uart->num, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); +#if SOC_UART_LP_NUM >= 1 + if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM + ret &= lp_uart_config_io(uart->num, txPin, RTC_GPIO_MODE_OUTPUT_ONLY, SOC_UART_TX_PIN_IDX); + } +#endif if (ret) { ret &= perimanSetPinBus(txPin, ESP32_BUS_TYPE_UART_TX, (void *)uart, uart_num, -1); if (ret) { @@ -234,6 +362,11 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t } // connect CTS Pad bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, ctsPin); +#if SOC_UART_LP_NUM >= 1 + if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM + ret &= lp_uart_config_io(uart->num, ctsPin, RTC_GPIO_MODE_INPUT_ONLY, SOC_UART_CTS_PIN_IDX); + } +#endif if (ret) { ret &= perimanSetPinBus(ctsPin, ESP32_BUS_TYPE_UART_CTS, (void *)uart, uart_num, -1); if (ret) { @@ -252,6 +385,11 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t } // connect RTS Pad bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, rtsPin, UART_PIN_NO_CHANGE); +#if SOC_UART_LP_NUM >= 1 + if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM + ret &= lp_uart_config_io(uart->num, rtsPin, RTC_GPIO_MODE_OUTPUT_ONLY, SOC_UART_RTS_PIN_IDX); + } +#endif if (ret) { ret &= perimanSetPinBus(rtsPin, ESP32_BUS_TYPE_UART_RTS, (void *)uart, uart_num, -1); if (ret) { @@ -315,6 +453,13 @@ bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, in // get UART information uart_t *uart = &_uart_bus_array[uart_num]; +#if SOC_UART_LP_NUM >= 1 + // check if LP UART is being used and if the pins are valid + if (!lpuartCheckPins(rxPin, txPin, ctsPin, rtsPin, uart_num)) { + return false; // failed to set pins + } +#endif + bool retCode = true; UART_MUTEX_LOCK(); @@ -407,6 +552,17 @@ uart_t *uartBegin( uart_t *uart = &_uart_bus_array[uart_nr]; log_v("UART%d baud(%ld) Mode(%x) rxPin(%d) txPin(%d)", uart_nr, baudrate, config, rxPin, txPin); +#if SOC_UART_LP_NUM >= 1 + // check if LP UART is being used and if the pins are valid + if (!lpuartCheckPins(rxPin, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, uart_nr)) { + if (uart_is_driver_installed(uart_nr)) { + return uart; // keep the same installed driver + } else { + return NULL; // no new driver was installed + } + } +#endif + #if !CONFIG_DISABLE_HAL_LOCKS if (uart->lock == NULL) { uart->lock = xSemaphoreCreateMutex(); @@ -423,20 +579,18 @@ uart_t *uartBegin( if (uart->_rx_buffer_size != rx_buffer_size || uart->_tx_buffer_size != tx_buffer_size || uart->_inverted != inverted || uart->_rxfifo_full_thrhd != rxfifo_full_thrhd) { log_v("UART%d changing buffer sizes or inverted signal or rxfifo_full_thrhd. IDF driver will be restarted", uart_nr); + log_v("RX buffer size: %d -> %d", uart->_rx_buffer_size, rx_buffer_size); + log_v("TX buffer size: %d -> %d", uart->_tx_buffer_size, tx_buffer_size); + log_v("Inverted signal: %s -> %s", uart->_inverted ? "true" : "false", inverted ? "true" : "false"); + log_v("RX FIFO full threshold: %d -> %d", uart->_rxfifo_full_thrhd, rxfifo_full_thrhd); uartEnd(uart_nr); } else { bool retCode = true; - UART_MUTEX_LOCK(); //User may just want to change some parameters, such as baudrate, data length, parity, stop bits or pins if (uart->_baudrate != baudrate) { - if (ESP_OK != uart_set_baudrate(uart_nr, baudrate)) { - log_e("UART%d changing baudrate failed.", uart_nr); - retCode = false; - } else { - log_v("UART%d changed baudrate to %d", uart_nr, baudrate); - uart->_baudrate = baudrate; - } + retCode = uartSetBaudRate(uart, baudrate); } + UART_MUTEX_LOCK(); uart_word_length_t data_bits = (config & 0xc) >> 2; uart_parity_t parity = config & 0x3; uart_stop_bits_t stop_bits = (config & 0x30) >> 4; @@ -487,7 +641,7 @@ uart_t *uartBegin( } UART_MUTEX_UNLOCK(); if (retCode) { - // UART driver was already working, just return the uart_t structure, syaing that no new driver was installed + // UART driver was already working, just return the uart_t structure, saying that no new driver was installed return uart; } // if we reach this point, it means that we need to restart the UART driver @@ -497,14 +651,55 @@ uart_t *uartBegin( log_v("UART%d not installed. Starting installation", uart_nr); } uart_config_t uart_config; + memset(&uart_config, 0, sizeof(uart_config_t)); + uart_config.flags.backup_before_sleep = false; // new flag from IDF v5.3 uart_config.data_bits = (config & 0xc) >> 2; uart_config.parity = (config & 0x3); uart_config.stop_bits = (config & 0x30) >> 4; uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; - uart_config.rx_flow_ctrl_thresh = rxfifo_full_thrhd; + uart_config.rx_flow_ctrl_thresh = rxfifo_full_thrhd >= UART_HW_FIFO_LEN(uart_nr) ? UART_HW_FIFO_LEN(uart_nr) - 6 : rxfifo_full_thrhd; + log_v( + "UART%d RX FIFO full threshold set to %d (value requested: %d || FIFO Max = %d)", uart_nr, uart_config.rx_flow_ctrl_thresh, rxfifo_full_thrhd, + UART_HW_FIFO_LEN(uart_nr) + ); + rxfifo_full_thrhd = uart_config.rx_flow_ctrl_thresh; // makes sure that it will be set correctly in the struct uart_config.baud_rate = baudrate; - // CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F40M for C2 -- CLK_PLL_F48M for H2 -- CLK_PLL_F80M for C6 - uart_config.source_clk = UART_SCLK_DEFAULT; +#if SOC_UART_LP_NUM >= 1 + if (uart_nr >= SOC_UART_HP_NUM) { // it is a LP UART NUM + if (uart->_uart_clock_source > 0) { + uart_config.lp_source_clk = (soc_periph_lp_uart_clk_src_t)uart->_uart_clock_source; // use user defined LP UART clock + log_v("Setting UART%d to user defined LP clock source (%d) ", uart_nr, uart->_uart_clock_source); + } else { + uart_config.lp_source_clk = LP_UART_SCLK_DEFAULT; // use default LP clock + log_v("Setting UART%d to Default LP clock source", uart_nr); + } + } else +#endif // SOC_UART_LP_NUM >= 1 + { + if (uart->_uart_clock_source >= 0) { + uart_config.source_clk = (soc_module_clk_t)uart->_uart_clock_source; // use user defined HP UART clock + log_v("Setting UART%d to user defined HP clock source (%d) ", uart_nr, uart->_uart_clock_source); + } else { + // there is an issue when returning from light sleep with the C6 and H2: the uart baud rate is not restored + // therefore, uart clock source will set to XTAL for all SoC that support it. This fix solves the C6|H2 issue. +#if SOC_UART_SUPPORT_XTAL_CLK + uart_config.source_clk = UART_SCLK_XTAL; // valid for C2, S3, C3, C6, H2 and P4 + log_v("Setting UART%d to use XTAL clock", uart_nr); +#elif SOC_UART_SUPPORT_REF_TICK + if (baudrate <= REF_TICK_BAUDRATE_LIMIT) { + uart_config.source_clk = UART_SCLK_REF_TICK; // valid for ESP32, S2 - MAX supported baud rate is 250 Kbps + log_v("Setting UART%d to use REF_TICK clock", uart_nr); + } else { + uart_config.source_clk = UART_SCLK_APB; // baudrate may change with the APB Frequency! + log_v("Setting UART%d to use APB clock", uart_nr); + } +#else + // Default CLK Source: CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F40M for C2 -- CLK_PLL_F48M for H2 -- CLK_PLL_F80M for C6|P4 + uart_config.source_clk = UART_SCLK_DEFAULT; // baudrate may change with the APB Frequency! + log_v("Setting UART%d to use DEFAULT clock", uart_nr); +#endif // SOC_UART_SUPPORT_XTAL_CLK + } + } UART_MUTEX_LOCK(); bool retCode = ESP_OK == uart_driver_install(uart_nr, rx_buffer_size, tx_buffer_size, 20, &(uart->uart_event_queue), 0); @@ -513,12 +708,16 @@ uart_t *uartBegin( retCode &= ESP_OK == uart_param_config(uart_nr, &uart_config); } - // Is it right or the idea is to swap rx and tx pins? - if (retCode && inverted) { - // invert signal for both Rx and Tx - retCode &= ESP_OK == uart_set_line_inverse(uart_nr, UART_SIGNAL_TXD_INV | UART_SIGNAL_RXD_INV); + if (retCode) { + if (inverted) { + // invert signal for both Rx and Tx + retCode &= ESP_OK == uart_set_line_inverse(uart_nr, UART_SIGNAL_TXD_INV | UART_SIGNAL_RXD_INV); + } else { + // disable invert signal for both Rx and Tx + retCode &= ESP_OK == uart_set_line_inverse(uart_nr, UART_SIGNAL_INV_DISABLE); + } } - + // if all fine, set internal parameters if (retCode) { uart->_baudrate = baudrate; uart->_config = config; @@ -528,6 +727,14 @@ uart_t *uartBegin( uart->_tx_buffer_size = tx_buffer_size; uart->has_peek = false; uart->peek_byte = 0; +#if SOC_UART_LP_NUM >= 1 + if (uart_nr >= SOC_UART_HP_NUM) { + uart->_uart_clock_source = uart_config.lp_source_clk; + } else +#endif + { + uart->_uart_clock_source = uart_config.source_clk; + } } UART_MUTEX_UNLOCK(); @@ -569,7 +776,11 @@ bool uartSetRxTimeout(uart_t *uart, uint8_t numSymbTimeout) { if (uart == NULL) { return false; } - + uint16_t maxRXTimeout = uart_get_max_rx_timeout(uart->num); + if (numSymbTimeout > maxRXTimeout) { + log_e("Invalid RX Timeout value, its limit is %d", maxRXTimeout); + return false; + } UART_MUTEX_LOCK(); bool retCode = (ESP_OK == uart_set_rx_timeout(uart->num, numSymbTimeout)); UART_MUTEX_UNLOCK(); @@ -580,9 +791,18 @@ bool uartSetRxFIFOFull(uart_t *uart, uint8_t numBytesFIFOFull) { if (uart == NULL) { return false; } - + uint8_t rxfifo_full_thrhd = numBytesFIFOFull >= UART_HW_FIFO_LEN(uart->num) ? UART_HW_FIFO_LEN(uart->num) - 6 : numBytesFIFOFull; UART_MUTEX_LOCK(); - bool retCode = (ESP_OK == uart_set_rx_full_threshold(uart->num, numBytesFIFOFull)); + bool retCode = (ESP_OK == uart_set_rx_full_threshold(uart->num, rxfifo_full_thrhd)); + if (retCode) { + uart->_rxfifo_full_thrhd = rxfifo_full_thrhd; + if (rxfifo_full_thrhd != numBytesFIFOFull) { + log_w("The RX FIFO Full value for UART%d was set to %d instead of %d", uart->num, rxfifo_full_thrhd, numBytesFIFOFull); + } + log_v("UART%d RX FIFO Full value set to %d from a requested value of %d", uart->num, rxfifo_full_thrhd, numBytesFIFOFull); + } else { + log_e("UART%d failed to set RX FIFO Full value to %d", uart->num, numBytesFIFOFull); + } UART_MUTEX_UNLOCK(); return retCode; } @@ -607,14 +827,14 @@ void uartSetRxInvert(uart_t *uart, bool invert) { if (uart == NULL) { return; } -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 // POTENTIAL ISSUE :: original code only set/reset rxd_inv bit // IDF or LL set/reset the whole inv_mask! // if (invert) // ESP_ERROR_CHECK(uart_set_line_inverse(uart->num, UART_SIGNAL_RXD_INV)); // else // ESP_ERROR_CHECK(uart_set_line_inverse(uart->num, UART_SIGNAL_INV_DISABLE)); - + log_e("uartSetRxInvert is not supported in ESP32C6, ESP32H2 and ESP32P4"); #else // this implementation is better over IDF API because it only affects RXD // this is supported in ESP32, ESP32-S2 and ESP32-C3 @@ -769,30 +989,79 @@ void uartFlushTxOnly(uart_t *uart, bool txOnly) { UART_MUTEX_UNLOCK(); } -void uartSetBaudRate(uart_t *uart, uint32_t baud_rate) { +bool uartSetBaudRate(uart_t *uart, uint32_t baud_rate) { if (uart == NULL) { - return; + return false; + } + bool retCode = true; + soc_module_clk_t newClkSrc = UART_SCLK_DEFAULT; + int8_t previousClkSrc = uart->_uart_clock_source; +#if SOC_UART_LP_NUM >= 1 + if (uart->num >= SOC_UART_HP_NUM) { // it is a LP UART NUM + if (uart->_uart_clock_source > 0) { + newClkSrc = (soc_periph_lp_uart_clk_src_t)uart->_uart_clock_source; // use user defined LP UART clock + log_v("Setting UART%d to user defined LP clock source (%d) ", uart->num, newClkSrc); + } else { + newClkSrc = LP_UART_SCLK_DEFAULT; // use default LP clock + log_v("Setting UART%d to Default LP clock source", uart->num); + } + } else +#endif // SOC_UART_LP_NUM >= 1 + { + if (uart->_uart_clock_source >= 0) { + newClkSrc = (soc_module_clk_t)uart->_uart_clock_source; // use user defined HP UART clock + log_v("Setting UART%d to use HP clock source (%d) ", uart->num, newClkSrc); + } else { + // there is an issue when returning from light sleep with the C6 and H2: the uart baud rate is not restored + // therefore, uart clock source will set to XTAL for all SoC that support it. This fix solves the C6|H2 issue. +#if SOC_UART_SUPPORT_XTAL_CLK + newClkSrc = UART_SCLK_XTAL; // valid for C2, S3, C3, C6, H2 and P4 + log_v("Setting UART%d to use XTAL clock", uart->num); +#elif SOC_UART_SUPPORT_REF_TICK + if (baud_rate <= REF_TICK_BAUDRATE_LIMIT) { + newClkSrc = UART_SCLK_REF_TICK; // valid for ESP32, S2 - MAX supported baud rate is 250 Kbps + log_v("Setting UART%d to use REF_TICK clock", uart->num); + } else { + newClkSrc = UART_SCLK_APB; // baudrate may change with the APB Frequency! + log_v("Setting UART%d to use APB clock", uart->num); + } +#else + // Default CLK Source: CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F40M for C2 -- CLK_PLL_F48M for H2 -- CLK_PLL_F80M for C6|P4 + // using newClkSrc = UART_SCLK_DEFAULT as defined in the variable declaration + log_v("Setting UART%d to use DEFAULT clock", uart->num); +#endif // SOC_UART_SUPPORT_XTAL_CLK + } } UART_MUTEX_LOCK(); - uint32_t sclk_freq; - if (uart_get_sclk_freq(UART_SCLK_DEFAULT, &sclk_freq) == ESP_OK) { - uart_ll_set_baudrate(UART_LL_GET_HW(uart->num), baud_rate, sclk_freq); + // if necessary, set the correct UART Clock Source before changing the baudrate + if (previousClkSrc < 0 || previousClkSrc != newClkSrc) { + HP_UART_SRC_CLK_ATOMIC() { + uart_ll_set_sclk(UART_LL_GET_HW(uart->num), newClkSrc); + } + uart->_uart_clock_source = newClkSrc; + } + if (uart_set_baudrate(uart->num, baud_rate) == ESP_OK) { + log_v("Setting UART%d baud rate to %ld.", uart->num, baud_rate); + uart->_baudrate = baud_rate; + } else { + retCode = false; + log_e("Setting UART%d baud rate to %ld has failed.", uart->num, baud_rate); } - uart->_baudrate = baud_rate; UART_MUTEX_UNLOCK(); + return retCode; } uint32_t uartGetBaudRate(uart_t *uart) { uint32_t baud_rate = 0; - uint32_t sclk_freq; if (uart == NULL) { return 0; } UART_MUTEX_LOCK(); - if (uart_get_sclk_freq(UART_SCLK_DEFAULT, &sclk_freq) == ESP_OK) { - baud_rate = uart_ll_get_baudrate(UART_LL_GET_HW(uart->num), sclk_freq); + if (uart_get_baudrate(uart->num, &baud_rate) != ESP_OK) { + log_e("Getting UART%d baud rate has failed.", uart->num); + baud_rate = (uint32_t)-1; // return value when failed } UART_MUTEX_UNLOCK(); return baud_rate; @@ -803,28 +1072,48 @@ static void ARDUINO_ISR_ATTR uart0_write_char(char c) { uart_ll_write_txfifo(&UART0, (const uint8_t *)&c, 1); } -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 static void ARDUINO_ISR_ATTR uart1_write_char(char c) { while (uart_ll_get_txfifo_len(&UART1) == 0); uart_ll_write_txfifo(&UART1, (const uint8_t *)&c, 1); } #endif -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 static void ARDUINO_ISR_ATTR uart2_write_char(char c) { while (uart_ll_get_txfifo_len(&UART2) == 0); uart_ll_write_txfifo(&UART2, (const uint8_t *)&c, 1); } #endif +#if SOC_UART_HP_NUM > 3 +static void ARDUINO_ISR_ATTR uart3_write_char(char c) { + while (uart_ll_get_txfifo_len(&UART3) == 0); + uart_ll_write_txfifo(&UART3, (const uint8_t *)&c, 1); +} +#endif + +#if SOC_UART_HP_NUM > 4 +static void ARDUINO_ISR_ATTR uart4_write_char(char c) { + while (uart_ll_get_txfifo_len(&UART4) == 0); + uart_ll_write_txfifo(&UART4, (const uint8_t *)&c, 1); +} +#endif + void uart_install_putc() { switch (s_uart_debug_nr) { case 0: ets_install_putc1((void (*)(char)) & uart0_write_char); break; -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 case 1: ets_install_putc1((void (*)(char)) & uart1_write_char); break; #endif -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 case 2: ets_install_putc1((void (*)(char)) & uart2_write_char); break; +#endif +#if SOC_UART_HP_NUM > 3 + case 3: ets_install_putc1((void (*)(char)) & uart3_write_char); break; +#endif +#if SOC_UART_HP_NUM > 4 + case 4: ets_install_putc1((void (*)(char)) & uart4_write_char); break; #endif default: ets_install_putc1(NULL); break; } @@ -844,8 +1133,34 @@ bool uartSetMode(uart_t *uart, uart_mode_t mode) { return retCode; } +// this function will set the uart clock source +// it must be called before uartBegin(), otherwise it won't change any thing. +bool uartSetClockSource(uint8_t uartNum, uart_sclk_t clkSrc) { + if (uartNum >= SOC_UART_NUM) { + log_e("UART%d is invalid. This device has %d UARTs, from 0 to %d.", uartNum, SOC_UART_NUM, SOC_UART_NUM - 1); + return false; + } + uart_t *uart = &_uart_bus_array[uartNum]; +#if SOC_UART_LP_NUM >= 1 + if (uart->num >= SOC_UART_HP_NUM) { + switch (clkSrc) { + case UART_SCLK_XTAL: uart->_uart_clock_source = LP_UART_SCLK_XTAL_D2; break; + case UART_SCLK_RTC: uart->_uart_clock_source = LP_UART_SCLK_LP_FAST; break; + case UART_SCLK_DEFAULT: + default: uart->_uart_clock_source = LP_UART_SCLK_DEFAULT; + } + } else +#endif + { + uart->_uart_clock_source = clkSrc; + } + //log_i("UART%d set clock source to %d", uart->num, uart->_uart_clock_source); + return true; +} + void uartSetDebug(uart_t *uart) { - if (uart == NULL || uart->num >= SOC_UART_NUM) { + // LP UART is not supported for debug + if (uart == NULL || uart->num >= SOC_UART_HP_NUM) { s_uart_debug_nr = -1; } else { s_uart_debug_nr = uart->num; @@ -871,7 +1186,7 @@ int log_printfv(const char *format, va_list arg) { return 0; } } -/* + /* // This causes dead locks with logging in specific cases and also with C++ constructors that may send logs #if !CONFIG_DISABLE_HAL_LOCKS if(s_uart_debug_nr != -1 && _uart_bus_array[s_uart_debug_nr].lock){ @@ -879,15 +1194,8 @@ int log_printfv(const char *format, va_list arg) { } #endif */ -#if CONFIG_IDF_TARGET_ESP32C3 || ((CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C6) && ARDUINO_USB_CDC_ON_BOOT) vsnprintf(temp, len + 1, format, arg); ets_printf("%s", temp); -#else - int wlen = vsnprintf(temp, len + 1, format, arg); - for (int i = 0; i < wlen; i++) { - ets_write_char_uart(temp[i]); - } -#endif /* // This causes dead locks with logging and also with constructors that may send logs #if !CONFIG_DISABLE_HAL_LOCKS @@ -1086,19 +1394,37 @@ unsigned long uartDetectBaudrate(uart_t *uart) { */ // gets the right TX or RX SIGNAL, based on the UART number from gpio_sig_map.h -#if SOC_UART_NUM > 2 +#ifdef CONFIG_IDF_TARGET_ESP32P4 +#define UART_TX_SIGNAL(uartNumber) \ + (uartNumber == UART_NUM_0 \ + ? UART0_TXD_PAD_OUT_IDX \ + : (uartNumber == UART_NUM_1 \ + ? UART1_TXD_PAD_OUT_IDX \ + : (uartNumber == UART_NUM_2 ? UART2_TXD_PAD_OUT_IDX : (uartNumber == UART_NUM_3 ? UART3_TXD_PAD_OUT_IDX : UART4_TXD_PAD_OUT_IDX)))) +#define UART_RX_SIGNAL(uartNumber) \ + (uartNumber == UART_NUM_0 \ + ? UART0_RXD_PAD_IN_IDX \ + : (uartNumber == UART_NUM_1 \ + ? UART1_RXD_PAD_IN_IDX \ + : (uartNumber == UART_NUM_2 ? UART2_RXD_PAD_IN_IDX : (uartNumber == UART_NUM_3 ? UART3_RXD_PAD_IN_IDX : UART4_RXD_PAD_IN_IDX)))) +#else +#if SOC_UART_HP_NUM > 2 #define UART_TX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0TXD_OUT_IDX : (uartNumber == UART_NUM_1 ? U1TXD_OUT_IDX : U2TXD_OUT_IDX)) #define UART_RX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0RXD_IN_IDX : (uartNumber == UART_NUM_1 ? U1RXD_IN_IDX : U2RXD_IN_IDX)) #else #define UART_TX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0TXD_OUT_IDX : U1TXD_OUT_IDX) #define UART_RX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0RXD_IN_IDX : U1RXD_IN_IDX) #endif +#endif // ifdef CONFIG_IDF_TARGET_ESP32P4 + /* This function internally binds defined UARTs TX signal with defined RX pin of any UART (same or different). This creates a loop that lets us receive anything we send on the UART without external wires. */ void uart_internal_loopback(uint8_t uartNum, int8_t rxPin) { - if (uartNum > SOC_UART_NUM - 1 || !GPIO_IS_VALID_GPIO(rxPin)) { + // LP UART is not supported for loopback + if (uartNum >= SOC_UART_HP_NUM || !GPIO_IS_VALID_GPIO(rxPin)) { + log_e("UART%d is not supported for loopback or RX pin %d is invalid.", uartNum, rxPin); return; } esp_rom_gpio_connect_out_signal(rxPin, UART_TX_SIGNAL(uartNum), false, false); @@ -1126,4 +1452,24 @@ int uart_send_msg_with_break(uint8_t uartNum, uint8_t *msg, size_t msgSize) { return uart_write_bytes_with_break(uartNum, (const void *)msg, msgSize, 12); } +// returns the maximum valid uart RX Timeout based on the UART Source Clock and Baudrate +uint16_t uart_get_max_rx_timeout(uint8_t uartNum) { + if (uartNum >= SOC_UART_NUM) { + log_e("UART%d is invalid. This device has %d UARTs, from 0 to %d.", uartNum, SOC_UART_NUM, SOC_UART_NUM - 1); + return (uint16_t)-1; + } + uint16_t tout_max_thresh = uart_ll_max_tout_thrd(UART_LL_GET_HW(uartNum)); + uint8_t symbol_len = 1; // number of bits per symbol including start + uart_parity_t parity_mode; + uart_stop_bits_t stop_bit; + uart_word_length_t data_bit; + uart_ll_get_data_bit_num(UART_LL_GET_HW(uartNum), &data_bit); + uart_ll_get_stop_bits(UART_LL_GET_HW(uartNum), &stop_bit); + uart_ll_get_parity(UART_LL_GET_HW(uartNum), &parity_mode); + symbol_len += (data_bit < UART_DATA_BITS_MAX) ? (uint8_t)data_bit + 5 : 8; + symbol_len += (stop_bit > UART_STOP_BITS_1) ? 2 : 1; + symbol_len += (parity_mode > UART_PARITY_DISABLE) ? 1 : 0; + return (uint16_t)(tout_max_thresh / symbol_len); +} + #endif /* SOC_UART_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-uart.h b/cores/esp32/esp32-hal-uart.h index 402b5785915..41b005aa151 100644 --- a/cores/esp32/esp32-hal-uart.h +++ b/cores/esp32/esp32-hal-uart.h @@ -1,4 +1,4 @@ -// Copyright 2015-2023 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2025 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. @@ -17,6 +17,7 @@ #include "soc/soc_caps.h" #if SOC_UART_SUPPORTED +#include "soc/uart_pins.h" #ifdef __cplusplus extern "C" { @@ -57,7 +58,7 @@ void uartWriteBuf(uart_t *uart, const uint8_t *data, size_t len); void uartFlush(uart_t *uart); void uartFlushTxOnly(uart_t *uart, bool txOnly); -void uartSetBaudRate(uart_t *uart, uint32_t baud_rate); +bool uartSetBaudRate(uart_t *uart, uint32_t baud_rate); uint32_t uartGetBaudRate(uart_t *uart); void uartSetRxInvert(uart_t *uart, bool invert); @@ -96,6 +97,19 @@ bool uartSetHwFlowCtrlMode(uart_t *uart, uart_hw_flowcontrol_t mode, uint8_t thr // UART_MODE_RS485_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes) bool uartSetMode(uart_t *uart, uart_mode_t mode); +// Used to set the UART clock source mode. It must be set before calling uartBegin(), otherwise it won't have any effect. +// Not all clock source are available to every SoC. The compatible option are listed here: +// UART_SCLK_DEFAULT :: any SoC - it will set whatever IDF defines as the default UART Clock Source +// UART_SCLK_APB :: ESP32, ESP32-S2, ESP32-C3 and ESP32-S3 +// UART_SCLK_PLL_F80M :: ESP32-C5, ESP32-C6, ESP32-C61 and ESP32-P4 +// UART_SCLK_PLL_F40M :: ESP32-C2 +// UART_SCLK_PLL_F48M :: ESP32-H2 +// UART_SCLK_XTAL :: ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, ESP32-S3 and ESP32-P4 +// UART_SCLK_RTC :: ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, ESP32-S3 and ESP32-P4 +// UART_SCLK_REF_TICK :: ESP32 and ESP32-S2 +// Note: ESP32-C6, C61, ESP32-P4 and ESP32-C5 have LP UART that will use only LP_UART_SCLK_LP_FAST (RTC_FAST) or LP_UART_SCLK_XTAL_D2 (XTAL/2) as Clock Source +bool uartSetClockSource(uint8_t uartNum, uart_sclk_t clkSrc); + void uartStartDetectBaudrate(uart_t *uart); unsigned long uartDetectBaudrate(uart_t *uart); @@ -115,6 +129,10 @@ void uart_send_break(uint8_t uartNum); // Sends a buffer and at the end of the stream, it generates BREAK in the line int uart_send_msg_with_break(uint8_t uartNum, uint8_t *msg, size_t msgSize); +// UART RX Timeout (in UART Symbols) depends on the UART Clock Source and the SoC that is used +// This is a helper function that calculates what is the maximum RX Timeout that a running UART IDF driver allows. +uint16_t uart_get_max_rx_timeout(uint8_t uartNum); + #ifdef __cplusplus } #endif diff --git a/cores/esp32/esp32-hal.h b/cores/esp32/esp32-hal.h index 60350ae960b..5ed99aeb205 100644 --- a/cores/esp32/esp32-hal.h +++ b/cores/esp32/esp32-hal.h @@ -61,6 +61,19 @@ extern "C" { #define ARDUINO_EVENT_RUNNING_CORE CONFIG_ARDUINO_EVENT_RUNNING_CORE #endif +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +static const uint8_t BOOT_PIN = 0; +#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C61 +static const uint8_t BOOT_PIN = 9; +#elif CONFIG_IDF_TARGET_ESP32P4 +static const uint8_t BOOT_PIN = 35; +#elif CONFIG_IDF_TARGET_ESP32C5 +static const uint8_t BOOT_PIN = 28; +#else +#error BOOT_PIN not defined for this chip! +#endif +#define BOOT_PIN BOOT_PIN + //forward declaration from freertos/portmacro.h void vPortYield(void); void yield(void); @@ -74,6 +87,7 @@ void yield(void); #include "esp32-hal-uart.h" #include "esp32-hal-gpio.h" #include "esp32-hal-touch.h" +#include "esp32-hal-touch-ng.h" #include "esp32-hal-dac.h" #include "esp32-hal-adc.h" #include "esp32-hal-spi.h" @@ -107,11 +121,11 @@ void feedLoopWDT(); //enable/disable WDT for the IDLE task on Core 0 (SYSTEM) void enableCore0WDT(); -void disableCore0WDT(); +bool disableCore0WDT(); #ifndef CONFIG_FREERTOS_UNICORE //enable/disable WDT for the IDLE task on Core 1 (Arduino) void enableCore1WDT(); -void disableCore1WDT(); +bool disableCore1WDT(); #endif //if xCoreID < 0 or CPU is unicore, it will use xTaskCreate, else xTaskCreatePinnedToCore diff --git a/cores/esp32/esp_arduino_version.h b/cores/esp32/esp_arduino_version.h index 7a9b194e020..b1355e908ae 100644 --- a/cores/esp32/esp_arduino_version.h +++ b/cores/esp32/esp_arduino_version.h @@ -21,9 +21,9 @@ extern "C" { /** Major version number (X.x.x) */ #define ESP_ARDUINO_VERSION_MAJOR 3 /** Minor version number (x.X.x) */ -#define ESP_ARDUINO_VERSION_MINOR 0 +#define ESP_ARDUINO_VERSION_MINOR 2 /** Patch version number (x.x.X) */ -#define ESP_ARDUINO_VERSION_PATCH 1 +#define ESP_ARDUINO_VERSION_PATCH 0 /** * Macro to convert ARDUINO version number into an integer diff --git a/cores/esp32/freertos_stats.cpp b/cores/esp32/freertos_stats.cpp new file mode 100644 index 00000000000..b37a5205e11 --- /dev/null +++ b/cores/esp32/freertos_stats.cpp @@ -0,0 +1,112 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "freertos_stats.h" +#include "sdkconfig.h" + +#if CONFIG_FREERTOS_USE_TRACE_FACILITY +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/portable.h" +#endif /* CONFIG_FREERTOS_USE_TRACE_FACILITY */ + +void printRunningTasks(Print &printer) { +#if CONFIG_FREERTOS_USE_TRACE_FACILITY +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS +#define FREERTOS_TASK_NUMBER_MAX_NUM 256 // RunTime stats for how many Tasks to be stored + static configRUN_TIME_COUNTER_TYPE ulRunTimeCounters[FREERTOS_TASK_NUMBER_MAX_NUM]; + static configRUN_TIME_COUNTER_TYPE ulLastRunTime = 0; + configRUN_TIME_COUNTER_TYPE ulCurrentRunTime = 0, ulTaskRunTime = 0; +#endif + configRUN_TIME_COUNTER_TYPE ulTotalRunTime = 0; + TaskStatus_t *pxTaskStatusArray = NULL; + volatile UBaseType_t uxArraySize = 0; + uint32_t x = 0; + const char *taskStates[] = {"Running", "Ready", "Blocked", "Suspended", "Deleted", "Invalid"}; + + // Take a snapshot of the number of tasks in case it changes while this function is executing. + uxArraySize = uxTaskGetNumberOfTasks(); + + // Allocate a TaskStatus_t structure for each task. + pxTaskStatusArray = (TaskStatus_t *)pvPortMalloc(uxArraySize * sizeof(TaskStatus_t)); + + if (pxTaskStatusArray != NULL) { + // Generate raw status information about each task. + uxArraySize = uxTaskGetSystemState(pxTaskStatusArray, uxArraySize, &ulTotalRunTime); + +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + ulCurrentRunTime = ulTotalRunTime - ulLastRunTime; + ulLastRunTime = ulTotalRunTime; +#endif + printer.printf( + "Tasks: %u" +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + ", Runtime: %lus, Period: %luus" +#endif + "\n", + uxArraySize +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + , + ulTotalRunTime / 1000000, ulCurrentRunTime +#endif + ); + printer.printf("Num\t Name" +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + "\tLoad" +#endif + "\tPrio\t Free" +#if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID + "\tCore" +#endif + "\tState\r\n"); + for (x = 0; x < uxArraySize; x++) { +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + if (pxTaskStatusArray[x].xTaskNumber < FREERTOS_TASK_NUMBER_MAX_NUM) { + ulTaskRunTime = (pxTaskStatusArray[x].ulRunTimeCounter - ulRunTimeCounters[pxTaskStatusArray[x].xTaskNumber]); + ulRunTimeCounters[pxTaskStatusArray[x].xTaskNumber] = pxTaskStatusArray[x].ulRunTimeCounter; + ulTaskRunTime = (ulTaskRunTime * 100) / ulCurrentRunTime; // in percentage + } else { + ulTaskRunTime = 0; + } +#endif + printer.printf( + "%3u\t%16s" +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + "\t%3lu%%" +#endif + "\t%4u\t%5lu" +#if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID + "\t%4c" +#endif + "\t%s\r\n", + pxTaskStatusArray[x].xTaskNumber, pxTaskStatusArray[x].pcTaskName, +#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + ulTaskRunTime, +#endif + pxTaskStatusArray[x].uxCurrentPriority, pxTaskStatusArray[x].usStackHighWaterMark, +#if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID + (pxTaskStatusArray[x].xCoreID == tskNO_AFFINITY) ? '*' : ('0' + pxTaskStatusArray[x].xCoreID), +#endif + taskStates[pxTaskStatusArray[x].eCurrentState] + ); + } + + // The array is no longer needed, free the memory it consumes. + vPortFree(pxTaskStatusArray); + printer.println(); + } +#else + printer.println("FreeRTOS trace facility is not enabled."); +#endif /* CONFIG_FREERTOS_USE_TRACE_FACILITY */ +} diff --git a/cores/esp32/freertos_stats.h b/cores/esp32/freertos_stats.h new file mode 100644 index 00000000000..ea9e1a55a21 --- /dev/null +++ b/cores/esp32/freertos_stats.h @@ -0,0 +1,28 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus + +#include "Print.h" + +/* + * Executing this function will cause interrupts and + * the scheduler to be blocked for some time. + * Please use only for debugging purposes. + */ +void printRunningTasks(Print &printer); + +#endif diff --git a/cores/esp32/io_pin_remap.h b/cores/esp32/io_pin_remap.h index 4e422632ea4..10f11a5bf4c 100644 --- a/cores/esp32/io_pin_remap.h +++ b/cores/esp32/io_pin_remap.h @@ -77,7 +77,7 @@ int8_t gpioNumberToDigitalPin(int8_t gpioNumber); #define pinMatrixOutDetach(pin, invertOut, invertEnable) pinMatrixOutDetach(digitalPinToGPIONumber(pin), invertOut, invertEnable) // cores/esp32/esp32-hal-rgb-led.h -#define neopixelWrite(pin, red_val, green_val, blue_val) neopixelWrite(digitalPinToGPIONumber(pin), red_val, green_val, blue_val) +#define rgbLedWrite(pin, red_val, green_val, blue_val) rgbLedWrite(digitalPinToGPIONumber(pin), red_val, green_val, blue_val) // cores/esp32/esp32-hal-rmt.h #define rmtInit(pin, channel_direction, memsize, frequency_Hz) rmtInit(digitalPinToGPIONumber(pin), channel_direction, memsize, frequency_Hz) @@ -106,7 +106,7 @@ int8_t gpioNumberToDigitalPin(int8_t gpioNumber); #define spiAttachMOSI(spi, mosi) spiAttachMOSI(spi, digitalPinToGPIONumber(mosi)) #define spiAttachSS(spi, cs_num, ss) spiAttachSS(spi, cs_num, digitalPinToGPIONumber(ss)) -// cores/esp32/esp32-hal-touch.h +// cores/esp32/esp32-hal-touch.h && cores/esp32/esp32-hal-touch-ng.h #define touchInterruptGetLastStatus(pin) touchInterruptGetLastStatus(digitalPinToGPIONumber(pin)) #define touchRead(pin) touchRead(digitalPinToGPIONumber(pin)) #define touchAttachInterruptArg(pin, userFunc, arg, threshold) touchAttachInterruptArg(digitalPinToGPIONumber(pin), userFunc, arg, threshold) diff --git a/cores/esp32/wiring_shift.c b/cores/esp32/wiring_shift.c index 7148ec3036b..2198b2e5243 100644 --- a/cores/esp32/wiring_shift.c +++ b/cores/esp32/wiring_shift.c @@ -20,7 +20,7 @@ #include "esp32-hal.h" #include "wiring_private.h" -uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { // codespell:ignore shiftin uint8_t value = 0; uint8_t i; diff --git a/docs/_static/logo_pio.png b/docs/_static/logo_pio.png deleted file mode 100644 index a64c1563964..00000000000 Binary files a/docs/_static/logo_pio.png and /dev/null differ diff --git a/docs/en/advanced_utils.rst b/docs/en/advanced_utils.rst index 465f7d37e3c..a1dbe54d04b 100644 --- a/docs/en/advanced_utils.rst +++ b/docs/en/advanced_utils.rst @@ -6,6 +6,6 @@ Advanced Utilities :maxdepth: 2 Library Builder - ESP-IDF as Component + Arduino as an ESP-IDF component OTA Web Update makeEspArduino diff --git a/docs/en/api/adc.rst b/docs/en/api/adc.rst index 7c7fbc5ed94..434384f8d9b 100644 --- a/docs/en/api/adc.rst +++ b/docs/en/api/adc.rst @@ -21,7 +21,7 @@ ADC OneShot mode The ADC OneShot mode API is fully compatible with Arduino's ``analogRead`` function. -When you call the ``analogRead`` or ``analogReadMillivolts`` function, it returns the result of a single conversion on the requested pin. +When you call the ``analogRead`` or ``analogReadMilliVolts`` function, it returns the result of a single conversion on the requested pin. analogRead ^^^^^^^^^^ @@ -36,7 +36,7 @@ This function is used to get the ADC raw value for a given pin/ADC channel. This function will return analog raw value (non-calibrated). -analogReadMillivolts +analogReadMilliVolts ^^^^^^^^^^^^^^^^^^^^ This function is used to get ADC raw value for a given pin/ADC channel and convert it to calibrated result in millivolts. @@ -53,7 +53,7 @@ analogReadResolution ^^^^^^^^^^^^^^^^^^^^ This function is used to set the resolution of ``analogRead`` return value. Default is 12 bits (range from 0 to 4095) -for all chips except ESP32S3 where default is 13 bits (range from 0 to 8191). +for all chips except ESP32-S3 where default is 13 bits (range from 0 to 8191). When different resolution is set, the values read will be shifted to match the given resolution. Range is 1 - 16 .The default value will be used, if this function is not used. @@ -146,7 +146,7 @@ analogSetWidth .. note:: This function is only available for ESP32 chip. This function is used to set the hardware sample bits and read resolution. -Default is 12bit (0 - 4095). +Default is 12 bits (0 - 4095). Range is 9 - 12. .. code-block:: arduino @@ -170,7 +170,7 @@ This function is used to configure ADC continuous peripheral on selected pins. .. code-block:: arduino - bool analogContinuous(uint8_t pins[], size_t pins_count, uint32_t conversions_per_pin, uint32_t sampling_freq_hz, void (*userFunc)(void)); + bool analogContinuous(const uint8_t pins[], size_t pins_count, uint32_t conversions_per_pin, uint32_t sampling_freq_hz, void (*userFunc)(void)); * ``pins[]`` array of pins to be set up * ``pins_count`` count of pins in array @@ -250,13 +250,13 @@ This function is used to set the attenuation for ADC continuous peripheral. For void analogContinuousSetAtten(adc_attenuation_t attenuation); -* ``attenuation`` sets the attenuation (default is 11db). +* ``attenuation`` sets the attenuation (default is 11 dB). analogContinuousSetWidth ^^^^^^^^^^^^^^^^^^^^^^^^ This function is used to set the hardware resolution bits. -Default value for all chips is 12bit (0 - 4095). +Default value for all chips is 12 bits (0 - 4095). .. note:: This function will take effect only for ESP32 chip, as it allows to set resolution in range 9-12 bits. diff --git a/docs/en/api/dac.rst b/docs/en/api/dac.rst index d66c6878c17..96939be96f3 100644 --- a/docs/en/api/dac.rst +++ b/docs/en/api/dac.rst @@ -33,7 +33,7 @@ This function is used to set the DAC value for a given pin/DAC channel. void dacWrite(uint8_t pin, uint8_t value); * ``pin`` GPIO pin. -* ``value`` to be set. Range is 0 - 255 (equals 0V - 3.3V). +* ``value`` to be set. Range is 0 - 255 (equals 0 V - 3.3 V). dacDisable ********** diff --git a/docs/en/api/espnow.rst b/docs/en/api/espnow.rst index d9f27ee711a..585c2e3f53e 100644 --- a/docs/en/api/espnow.rst +++ b/docs/en/api/espnow.rst @@ -104,7 +104,7 @@ Create an instance of the `ESP_NOW_Peer` class. * ``mac_addr``: MAC address of the peer device. * ``channel``: Communication channel. -* ``iface``: WiFi interface. +* ``iface``: Wi-Fi interface. * ``lmk``: Optional. Pass the local master key (LMK) if encryption is enabled. add @@ -190,24 +190,24 @@ Set the communication channel of the peer. getInterface ^^^^^^^^^^^^ -Get the WiFi interface of the peer. +Get the Wi-Fi interface of the peer. .. code-block:: cpp wifi_interface_t getInterface() const; -Returns the WiFi interface. +Returns the Wi-Fi interface. setInterface ^^^^^^^^^^^^ -Set the WiFi interface of the peer. +Set the Wi-Fi interface of the peer. .. code-block:: cpp void setInterface(wifi_interface_t iface); -* ``iface``: WiFi interface. +* ``iface``: Wi-Fi interface. isEncrypted ^^^^^^^^^^^ diff --git a/docs/en/api/gpio.rst b/docs/en/api/gpio.rst index e74f90bff92..ebf31088ffd 100644 --- a/docs/en/api/gpio.rst +++ b/docs/en/api/gpio.rst @@ -9,7 +9,7 @@ One of the most used and versatile peripheral in a microcontroller is the GPIO. GPIO stands to General Purpose Input Output, and is responsible to control or read the state of a specific pin in the digital world. For example, this peripheral is widely used to create the LED blinking or to read a simple button. -.. note:: There are some GPIOs with special restrictions, and not all GPIOs are accessible through the developemnt board. For more information about it, see the corresponding board pin layout information. +.. note:: There are some GPIOs with special restrictions, and not all GPIOs are accessible through the development board. For more information about it, see the corresponding board pin layout information. GPIOs Modes *********** diff --git a/docs/en/api/i2c.rst b/docs/en/api/i2c.rst index 3723b5e3947..eac04b76a23 100644 --- a/docs/en/api/i2c.rst +++ b/docs/en/api/i2c.rst @@ -103,7 +103,7 @@ This function will return the current frequency configuration. setTimeOut ^^^^^^^^^^ -Set the bus timeout given in milliseconds. The default value is 50ms. +Set the bus timeout given in milliseconds. The default value is 50 ms. .. code-block:: arduino diff --git a/docs/en/api/i2s.rst b/docs/en/api/i2s.rst index 8040dccbb5c..f67713c750f 100644 --- a/docs/en/api/i2s.rst +++ b/docs/en/api/i2s.rst @@ -536,7 +536,7 @@ Sample code #include const int buff_size = 128; - int available, read; + int available_bytes, read_bytes; uint8_t buffer[buff_size]; I2SClass I2S; @@ -544,13 +544,13 @@ Sample code I2S.setPins(5, 25, 26, 35, 0); //SCK, WS, SDOUT, SDIN, MCLK I2S.begin(I2S_MODE_STD, 16000, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); I2S.read(); - available = I2S.available(); - if(available < buff_size) { - read = I2S.read(buffer, available); + available_bytes = I2S.available(); + if(available_bytes < buff_size) { + read_bytes = I2S.readBytes(buffer, available_bytes); } else { - read = I2S.read(buffer, buff_size); + read_bytes = I2S.readBytes(buffer, buff_size); } - I2S.write(buffer, read); + I2S.write(buffer, read_bytes); I2S.end(); } diff --git a/docs/en/api/insights.rst b/docs/en/api/insights.rst index 1350c7bcee3..a5e294f82f1 100644 --- a/docs/en/api/insights.rst +++ b/docs/en/api/insights.rst @@ -5,7 +5,7 @@ ESP Insights About ----- -ESP Insights is a remote diagnostics solution that allows users to remotely monitor the health of ESP devices in the field. +ESP Insights is a remote diagnostics solution that allows users to remotely monitor the health of Espressif devices in the field. Developers normally prefer debugging issues by physically probing them using gdb or observing the logs. This surely helps debug issues, but there are often cases wherein issues are seen only in specific environments under specific conditions. Even things like casings and placement of the product can affect the behavior. A few examples are @@ -156,8 +156,8 @@ This function will return Insights.metrics.dumpWiFi ************************* -Dumps the wifi metrics and prints them to the console. -This API can be used to collect wifi metrics at any given point in time. +Dumps the Wi-Fi metrics and prints them to the console. +This API can be used to collect Wi-Fi metrics at any given point in time. .. code-block:: arduino @@ -185,8 +185,8 @@ Insights.metrics.setWiFiPeriod ****************************** Reset the periodic interval -By default, wifi metrics are collected every 30 seconds, this function can be used to change the interval. -If the interval is set to 0, wifi metrics collection disabled. +By default, Wi-Fi metrics are collected every 30 seconds, this function can be used to change the interval. +If the interval is set to 0, Wi-Fi metrics collection disabled. .. code-block:: arduino diff --git a/docs/en/api/ledc.rst b/docs/en/api/ledc.rst index 908165717f1..6ea3437bbf5 100644 --- a/docs/en/api/ledc.rst +++ b/docs/en/api/ledc.rst @@ -23,6 +23,34 @@ ESP32-H2 6 Arduino-ESP32 LEDC API ---------------------- +ledcSetCLockSource +****************** + +This function is used to set the LEDC peripheral clock source. Must be called before any LEDC channel is used. +The default clock source is XTAL clock (``LEDC_USE_XTAL_CLK``) if supported by the SoC, otherwise it is AUTO clock (``LEDC_AUTO_CLK``). + +.. code-block:: arduino + + bool ledcSetClockSource(ledc_clk_cfg_t source); + +* ``source`` select the clock source for LEDC peripheral. + + * ``LEDC_APB_CLK`` - APB clock. + * ``LEDC_REF_CLK`` - REF clock. + +This function will return ``true`` if setting the clock source is successful, otherwise it will return ``false``. + +ledcGetClockSource +****************** + +This function is used to get the LEDC peripheral clock source. + +.. code-block:: arduino + + ledc_clk_cfg_t ledcGetClockSource(void); + +This function will return the clock source for the LEDC peripheral. + ledcAttach ********** @@ -45,6 +73,7 @@ ledcAttachChannel ***************** This function is used to setup LEDC pin with given frequency, resolution and channel. +Attaching multiple pins to the same channel will make them share the same duty cycle. Given frequency, resolution will be ignored if channel is already configured. .. code-block:: arduino @@ -76,6 +105,21 @@ This function is used to set duty for the LEDC pin. This function will return ``true`` if setting duty is successful. If ``false`` is returned, error occurs and duty was not set. +ledcWriteChannel +**************** + +This function is used to set duty for the LEDC channel. + +.. code-block:: arduino + + bool ledcWriteChannel(uint8_t channel, uint32_t duty); + +* ``channel`` select LEDC channel. +* ``duty`` select duty to be set for selected LEDC channel. + +This function will return ``true`` if setting duty is successful. +If ``false`` is returned, error occurs and duty was not set. + ledcRead ******** diff --git a/docs/en/api/preferences.rst b/docs/en/api/preferences.rst index 2b06b78df07..2ff6f178347 100644 --- a/docs/en/api/preferences.rst +++ b/docs/en/api/preferences.rst @@ -62,12 +62,12 @@ Preferences directly supports the following data types: +-------------------+-------------------+---------------+ | ULong | uint32_t | 4 | +-------------------+-------------------+---------------+ + | Float | float_t | 4 | + +-------------------+-------------------+---------------+ | Long64 | int64_t | 8 | +-------------------+-------------------+---------------+ | ULong64 | uint64_t | 8 | +-------------------+-------------------+---------------+ - | Float | float_t | 8 | - +-------------------+-------------------+---------------+ | Double | double_t | 8 | +-------------------+-------------------+---------------+ | | const char* | variable | @@ -258,6 +258,8 @@ Arduino-esp32 Preferences API ``putInt, putUInt`` ******************** ``putLong, putULong`` +********************** +``putFloat`` ********************** Store a value against a given key in the currently open namespace. @@ -268,6 +270,7 @@ Arduino-esp32 Preferences API size_t putUInt(const char* key, uint32_t value) size_t putLong(const char* key, int32_t value) size_t putULong(const char* key, uint32_t value) + size_t putFloat(const char* key, float_t value) .. @@ -288,8 +291,8 @@ Arduino-esp32 Preferences API ``putLong64, putULong64`` ************************* -``putFloat, putDouble`` -*********************** +``putDouble`` +************************* Store a value against a given key in the currently open namespace. @@ -297,7 +300,6 @@ Arduino-esp32 Preferences API size_t putLong64(const char* key, int64_t value) size_t putULong64(const char* key, uint64_t value) - size_t putFloat(const char* key, float_t value) size_t putDouble(const char* key, double_t value) .. @@ -524,7 +526,7 @@ Arduino-esp32 Preferences API .. code-block:: arduino - uint8_t getUChar(const char* key, uint8_t defaultValue = 0); + bool getBool(const char* key, bool defaultValue = false); .. diff --git a/docs/en/api/rainmaker.rst b/docs/en/api/rainmaker.rst index 3c8a7958ba9..01309f605ad 100644 --- a/docs/en/api/rainmaker.rst +++ b/docs/en/api/rainmaker.rst @@ -29,7 +29,7 @@ ESP RainMaker Agent API RMaker.initNode *************** -This initializes the ESP RainMaker agent, wifi and creates the node. +This initializes the ESP RainMaker agent, Wi-Fi and creates the node. You can also set the configuration of the node using the following API @@ -54,7 +54,7 @@ It starts the ESP RainMaker agent. **NOTE**: 1. ESP RainMaker agent should be initialized before this call. -2. Once ESP RainMaker agent starts, compulsorily call WiFi.beginProvision() API. +2. Once ESP RainMaker agent starts, compulsorily call ``WiFi.beginProvision()`` API. .. code-block:: arduino diff --git a/docs/en/api/rmt.rst b/docs/en/api/rmt.rst index 0a348592766..6f87054a9c2 100644 --- a/docs/en/api/rmt.rst +++ b/docs/en/api/rmt.rst @@ -14,10 +14,10 @@ Example To get started with RMT, you can try: -RMT Write Neo Pixel -******************* +RMT Write RGB LED +***************** -.. literalinclude:: ../../../libraries/ESP32/examples/RMT/RMTWriteNeoPixel/RMTWriteNeoPixel.ino +.. literalinclude:: ../../../libraries/ESP32/examples/RMT/RMTWrite_RGB_LED/RMTWrite_RGB_LED.ino :language: arduino diff --git a/docs/en/api/timer.rst b/docs/en/api/timer.rst index 58706d8e453..2637f9eec1d 100644 --- a/docs/en/api/timer.rst +++ b/docs/en/api/timer.rst @@ -119,14 +119,14 @@ This function is used to read counter value in microseconds of the timer. This function will return ``counter value`` of the timer in microseconds. -timerReadMilis -************** +timerReadMillis +*************** This function is used to read counter value in milliseconds of the timer. .. code-block:: arduino - uint64_t timerReadMilis(hw_timer_t * timer); + uint64_t timerReadMillis(hw_timer_t * timer); * ``timer`` timer struct. diff --git a/docs/en/api/touch.rst b/docs/en/api/touch.rst index 7b9775b2c80..d4a905f86e8 100644 --- a/docs/en/api/touch.rst +++ b/docs/en/api/touch.rst @@ -36,7 +36,7 @@ touchSetCycles ^^^^^^^^^^^^^^ This function is used to set cycles that measurement operation takes. The result from touchRead, threshold and detection accuracy depend on these values. -The defaults are setting touchRead to take ~0.5ms. +The defaults are setting touchRead to take ~0.5 ms. .. code-block:: arduino @@ -112,8 +112,8 @@ the threshold value. Default is lower. void touchInterruptSetThresholdDirection(bool mustbeLower); -TOUCH API specific for ESP32S2 and ESP32S3 chip (TOUCH_V2) -********************************************************** +TOUCH API specific for ESP32-S2 and ESP32-S3 chip (TOUCH_V2) +************************************************************ touchInterruptGetLastStatus ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/en/api/usb.rst b/docs/en/api/usb.rst index b7d77b9d5d5..8e5388a4d0e 100644 --- a/docs/en/api/usb.rst +++ b/docs/en/api/usb.rst @@ -154,7 +154,7 @@ Get the USB power configuration. uint16_t usbPower(void); -Return the current in mA. The default value is: ``0x500`` (500mA). +Return the current in mA. The default value is: ``0x500`` (500 mA). usbClass ^^^^^^^^ diff --git a/docs/en/api/wifi.rst b/docs/en/api/wifi.rst index 5bdd050ac5b..16d8a9d5666 100644 --- a/docs/en/api/wifi.rst +++ b/docs/en/api/wifi.rst @@ -43,7 +43,7 @@ This is the mode to be used if you want to connect your project to the Internet. API Description --------------- -Here is the description of the WiFi API. +Here is the description of the Wi-Fi API. Common API ---------- @@ -53,7 +53,7 @@ Here are the common APIs that are used for both modes, AP and STA. onEvent (and removeEvent) ************************* -Registers a caller-supplied function to be called when WiFi events +Registers a caller-supplied function to be called when Wi-Fi events occur. Several forms are available. Function pointer callback taking the event ID: @@ -92,7 +92,7 @@ A similar set of functions are available to remove callbacks: In all cases, the subscribing function accepts an optional event type to invoke the callback only for that specific event; with the default -``ARDUINO_EVENT_MAX``, the callback will be invoked for all WiFi events. +``ARDUINO_EVENT_MAX``, the callback will be invoked for all Wi-Fi events. Any callback function is given the event type in a parameter. Some of the possible callback function formats also take an @@ -141,9 +141,9 @@ may be retrieved: .. warning:: - The ``setHostname()`` function must be called BEFORE WiFi is started with + The ``setHostname()`` function must be called BEFORE Wi-Fi is started with ``WiFi.begin()``, ``WiFi.softAP()``, ``WiFi.mode()``, or ``WiFi.run()``. - To change the name, reset WiFi with ``WiFi.mode(WIFI_MODE_NULL)``, + To change the name, reset Wi-Fi with ``WiFi.mode(WIFI_MODE_NULL)``, then proceed with ``WiFi.setHostname(...)`` and restart WiFi from scratch. useStaticBuffers @@ -619,7 +619,7 @@ WiFiScan To perform the Wi-Fi scan for networks, you can use the following functions: -Start scan WiFi networks available. +Start scan Wi-Fi networks available. .. code-block:: arduino @@ -637,7 +637,7 @@ Delete last scan result from RAM. void scanDelete(); -Loads all infos from a scanned wifi in to the ptr parameters. +Loads all infos from a scanned Wi-Fi in to the ptr parameters. .. code-block:: arduino @@ -648,7 +648,7 @@ To see how to use the ``WiFiScan``, take a look at the ``WiFiScan.ino`` or ``WiF Examples -------- -`Complete list of WiFi examples `_. +`Complete list of Wi-Fi examples `_. .. _ap example: diff --git a/docs/en/boards/ESP32-C3-DevKitM-1.rst b/docs/en/boards/ESP32-C3-DevKitM-1.rst index 763e5e5d630..abf7d2cef34 100644 --- a/docs/en/boards/ESP32-C3-DevKitM-1.rst +++ b/docs/en/boards/ESP32-C3-DevKitM-1.rst @@ -7,8 +7,8 @@ The ESP32-C3-DevKitM-1 development board is one of Espressif's official boards. Specifications -------------- -- Small­ sized 2.4 GHz Wi­Fi (802.11 b/g/n) and Bluetooth® 5 module -- Built around ESP32­C3 series of SoCs, RISC­V single­core microprocessor +- Small sized 2.4 GHz Wi-Fi (802.11b/g/n) and Bluetooth® 5 module +- Built around ESP32-C3 series of SoCs, RISC-V single-core microprocessor - 4 MB flash in chip package - 15 available GPIOs (module) - Peripherals @@ -30,7 +30,7 @@ Specifications - 2 × 54-bit general-purpose timers - 3 × watchdog timers - 1 × 52-bit system timer -- On­board PCB antenna or external antenna connector +- PCB antenna or external antenna connector Header Block ------------ @@ -40,6 +40,9 @@ Header Block J1 ^^^ + +.. vale off + === ==== ========== =================================== No. Name Type [1]_ Function === ==== ========== =================================== @@ -60,6 +63,8 @@ No. Name Type [1]_ Function 15 GND G Ground === ==== ========== =================================== +.. vale on + J3 ^^^ === ==== ========== ==================================== diff --git a/docs/en/boards/ESP32-DevKitC-1.rst b/docs/en/boards/ESP32-DevKitC-1.rst index f7aa63da61c..6a7f1c78864 100644 --- a/docs/en/boards/ESP32-DevKitC-1.rst +++ b/docs/en/boards/ESP32-DevKitC-1.rst @@ -7,7 +7,7 @@ The `ESP32-DevKitC-1`_ development board is one of Espressif's official boards. Specifications -------------- -- Wi-Fi 802.11 b/g/n (802.11n up to 150 Mbps) +- Wi-Fi 802.11b/g/n (802.11n up to 150 Mbps) - Bluetooth v4.2 BR/EDR and BLE specification - Built around ESP32 series of SoCs - Integrated 4 MB SPI flash @@ -28,7 +28,7 @@ Specifications - ADC - DAC - Two-Wire Automotive Interface (TWAI®, compatible with ISO11898-1) -- On­board PCB antenna or external antenna connector +- PCB antenna or external antenna connector Header Block ------------ @@ -38,6 +38,9 @@ Header Block J1 ^^^ + +.. vale off + === ==== ===== =================================== No. Name Type Function === ==== ===== =================================== @@ -62,6 +65,8 @@ No. Name Type Function 19 5V0 P 5 V power supply === ==== ===== =================================== +.. vale on + J3 ^^^ === ==== ===== ==================================== @@ -110,7 +115,7 @@ Some of the GPIO's have important features during the booting process. Here is t ==== ========= ===================================================================== ============ ============== GPIO Default Function Pull-up Pull-down ==== ========= ===================================================================== ============ ============== -IO12 Pull-down Voltage of Internal LDO (VDD_SDIO) 1V8 3V3 +IO12 Pull-down Voltage of Internal LDO (VDD_SDIO) 1.8 V 3.3 V IO0 Pull-up Booting Mode SPI Boot Download Boot IO2 Pull-down Booting Mode Don't Care Download Boot IO15 Pull-up Enabling/Disabling Log Print During Booting and Timing of SDIO Slave U0TXD Active U0TXD Silent diff --git a/docs/en/boards/ESP32-S2-Saola-1.rst b/docs/en/boards/ESP32-S2-Saola-1.rst index 99b4890247b..9c8c83c6211 100644 --- a/docs/en/boards/ESP32-S2-Saola-1.rst +++ b/docs/en/boards/ESP32-S2-Saola-1.rst @@ -7,7 +7,7 @@ The `ESP32-S2-Saola-1`_ development board is one of Espressif's official boards. Specifications -------------- -- Wi-Fi 802.11 b/g/n (802.11n up to 150 Mbps) +- Wi-Fi 802.11b/g/n (802.11n up to 150 Mbps) - Built around ESP32-S2 series of SoCs Xtensa® single-core - Integrated 4 MB SPI flash - Integrated 2 MB PSRAM @@ -28,7 +28,7 @@ Specifications - 1 × LCD interface (8-bit serial RGB/8080/6800), implemented using the hardware resources of SPI2 - 1 × LCD interface (8/16/24-bit parallel), implemented using the hardware resources of I2S - 1 × TWAI® controller (compatible with ISO 11898-1) -- On­board PCB antenna or external antenna connector +- PCB antenna or external antenna connector Header Block ------------ @@ -38,6 +38,9 @@ Header Block J2 ^^^ + +.. vale off + === ==== ===== =================================== No. Name Type Function === ==== ===== =================================== @@ -64,6 +67,8 @@ No. Name Type Function 21 GND G Ground === ==== ===== =================================== +.. vale on + J3 ^^^ === ==== ===== ==================================== @@ -114,7 +119,7 @@ Some of the GPIO's have important features during the booting process. Here is t ==== ========= ===================================================================== ============ ============== GPIO Default Function Pull-up Pull-down ==== ========= ===================================================================== ============ ============== -IO45 Pull-down Voltage of Internal LDO (VDD_SDIO) 1V8 3V3 +IO45 Pull-down Voltage of Internal LDO (VDD_SDIO) 1.8 V 3.3 V IO0 Pull-up Booting Mode SPI Boot Download Boot IO46 Pull-down Booting Mode Don't Care Download Boot IO46 Pull-up Enabling/Disabling Log Print During Booting and Timing of SDIO Slave U0TXD Active U0TXD Silent diff --git a/docs/en/boards/boards.rst b/docs/en/boards/boards.rst index cd0b310a66a..407b019a78b 100644 --- a/docs/en/boards/boards.rst +++ b/docs/en/boards/boards.rst @@ -17,13 +17,19 @@ One important information that usually bring about some confusion is regarding t The ESP32 is divided by family: * ESP32 - * Wi-Fi and BLE -* ESP32-S + * Wi-Fi, BT and BLE 4 +* ESP32-C3 + * Wi-Fi and BLE 5 +* ESP32-C6 + * Wi-Fi, BLE 5 and IEEE 802.15.4 +* ESP32-H2 + * BLE 5 and IEEE 802.15.4 +* ESP32-P4 + * 400 MHz Dual Core RISC-V CPU, 40 MHz ULP Co-processor, single-precision FPU and AI extensions. +* ESP32-S2 * Wi-Fi only -* ESP32-C +* ESP32-S3 * Wi-Fi and BLE 5 -* ESP32-H - * BLE and IEEE 802.15.4 For each family, we have SoC variants with some differentiation. The differences are more about the embedded flash and its size and the number of the cores (dual or single). diff --git a/docs/en/boards/generic.rst b/docs/en/boards/generic.rst index 8ca4a79eace..d40db616f13 100644 --- a/docs/en/boards/generic.rst +++ b/docs/en/boards/generic.rst @@ -12,6 +12,9 @@ Header Block Header1 ^^^^^^^ + +.. vale off + === ==== ===== =================================== No. Name Type Function === ==== ===== =================================== @@ -21,6 +24,8 @@ No. Name Type Function 4 GND G Ground === ==== ===== =================================== +.. vale on + Pin Layout ---------- diff --git a/docs/en/common/datasheet.inc b/docs/en/common/datasheet.inc index 193359fb73a..7086a12d1a8 100644 --- a/docs/en/common/datasheet.inc +++ b/docs/en/common/datasheet.inc @@ -2,16 +2,20 @@ Datasheet --------- * `ESP32`_ (Datasheet) -* `ESP32-S2`_ (Datasheet) +* `ESP32-C2`_ (Datasheet) * `ESP32-C3`_ (Datasheet) -* `ESP32-S3`_ (Datasheet) * `ESP32-C6`_ (Datasheet) * `ESP32-H2`_ (Datasheet) +* `ESP32-P4`_ (Datasheet) +* `ESP32-S2`_ (Datasheet) +* `ESP32-S3`_ (Datasheet) .. _Espressif Product Selector: https://products.espressif.com/ .. _ESP32: https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf -.. _ESP32-S2: https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf +.. _ESP32-C2: https://www.espressif.com/sites/default/files/documentation/esp8684_datasheet_en.pdf .. _ESP32-C3: https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf -.. _ESP32-S3: https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf .. _ESP32-C6: https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf .. _ESP32-H2: https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf +.. _ESP32-P4: https://www.espressif.com/sites/default/files/documentation/esp32-p4_datasheet_en.pdf +.. _ESP32-S2: https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf +.. _ESP32-S3: https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf diff --git a/docs/en/contributing.rst b/docs/en/contributing.rst index 1c2b27c98bf..4ebe01cbf5b 100644 --- a/docs/en/contributing.rst +++ b/docs/en/contributing.rst @@ -15,7 +15,11 @@ Before Contributing Before sending us a Pull Request, please consider this: -* Is the contribution entirely your own work, or is it already licensed under an LGPL 2.1 compatible Open Source License? If not, cannot accept it. +* All contributions must be written in English to ensure effective communication and support. + Pull Requests written in other languages will be closed, with a request to rewrite them in English. + +* Is the contribution entirely your own work, or is it already licensed under an LGPL 2.1 compatible Open Source License? + If not, cannot accept it. * Is the code adequately commented and can people understand how it is structured? @@ -25,9 +29,10 @@ Before sending us a Pull Request, please consider this: * Example contributions are also welcome. - * If you are contributing by adding a new example, please use the `Arduino style guide`_ and the example guideline below. + * If you are contributing by adding a new example, please use the `Arduino style guide`_ and the example guideline below. -* If the contribution contains multiple commits, are they grouped together into logical changes (one major change per pull request)? Are any commits with names like "fixed typo" `squashed into previous commits `_? +* If the contribution contains multiple commits, are they grouped together into logical changes (one major change per pull request)? + Are any commits with names like "fixed typo" `squashed into previous commits `_? If you're unsure about any of these points, please open the Pull Request anyhow and then ask us for feedback. @@ -49,20 +54,22 @@ Checklist * Check if your example proposal has no similarities to the project (**already existing examples**) * Use the `Arduino style guide`_ * Add the header to all source files -* Add the `README.md` file +* Add the ``README.md`` file * Add inline comments if needed * Test the example Header ****** -All the source files must include the header with the example name and license, if applicable. You can change this header as you wish, but it will be reviewed by the community and may not be accepted. +All the source files must include the header with the example name and license, if applicable. You can change this header as you wish, +but it will be reviewed by the community and may not be accepted. -Ideally, you can add some description about the example, links to the documentation, or the author's name. Just have in mind to keep it simple and short. +Ideally, you can add some description about the example, links to the documentation, or the author's name. +Just have in mind to keep it simple and short. **Header Example** -.. code-block:: arduino +.. code-block:: arduino /* Wi-Fi FTM Initiator Arduino Example @@ -77,9 +84,9 @@ Ideally, you can add some description about the example, links to the documentat README file *********** -The **README.md** file should contain the example details. +The ``README.md`` file should contain the example details. -Please see the recommended **README.md** file in the `example template folder `_. +Please see the recommended ``README.md`` file in the `example template folder `_. Inline Comments *************** @@ -88,17 +95,16 @@ Inline comments are important if the example contains complex algorithms or spec Brief and clear inline comments are really helpful for the example understanding and it's fast usage. -**Example** - -See the `FTM example `_ as a reference. +See the `FTM example `_ +as a reference: -.. code-block:: arduino +.. code-block:: arduino // Number of FTM frames requested in terms of 4 or 8 bursts (allowed values - 0 (No pref), 16, 24, 32, 64) -and +Also: -.. code-block:: arduino +.. code-block:: arduino const char * WIFI_FTM_SSID = "WiFi_FTM_Responder"; // SSID of AP that has FTM Enabled const char * WIFI_FTM_PASS = "ftm_responder"; // STA Password @@ -106,33 +112,379 @@ and Testing ******* -Be sure you have tested the example in all the supported targets. If the example works only with specific targets, add this information in the **README.md** file on the **Supported Targets** and in the example code as an inline comment. +Be sure you have tested the example in all the supported targets. If the example some specific hardware requirements, +edit/add the ``ci.json`` in the same folder as the sketch to specify the regular expression for the +required configurations from ``sdkconfig``. +This will ensure that the CI system will run the test only on the targets that have the required configurations. + +You can check the available configurations in the ``sdkconfig`` file in the ``tools/esp32-arduino-libs/`` folder. + +Here is an example of the ``ci.json`` file where the example requires Wi-Fi to work properly: + +.. code-block:: json + + { + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] + } + +.. note:: + + The list of configurations will be checked against the ``sdkconfig`` file in the target folder. If the configuration is not present in the ``sdkconfig``, + the test will be skipped for that target. That means that the test will only run on the targets that have **ALL** the required configurations. -**Example** + Also, by default, the "match start of line" character (``^``) will be added to the beginning of each configuration. + That means that the configuration must be at the beginning of the line in the ``sdkconfig`` file. -.. code-block:: arduino +Sometimes, the example might not be supported by some target, even if the target has the required configurations +(like resources limitations or requiring a specific SoC). To avoid compilation errors, you can add the target to the ``ci.json`` +file so the CI system will force to skip the test on that target. + +Here is an example of the ``ci.json`` file where the example is requires Wi-Fi to work properly but is also not supported by the ESP32-S2 target: + +.. code-block:: json + + { + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ], + "targets": { + "esp32s2": false + } + } + +You also need to add this information in the ``README.md`` file, on the **Supported Targets**, and in the example code as an inline comment. +For example, in the sketch: + +.. code-block:: arduino /* - THIS FEATURE IS SUPPORTED ONLY BY ESP32-S2 AND ESP32-C3 + THIS FEATURE REQUIRES WI-FI SUPPORT AND IS NOT AVAILABLE FOR ESP32-S2 AS IT DOES NOT HAVE ENOUGH RAM. */ -and +And in the ``README.md`` file: -.. code-block:: markdown +.. code-block:: markdown - Currently, this example supports the following targets. + Currently, this example requires Wi-Fi and supports the following targets. - | Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | + | Supported Targets | ESP32 | ESP32-S3 | ESP32-C3 | ESP32-C6 | | ----------------- | ----- | -------- | -------- | -------- | +By default, the CI system will use the FQBNs specified in the ``.github/scripts/sketch_utils.sh`` file to compile the sketches. +Currently, the default FQBNs are: + +* ``espressif:esp32:esp32:PSRAM=enabled`` +* ``espressif:esp32:esp32s2:PSRAM=enabled`` +* ``espressif:esp32:esp32s3:PSRAM=opi,USBMode=default`` +* ``espressif:esp32:esp32c3`` +* ``espressif:esp32:esp32c6`` +* ``espressif:esp32:esp32h2`` +* ``espressif:esp32:esp32p4:USBMode=default`` + +There are two ways to alter the FQBNs used to compile the sketches: by using the ``fqbn`` or ``fqbn_append`` fields in the ``ci.json`` file. + +If you just want to append a string to the default FQBNs, you can use the ``fqbn_append`` field. For example, to add the ``DebugLevel=debug`` to the FQBNs, you would use: + +.. code-block:: json + + { + "fqbn_append": "DebugLevel=debug" + } + +If you want to override the default FQBNs, you can use the ``fqbn`` field. It is a dictionary where the key is the target name and the value is a list of FQBNs. +The FQBNs in the list will be used in sequence to compile the sketch. For example, to compile a sketch for ESP32-S2 with and without PSRAM enabled, you would use: + +.. code-block:: json + + { + "fqbn": { + "esp32s2": [ + "espressif:esp32:esp32s2:PSRAM=enabled,FlashMode=dio", + "espressif:esp32:esp32s2:PSRAM=disabled,FlashMode=dio" + ] + } + } + +.. note:: + + The FQBNs specified in the ``fqbn`` field will also override the options specified in the ``fqbn_append`` field. + That means that if the ``fqbn`` field is specified, the ``fqbn_append`` field will be ignored and will have no effect. + Example Template **************** -The example template can be found `here `_ and can be used as a reference. +The example template can be found `here `_ +and can be used as a reference. + +Documentation +------------- + +If you are contributing to the documentation, please follow the instructions described in the +`documentation guidelines `_ to properly format and test your changes. + +Testing and CI +-------------- + +After you have made your changes, you should test them. You can do this in different ways depending on the type of change you have made. + +Examples +******** + +The easiest way to test an example is to load it into the Arduino IDE and run it on your board. If you have multiple boards, +you should test it on all of them to ensure that the example works on all supported targets. + +You can refer to the `Example Contribution Guideline`_ section for more information on how to write and test examples. + +Library Changes +*************** + +If you have made changes to a library, you should test it on all supported targets. You can do this by loading the library examples (or creating new ones) +into the Arduino IDE and running them on your board. If you have multiple boards, you should test it on all of them to ensure that the library +works as expected on all targets. + +You can also add a new test suite to automatically check the library. You can refer to the `Adding a New Test Suite`_ section for more information. + +Core Changes +************ + +If you have made changes to the core, it is important to ensure that the changes do not break the existing functionality. You can do this by running the +tests on all supported targets. You can refer to the `Runtime Tests`_ section for more information. + +CI +** + +In our repository, we have a Continuous Integration (CI) system that runs tests and fixes on every Pull Request. This system will run the tests +on all supported targets and check if everything is working as expected. + +We have many types of tests and checks, including: + +* Compilation tests; +* Runtime tests; +* Documentation checks; +* Code style checks; +* And more. + +Let's go deeper into each type of test in the CI system: + +Compilation Tests +^^^^^^^^^^^^^^^^^ + +The compilation tests are the first type of tests in the CI system. They check if the code compiles on all supported targets. +If the code does not compile, the CI system will fail the test and the Pull Request will not be merged. +This is important to ensure that the code is compatible with all supported targets and no broken code is merged. + +It will go through all the sketches in the repository and check if they compile on all supported targets. This process is automated and controlled +by GitHub Actions. The CI system will run the ``arduino-cli`` tool to compile the sketches on all supported targets. + +Testing it locally using the CI scripts would be too time consuming, so we recommend running the tests locally using the Arduino IDE with +a sketch that uses the changes you made (you can also add the sketch as an example if your change is not covered by the existing ones). +Make sure to set ``Compiler Warnings`` to ``All`` in the Arduino IDE to catch any potential issues. + +Runtime Tests +^^^^^^^^^^^^^ + +Another type of test is the runtime tests. They check if the code runs and behaves as expected on all supported targets. If the +code does not run as expected, the CI system will fail the test and the Pull Request will not be merged. This is important to ensure that the code +works as expected on all supported targets and no unintended crashes or bugs are introduced. + +These tests are specialized sketches that run on the target board and check if the code behaves as expected. This process is automated and +controlled by the ``pytest_embedded`` tool. You can read more about this tool in its +`documentation `_. + +The tests are divided into two categories inside the ``tests`` folder: + +* ``validation``: These tests are used to validate the behavior of the Arduino core and libraries. They are used to check if the core and libraries + are working as expected; +* ``performance``: These tests are used to check the performance of the Arduino core and libraries. They are used to check if the changes made + to the core and libraries have any big impact on the performance. These tests usually run for a longer time than the validation tests and include + common benchmark tools like `CoreMark `_. + +To run the runtime tests locally, first install the required dependencies by running: + +.. code-block:: bash + + pip install -U -r tests/requirements.txt + +Before running the test, we need to build it by running: + +.. code-block:: bash + + ./.github/scripts/tests_build.sh -s -t + +The ```` is the name of the test you want to run (you can check the available tests in the ``tests/validation`` and +``tests/performance`` folders), and the ```` is the target board you want to run the test on. For example, to run the ``uart`` test on the +ESP32-C3 target, you would run: + +.. code-block:: bash + + ./.github/scripts/tests_build.sh -s uart -t esp32c3 + +You should see the output of the build process and the test binary should be generated in the ``~/.arduino/tests///build.tmp`` folder. + +Now that the test is built, you can run it in the target board. Connect the target board to your computer and run: + +.. code-block:: bash + + ./.github/scripts/tests_run.sh -s -t + +For example, to run the ``uart`` test on the ESP32-C3 target, you would run: + +.. code-block:: bash + + ./.github/scripts/tests_run.sh -s uart -t esp32c3 + +The test will run on the target board and you should see the output of the test in the terminal: + +.. code-block:: bash + + lucassvaz@Lucas--MacBook-Pro esp32 % ./.github/scripts/tests_run.sh -s uart -t esp32c3 + Sketch uart test type: validation + Running test: uart -- Config: Default + pytest tests --build-dir /Users/lucassvaz/.arduino/tests/esp32c3/uart/build.tmp -k test_uart --junit-xml=/Users/lucassvaz/Espressif/Arduino/hardware/espressif/esp32/tests/validation/uart/esp32c3/uart.xml --embedded-services esp,arduino + =============================================================================================== test session starts ================================================================================================ + platform darwin -- Python 3.12.3, pytest-8.2.2, pluggy-1.5.0 + rootdir: /Users/lucassvaz/Espressif/Arduino/hardware/espressif/esp32/tests + configfile: pytest.ini + plugins: cov-5.0.0, embedded-1.11.5, anyio-4.4.0 + collected 15 items / 14 deselected / 1 selected + + tests/validation/uart/test_uart.py::test_uart + -------------------------------------------------------------------------------------------------- live log setup -------------------------------------------------------------------------------------------------- + 2024-08-22 11:49:30 INFO Target: esp32c3, Port: /dev/cu.usbserial-2120 + PASSED [100%] + ------------------------------------------------------------------------------------------------ live log teardown ------------------------------------------------------------------------------------------------- + 2024-08-22 11:49:52 INFO Created unity output junit report: /private/var/folders/vp/g9wctsvn7b91k3pv_7cwpt_h0000gn/T/pytest-embedded/2024-08-22_14-49-30-392993/test_uart/dut.xml + + + ---------------------------------------------- generated xml file: /Users/lucassvaz/Espressif/Arduino/hardware/espressif/esp32/tests/validation/uart/esp32c3/uart.xml ---------------------------------------------- + ======================================================================================== 1 passed, 14 deselected in 22.18s ========================================================================================= + +After the test is finished, you can check the output in the terminal and the generated XML file in the test folder. +Additionally, for performance tests, you can check the generated JSON file in the same folder. + +You can also run the tests in `Wokwi `_ or `Espressif's QEMU `_ +by using the ``-W `` and ``-Q`` flags respectively. You will need to have the Wokwi and/or QEMU installed in your system +and set the ``WOKWI_CLI_TOKEN`` and/or ``QEMU_PATH`` environment variables. The ``WOKWI_CLI_TOKEN`` is the CI token that can be obtained from the +`Wokwi website `_ and the ``QEMU_PATH`` is the path to the QEMU binary. + +For example, to run the ``uart`` test using Wokwi, you would run: + +.. code-block:: bash + + WOKWI_CLI_TOKEN= ./.github/scripts/tests_run.sh -s uart -t esp32c3 -W + +And to run the ``uart`` test using QEMU, you would run: + +.. code-block:: bash + + QEMU_PATH= ./.github/scripts/tests_run.sh -s uart -t esp32c3 -Q + +.. note:: + + Not all tests are supported by Wokwi and QEMU. QEMU is only supported for ESP32 and ESP32-C3 targets. + Wokwi support depends on the `currently implemented peripherals `_. + +Adding a New Test Suite +####################### + +If you want to add a new test suite, you can create a new folder inside ``tests/validation`` or ``tests/performance`` with the name of the test suite. +You can use the ``hello_world`` test suite as a starting point and the other test suites as a reference. + +A test suite contains the following files: + +* ``test_.py``: The test file that contains the test cases. Required. +* ``.ino``: The sketch that will be tested. Required. +* ``ci.json``: The file that specifies how the test suite will be run in the CI system. Optional. +* ``diagram..json``: The diagram file that specifies the connections between the components in Wokwi. Optional. +* ``scenario.yaml``: The scenario file that specifies how Wokwi will interact with the components. Optional. +* Any other files that are needed for the test suite. + +You can read more about the test python API in the `pytest-embedded documentation `_. +For more information about the Unity testing framework, you can check the `Unity documentation `_. + +After creating the test suite, make sure to test it locally and run it in the CI system to ensure that it works as expected. + +CI JSON File +############ + +The ``ci.json`` file is used to specify how the test suite and sketches will handled by the CI system. It can contain the following fields: + +* ``requires``: A list of configurations in ``sdkconfig`` that are required to run the test suite. The test suite will only run on the targets + that have **ALL** the required configurations. By default, no configurations are required. +* ``requires_any``: A list of configurations in ``sdkconfig`` that are required to run the test suite. The test suite will only run on the targets + that have **ANY** of the required configurations. By default, no configurations are required. +* ``targets``: A dictionary that specifies the targets for which the tests will be run. The key is the target name and the value is a boolean + that specifies if the test should be run for that target. By default, all targets are enabled as long as they have the required configurations + specified in the ``requires`` field. This field is also valid for examples. +* ``platforms``: A dictionary that specifies the supported platforms. The key is the platform name and the value is a boolean that specifies if + the platform is supported. By default, all platforms are assumed to be supported. +* ``extra_tags``: A list of extra tags that the runner will require when running the test suite in hardware. By default, no extra tags are required. +* ``fqbn_append``: A string to be appended to the default FQBNs. By default, no string is appended. This has no effect if ``fqbn`` is specified. +* ``fqbn``: A dictionary that specifies the FQBNs that will be used to compile the sketch. The key is the target name and the value is a list + of FQBNs. The `default FQBNs `_ + are used if this field is not specified. This overrides the default FQBNs and the ``fqbn_append`` field. + +The ``wifi`` test suite is a good example of how to use the ``ci.json`` file: + +.. literalinclude:: ../../tests/validation/wifi/ci.json + :language: json + +Documentation Checks +^^^^^^^^^^^^^^^^^^^^ + +The CI also checks the documentation for any compilation errors. This is important to ensure that the documentation layout is not broken. +To build the documentation locally, please refer to the `documentation guidelines `_. + +Code Style Checks +^^^^^^^^^^^^^^^^^ + +For checking the code style and other code quality checks, we use pre-commit hooks. +These hooks will be automatically run by the CI when a Pull Request is marked as ``Status: Pending Merge``. +You can check which hooks are being run in the ``.pre-commit-config.yaml`` file. + +Currently, we have hooks for the following tasks: + +* Formatters for C, C++, Python, Bash, JSON, Markdown and ReStructuredText files; +* Linters for Python, Bash and prose (spoken language); +* Checking for spelling errors in the code and documentation; +* Removing trailing whitespaces and tabs in the code; +* Checking for the presence of private keys and other sensitive information in the code; +* Fixing the line endings and end of files (EOF) in the code; +* And more. + +You can read more about the pre-commit hooks in the `pre-commit documentation `_. + +If you want to run the pre-commit hooks locally, you first need to install the required dependencies by running: + +.. code-block:: bash + + pip install -U -r tools/pre-commit/requirements.txt + +Then, you can run the pre-commit hooks staging your changes and running: + +.. code-block:: bash + + pre-commit run + +To run a specific hook, you can use the hook name as an argument. For example, to run the ``codespell`` hook, you would run: + +.. code-block:: bash + + pre-commit run codespell + +If you want to run the pre-commit hooks automatically against the changed files on every ``git commit``, +you can install the pre-commit hooks by running: + +.. code-block:: bash + + pre-commit install Legal Part ---------- -Before a contribution can be accepted, you will need to sign our contributor agreement. You will be prompted for this automatically as part of the Pull Request process. +Before a contribution can be accepted, you will need to sign our contributor agreement. You will be prompted for this automatically as part of +the Pull Request process. .. _Arduino style guide: https://docs.arduino.cc/learn/contributions/arduino-writing-style-guide diff --git a/docs/en/esp-idf_component.rst b/docs/en/esp-idf_component.rst index aa946c61744..f38dc44ec0c 100644 --- a/docs/en/esp-idf_component.rst +++ b/docs/en/esp-idf_component.rst @@ -14,14 +14,36 @@ For a simplified method, see `Installing using Boards Manager `_. +.. note:: Latest Arduino Core ESP32 version (3.0.X) is now compatible with `ESP-IDF v5.1 `_. Please consider this compatibility when using Arduino as a component in ESP-IDF. + +For easiest use of Arduino framework as a ESP-IDF component, you can use the `IDF Component Manager `_ to add the Arduino component to your project. +This will automatically clone the repository and its submodules. You can find the Arduino component in the `ESP Registry `_ together with dependencies list and examples. + Installation ------------ -.. note:: Latest Arduino Core ESP32 version is now compatible with `ESP-IDF v4.4 `_. Please consider this compatibility when using Arduino as a component in ESP-IDF. - #. Download and install `ESP-IDF `_. * For more information see `Get Started `_. + +Installing using IDF Component Manager +************************************** + +To add the Arduino component to your project using the IDF Component Manager, run the following command in your project directory: + +.. code-block:: bash + + idf.py add-dependency "espressif/arduino-esp32^3.0.2" + +Or you can start a new project from a template with the Arduino component: + +.. code-block:: bash + + idf.py create-project-from-example "espressif/arduino-esp32^3.0.2:hello_world" + +Manual installation of Arduino framework +**************************************** + #. Create a blank ESP-IDF project (use sample_project from /examples/get-started) or choose one of the examples. #. In the project folder, create a new folder called ``components`` and clone this repository inside the newly created folder. @@ -156,12 +178,14 @@ If you are writing code that does not require Arduino to compile and you want yo FreeRTOS Tick Rate (Hz) ----------------------- -The Arduino component requires the FreeRTOS tick rate `CONFIG_FREERTOS_HZ` set to 1000Hz in `make menuconfig` -> `Component config` -> `FreeRTOS` -> `Tick rate`. +The Arduino component requires the FreeRTOS tick rate `CONFIG_FREERTOS_HZ` set to 1000 Hz in `make menuconfig` -> `Component config` -> `FreeRTOS` -> `Tick rate`. Compilation Errors ------------------ -As commits are made to esp-idf and submodules, the codebases can develop incompatibilities that cause compilation errors. If you have problems compiling, follow the instructions in `Issue #1142 `_ to roll esp-idf back to a different version. +As commits are made to ESP-IDF and submodules, the codebases can develop incompatibilities that cause compilation errors. +If you have problems compiling, follow the instructions in `Issue #1142 `_ +to roll ESP-IDF back to a different version. Adding arduino library ---------------------- diff --git a/docs/en/getting_started.rst b/docs/en/getting_started.rst index 13fe99300e7..1b0f1bba87a 100644 --- a/docs/en/getting_started.rst +++ b/docs/en/getting_started.rst @@ -38,17 +38,18 @@ Here are the ESP32 series supported by the Arduino-ESP32 project: SoC Stable Development Datasheet ========== ====== =========== ================================= ESP32 Yes Yes `ESP32`_ -ESP32-S2 Yes Yes `ESP32-S2`_ ESP32-C3 Yes Yes `ESP32-C3`_ -ESP32-S3 Yes Yes `ESP32-S3`_ ESP32-C6 Yes Yes `ESP32-C6`_ ESP32-H2 Yes Yes `ESP32-H2`_ +ESP32-P4 Yes Yes `ESP32-P4`_ +ESP32-S2 Yes Yes `ESP32-S2`_ +ESP32-S3 Yes Yes `ESP32-S3`_ ========== ====== =========== ================================= .. note:: - ESP32-C2 is also supported by Arduino-ESP32 but requires rebuilding the static libraries. - This is not trivial and requires a good understanding of the ESP-IDF build system. - For more information, see the `Lib Builder documentation `_. + ESP32-C2 is also supported by Arduino-ESP32 but requires using Arduino as an ESP-IDF component or rebuilding the static libraries. + For more information, see the `Arduino as an ESP-IDF component documentation `_ or the + `Lib Builder documentation `_, respectively. See `Boards `_ for more details about ESP32 development boards. @@ -64,28 +65,27 @@ Supported Operating Systems --------------------------- +-------------------+-------------------+-------------------+ -| |windows-logo| | |linux-logo| | |macos-logo| | +| |windows-logo| | |linux-logo| | |macOS-logo| | +-------------------+-------------------+-------------------+ | Windows | Linux | macOS | +-------------------+-------------------+-------------------+ .. |windows-logo| image:: ../_static/logo_windows.png .. |linux-logo| image:: ../_static/logo_linux.png -.. |macos-logo| image:: ../_static/logo_macos.png +.. |macOS-logo| image:: ../_static/logo_macos.png Supported IDEs --------------------------- Here is the list of supported IDE for Arduino ESP32 support integration. -+-------------------+-------------------+ -| |arduino-logo| | |pio-logo| | -+-------------------+-------------------+ -| Arduino IDE | PlatformIO | -+-------------------+-------------------+ ++-------------------+ +| |arduino-logo| | ++-------------------+ +| Arduino IDE | ++-------------------+ .. |arduino-logo| image:: ../_static/logo_arduino.png -.. |pio-logo| image:: ../_static/logo_pio.png See `Installing Guides `_ for more details on how to install the Arduino ESP32 support. @@ -103,7 +103,8 @@ Here are some community channels where you may find information and ask for some - `ESP32 Forum`_: Official Espressif Forum. - `ESP32 Forum - Arduino`_: Official Espressif Forum for Arduino related discussions. - `ESP32 Forum - Hardware`_: Official Espressif Forum for Hardware related discussions. -- `Gitter`_ +- `Espressif Developer Portal`_: Official Espressif Developer Portal with tutorials, examples, workshops, and more. +- `Arduino Core for Espressif (Discord)`_: Official Espressif Discord channel for the Arduino Core. - `Espressif MCUs (Discord)`_ - `ESP32 on Reddit`_ @@ -149,12 +150,13 @@ Resources .. _Espressif Systems: https://www.espressif.com .. _Espressif Product Selector: https://products.espressif.com/ +.. _Espressif Developer Portal: https://developer.espressif.com/ .. _Arduino.cc: https://www.arduino.cc/en/Main/Software .. _Arduino Reference: https://www.arduino.cc/reference/en/ .. _ESP32 Forum: https://esp32.com .. _ESP32 Forum - Arduino: https://esp32.com/viewforum.php?f=19 .. _ESP32 Forum - Hardware: https://esp32.com/viewforum.php?f=12 -.. _Gitter: https://gitter.im/espressif/arduino-esp32 +.. _Arduino Core for Espressif (Discord): https://discord.gg/8xY6e9crwv .. _Adafruit (Discord): https://discord.gg/adafruit -.. _Espressif MCUs (Discord): https://discord.gg/nKxMTnkD +.. _Espressif MCUs (Discord): https://discord.com/invite/XqnZPbF .. _ESP32 on Reddit: https://www.reddit.com/r/esp32 diff --git a/docs/en/guides/docs_contributing.rst b/docs/en/guides/docs_contributing.rst index c167c6176d2..20dc4c84cab 100644 --- a/docs/en/guides/docs_contributing.rst +++ b/docs/en/guides/docs_contributing.rst @@ -104,7 +104,7 @@ If everything is ok, you will see some output logs similar to this one: dumping object inventory... done build succeeded. -The HTML pages are in `_build/en/generic/html`. +The HTML pages are in ``_build/en/generic/html``. Sections -------- @@ -316,7 +316,7 @@ After that, you can use the following structure to include the image in the docs You can adjust the ``width`` according to the image size. -Be sure the file size does not exceed 600kB. +Be sure the file size does not exceed 600 kB. Support ******* diff --git a/docs/en/guides/tools_menu.rst b/docs/en/guides/tools_menu.rst index e43e2693f7e..f4ea4929944 100644 --- a/docs/en/guides/tools_menu.rst +++ b/docs/en/guides/tools_menu.rst @@ -66,12 +66,12 @@ Flash Frequency Use this function to select the flash memory frequency. The frequency will be dependent on the memory model. -* **40MHz** -* **80MHz** +* **40 MHz** +* **80 MHz** -If you don't know if your memory supports **80Mhz**, you can try to upload the sketch using the **80MHz** option and watch the log output via the serial monitor. +If you don't know if your memory supports **80 MHz**, you can try to upload the sketch using the **80 MHz** option and watch the log output via the serial monitor. -.. note:: In some boards/SoC, the flash frequency is automatically selected according to the flash mode. In some cases (i.e ESP32-S3), the flash frequency is up to 120MHz. +.. note:: In some boards/SoC, the flash frequency is automatically selected according to the flash mode. In some cases (i.e ESP32-S3), the flash frequency is up to 120 MHz. Flash Mode ********** @@ -95,17 +95,17 @@ Depending on the application, this mode can be changed in order to increase the * **OPI** - Octal I/O * Eight SPI pins are used to write and to read from the flash. -If you don't know how the board flash is physically connected or the flash memory model, try the **QIO** at **80MHz** first. +If you don't know how the board flash is physically connected or the flash memory model, try the **QIO** at **80 MHz** first. Flash Size ********** This option is used to select the flash size. The flash size should be selected according to the flash model used on your board. -* **2MB** (16Mb) -* **4MB** (32Mb) -* **8MB** (64Mb) -* **16MB** (128Mb) +* **2 MB** (16 Mb) +* **4 MB** (32 Mb) +* **8 MB** (64 Mb) +* **16 MB** (128 Mb) If you choose the wrong size, you may have issues when selecting the partition scheme. @@ -118,13 +118,13 @@ Some SoC has embedded flash. The ESP32-S3 is a good example. Example: **ESP32-S3FH4R2** -This particular ESP32-S3 variant comes with 4MB Flash and 2MB PSRAM. +This particular ESP32-S3 variant comes with 4 MB Flash and 2 MB PSRAM. **Options for Embedded Flash** -* **Fx4** 4MB Flash (*QIO*) -* **Fx8** 8MB Flash (*QIO*) -* **V** 1.8V SPI +* **Fx4** 4 MB Flash (*QIO*) +* **Fx8** 8 MB Flash (*QIO*) +* **V** 1.8 V SPI The **x** stands for the temperature range specification. @@ -169,13 +169,13 @@ Some SoC has embedded PSRAM. The ESP32-S3 is a good example. Example: **ESP32-S3FH4R2** -This particular ESP32-S3 comes with 4MB Flash and 2MB PSRAM. +This particular ESP32-S3 comes with 4 MB Flash and 2 MB PSRAM. **Options for Embedded Flash and PSRAM** -* **R2** 2MB PSRAM (*QSPI*) -* **R8** 8MB PSRAM (*OPI*) -* **V** 1.8V SPI +* **R2** 2 MB PSRAM (*QSPI*) +* **R8** 8 MB PSRAM (*OPI*) +* **V** 1.8 V SPI The **x** stands for the temperature range specification. diff --git a/docs/en/index.rst b/docs/en/index.rst index 40b3251c912..1314a8fc78d 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -16,6 +16,7 @@ Here you will find all the relevant information about the project. Guides Tutorials Advanced Utilities + Third Party Tools Migration Guides FAQ Troubleshooting diff --git a/docs/en/installing.rst b/docs/en/installing.rst index 491e8f6d8a4..35342020864 100644 --- a/docs/en/installing.rst +++ b/docs/en/installing.rst @@ -10,6 +10,11 @@ Before Installing We recommend you install the support using your favorite IDE, but other options are available depending on your operating system. To install Arduino-ESP32 support, you can use one of the following options. +.. note:: + Users in China might have troubles with connection and download speeds using GitHub. Please use our Jihulab mirror as the repository source: + + ``https://jihulab.com/esp-mirror/espressif/arduino-esp32.git`` + Installing using Arduino IDE ---------------------------- @@ -32,6 +37,16 @@ This is the way to install Arduino-ESP32 directly from the Arduino IDE. https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json +Users in China might have troubles with connection and download speeds using the links above. Please use our Jihulab mirror: + +- Stable release link:: + + https://jihulab.com/esp-mirror/espressif/arduino-esp32/-/raw/gh-pages/package_esp32_index_cn.json + +- Development release link:: + + https://jihulab.com/esp-mirror/espressif/arduino-esp32/-/raw/gh-pages/package_esp32_dev_index_cn.json + .. note:: Starting with the Arduino IDE version 1.6.4, Arduino allows installation of third-party platform packages using Boards Manager. We have packages available for Windows, macOS, and Linux. @@ -63,92 +78,6 @@ To start the installation process using the Boards Manager, follow these steps: - Restart Arduino IDE. -Installing using PlatformIO ---------------------------- - -.. figure:: ../_static/logo_pio.png - :align: center - :width: 200 - :figclass: align-center - -PlatformIO is a professional collaborative platform for embedded development. It has out-of-the-box support for ESP32 SoCs and allows working with Arduino ESP32 as well as ESP-IDF from Espressif without changing your development environment. PlatformIO includes lots of instruments for the most common development tasks such as debugging, unit testing, and static code analysis. - -.. warning:: Integration of the Arduino Core ESP32 project in PlatformIO is maintained by PlatformIO developers. Arduino Core ESP32 Project Team cannot support PlatformIO-specific issues. Please report these issues in official `PlatformIO repositories `_. - -A detailed overview of the PlatformIO ecosystem and its philosophy can be found in `the official documentation `_. - -PlatformIO can be used in two flavors: - -- `PlatformIO IDE `_ is a toolset for embedded C/C++ development available on Windows, macOS and Linux platforms - -- `PlatformIO Core (CLI) `_ is a command-line tool that consists of a multi-platform build system, platform and library managers and other integration components. It can be used with a variety of code development environments and allows integration with cloud platforms and web services - -To install PlatformIO, you can follow this Getting Started, provided at `docs.platformio.org`_. - -Using the stable code -********************* - -.. note:: - A detailed overview of supported development boards, examples and frameworks can be found on `the official Espressif32 dev-platform page `_ in the PlatformIO Registry. - -The most reliable and easiest way to get started is to use the latest stable version of the ESP32 development platform that passed all tests/verifications and can be used in production. - -Create a new project and select one of the available boards. You can change after by changing the `platformio.ini `_ file. - -- For ESP32 - -.. code-block:: bash - - [env:esp32dev] - platform = espressif32 - board = esp32dev - framework = arduino - -- For ESP32-S2 (ESP32-S2-Saola-1 board) - -.. code-block:: bash - - [env:esp32-s2-saola-1] - platform = espressif32 - board = esp32-s2-saola-1 - framework = arduino - -- For ESP32-C3 (ESP32-C3-DevKitM-1 board) - -.. code-block:: bash - - [env:esp32-c3-devkitm-1] - platform = espressif32 - board = esp32-c3-devkitm-1 - framework = arduino - -How to update to the latest code -******************************** - -To test the latest Arduino ESP32, you need to change your project *platformio.ini* accordingly. -The following configuration uses the upstream version of the Espressif development platform and the latest Arduino core directly from the Espressif GitHub repository: - -.. code-block:: bash - - [env:esp32-c3-devkitm-1] - platform = https://github.com/platformio/platform-espressif32.git - board = esp32-c3-devkitm-1 - framework = arduino - platform_packages = - framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#master - - -To get more information about PlatformIO, see the following links: - -- `PlatformIO Core (CLI) `_ - -- `PlatformIO Home `_ - -- `Tutorials and Examples `_ - -- `Library Management `_ - - Windows (manual installation) ----------------------------- @@ -355,9 +284,8 @@ Where ``~/Documents/Arduino`` represents your sketch book location as per "Ardui - Try ``python3`` instead of ``python`` if you get the error: ``IOError: [Errno socket error] [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:590)`` when running ``python get.py`` -- If you get the following error when running ``python get.py`` urllib.error.URLError: Applications > Python3.6 folder (or any other python version), and run the following scripts: Install Certificates.command and Update Shell Profile.command +- If you get the following error when running ``python get.py``: ``urllib.error.URLError: Applications > Python3.6 folder (or any other python version)``, and run the following scripts: Install Certificates.command and Update Shell Profile.command - Restart Arduino IDE. .. _Arduino.cc: https://www.arduino.cc/en/Main/Software -.. _docs.platformio.org: https://docs.platformio.org/en/latest/integration/ide/pioide.html diff --git a/docs/en/lib_builder.rst b/docs/en/lib_builder.rst index fb1a9b189ee..e7edb331fd3 100644 --- a/docs/en/lib_builder.rst +++ b/docs/en/lib_builder.rst @@ -5,7 +5,7 @@ Library Builder About ----- -Espressif provides a `tool `_ to simplify building your own compiled libraries for use in Arduino IDE (or your favorite IDE). +Espressif provides a macOS and Linux `tool `_ to simplify building your own compiled libraries for use in Arduino IDE (or your favorite IDE). This tool can be used to change the project or a specific configuration according to your needs. @@ -151,12 +151,13 @@ Set the build target(chip). ex. 'esp32s3' This build command will build for the ESP32-S3 target. You can specify other targets. * esp32 -* esp32s2 -* esp32s3 * esp32c2 * esp32c3 * esp32c6 * esp32h2 +* esp32p4 +* esp32s2 +* esp32s3 Set Build Type ^^^^^^^^^^^^^^ @@ -172,7 +173,7 @@ Set the build type. ex. 'build' to build the project and prepare for uploading t Additional Configuration ^^^^^^^^^^^^^^^^^^^^^^^^ -Specify additional configs to be applied. ex. 'qio 80m' to compile for QIO Flash@80MHz. +Specify additional configs to be applied. ex. ``qio 80m`` to compile for QIO Flash at 80 MHz. .. note:: This command requires the ``-b`` to work properly. @@ -181,6 +182,73 @@ Specify additional configs to be applied. ex. 'qio 80m' to compile for QIO Flash ./build.sh -t esp32 -b idf_libs qio 80m +User Interface +-------------- + +Starting from ``arduino-esp32`` version 3.0.0 (IDF v5.1), there is also a terminal user interface that can be used +to configure the libraries to be compiled. + +It allows the user to select the targets to compile, change the configuration options and compile the libraries. +It has mouse support and can be pre-configured using command line arguments. + +For more information and troubleshooting, check `the documentation `_. + +To use the terminal user interface, make sure to have ``python>=3.9``, all the previous dependencies and install the ``textual`` library: + +.. code-block:: bash + + pip install --user textual + +You can then run the UI using the following command: + +.. code-block:: bash + + ./tools/config_editor/app.py + +Pre-Configuring the UI +********************** + +The UI can be pre-configured using command line arguments. The following arguments are available: + +- ``-t, --target ``: Comma-separated list of targets to be compiled. + Choose from: *all*, *esp32*, *esp32s2*, *esp32s3*, *esp32c2*, *esp32c3*, *esp32c6*, *esp32h2*. Default: all except *esp32c2*; +- ``--copy, --no-copy``: Enable/disable copying the compiled libraries to ``arduino-esp32``. Enabled by default; +- ``-c, --arduino-path ``: Path to ``arduino-esp32`` directory. Default: OS dependent; +- ``-A, --arduino-branch ``: Branch of the ``arduino-esp32`` repository to be used. Default: set by the build script; +- ``-I, --idf-branch ``: Branch of the ``ESP-IDF`` repository to be used. Default: set by the build script; +- ``-i, --idf-commit ``: Commit of the ``ESP-IDF`` repository to be used. Default: set by the build script; +- ``-D, --debug-level ``: Debug level to be set in ``ESP-IDF``. + Choose from: *default*, *none*, *error*, *warning*, *info*, *debug*, *verbose*. Default: *default*. + +Please note that all these options can be changed in the UI itself and are only used for automation purposes. + +Screens +******* + +There are many screens in the UI that are used to configure the libraries to be compiled. +Note that in all screens you can also use the shortcut keys shown in the footer bar to navigate. + +The UI consists of the following screens: + +- **Main Menu**: The main screen shows buttons to navigate to the other screens. +- **Compile Screen**: The compile screen shows the output of the compilation process and any errors that may have occurred. +- **Sdkconfig Editor**: The sdkconfig editor screen is a simple text editor that shows you the sdkconfig files that will be used for compilation. + You can edit the files here to customize the generated libraries. +- **Settings Screen**: The settings screen allows you to change the settings of the compilation process. + Here you can change: + + - The targets that the libraries will be compiled for. To save time, you can compile the libraries only for the target you are using; + - Whether the compiled libraries will be copied to the ``arduino-esp32`` directory after compilation so that they can be used in the Arduino IDE; + - The path to the ``arduino-esp32`` directory. This will be automatically set if the ``arduino-esp32`` repository is in one of the default locations. + If not, you can set it manually here. If using the docker image, it should not be changed as the mount point is fixed; + - The branch of the ``arduino-esp32`` repository to be used. This is useful if you want to compile the libraries for a + specific branch or pull request of the ``arduino-esp32`` repository. Leave empty to use the default branch for this ``ESP-IDF`` version; + - The branch of the ``ESP-IDF`` repository to be used. This is useful if you want to compile the libraries for a specific branch of the ``ESP-IDF`` repository. + Leave empty to use the default branch for this IDF version; + - The commit of the ``ESP-IDF`` repository to be used. This is useful if you want to compile the libraries for a specific commit on the selected branch. + Leave empty to use the latest commit; + - The debug level to be set in ``ESP-IDF``. + Docker Image ------------ @@ -194,15 +262,16 @@ The current supported architectures by the Docker image are: .. note:: Building the libraries using the Docker image is much slower than building them natively on the host machine. - It is recommended to use the Docker image only when the host machine does not meet the requirements for building the libraries. + It is recommended to use the Docker image only when the host machine does not meet the requirements for building the libraries (e.g., building on Windows). Tags **** Multiple tags of this image are maintained: -- ``latest``: tracks ``master`` branch of the Lib Builder -- ``release-vX.Y``: tracks ``release/vX.Y`` branch of the Lib Builder +- ``latest``: tracks ``master`` branch of the Lib Builder. Note that the ``latest`` tag is not recommended for use as, depending on the + development stage of the Lib Builder, it might not be stable or might not contain the latest changes; +- ``release-vX.Y``: tracks ``release/vX.Y`` branch of the Lib Builder. .. note:: Versions of Lib Builder released before this feature was introduced do not have corresponding Docker image versions. @@ -211,7 +280,7 @@ Multiple tags of this image are maintained: Usage ***** -Before using the ``espressif/esp32-arduino-lib-builder`` Docker image locally, make sure you have Docker installed. +Before using the ``espressif/esp32-arduino-lib-builder`` Docker image locally, make sure you have Docker installed and running on your machine. Follow the instructions at https://docs.docker.com/install/, if it is not installed yet. If using the image in a CI environment, consult the documentation of your CI service on how to specify the image used for the build process. @@ -225,7 +294,7 @@ To run the Docker image manually, use the following command from the root of the .. code-block:: bash - docker run --rm -it -v $PWD:/arduino-esp32 -e TERM=xterm-256color espressif/esp32-arduino-lib-builder + docker run --rm -it -v $PWD:/arduino-esp32 -e TERM=xterm-256color espressif/esp32-arduino-lib-builder:release-v5.1 This will start the Lib Builder UI for compiling the libraries. The above command explained: @@ -235,7 +304,8 @@ This will start the Lib Builder UI for compiling the libraries. The above comman - ``-t`` Allocate a pseudo-TTY; - ``-e TERM=xterm-256color``: Optional. Sets the terminal type to ``xterm-256color`` to display colors correctly; - ``-v $PWD:/arduino-esp32``: Optional. Mounts the current folder at ``/arduino-esp32`` inside the container. If not provided, the container will not copy the compiled libraries to the host machine; -- ``espressif/esp32-arduino-lib-builder``: uses Docker image ``espressif/esp32-arduino-lib-builder`` with tag ``latest``. The ``latest`` tag is implicitly added by Docker when no tag is specified. +- ``espressif/esp32-arduino-lib-builder:release-v5.1``: uses Docker image ``espressif/esp32-arduino-lib-builder`` with tag ``release-v5.1``. + The ``latest`` tag is implicitly added by Docker when no tag is specified. It is recommended to use a specific version tag to ensure reproducibility of the build process. .. warning:: The ``-v`` option is used to mount a folder from the host machine to the container. Make sure the folder already exists on the host machine before running the command. @@ -255,14 +325,15 @@ For example, to run a terminal inside the container, you can run: .. code-block:: bash - docker run -it espressif/esp32-arduino-lib-builder:latest /bin/bash + docker run -it espressif/esp32-arduino-lib-builder:release-v5.1 /bin/bash Running the Docker image using the provided run script will depend on the host OS. -Use the following command from the root of the ``arduino-esp32`` repository to execute the image in a Linux or macOS environment: +Use the following command from the root of the ``arduino-esp32`` repository to execute the image in a Linux or macOS environment for +the ``release-v5.1`` tag: .. code-block:: bash - curl -LJO https://raw.githubusercontent.com/espressif/esp32-arduino-lib-builder/master/tools/docker/run.sh + curl -LJO https://raw.githubusercontent.com/espressif/esp32-arduino-lib-builder/refs/heads/release/v5.1/tools/docker/run.sh chmod +x run.sh ./run.sh $PWD @@ -270,9 +341,16 @@ For Windows, use the following command in PowerShell from the root of the ``ardu .. code-block:: powershell - Invoke-WebRequest -Uri "https://raw.githubusercontent.com/espressif/esp32-arduino-lib-builder/master/tools/docker/run.ps1" -OutFile "run.ps1" + Invoke-WebRequest -Uri "https://raw.githubusercontent.com/espressif/esp32-arduino-lib-builder/refs/heads/release/v5.1/tools/docker/run.ps1" -OutFile "run.ps1" .\run.ps1 $pwd +As the script is unsigned, you may need to change the execution policy of the current session before running the script. +To do so, run the following command in PowerShell: + +.. code-block:: powershell + + Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass + .. warning:: It is always a good practice to understand what the script does before running it. Make sure to analyze the content of the script to ensure it is safe to run and won't cause any harm to your system. diff --git a/docs/en/libraries.rst b/docs/en/libraries.rst index 0e3499f7783..525a5c4ba26 100644 --- a/docs/en/libraries.rst +++ b/docs/en/libraries.rst @@ -9,60 +9,68 @@ Supported Peripherals Currently, the Arduino ESP32 supports the following peripherals with Arduino APIs. -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| Peripheral | ESP32 | S2 | C3 | S3 | C6 | H2 | Notes | -+===============+=======+=======+=======+=======+=======+=======+=======+ -| ADC | Yes | Yes | Yes | Yes | Yes | Yes | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| BT Classic | Yes | N/A | N/A | N/A | N/A | N/A | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| BLE | Yes | N/A | Yes | Yes | Yes | Yes | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| DAC | Yes | Yes | N/A | N/A | N/A | N/A | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| Ethernet | Yes | N/A | N/A | N/A | N/A | N/A | (*) | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| GPIO | Yes | Yes | Yes | Yes | Yes | Yes | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| Hall Sensor | N/A | N/A | N/A | N/A | N/A | N/A | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| I2C | Yes | Yes | Yes | Yes | Yes | Yes | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| I2S | Yes | Yes | Yes | Yes | Yes | Yes | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| LEDC | Yes | Yes | Yes | Yes | Yes | Yes | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| Motor PWM | No | N/A | N/A | N/A | N/A | N/A | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| Pulse Counter | No | No | No | No | No | No | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| RMT | Yes | Yes | Yes | Yes | Yes | Yes | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| SDIO | No | No | No | No | No | No | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| SDMMC | Yes | N/A | N/A | Yes | N/A | N/A | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| Timer | Yes | Yes | Yes | Yes | Yes | Yes | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| Temp. Sensor | N/A | Yes | Yes | Yes | Yes | Yes | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| Touch | Yes | Yes | N/A | Yes | N/A | N/A | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| TWAI | No | No | No | No | No | No | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| UART | Yes | Yes | Yes | Yes | Yes | Yes | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| USB | N/A | Yes | Yes | Yes | Yes | Yes | (**) | -+---------------+-------+-------+-------+-------+-------+-------+-------+ -| Wi-Fi | Yes | Yes | Yes | Yes | Yes | N/A | | -+---------------+-------+-------+-------+-------+-------+-------+-------+ ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| Peripheral | ESP32 | C3 | C6 | H2 | P4 | S2 | S3 | Notes | ++===============+=======+=======+=======+=======+=======+=======+=======+=======+ +| ADC | Yes | Yes | Yes | Yes | Yes | Yes | Yes | (1) | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| BT Classic | Yes | N/A | N/A | N/A | N/A | N/A | N/A | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| BLE | Yes | Yes | Yes | Yes | No | N/A | Yes | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| DAC | Yes | N/A | N/A | N/A | Yes | Yes | N/A | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| Ethernet | Yes | N/A | N/A | N/A | Yes | N/A | N/A | (2) | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| GPIO | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| Hall Sensor | N/A | N/A | N/A | N/A | N/A | N/A | N/A | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| I2C | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| I2S | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| LEDC | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| MIPI | N/A | N/A | N/A | N/A | No | N/A | N/A | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| Motor PWM | No | N/A | N/A | N/A | N/A | N/A | N/A | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| MSPI | N/A | N/A | N/A | N/A | No | N/A | N/A | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| Pulse Counter | No | No | No | No | No | No | No | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| RMT | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| SDIO | No | No | No | No | No | No | No | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| SDMMC | Yes | N/A | N/A | N/A | N/A | N/A | Yes | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| Timer | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| Temp. Sensor | N/A | Yes | Yes | Yes | Yes | Yes | Yes | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| Touch | Yes | N/A | N/A | N/A | Yes | Yes | Yes | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| TWAI | No | No | No | No | No | No | No | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| UART | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| USB | N/A | Yes | Yes | Yes | Yes | Yes | Yes | (3) | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ +| Wi-Fi | Yes | Yes | Yes | N/A | Yes | Yes | Yes | (4) | ++---------------+-------+-------+-------+-------+-------+-------+-------+-------+ Notes ^^^^^ -(*) SPI Ethernet is supported by all ESP32 families and RMII only for ESP32. +(1) ESP32-P4 calibration schemes not supported yet in IDF and ADC Continuous also lacks IDF support. -(**) ESP32-C3, C6, H2 only support USB CDC/JTAG +(2) SPI Ethernet is supported by all ESP32 families and RMII only for ESP32 and ESP32-P4. + +(3) ESP32-C3, C6, H2 only support USB CDC/JTAG + +(4) ESP32-P4 only supports Wi-Fi through another SoC by using ``esp_hosted``. .. note:: Some peripherals are not available for all ESP32 families. To see more details about it, see the corresponding SoC at `Product Selector `_ page. diff --git a/docs/en/migration_guides/2.x_to_3.0.rst b/docs/en/migration_guides/2.x_to_3.0.rst index bb6cab294cc..a7730ceb1b4 100644 --- a/docs/en/migration_guides/2.x_to_3.0.rst +++ b/docs/en/migration_guides/2.x_to_3.0.rst @@ -217,8 +217,8 @@ Functional changes * ``begin(baud)`` will not change any pins that have been set before this call, through a previous ``begin(baud, rx, tx)`` or ``setPin()``. * If the application only uses RX or TX, ``begin(baud, -1, tx)`` or ``begin(baud, rx)`` will change only the assigned pin and keep the other unchanged. -WiFi -**** +Wi-Fi +***** Functional changes ^^^^^^^^^^^^^^^^^^ diff --git a/docs/en/third_party/pioarduino.rst b/docs/en/third_party/pioarduino.rst new file mode 100644 index 00000000000..49af583befa --- /dev/null +++ b/docs/en/third_party/pioarduino.rst @@ -0,0 +1,14 @@ +####################################################### +pioarduino - (p)eople (i)nitiated (o)ptimized (arduino) +####################################################### + +.. warning:: + This tool is **not maintained by the ESP32 Arduino Core team**, so we cannot provide support or guarantee that it will work as expected. + +.. note:: + This is a work in progress documentation and we will appreciate your help! We are looking for contributors! + +About +----- + +For more information, please refer to the `official documentation `_. diff --git a/docs/en/third_party/wokwi.rst b/docs/en/third_party/wokwi.rst new file mode 100644 index 00000000000..0a6eb9d0992 --- /dev/null +++ b/docs/en/third_party/wokwi.rst @@ -0,0 +1,42 @@ +##### +Wokwi +##### + +.. warning:: + This tool is **not maintained by the ESP32 Arduino Core team**, so we cannot provide support or guarantee that it will work as expected. + +.. note:: + This is a work in progress documentation and we will appreciate your help! We are looking for contributors! + +About +----- + +Wokwi is an online Electronics simulator. You can use it to simulate Arduino, ESP32, and many other popular boards, parts and sensors. + +The advantages of using Wokwi include: + +- Immediate start: No need to wait for components or download large software. Everything required is available in your browser, enabling you to begin coding your IoT project within seconds. +- Safe experimentation: Virtual hardware cannot be damaged, allowing users to experiment freely without the risk of destroying components. Mistakes can be easily undone. +- Easy collaboration: Sharing a link to your Wokwi project facilitates obtaining help and feedback from others. +- Code reliability: Helps in distinguishing between hardware and software issues, thereby increasing confidence in your code. +- Unlimited resources: Access to an unlimited number of parts without concerns about cost or availability. +- Supportive community: A maker-friendly environment where users can share projects, seek assistance, and find inspiration. + +Unique features provided by Wokwi: + +- Wi-Fi simulation - Connect your simulated project to the internet. You can use MQTT, HTTP, NTP, and many other network protocols. +- Virtual Logic Analyzer - Capture digital signals in your simulation (e.g. UART, I2C, SPI) and analyze them on your computer. +- Advanced debugging with GDB - Powerful Arduino debugger for advanced users. +- SD card simulation - Store and retrieve files and directories from your code. Paying users can also upload binary files (such as images) +- Chips API - Create your own custom chips and parts, and share them with the community. +- Visual Studio Code integration - Simulate your embedded projects directly from VS Code. + +Pricing +------- + +Wokwi is free for personal use. For commercial users and professionals, please check out the paid plans in the `pricing page `_. + +Learn more +---------- + +For more information, please refer to the `official Wokwi website `_ and the `Wokwi documentation `_. diff --git a/docs/en/third_party_tools.rst b/docs/en/third_party_tools.rst new file mode 100644 index 00000000000..fd8fd92ae0c --- /dev/null +++ b/docs/en/third_party_tools.rst @@ -0,0 +1,16 @@ +################# +Third Party Tools +################# + +Here you will find documentation pages for third party tools that can be used with the ESP32 Arduino Core. + +.. warning:: + These tools are **not maintained by the ESP32 Arduino Core team**, so we cannot provide support or guarantee that they will work as expected. + Each tool documentation should be provided and maintained by the community. + +.. toctree:: + :maxdepth: 1 + :caption: Contents: + + pioarduino + Wokwi diff --git a/docs/en/troubleshooting.rst b/docs/en/troubleshooting.rst index b80b50203db..ea9a6db94d6 100644 --- a/docs/en/troubleshooting.rst +++ b/docs/en/troubleshooting.rst @@ -14,6 +14,23 @@ Installing Here are the common issues during the installation. +Slow or unstable downloads +************************** + +Users in China might have troubles with connection and download speeds using GitHub. Please use our Jihulab mirror as the repository source: + +`https://jihulab.com/esp-mirror/espressif/arduino-esp32.git `_ + +JSON files for the boards manager are available here: + +- Stable release:: + + https://jihulab.com/esp-mirror/espressif/arduino-esp32/-/raw/gh-pages/package_esp32_index_cn.json + +- Development release:: + + https://jihulab.com/esp-mirror/espressif/arduino-esp32/-/raw/gh-pages/package_esp32_dev_index_cn.json + Building -------- @@ -62,8 +79,8 @@ Here are some steps that you can try: * Make sure that nothing is connected to pins labeled **TX** and **RX**. Please refer to the pin layout table - some TX and RX pins may not be labeled on the dev board. * In some instances, you must keep **GPIO0** LOW during the uploading process via the serial interface. * Hold down the **“BOOT”** button on your ESP32 board while uploading/flashing. -* Solder a **10uF** capacitor in parallel with **RST** and **GND**. -* If you are using external power connected to pins, it is easy to confuse pins **CMD** (which is usually next to the 5V pin) and **GND**. +* Solder a **10 uF** capacitor in parallel with **RST** and **GND**. +* If you are using external power connected to pins, it is easy to confuse pins **CMD** (which is usually next to the ``5V`` pin) and **GND**. In some development boards, you can try adding the reset delay circuit, as described in the *Power-on Sequence* section on the `ESP32 Hardware Design Guidelines `_ to get into the download mode automatically. @@ -131,7 +148,7 @@ I have uploaded firmware to the ESP32 device, but I don't see any response from Solution ^^^^^^^^ -Newer ESP32 variants have two possible USB connectors- USB and UART. The UART connector will go through a USB->UART adapter, and will typically present itself with the name of that mfr (eg, Silicon Labs CP210x UART Bridge). The USB connector can be used as a USB-CDC bridge and will appear as an Espressif device (Espressif USB JTAG/serial debug unit). On Espressif devkits, both connections are available, and will be labeled. ESP32 can only use UART, so will only have one connector. Other variants with one connector will typically be using USB. Please check in the product [datasheet](https://products.espressif.com) or [hardware guide](https://www.espressif.com/en/products/devkits) to find Espressif products with the appropriate USB connections for your needs. +Newer ESP32 variants have two possible USB connectors - USB and UART. The UART connector will go through a USB->UART adapter, and will typically present itself with the name of that mfr (eg, Silicon Labs CP210x UART Bridge). The USB connector can be used as a USB-CDC bridge and will appear as an Espressif device (Espressif USB JTAG/serial debug unit). On Espressif devkits, both connections are available, and will be labeled. ESP32 can only use UART, so will only have one connector. Other variants with one connector will typically be using USB. Please check in the product [datasheet](https://products.espressif.com) or [hardware guide](https://www.espressif.com/en/products/devkits) to find Espressif products with the appropriate USB connections for your needs. If you use the UART connector, you should disable USB-CDC on boot under the Tools menu (-D ARDUINO_USB_CDC_ON_BOOT=0). If you use the USB connector, you should have that enabled (-D ARDUINO_USB_CDC_ON_BOOT=1) and set USB Mode to "Hardware CDC and JTAG" (-D ARDUINO_USB_MODE=0). USB-CDC may not be able to initialize in time to catch all the data if your device is in a tight reboot loop. This can make it difficult to troubleshoot initialization issues. diff --git a/docs/en/tutorials/blink.rst b/docs/en/tutorials/blink.rst index b5f6a767f8d..f4a53ec945d 100644 --- a/docs/en/tutorials/blink.rst +++ b/docs/en/tutorials/blink.rst @@ -7,7 +7,7 @@ Introduction This is the interactive blink tutorial using `Wokwi`_. For this tutorial, you don't need the ESP32 board or the Arduino toolchain. -.. note:: If you don't want to use this tutorial with the simulation, you can copy and paste the :ref:`blink_example_code` from `Wokwi`_ editor and use it on the `Arduino IDE`_ or `PlatformIO`_. +.. note:: If you don't want to use this tutorial with the simulation, you can copy and paste the :ref:`blink_example_code` from `Wokwi`_ editor and use it on the `Arduino IDE`. About this Tutorial ------------------- @@ -109,5 +109,4 @@ Resources .. _ESP32 Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf .. _Wokwi: https://wokwi.com/ -.. _PlatformIO: https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html#platformio .. _Arduino IDE: https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html#installing-using-boards-manager diff --git a/docs/en/tutorials/cdc_dfu_flash.rst b/docs/en/tutorials/cdc_dfu_flash.rst index 1c291edac73..0c54e38d67b 100644 --- a/docs/en/tutorials/cdc_dfu_flash.rst +++ b/docs/en/tutorials/cdc_dfu_flash.rst @@ -66,8 +66,8 @@ Go to the Tools menu in the Arduino IDE and set the following options: * USB DFU On Boot -> Enabled -Setp 3 - Flash -^^^^^^^^^^^^^^ +3. Flash +^^^^^^^^ Now you can upload your sketch to the device. After flashing, you need to manually reset the device. diff --git a/docs/en/tutorials/partition_table.rst b/docs/en/tutorials/partition_table.rst index b267461bd1c..fdaee9f9bbb 100644 --- a/docs/en/tutorials/partition_table.rst +++ b/docs/en/tutorials/partition_table.rst @@ -39,25 +39,25 @@ Where: ``ota`` The ota subtype is used to store the OTA information. This partition is used only when the OTA is used to select the initialization partition, otherwise no need to add it to your custom partition table. - The size of this partition should be a fixed size of 8kB (0x2000 bytes). + The size of this partition should be a fixed size of 8 kB (0x2000 bytes). ``nvs`` - The nvs partition subtype is used to define the partition to store general data, like the WiFi data, device PHY calibration data and any other data to be stored on the non-volatile memory. + The nvs partition subtype is used to define the partition to store general data, like the Wi-Fi data, device PHY calibration data and any other data to be stored on the non-volatile memory. This kind of partition is suitable for small custom configuration data, cloud certificates, etc. Another usage for the NVS is to store sensitive data, since the NVS supports encryption. - It is highly recommended to add at least one nvs partition, labeled with the name nvs, in your custom partition tables with size of at least 12kB (0x3000 bytes). If needed, you can increase the size of the nvs partition. - The recommended size for this partition is from 12kb to 64kb. Although larger NVS partitions can be defined, we recommend using FAT or SPIFFS filesystem for storage of larger amounts of data. + It is highly recommended to add at least one nvs partition, labeled with the name nvs, in your custom partition tables with size of at least 12 kB (0x3000 bytes). If needed, you can increase the size of the nvs partition. + The recommended size for this partition is from 12 kB to 64 kB. Although larger NVS partitions can be defined, we recommend using FAT or SPIFFS filesystem for storage of larger amounts of data. ``coredump`` The coredump partition subtype is used to store the core dump on the flash. The core dump is used to analyze critical errors like crash and panic. This function must be enabled in the project configuration menu and set the data destination to flash. - The recommended size for this partition is 64kB (0x10000). + The recommended size for this partition is 64 kB (0x10000). ``nvs_keys`` The nvs_keys partition subtype is used to store the keys when the NVS encryption is used. - The size for this partition is 4kB (0x1000). + The size for this partition is 4 kB (0x1000). ``fat`` @@ -90,7 +90,7 @@ Where: The offset defines the partition start address. The offset is defined by the sum of the offset and the size of the earlier partition. .. note:: - Offset must be multiple of 4kB (0x1000) and for app partitions it must be aligned by 64kB (0x10000). + Offset must be multiple of 4 kB (0x1000) and for app partitions it must be aligned by 64 kB (0x10000). If left blank, the offset will be automatically calculated based on the end of the previous partition, including any necessary alignment, however, the offset for the first partition must be always set as **0x9000** and for the first application partition **0x10000**. 5. **Size** @@ -129,13 +129,13 @@ Here is an example you can use for a custom partition table: app1, app, ota_1, , 2M, spiffs, data, spiffs, , 8M, -This partition will use about 12MB of the 16MB flash. The offset will be automatically calculated after the first application partition and the units are in K and M. +This partition will use about 12 MB of the 16 MB flash. The offset will be automatically calculated after the first application partition and the units are in K and M. An alternative is to create the new partition table as a new file in the `tools/partitions `_ folder and edit the `boards.txt `_ file to add your custom partition table. Another alternative is to create the new partition table as a new file, and place it in the `variants `_ folder under your boards folder, and edit the `boards.txt `_ file to add your custom partition table, noting that in order for the compiler to find your custom partition table file you must use the '.build.custom_partitions=' option in the boards.txt file, rather than the standard '.build.partitions=' option. The '.build.variant=' option has the name of the folder holding your custom partition table in the variants folder. -An example of the PartitionScheme listing using the ESP32S3 Dev Module as a reference, would be to have the following: +An example of the PartitionScheme listing using the ESP32-S3 Dev Module as a reference, would be to have the following: **Custom Partition - CSV file in /variants/custom_esp32s3/ folder** @@ -150,7 +150,7 @@ An example of the PartitionScheme listing using the ESP32S3 Dev Module as a refe Examples -------- -**2MB no OTA** +**2 MB no OTA** .. code-block:: @@ -158,7 +158,7 @@ Examples nvs, data, nvs, 36K, 20K, factory, app, factory, 64K, 1900K, -**4MB no OTA** +**4 MB no OTA** .. code-block:: @@ -166,7 +166,7 @@ Examples nvs, data, nvs, 36K, 20K, factory, app, factory, 64K, 4000K, -**4MB with OTA** +**4 MB with OTA** .. code-block:: @@ -176,7 +176,7 @@ Examples app0, app, ota_0, 64K, 1900K, app1, app, ota_1, , 1900K, -**8MB no OTA with Storage** +**8 MB no OTA with Storage** .. code-block:: @@ -185,7 +185,7 @@ Examples factory, app, factory, 64K, 2M, spiffs, data, spiffs, , 5M, -**8MB with OTA and Storage** +**8 MB with OTA and Storage** .. code-block:: diff --git a/docs/en/tutorials/preferences.rst b/docs/en/tutorials/preferences.rst index dd27913c38f..9354fa83b16 100644 --- a/docs/en/tutorials/preferences.rst +++ b/docs/en/tutorials/preferences.rst @@ -70,16 +70,16 @@ Preferences directly supports the following data types: +-------------------+-------------------+---------------+ | ULong | uint32_t | 4 | +-------------------+-------------------+---------------+ + | Float | float_t | 4 | + +-------------------+-------------------+---------------+ | Long64 | int64_t | 8 | +-------------------+-------------------+---------------+ | ULong64 | uint64_t | 8 | +-------------------+-------------------+---------------+ - | Float | float_t | 8 | - +-------------------+-------------------+---------------+ | Double | double_t | 8 | +-------------------+-------------------+---------------+ - | | const char* | | - | String +-------------------+ variable | + | | const char* | variable | + | String +-------------------+ | | | String | | +-------------------+-------------------+---------------+ | Bytes | uint8_t | variable | @@ -233,9 +233,9 @@ Like so: .. code-block:: arduino - float myFloat = myPreferences.getFloat("pi"); + float_t myFloat = myPreferences.getFloat("pi"); -This will retrieve the float value from the namespace key ``"pi"`` and assign it to the float type variable ``myFloat``. +This will retrieve the float_t value from the namespace key ``"pi"`` and assign it to the float_t type variable ``myFloat``. Summary @@ -386,7 +386,7 @@ To send to the serial monitor the number of available entries the following coul The number of available entries in the key table changes depending on the number of keys in the namespace and also the dynamic size of certain types of data stored in the namespace. Details are in the `Preferences API Reference`_. -Do note that the number of entries in the key table does not guarantee that there is room in the opened NVS namespace for all the data to be stored in that namespace. Refer to the espressif `Non-volatile storage library`_ documentation for full details. +Do note that the number of entries in the key table does not guarantee that there is room in the opened NVS namespace for all the data to be stored in that namespace. Refer to the Espressif `Non-volatile storage library`_ documentation for full details. Determining the Type of a key-value Pair @@ -565,7 +565,7 @@ If you need to access a different namespace, close the one before opening the ot currentNamespace.end(); // closes 'myNamespace' - currentNamespace.begin("myOtherNamespace", false); // opens a different Preferences namesspace. + currentNamespace.begin("myOtherNamespace", false); // opens a different Preferences namespace. // do other stuff... currentNamespace.end(); // closes 'myOtherNamespace' @@ -644,7 +644,7 @@ Returning to the example above: .. -will assign to the variable ``dessert`` the String ``gravel`` if an error occurred, or the value stored against the key ``favourites`` if not. +will assign to the variable ``dessert`` the String ``gravel`` if an error occurred, or the value stored against the key ``favorites`` if not. If we predetermine a default value that is outside all legitimate values, we now have a way to test if an error actually occurred. diff --git a/docs/requirements.txt b/docs/requirements.txt index 71b14c5c135..d3017fb5adc 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,5 @@ esp-docs>=1.4.0 sphinx-copybutton==0.5.0 sphinx-tabs==3.2.0 +numpydoc==1.5.0 +standard-imghdr==3.13.0 diff --git a/docs/utils.sh b/docs/utils.sh index 84f37489975..3a860ac8a2c 100644 --- a/docs/utils.sh +++ b/docs/utils.sh @@ -1,18 +1,19 @@ +#!/bin/bash # Bash helper functions for adding SSH keys -function add_ssh_keys() { - local key_string="${1}" - mkdir -p ~/.ssh - chmod 700 ~/.ssh - echo -n "${key_string}" >~/.ssh/id_rsa_base64 - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 >~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa +function add_ssh_keys { + local key_string="${1}" + mkdir -p ~/.ssh + chmod 700 ~/.ssh + echo -n "${key_string}" >~/.ssh/id_rsa_base64 + base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 >~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa } -function add_doc_server_ssh_keys() { - local key_string="${1}" - local server_url="${2}" - local server_user="${3}" - add_ssh_keys "${key_string}" - echo -e "Host ${server_url}\n\tStrictHostKeyChecking no\n\tUser ${server_user}\n" >>~/.ssh/config +function add_doc_server_ssh_keys { + local key_string="${1}" + local server_url="${2}" + local server_user="${3}" + add_ssh_keys "${key_string}" + echo -e "Host ${server_url}\n\tStrictHostKeyChecking no\n\tUser ${server_user}\n" >>~/.ssh/config } diff --git a/idf_component.yml b/idf_component.yml index a9bc90f8788..967c4ecf0f6 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -9,6 +9,7 @@ targets: - esp32c3 - esp32c6 - esp32h2 + - esp32p4 tags: - arduino files: @@ -20,6 +21,7 @@ files: - "variants/esp32c3/**/*" - "variants/esp32c6/**/*" - "variants/esp32h2/**/*" + - "variants/esp32p4/**/*" exclude: - "docs/" - "docs/**/*" @@ -42,7 +44,7 @@ files: - "platform.txt" - "programmers.txt" dependencies: - idf: ">=5.1,<5.2" + idf: ">=5.3,<5.5" # mdns 1.2.1 is necessary to build H2 with no WiFi espressif/mdns: version: "^1.2.3" @@ -50,40 +52,70 @@ dependencies: espressif/esp_modem: version: "^1.1.0" espressif/esp-zboss-lib: - version: "^1.0.1" + version: "==1.6.3" + require: public rules: - - if: "target != esp32c2" + - if: "target not in [esp32c2, esp32p4]" espressif/esp-zigbee-lib: - version: "^1.0.1" + version: "==1.6.3" + require: public rules: - - if: "target != esp32c2" + - if: "target not in [esp32c2, esp32p4]" espressif/esp-dsp: version: "^1.3.4" rules: - if: "target != esp32c2" + # RainMaker Start (Fixed versions, because Matter supports only Insights 1.0.1) + espressif/network_provisioning: + version: "1.0.2" espressif/esp_rainmaker: - version: "^1.0.0" + version: "1.5.2" rules: - - if: "target != esp32c2" + - if: "target not in [esp32c2, esp32p4]" espressif/rmaker_common: - version: "^1.4.3" + version: "1.4.6" rules: - - if: "target != esp32c2" + - if: "target not in [esp32c2, esp32p4]" espressif/esp_insights: - version: "^1.0.1" + version: "1.2.2" rules: - - if: "target != esp32c2" + - if: "target not in [esp32c2, esp32p4]" + # New version breaks esp_insights 1.0.1 + espressif/esp_diag_data_store: + version: "1.0.2" + rules: + - if: "target not in [esp32c2, esp32p4]" + espressif/esp_diagnostics: + version: "1.2.1" + rules: + - if: "target not in [esp32c2, esp32p4]" + espressif/cbor: + version: "0.6.0~1" + rules: + - if: "target not in [esp32c2, esp32p4]" espressif/qrcode: - version: "^0.1.0~1" + version: "0.1.0~2" rules: - - if: "target != esp32c2" + - if: "target not in [esp32c2, esp32p4]" + # RainMaker End espressif/esp-sr: version: "^1.4.2" rules: - if: "target in [esp32s3]" + espressif/esp_hosted: + version: "^0.0.25" + rules: + - if: "target == esp32p4" + espressif/esp_wifi_remote: + version: "^0.4.1" + rules: + - if: "target == esp32p4" espressif/libsodium: version: "^1.0.20~1" require: public + espressif/esp-modbus: + version: "^1.0.15" + require: public joltwallet/littlefs: version: "^1.10.2" chmorgan/esp-libhelix-mp3: @@ -91,3 +123,5 @@ dependencies: require: public examples: - path: ./idf_component_examples/hello_world + - path: ./idf_component_examples/hw_cdc_hello_world + - path: ./idf_component_examples/esp_matter_light diff --git a/idf_component_examples/.gitignore b/idf_component_examples/.gitignore new file mode 100644 index 00000000000..6052fd4e70b --- /dev/null +++ b/idf_component_examples/.gitignore @@ -0,0 +1,4 @@ +build/ +managed_components/ +dependencies.lock +sdkconfig diff --git a/idf_component_examples/esp_matter_light/CMakeLists.txt b/idf_component_examples/esp_matter_light/CMakeLists.txt new file mode 100644 index 00000000000..1430df8ff78 --- /dev/null +++ b/idf_component_examples/esp_matter_light/CMakeLists.txt @@ -0,0 +1,28 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(PROJECT_VER "1.0") +set(PROJECT_VER_NUMBER 1) + +# This should be done before using the IDF_TARGET variable. +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +idf_build_set_property(MINIMAL_BUILD ON) +project(arduino_managed_component_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++2a;-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) diff --git a/idf_component_examples/esp_matter_light/README.md b/idf_component_examples/esp_matter_light/README.md new file mode 100644 index 00000000000..b0173f6a437 --- /dev/null +++ b/idf_component_examples/esp_matter_light/README.md @@ -0,0 +1,124 @@ +| Supported Targets | ESP32-S3 | ESP32-C3 | ESP32-C6 | +| ----------------- | -------- | -------- | -------- | + + +# Managed Component Light + +This example sets automatically the RGB LED GPIO and BOOT Button GPIO based on the default pin used by the selected Devkit Board. + +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. + +Read the [documentation](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` + +Each Devkit Board has a built-in LED that will be used as the Matter Light. +The default setting for ESP32-S3 is pin 48, for ESP32-C3 and ESP32-C6, it is pin 8. +The BOOT Button pin of ESP32-S3 is GPIO 0, by toher hand, the ESP32-C3 and ESP32-C6 use GPIO 9. +Please change it in using the MenuConfig executing `idf.py menuconfig` and selecting `Menu->Light Matter Accessory` options. + +## 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 Wi-Fi connection. + +Once it connects to the Wi-Fi 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 Wi-Fi using an ESP32 device will connect to a 2.4 GHz Wi-Fi SSID, therefore the Commissioner APP Smartphone shall be connected to this SSID. + +The Matter and Wi-Fi configuration will be stored in NVS to ensure that it will connect to the Matter Fabric and Wi-Fi 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 Wi-Fi 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 Wi-Fi 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 + +The project will download all necessary components, including the Arduino Core. +Execute this sequence: + ` using linux rm command or Windows rmdir command` + `idf.py set-target ` + `idf.py -D SDKCONFIG_DEFAULTS="sdkconfig_file1;sdkconfig_file2;sdkconfig_fileX" -p flash monitor` + +Example for ESP32-S3/Linux | macOS: +``` +rm -rf build +idf.py set-target esp32s3 +idf.py -D SDKCONFIG_DEFAULTS="sdkconfig.defaults" -p /dev/ttyACM0 flash monitor +``` +Example for ESP32-C3/Windows: +``` +rmdir /s/q build +idf.py set-target esp32c3 +idf.py -D SDKCONFIG_DEFAULTS="sdkconfig.defaults" -p com3 flash monitor +``` + +It may be necessary to delete some folders and files before running `idf.py` +- Linux/macOS: + ``` + rm -rf build managed_components sdkconfig dependencies.lock + ``` +- Windows: + ``` + rmdir /s/q build managed_components && del sdkconfig dependencies.lock + ``` + +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, Wi-Fi and Matter. + +In case it is necessary to change the Button Pin or the REG LED Pin, please use the `menuconfig` +`idf.py menuconfig` and change the Menu Option `Light Matter Accessory` + +## Building the Application using OpenThread and Matter + +This is possible with the ESP32-C6. +It is necessary to have a Thread Border Router in the Matter Environment. +Check your Matter hardware provider. +In order to build the application that will use Thread Networking instead of Wi-Fi, please execute: + +Example for ESP32-C6/Linux | macOS: +``` +rm -rf build +idf.py set-target esp32c6 +idf.py -D SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.c6_thread" -p /dev/ttyACM0 flash monitor +``` +Example for ESP32-C6/Windows: +``` +rmdir /s/q build +idf.py set-targt esp32c6 +idf.py -D SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.c6_thread" -p com3 flash monitor +``` + +It may be necessary to delete some folders and files before running `idf.py` +- Linux/macOS + ``` + rm -rf build managed_components sdkconfig dependencies.lock + ``` +- Windows + ``` + rmdir /s/q build managed_components && del sdkconfig dependencies.lock + ``` diff --git a/idf_component_examples/esp_matter_light/ci.json b/idf_component_examples/esp_matter_light/ci.json new file mode 100644 index 00000000000..f23a085285d --- /dev/null +++ b/idf_component_examples/esp_matter_light/ci.json @@ -0,0 +1,11 @@ +{ + "targets": { + "esp32c2": false, + "esp32s2": false + }, + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y", + "CONFIG_MBEDTLS_HKDF_C=y" + ] +} diff --git a/idf_component_examples/esp_matter_light/main/CMakeLists.txt b/idf_component_examples/esp_matter_light/main/CMakeLists.txt new file mode 100644 index 00000000000..6b91a8cf510 --- /dev/null +++ b/idf_component_examples/esp_matter_light/main/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register(SRC_DIRS "." + INCLUDE_DIRS ".") + +set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) +target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") diff --git a/idf_component_examples/esp_matter_light/main/Kconfig.projbuild b/idf_component_examples/esp_matter_light/main/Kconfig.projbuild new file mode 100644 index 00000000000..3e0a35c5e15 --- /dev/null +++ b/idf_component_examples/esp_matter_light/main/Kconfig.projbuild @@ -0,0 +1,42 @@ +menu "Light Matter Accessory" + menu "On Board Light ON/OFF Button" + config BUTTON_PIN + int + prompt "Button 1 GPIO" + default 9 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C6 + default 0 + 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 8 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C6 + default 48 + 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 + + config ENV_GPIO_RANGE_MIN + int + default 0 + + config ENV_GPIO_RANGE_MAX + int + default 19 if IDF_TARGET_ESP32C3 + default 30 if IDF_TARGET_ESP32C6 + 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 + +endmenu diff --git a/idf_component_examples/esp_matter_light/main/builtinLED.cpp b/idf_component_examples/esp_matter_light/main/builtinLED.cpp new file mode 100644 index 00000000000..8795dde2756 --- /dev/null +++ b/idf_component_examples/esp_matter_light/main/builtinLED.cpp @@ -0,0 +1,237 @@ +/* + 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); +} diff --git a/idf_component_examples/esp_matter_light/main/builtinLED.h b/idf_component_examples/esp_matter_light/main/builtinLED.h new file mode 100644 index 00000000000..1ca8c935569 --- /dev/null +++ b/idf_component_examples/esp_matter_light/main/builtinLED.h @@ -0,0 +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); +}; diff --git a/idf_component_examples/esp_matter_light/main/idf_component.yml b/idf_component_examples/esp_matter_light/main/idf_component.yml new file mode 100644 index 00000000000..e0286324591 --- /dev/null +++ b/idf_component_examples/esp_matter_light/main/idf_component.yml @@ -0,0 +1,12 @@ +dependencies: + espressif/esp_matter: + version: ">=1.3.0" + # Adds Arduino Core from GitHub repository using main branch + espressif/arduino-esp32: + version: ">=3.0.5" + override_path: "../../../" + pre_release: true + + # testing - using Arduino from the repository + # version: "master" # branch or commit + # git: https://github.com/espressif/arduino-esp32.git diff --git a/idf_component_examples/esp_matter_light/main/matter_accessory_driver.cpp b/idf_component_examples/esp_matter_light/main/matter_accessory_driver.cpp new file mode 100644 index 00000000000..523c38e6855 --- /dev/null +++ b/idf_component_examples/esp_matter_light/main/matter_accessory_driver.cpp @@ -0,0 +1,89 @@ +/* + 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" + +/* 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); + return (app_driver_handle_t)&builtinLED; +} diff --git a/idf_component_examples/esp_matter_light/main/matter_accessory_driver.h b/idf_component_examples/esp_matter_light/main/matter_accessory_driver.h new file mode 100644 index 00000000000..3bf6655ab16 --- /dev/null +++ b/idf_component_examples/esp_matter_light/main/matter_accessory_driver.h @@ -0,0 +1,47 @@ +#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(); diff --git a/idf_component_examples/esp_matter_light/main/matter_light.cpp b/idf_component_examples/esp_matter_light/main/matter_light.cpp new file mode 100644 index 00000000000..6079ce46add --- /dev/null +++ b/idf_component_examples/esp_matter_light/main/matter_light.cpp @@ -0,0 +1,384 @@ +/* + 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 + +// 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; +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 + +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 %s Address changed", event->InterfaceIpAddressChanged.Type == chip::DeviceLayer::InterfaceIpChangeType::kIpV4_Assigned ? "IPv4" : "IPV6" + ); + break; + + case chip::DeviceLayer::DeviceEventType::kCommissioningComplete: log_i("Commissioning complete"); break; + + case chip::DeviceLayer::DeviceEventType::kFailSafeTimerExpired: log_i("Commissioning failed, fail safe timer expired"); break; + + case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStarted: log_i("Commissioning session started"); break; + + case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStopped: log_i("Commissioning session stopped"); break; + + case chip::DeviceLayer::DeviceEventType::kCommissioningWindowOpened: log_i("Commissioning window opened"); break; + + case chip::DeviceLayer::DeviceEventType::kCommissioningWindowClosed: log_i("Commissioning window closed"); break; + + case chip::DeviceLayer::DeviceEventType::kFabricRemoved: + { + log_i("Fabric removed successfully"); + if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0) { + 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; + } +} + +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 */ + pinMode(button_gpio, INPUT_PULLUP); +} + +// 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 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); // codespell:ignore + 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(); + } + +#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() { + 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 restored to factory settings."); + esp_matter::factory_reset(); + } + } + + delay(50); // WDT is happier with a delay +} diff --git a/idf_component_examples/esp_matter_light/partitions.csv b/idf_component_examples/esp_matter_light/partitions.csv new file mode 100644 index 00000000000..ffe5f242e76 --- /dev/null +++ b/idf_component_examples/esp_matter_light/partitions.csv @@ -0,0 +1,10 @@ +# 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 +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/idf_component_examples/esp_matter_light/sdkconfig.defaults b/idf_component_examples/esp_matter_light/sdkconfig.defaults new file mode 100644 index 00000000000..43871661856 --- /dev/null +++ b/idf_component_examples/esp_matter_light/sdkconfig.defaults @@ -0,0 +1,62 @@ +# 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 Requester +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/idf_component_examples/esp_matter_light/sdkconfig.defaults.c6_thread b/idf_component_examples/esp_matter_light/sdkconfig.defaults.c6_thread new file mode 100644 index 00000000000..502480f94b1 --- /dev/null +++ b/idf_component_examples/esp_matter_light/sdkconfig.defaults.c6_thread @@ -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 + +# 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 Requester +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/idf_component_examples/esp_matter_light/sdkconfig.defaults.esp32c6 b/idf_component_examples/esp_matter_light/sdkconfig.defaults.esp32c6 new file mode 100644 index 00000000000..9fe589613ef --- /dev/null +++ b/idf_component_examples/esp_matter_light/sdkconfig.defaults.esp32c6 @@ -0,0 +1,16 @@ +CONFIG_IDF_TARGET="esp32c6" + +# 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/idf_component_examples/hello_world/CMakeLists.txt b/idf_component_examples/hello_world/CMakeLists.txt index 664d45871d0..af087cf42b6 100644 --- a/idf_component_examples/hello_world/CMakeLists.txt +++ b/idf_component_examples/hello_world/CMakeLists.txt @@ -5,4 +5,6 @@ cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +idf_build_set_property(MINIMAL_BUILD ON) project(main) diff --git a/idf_component_examples/hw_cdc_hello_world/CMakeLists.txt b/idf_component_examples/hw_cdc_hello_world/CMakeLists.txt new file mode 100644 index 00000000000..1c3971f4dbf --- /dev/null +++ b/idf_component_examples/hw_cdc_hello_world/CMakeLists.txt @@ -0,0 +1,13 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +# Adds necessary definitions for compiling it using Serial symbol attached to the HW USB CDC port +list(APPEND compile_definitions "ARDUINO_USB_CDC_ON_BOOT=1") +list(APPEND compile_definitions "ARDUINO_USB_MODE=1") + +idf_build_set_property(MINIMAL_BUILD ON) +project(hw_cdc_hello_world) diff --git a/idf_component_examples/hw_cdc_hello_world/README.md b/idf_component_examples/hw_cdc_hello_world/README.md new file mode 100644 index 00000000000..e4356d75ac3 --- /dev/null +++ b/idf_component_examples/hw_cdc_hello_world/README.md @@ -0,0 +1,63 @@ +| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | + +# _HW Serial USB CDC example_ + +This is the simplest buildable example made to be used as a template for new projects running Arduino-ESP32 as an ESP-IDF component that will redefine the `Serial` interface to be attached to the USB CDC Hardware Serial port.\ +See [arduino-esp32](https://components.espressif.com/components/espressif/arduino-esp32) in ESP Registry. + +## How to use example + +After cloning this repository, go to the `hw_cdc_hello_world` folder and select the target by executing\ +`idf.py set-target `.\ +`` can be one of the installed IDF version supported targets. + +It is possible to just clone this folder be executing\ +`idf.py create-project-from-example "espressif/arduino-esp32^3.0.5:hw_cdc_hello_world"` + +For IDF 5.1.x and forward, the list of targets that support Hardware USB CDC are, at least: esp32s3, esp32c3, esp32c6 and esp32h2.\ +Then just run command: `idf.py build` or `idf.py -p USB_PORT flash monitor`. + +Usually, it is necessary to make the ESP32 SoC to enter in `Download Mode` before uploading the firmware.\ +After that, just press `RESET/EN` to start the new firmware. + +## Example folder contents + +The project **hw_serial_example** contains one source file in C++ language [main.cpp](main/main.cpp). The file is located in folder [main](main). + +ESP-IDF projects are built using CMake. The project building configuration is contained in `CMakeLists.txt` +file that provide a set of directives and instructions describing the project's source files and targets +(executable, library, or both). + +Below is the minimum list of files in the project folder. + +``` +├── CMakeLists.txt Global project CMake configuration file +├── sdkconfig.defaults sdkconfig setting for an Arduino project +├── main +│   ├── CMakeLists.txt Arduino sketch CMake configuration file +│ ├── idf_component.yml List of IDF components necessary to build the project +│   └── main.cpp Arduino Sketch code - don't forget to add "#include " on it +└── README.md This is the file you are currently reading +``` + +## Configuring the Hardware USB CDC Serial + +ESP32 Arduino has two macro defined symbols that control what `Serial` symbol will represent. +Default `Serial` is the UART0 from `HardwareSerial` class. + +`Serial` can be changed to be attached to the HW Serial JTAG port fro the SoC. +In order to make it work, it is necessary to define 2 symbols: `ARDUINO_USB_CDC_ON_BOOT` and `ARDUINO_USB_MODE` to `1`. +This is achieved by adding a couple lines to the [Project Folder CMakeLists.txt](CMakeLists.txt) file. + + +``` +# Adds necessary definitions for compiling it using Serial symbol attached to the HW USB CDC port +list(APPEND compile_definitions "ARDUINO_USB_CDC_ON_BOOT=1") +list(APPEND compile_definitions "ARDUINO_USB_MODE=1") + +``` + +Those two lines will add a `-DSYMBOL=VAL` when compiling every source code file. + +In order to make sure that it is actually working correctly, the [sketch](main/main.cpp) will execute `Serial.begin();` with no baudrate, which only works for USB CDC. diff --git a/idf_component_examples/hw_cdc_hello_world/ci.json b/idf_component_examples/hw_cdc_hello_world/ci.json new file mode 100644 index 00000000000..80669afc2cc --- /dev/null +++ b/idf_component_examples/hw_cdc_hello_world/ci.json @@ -0,0 +1,5 @@ +{ + "requires": [ + "CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED=y" + ] +} diff --git a/idf_component_examples/hw_cdc_hello_world/main/CMakeLists.txt b/idf_component_examples/hw_cdc_hello_world/main/CMakeLists.txt new file mode 100644 index 00000000000..25a78dec2a6 --- /dev/null +++ b/idf_component_examples/hw_cdc_hello_world/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register( + SRC_DIRS "." + INCLUDE_DIRS "." +) diff --git a/idf_component_examples/hw_cdc_hello_world/main/idf_component.yml b/idf_component_examples/hw_cdc_hello_world/main/idf_component.yml new file mode 100644 index 00000000000..f955824767c --- /dev/null +++ b/idf_component_examples/hw_cdc_hello_world/main/idf_component.yml @@ -0,0 +1,6 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/arduino-esp32: + version: "*" + override_path: "../../../" + pre_release: true diff --git a/idf_component_examples/hw_cdc_hello_world/main/main.cpp b/idf_component_examples/hw_cdc_hello_world/main/main.cpp new file mode 100644 index 00000000000..18718678430 --- /dev/null +++ b/idf_component_examples/hw_cdc_hello_world/main/main.cpp @@ -0,0 +1,18 @@ +#include + +void setup() { + // USB CDC doesn't need a baud rate + Serial.begin(); + + // wait for the Serial Monitor to be open + while (!Serial) { + delay(100); + } + + Serial.println("\r\nStarting...\r\n"); +} + +void loop() { + Serial.println("Hello world!"); + delay(1000); +} diff --git a/idf_component_examples/hw_cdc_hello_world/sdkconfig.defaults b/idf_component_examples/hw_cdc_hello_world/sdkconfig.defaults new file mode 100644 index 00000000000..bb723653f8a --- /dev/null +++ b/idf_component_examples/hw_cdc_hello_world/sdkconfig.defaults @@ -0,0 +1,12 @@ +# +# Arduino ESP32 +# +CONFIG_AUTOSTART_ARDUINO=y +# end of Arduino ESP32 + +# +# FREERTOS +# +CONFIG_FREERTOS_HZ=1000 +# end of FREERTOS +# end of Component config diff --git a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino index cac1e4f4bdc..b3b01be61cd 100644 --- a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino +++ b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino @@ -1,3 +1,17 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include #include #include diff --git a/libraries/ArduinoOTA/examples/BasicOTA/ci.json b/libraries/ArduinoOTA/examples/BasicOTA/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/ArduinoOTA/examples/BasicOTA/ci.json +++ b/libraries/ArduinoOTA/examples/BasicOTA/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/ArduinoOTA/keywords.txt b/libraries/ArduinoOTA/keywords.txt index 0f3921b73fc..9774de881ea 100644 --- a/libraries/ArduinoOTA/keywords.txt +++ b/libraries/ArduinoOTA/keywords.txt @@ -7,19 +7,40 @@ ####################################### ArduinoOTA KEYWORD1 +ArduinoOTAClass KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) ####################################### begin KEYWORD2 -setup KEYWORD2 +end KEYWORD2 handle KEYWORD2 onStart KEYWORD2 onEnd KEYWORD2 onError KEYWORD2 onProgress KEYWORD2 +setPort KEYWORD2 +setHostname KEYWORD2 +getHostname KEYWORD2 +setPassword KEYWORD2 +setPasswordHash KEYWORD2 +setPartitionLabel KEYWORD2 +getPartitionLabel KEYWORD2 +setRebootOnSuccess KEYWORD2 +setMdnsEnabled KEYWORD2 +getCommand KEYWORD2 +setTimeout KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### + +OTA_IDLE LITERAL1 +OTA_WAITAUTH LITERAL1 +OTA_RUNUPDATE LITERAL1 +OTA_AUTH_ERROR LITERAL1 +OTA_BEGIN_ERROR LITERAL1 +OTA_CONNECT_ERROR LITERAL1 +OTA_RECEIVE_ERROR LITERAL1 +OTA_END_ERROR LITERAL1 diff --git a/libraries/ArduinoOTA/library.properties b/libraries/ArduinoOTA/library.properties index f8a3b508781..0796eddf318 100644 --- a/libraries/ArduinoOTA/library.properties +++ b/libraries/ArduinoOTA/library.properties @@ -1,9 +1,9 @@ name=ArduinoOTA -version=2.0.0 +version=3.2.0 author=Ivan Grokhotkov and Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables Over The Air upgrades, via wifi and espota.py UDP request/TCP download. -paragraph=With this library you can enable your sketch to be upgraded over network. Includes mdns anounces to get discovered by the arduino IDE. +paragraph=With this library you can enable your sketch to be upgraded over network. Includes mdns announces to get discovered by the arduino IDE. category=Communication url= architectures=esp32 diff --git a/libraries/ArduinoOTA/src/ArduinoOTA.cpp b/libraries/ArduinoOTA/src/ArduinoOTA.cpp index 6fa482e1335..cb3ddc1e797 100644 --- a/libraries/ArduinoOTA/src/ArduinoOTA.cpp +++ b/libraries/ArduinoOTA/src/ArduinoOTA.cpp @@ -1,3 +1,17 @@ +// 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. + #ifndef LWIP_OPEN_SRC #define LWIP_OPEN_SRC #endif @@ -15,7 +29,7 @@ ArduinoOTAClass::ArduinoOTAClass() _start_callback(NULL), _end_callback(NULL), _error_callback(NULL), _progress_callback(NULL) {} ArduinoOTAClass::~ArduinoOTAClass() { - _udp_ota.stop(); + end(); } ArduinoOTAClass &ArduinoOTAClass::onStart(THandlerFunction fn) { @@ -57,25 +71,28 @@ String ArduinoOTAClass::getHostname() { } ArduinoOTAClass &ArduinoOTAClass::setPassword(const char *password) { - if (!_initialized && !_password.length() && password) { + if (_state == OTA_IDLE && password) { MD5Builder passmd5; passmd5.begin(); passmd5.add(password); passmd5.calculate(); + _password.clear(); _password = passmd5.toString(); } return *this; } ArduinoOTAClass &ArduinoOTAClass::setPasswordHash(const char *password) { - if (!_initialized && !_password.length() && password) { + if (_state == OTA_IDLE && password) { + _password.clear(); _password = password; } return *this; } ArduinoOTAClass &ArduinoOTAClass::setPartitionLabel(const char *partition_label) { - if (!_initialized && !_partition_label.length() && partition_label) { + if (_state == OTA_IDLE && partition_label) { + _partition_label.clear(); _partition_label = partition_label; } return *this; @@ -117,10 +134,12 @@ void ArduinoOTAClass::begin() { sprintf(tmp, "esp32-%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); _hostname = tmp; } +#ifdef CONFIG_MDNS_MAX_INTERFACES if (_mdnsEnabled) { MDNS.begin(_hostname.c_str()); MDNS.enableArduino(_port, (_password.length() > 0)); } +#endif _initialized = true; _state = OTA_IDLE; log_i("OTA server at: %s.local:%u", _hostname.c_str(), _port); @@ -355,9 +374,11 @@ void ArduinoOTAClass::_runUpdate() { void ArduinoOTAClass::end() { _initialized = false; _udp_ota.stop(); +#ifdef CONFIG_MDNS_MAX_INTERFACES if (_mdnsEnabled) { MDNS.end(); } +#endif _state = OTA_IDLE; log_i("OTA server stopped."); } @@ -373,7 +394,7 @@ void ArduinoOTAClass::handle() { if (_udp_ota.parsePacket()) { _onRx(); } - _udp_ota.flush(); // always flush, even zero length packets must be flushed. + _udp_ota.clear(); // always clear, even zero length packets must be cleared. } int ArduinoOTAClass::getCommand() { diff --git a/libraries/ArduinoOTA/src/ArduinoOTA.h b/libraries/ArduinoOTA/src/ArduinoOTA.h index 02960d06f63..7916e3b328d 100644 --- a/libraries/ArduinoOTA/src/ArduinoOTA.h +++ b/libraries/ArduinoOTA/src/ArduinoOTA.h @@ -1,3 +1,17 @@ +// 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. + #ifndef __ARDUINO_OTA_H #define __ARDUINO_OTA_H diff --git a/libraries/AsyncUDP/examples/AsyncUDPClient/ci.json b/libraries/AsyncUDP/examples/AsyncUDPClient/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/AsyncUDP/examples/AsyncUDPClient/ci.json +++ b/libraries/AsyncUDP/examples/AsyncUDPClient/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/AsyncUDP/examples/AsyncUDPMulticastServer/ci.json b/libraries/AsyncUDP/examples/AsyncUDPMulticastServer/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/AsyncUDP/examples/AsyncUDPMulticastServer/ci.json +++ b/libraries/AsyncUDP/examples/AsyncUDPMulticastServer/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/AsyncUDP/examples/AsyncUDPServer/ci.json b/libraries/AsyncUDP/examples/AsyncUDPServer/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/AsyncUDP/examples/AsyncUDPServer/ci.json +++ b/libraries/AsyncUDP/examples/AsyncUDPServer/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/AsyncUDP/keywords.txt b/libraries/AsyncUDP/keywords.txt index 67c0b97a715..1401ea66c72 100644 --- a/libraries/AsyncUDP/keywords.txt +++ b/libraries/AsyncUDP/keywords.txt @@ -8,6 +8,7 @@ AsyncUDP KEYWORD1 AsyncUDPPacket KEYWORD1 +AsyncUDPMessage KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) @@ -19,6 +20,21 @@ listen KEYWORD2 listenMulticast KEYWORD2 close KEYWORD2 write KEYWORD2 +space KEYWORD2 +flush KEYWORD2 +isBroadcast KEYWORD2 +isMulticast KEYWORD2 +isIPv6 KEYWORD2 +interface KEYWORD2 +localIPv6 KEYWORD2 +remoteIPv6 KEYWORD2 +remoteMac KEYWORD2 +send KEYWORD2 +peek KEYWORD2 +available KEYWORD2 +writeTo KEYWORD2 +broadcastTo KEYWORD2 +sendTo KEYWORD2 broadcast KEYWORD2 onPacket KEYWORD2 data KEYWORD2 @@ -27,7 +43,17 @@ localIP KEYWORD2 localPort KEYWORD2 remoteIP KEYWORD2 remotePort KEYWORD2 +listenIP KEYWORD2 +listenIPv6 KEYWORD2 +lastErr KEYWORD2 +_s_recv KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### + +TCPIP_ADAPTER_IF_STA LITERAL1 +TCPIP_ADAPTER_IF_STA LITERAL1 +TCPIP_ADAPTER_IF_AP LITERAL1 +TCPIP_ADAPTER_IF_ETH LITERAL1 +TCPIP_ADAPTER_IF_PPP LITERAL1 diff --git a/libraries/AsyncUDP/library.properties b/libraries/AsyncUDP/library.properties index f606bb8c32f..116dcbacaa8 100644 --- a/libraries/AsyncUDP/library.properties +++ b/libraries/AsyncUDP/library.properties @@ -1,5 +1,5 @@ name=ESP32 Async UDP -version=2.0.0 +version=3.2.0 author=Me-No-Dev maintainer=Me-No-Dev sentence=Async UDP Library for ESP32 diff --git a/libraries/AsyncUDP/src/AsyncUDP.cpp b/libraries/AsyncUDP/src/AsyncUDP.cpp index 4f799b4d4a4..f44cc839c97 100644 --- a/libraries/AsyncUDP/src/AsyncUDP.cpp +++ b/libraries/AsyncUDP/src/AsyncUDP.cpp @@ -15,6 +15,21 @@ extern "C" { #include "lwip/priv/tcpip_priv.h" +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING +#define UDP_MUTEX_LOCK() \ + if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \ + LOCK_TCPIP_CORE(); \ + } + +#define UDP_MUTEX_UNLOCK() \ + if (sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \ + UNLOCK_TCPIP_CORE(); \ + } +#else // CONFIG_LWIP_TCPIP_CORE_LOCKING +#define UDP_MUTEX_LOCK() +#define UDP_MUTEX_UNLOCK() +#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING + static const char *netif_ifkeys[TCPIP_ADAPTER_IF_MAX] = {"WIFI_STA_DEF", "WIFI_AP_DEF", "ETH_DEF", "PPP_DEF"}; static esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void **netif) { @@ -28,7 +43,9 @@ static esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void **net if (netif_index < 0) { return ESP_FAIL; } + UDP_MUTEX_LOCK(); *netif = (void *)netif_get_by_index(netif_index); + UDP_MUTEX_UNLOCK(); } else { *netif = netif_default; } @@ -232,9 +249,6 @@ static bool _udp_task_stop(){ } */ -#define UDP_MUTEX_LOCK() //xSemaphoreTake(_lock, portMAX_DELAY) -#define UDP_MUTEX_UNLOCK() //xSemaphoreGive(_lock) - AsyncUDPMessage::AsyncUDPMessage(size_t size) { _index = 0; if (size > CONFIG_TCP_MSS) { @@ -314,25 +328,36 @@ AsyncUDPPacket::AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *raddr, pbuf_ref(_pb); //memcpy(&_remoteIp, raddr, sizeof(ip_addr_t)); +#if CONFIG_LWIP_IPV6 _remoteIp.type = raddr->type; _localIp.type = _remoteIp.type; +#endif eth_hdr *eth = NULL; udp_hdr *udphdr = (udp_hdr *)(_data - UDP_HLEN); _localPort = ntohs(udphdr->dest); _remotePort = ntohs(udphdr->src); +#if CONFIG_LWIP_IPV6 if (_remoteIp.type == IPADDR_TYPE_V4) { +#endif eth = (eth_hdr *)(_data - UDP_HLEN - IP_HLEN - SIZEOF_ETH_HDR); struct ip_hdr *iphdr = (struct ip_hdr *)(_data - UDP_HLEN - IP_HLEN); +#if CONFIG_LWIP_IPV6 _localIp.u_addr.ip4.addr = iphdr->dest.addr; _remoteIp.u_addr.ip4.addr = iphdr->src.addr; +#else + _localIp.addr = iphdr->dest.addr; + _remoteIp.addr = iphdr->src.addr; +#endif +#if CONFIG_LWIP_IPV6 } else { eth = (eth_hdr *)(_data - UDP_HLEN - IP6_HLEN - SIZEOF_ETH_HDR); struct ip6_hdr *ip6hdr = (struct ip6_hdr *)(_data - UDP_HLEN - IP6_HLEN); memcpy(&_localIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16); memcpy(&_remoteIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->src.addr, 16); } +#endif memcpy(_remoteMac, eth->src.addr, 6); struct netif *netif = NULL; @@ -399,36 +424,48 @@ tcpip_adapter_if_t AsyncUDPPacket::interface() { } IPAddress AsyncUDPPacket::localIP() { +#if CONFIG_LWIP_IPV6 if (_localIp.type != IPADDR_TYPE_V4) { return IPAddress(); } return IPAddress(_localIp.u_addr.ip4.addr); +#else + return IPAddress(_localIp.addr); +#endif } +#if CONFIG_LWIP_IPV6 IPAddress AsyncUDPPacket::localIPv6() { if (_localIp.type != IPADDR_TYPE_V6) { return IPAddress(IPv6); } return IPAddress(IPv6, (const uint8_t *)_localIp.u_addr.ip6.addr, _localIp.u_addr.ip6.zone); } +#endif uint16_t AsyncUDPPacket::localPort() { return _localPort; } IPAddress AsyncUDPPacket::remoteIP() { +#if CONFIG_LWIP_IPV6 if (_remoteIp.type != IPADDR_TYPE_V4) { return IPAddress(); } return IPAddress(_remoteIp.u_addr.ip4.addr); +#else + return IPAddress(_remoteIp.addr); +#endif } +#if CONFIG_LWIP_IPV6 IPAddress AsyncUDPPacket::remoteIPv6() { if (_remoteIp.type != IPADDR_TYPE_V6) { return IPAddress(IPv6); } return IPAddress(IPv6, (const uint8_t *)_remoteIp.u_addr.ip6.addr, _remoteIp.u_addr.ip6.zone); } +#endif uint16_t AsyncUDPPacket::remotePort() { return _remotePort; @@ -439,14 +476,22 @@ void AsyncUDPPacket::remoteMac(uint8_t *mac) { } bool AsyncUDPPacket::isIPv6() { +#if CONFIG_LWIP_IPV6 return _localIp.type == IPADDR_TYPE_V6; +#else + return false; +#endif } bool AsyncUDPPacket::isBroadcast() { +#if CONFIG_LWIP_IPV6 if (_localIp.type == IPADDR_TYPE_V6) { return false; } uint32_t ip = _localIp.u_addr.ip4.addr; +#else + uint32_t ip = _localIp.addr; +#endif return ip == 0xFFFFFFFF || ip == 0 || (ip & 0xFF000000) == 0xFF000000; } @@ -473,12 +518,14 @@ bool AsyncUDP::_init() { if (_pcb) { return true; } + UDP_MUTEX_LOCK(); _pcb = udp_new(); if (!_pcb) { + UDP_MUTEX_UNLOCK(); return false; } - //_lock = xSemaphoreCreateMutex(); udp_recv(_pcb, &_udp_recv, (void *)this); + UDP_MUTEX_UNLOCK(); return true; } @@ -493,14 +540,12 @@ AsyncUDP::~AsyncUDP() { close(); UDP_MUTEX_LOCK(); udp_recv(_pcb, NULL, NULL); + UDP_MUTEX_UNLOCK(); _udp_remove(_pcb); _pcb = NULL; - UDP_MUTEX_UNLOCK(); - //vSemaphoreDelete(_lock); } void AsyncUDP::close() { - UDP_MUTEX_LOCK(); if (_pcb != NULL) { if (_connected) { _udp_disconnect(_pcb); @@ -508,7 +553,6 @@ void AsyncUDP::close() { _connected = false; //todo: unjoin multicast group } - UDP_MUTEX_UNLOCK(); } bool AsyncUDP::connect(const ip_addr_t *addr, uint16_t port) { @@ -520,14 +564,11 @@ bool AsyncUDP::connect(const ip_addr_t *addr, uint16_t port) { return false; } close(); - UDP_MUTEX_LOCK(); _lastErr = _udp_connect(_pcb, addr, port); if (_lastErr != ERR_OK) { - UDP_MUTEX_UNLOCK(); return false; } _connected = true; - UDP_MUTEX_UNLOCK(); return true; } @@ -544,13 +585,10 @@ bool AsyncUDP::listen(const ip_addr_t *addr, uint16_t port) { IP_SET_TYPE_VAL(_pcb->local_ip, addr->type); IP_SET_TYPE_VAL(_pcb->remote_ip, addr->type); } - UDP_MUTEX_LOCK(); if (_udp_bind(_pcb, addr, port) != ERR_OK) { - UDP_MUTEX_UNLOCK(); return false; } _connected = true; - UDP_MUTEX_UNLOCK(); return true; } @@ -563,52 +601,84 @@ static esp_err_t joinMulticastGroup(const ip_addr_t *addr, bool join, tcpip_adap return ESP_ERR_INVALID_ARG; } netif = (struct netif *)nif; + UDP_MUTEX_LOCK(); +#if CONFIG_LWIP_IPV6 if (addr->type == IPADDR_TYPE_V4) { if (join) { if (igmp_joingroup_netif(netif, (const ip4_addr *)&(addr->u_addr.ip4))) { - return ESP_ERR_INVALID_STATE; + goto igmp_fail; } } else { if (igmp_leavegroup_netif(netif, (const ip4_addr *)&(addr->u_addr.ip4))) { - return ESP_ERR_INVALID_STATE; + goto igmp_fail; } } } else { if (join) { if (mld6_joingroup_netif(netif, &(addr->u_addr.ip6))) { - return ESP_ERR_INVALID_STATE; + goto igmp_fail; } } else { if (mld6_leavegroup_netif(netif, &(addr->u_addr.ip6))) { - return ESP_ERR_INVALID_STATE; + goto igmp_fail; } } } +#else + if (join) { + if (igmp_joingroup_netif(netif, (const ip4_addr *)(addr))) { + goto igmp_fail; + } + } else { + if (igmp_leavegroup_netif(netif, (const ip4_addr *)(addr))) { + goto igmp_fail; + } + } +#endif + UDP_MUTEX_UNLOCK(); } else { + UDP_MUTEX_LOCK(); +#if CONFIG_LWIP_IPV6 if (addr->type == IPADDR_TYPE_V4) { if (join) { if (igmp_joingroup((const ip4_addr *)IP4_ADDR_ANY, (const ip4_addr *)&(addr->u_addr.ip4))) { - return ESP_ERR_INVALID_STATE; + goto igmp_fail; } } else { if (igmp_leavegroup((const ip4_addr *)IP4_ADDR_ANY, (const ip4_addr *)&(addr->u_addr.ip4))) { - return ESP_ERR_INVALID_STATE; + goto igmp_fail; } } } else { if (join) { if (mld6_joingroup((const ip6_addr *)IP6_ADDR_ANY, &(addr->u_addr.ip6))) { - return ESP_ERR_INVALID_STATE; + goto igmp_fail; } } else { if (mld6_leavegroup((const ip6_addr *)IP6_ADDR_ANY, &(addr->u_addr.ip6))) { - return ESP_ERR_INVALID_STATE; + goto igmp_fail; } } } +#else + if (join) { + if (igmp_joingroup((const ip4_addr *)IP4_ADDR_ANY, (const ip4_addr *)(addr))) { + goto igmp_fail; + } + } else { + if (igmp_leavegroup((const ip4_addr *)IP4_ADDR_ANY, (const ip4_addr *)(addr))) { + goto igmp_fail; + } + } +#endif + UDP_MUTEX_UNLOCK(); } return ESP_OK; + +igmp_fail: + UDP_MUTEX_UNLOCK(); + return ESP_ERR_INVALID_STATE; } bool AsyncUDP::listenMulticast(const ip_addr_t *addr, uint16_t port, uint8_t ttl, tcpip_adapter_if_t tcpip_if) { @@ -624,12 +694,10 @@ bool AsyncUDP::listenMulticast(const ip_addr_t *addr, uint16_t port, uint8_t ttl return false; } - UDP_MUTEX_LOCK(); _pcb->mcast_ttl = ttl; _pcb->remote_port = port; ip_addr_copy(_pcb->remote_ip, *addr); //ip_addr_copy(_pcb->remote_ip, ip_addr_any_type); - UDP_MUTEX_UNLOCK(); return true; } @@ -651,7 +719,6 @@ size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, const ip_addr_t *addr, if (pbt != NULL) { uint8_t *dst = reinterpret_cast(pbt->payload); memcpy(dst, data, len); - UDP_MUTEX_LOCK(); if (tcpip_if < TCPIP_ADAPTER_IF_MAX) { void *nif = NULL; tcpip_adapter_get_netif((tcpip_adapter_if_t)tcpip_if, &nif); @@ -663,7 +730,6 @@ size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, const ip_addr_t *addr, } else { _lastErr = _udp_sendto(_pcb, pbt, addr, port); } - UDP_MUTEX_UNLOCK(); pbuf_free(pbt); if (_lastErr < ERR_OK) { return 0; @@ -719,18 +785,24 @@ size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, const IPAddress addr, } IPAddress AsyncUDP::listenIP() { +#if CONFIG_LWIP_IPV6 if (!_pcb || _pcb->remote_ip.type != IPADDR_TYPE_V4) { return IPAddress(); } return IPAddress(_pcb->remote_ip.u_addr.ip4.addr); +#else + return IPAddress(_pcb->remote_ip.addr); +#endif } +#if CONFIG_LWIP_IPV6 IPAddress AsyncUDP::listenIPv6() { if (!_pcb || _pcb->remote_ip.type != IPADDR_TYPE_V6) { return IPAddress(IPv6); } return IPAddress(IPv6, (const uint8_t *)_pcb->remote_ip.u_addr.ip6.addr, _pcb->remote_ip.u_addr.ip6.zone); } +#endif size_t AsyncUDP::write(const uint8_t *data, size_t len) { return writeTo(data, len, &(_pcb->remote_ip), _pcb->remote_port); diff --git a/libraries/AsyncUDP/src/AsyncUDP.h b/libraries/AsyncUDP/src/AsyncUDP.h index 160fb7b1515..cd96d852542 100644 --- a/libraries/AsyncUDP/src/AsyncUDP.h +++ b/libraries/AsyncUDP/src/AsyncUDP.h @@ -79,10 +79,14 @@ class AsyncUDPPacket : public Stream { tcpip_adapter_if_t interface(); IPAddress localIP(); +#if CONFIG_LWIP_IPV6 IPAddress localIPv6(); +#endif uint16_t localPort(); IPAddress remoteIP(); +#if CONFIG_LWIP_IPV6 IPAddress remoteIPv6(); +#endif uint16_t remotePort(); void remoteMac(uint8_t *mac); @@ -146,7 +150,9 @@ class AsyncUDP : public Print { size_t broadcast(AsyncUDPMessage &message); IPAddress listenIP(); +#if CONFIG_LWIP_IPV6 IPAddress listenIPv6(); +#endif bool connected(); esp_err_t lastErr(); operator bool(); diff --git a/libraries/BLE/README.md b/libraries/BLE/README.md index 05cc8bf68e2..eb70ee9ff00 100644 --- a/libraries/BLE/README.md +++ b/libraries/BLE/README.md @@ -1,15 +1,8 @@ # ESP32 BLE for Arduino -The Arduino IDE provides an excellent library package manager where versions of libraries can be downloaded and installed. This Github project provides the repository for the ESP32 BLE support for Arduino. +The Arduino IDE provides an excellent library package manager where versions of libraries can be downloaded and installed. This Github project provides the repository for the ESP32 BLE support for Arduino. -The actual source of the project which is being maintained can be found here: +The original source of the project, **which is not maintained anymore**, can be found here: https://github.com/nkolban/esp32-snippets -https://github.com/nkolban/esp32-snippets +Issues and questions should be raised here: https://github.com/espressif/arduino-esp32/issues
(please don't use https://github.com/nkolban/esp32-snippets/issues!) -Issues and questions should be raised here: - -https://github.com/nkolban/esp32-snippets/issues - - -Documentation for using the library can be found here: - -https://github.com/nkolban/esp32-snippets/tree/master/Documentation +Documentation for using the library can be found here: https://github.com/nkolban/esp32-snippets/tree/master/Documentation diff --git a/libraries/BLE/examples/BLE5_extended_scan/BLE5_extended_scan.ino b/libraries/BLE/examples/BLE5_extended_scan/BLE5_extended_scan.ino index f49794b6b0e..42daff86835 100644 --- a/libraries/BLE/examples/BLE5_extended_scan/BLE5_extended_scan.ino +++ b/libraries/BLE/examples/BLE5_extended_scan/BLE5_extended_scan.ino @@ -25,7 +25,7 @@ class MyBLEExtAdvertisingCallbacks : public BLEExtAdvertisingCallbacks { // here we can receive regular advertising data from BLE4.x devices Serial.println("BLE4.2"); } else { - // here we will get extended advertising data that are advertised over data channel by BLE5 divices + // here we will get extended advertising data that are advertised over data channel by BLE5 devices Serial.printf("Ext advertise: data_le: %d, data_status: %d \n", report.adv_data_len, report.data_status); } } diff --git a/libraries/BLE/examples/BLE5_extended_scan/ci.json b/libraries/BLE/examples/BLE5_extended_scan/ci.json index edef5051e09..184cc25a2b0 100644 --- a/libraries/BLE/examples/BLE5_extended_scan/ci.json +++ b/libraries/BLE/examples/BLE5_extended_scan/ci.json @@ -1,6 +1,6 @@ { - "targets": { - "esp32": false, - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_50_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/BLE5_multi_advertising/ci.json b/libraries/BLE/examples/BLE5_multi_advertising/ci.json index edef5051e09..184cc25a2b0 100644 --- a/libraries/BLE/examples/BLE5_multi_advertising/ci.json +++ b/libraries/BLE/examples/BLE5_multi_advertising/ci.json @@ -1,6 +1,6 @@ { - "targets": { - "esp32": false, - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_50_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/BLE5_periodic_advertising/BLE5_periodic_advertising.ino b/libraries/BLE/examples/BLE5_periodic_advertising/BLE5_periodic_advertising.ino index 796f63666db..0b9d4f87630 100644 --- a/libraries/BLE/examples/BLE5_periodic_advertising/BLE5_periodic_advertising.ino +++ b/libraries/BLE/examples/BLE5_periodic_advertising/BLE5_periodic_advertising.ino @@ -1,5 +1,5 @@ /* - Simple BLE5 multi advertising example on esp32 C3/S3 + Simple BLE5 periodic advertising example on esp32 C3/S3 only ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED can be used for periodic advertising author: chegewara diff --git a/libraries/BLE/examples/BLE5_periodic_advertising/ci.json b/libraries/BLE/examples/BLE5_periodic_advertising/ci.json index edef5051e09..184cc25a2b0 100644 --- a/libraries/BLE/examples/BLE5_periodic_advertising/ci.json +++ b/libraries/BLE/examples/BLE5_periodic_advertising/ci.json @@ -1,6 +1,6 @@ { - "targets": { - "esp32": false, - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_50_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/BLE5_periodic_sync/ci.json b/libraries/BLE/examples/BLE5_periodic_sync/ci.json index edef5051e09..184cc25a2b0 100644 --- a/libraries/BLE/examples/BLE5_periodic_sync/ci.json +++ b/libraries/BLE/examples/BLE5_periodic_sync/ci.json @@ -1,6 +1,6 @@ { - "targets": { - "esp32": false, - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_50_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/Beacon_Scanner/ci.json b/libraries/BLE/examples/Beacon_Scanner/ci.json index 1443137ab0d..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Beacon_Scanner/ci.json +++ b/libraries/BLE/examples/Beacon_Scanner/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/Client/ci.json b/libraries/BLE/examples/Client/ci.json index 1443137ab0d..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Client/ci.json +++ b/libraries/BLE/examples/Client/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/EddystoneTLM_Beacon/ci.json b/libraries/BLE/examples/EddystoneTLM_Beacon/ci.json index 521ae8f5ff1..abe13a7ebbb 100644 --- a/libraries/BLE/examples/EddystoneTLM_Beacon/ci.json +++ b/libraries/BLE/examples/EddystoneTLM_Beacon/ci.json @@ -1,6 +1,6 @@ { - "targets": { - "esp32h2": false, - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/EddystoneURL_Beacon/ci.json b/libraries/BLE/examples/EddystoneURL_Beacon/ci.json index 521ae8f5ff1..abe13a7ebbb 100644 --- a/libraries/BLE/examples/EddystoneURL_Beacon/ci.json +++ b/libraries/BLE/examples/EddystoneURL_Beacon/ci.json @@ -1,6 +1,6 @@ { - "targets": { - "esp32h2": false, - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/Notify/Notify.ino b/libraries/BLE/examples/Notify/Notify.ino index 896cc2260f7..6b552b01d11 100644 --- a/libraries/BLE/examples/Notify/Notify.ino +++ b/libraries/BLE/examples/Notify/Notify.ino @@ -23,9 +23,12 @@ #include #include #include +#include BLEServer *pServer = NULL; BLECharacteristic *pCharacteristic = NULL; +BLE2901 *descriptor_2901 = NULL; + bool deviceConnected = false; bool oldDeviceConnected = false; uint32_t value = 0; @@ -65,9 +68,13 @@ void setup() { BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_INDICATE ); - // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml - // Create a BLE Descriptor + // Creates BLE Descriptor 0x2902: Client Characteristic Configuration Descriptor (CCCD) pCharacteristic->addDescriptor(new BLE2902()); + // Adds also the Characteristic User Description - 0x2901 descriptor + descriptor_2901 = new BLE2901(); + descriptor_2901->setDescription("My own description for this characteristic."); + descriptor_2901->setAccessPermissions(ESP_GATT_PERM_READ); // enforce read only - default is Read|Write + pCharacteristic->addDescriptor(descriptor_2901); // Start the service pService->start(); @@ -87,7 +94,7 @@ void loop() { pCharacteristic->setValue((uint8_t *)&value, 4); pCharacteristic->notify(); value++; - delay(3); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms + delay(500); } // disconnecting if (!deviceConnected && oldDeviceConnected) { diff --git a/libraries/BLE/examples/Notify/ci.json b/libraries/BLE/examples/Notify/ci.json index 1443137ab0d..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Notify/ci.json +++ b/libraries/BLE/examples/Notify/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/Scan/ci.json b/libraries/BLE/examples/Scan/ci.json index 1443137ab0d..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Scan/ci.json +++ b/libraries/BLE/examples/Scan/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/Server/ci.json b/libraries/BLE/examples/Server/ci.json index 1443137ab0d..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Server/ci.json +++ b/libraries/BLE/examples/Server/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/Server_multiconnect/ci.json b/libraries/BLE/examples/Server_multiconnect/ci.json index 1443137ab0d..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Server_multiconnect/ci.json +++ b/libraries/BLE/examples/Server_multiconnect/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/UART/ci.json b/libraries/BLE/examples/UART/ci.json index 1443137ab0d..abe13a7ebbb 100644 --- a/libraries/BLE/examples/UART/ci.json +++ b/libraries/BLE/examples/UART/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/Write/ci.json b/libraries/BLE/examples/Write/ci.json index 1443137ab0d..abe13a7ebbb 100644 --- a/libraries/BLE/examples/Write/ci.json +++ b/libraries/BLE/examples/Write/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_SUPPORTED=y" + ] } diff --git a/libraries/BLE/examples/iBeacon/ci.json b/libraries/BLE/examples/iBeacon/ci.json index 1443137ab0d..abe13a7ebbb 100644 --- a/libraries/BLE/examples/iBeacon/ci.json +++ b/libraries/BLE/examples/iBeacon/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32s2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_BLE_SUPPORTED=y" + ] } diff --git a/libraries/BLE/library.properties b/libraries/BLE/library.properties index 074eaa639a6..7ef636223ec 100644 --- a/libraries/BLE/library.properties +++ b/libraries/BLE/library.properties @@ -1,10 +1,10 @@ name=BLE -version=2.0.0 +version=3.2.0 author=Neil Kolban maintainer=Dariusz Krempa sentence=BLE functions for ESP32 paragraph=This library provides an implementation Bluetooth Low Energy support for the ESP32 using the Arduino platform. category=Communication -url=https://github.com/nkolban/ESP32_BLE_Arduino +url=https://github.com/espressif/arduino-esp32/tree/master/libraries/BLE architectures=esp32 includes=BLEDevice.h, BLEUtils.h, BLEScan.h, BLEAdvertisedDevice.h diff --git a/libraries/BLE/src/BLE2901.cpp b/libraries/BLE/src/BLE2901.cpp new file mode 100644 index 00000000000..e929262b023 --- /dev/null +++ b/libraries/BLE/src/BLE2901.cpp @@ -0,0 +1,40 @@ +/* + BLE2901.h + + GATT Descriptor 0x2901 Characteristic User Description + + The value of this description is a user-readable string + describing the characteristic. + + The Characteristic User Description descriptor + provides a textual user description for a characteristic + value. + If the Writable Auxiliary bit of the Characteristics + Properties is set then this descriptor is written. Only one + User Description descriptor exists in a characteristic + definition. +*/ + +#include "soc/soc_caps.h" +#if SOC_BLE_SUPPORTED + +#include "sdkconfig.h" +#if defined(CONFIG_BLUEDROID_ENABLED) + +#include "BLE2901.h" + +BLE2901::BLE2901() : BLEDescriptor(BLEUUID((uint16_t)0x2901)) {} // BLE2901 + +/** + * @brief Set the Characteristic User Description + */ +void BLE2901::setDescription(String userDesc) { + if (userDesc.length() > ESP_GATT_MAX_ATTR_LEN) { + log_e("Size %d too large, must be no bigger than %d", userDesc.length(), ESP_GATT_MAX_ATTR_LEN); + return; + } + setValue(userDesc); +} + +#endif +#endif /* SOC_BLE_SUPPORTED */ diff --git a/libraries/BLE/src/BLE2901.h b/libraries/BLE/src/BLE2901.h new file mode 100644 index 00000000000..f5ad7c94add --- /dev/null +++ b/libraries/BLE/src/BLE2901.h @@ -0,0 +1,37 @@ +/* + BLE2901.h + + GATT Descriptor 0x2901 Characteristic User Description + + The value of this description is a user-readable string + describing the characteristic. + + The Characteristic User Description descriptor + provides a textual user description for a characteristic + value. + If the Writable Auxiliary bit of the Characteristics + Properties is set then this descriptor is written. Only one + User Description descriptor exists in a characteristic + definition. + +*/ + +#ifndef COMPONENTS_CPP_UTILS_BLE2901_H_ +#define COMPONENTS_CPP_UTILS_BLE2901_H_ +#include "soc/soc_caps.h" +#if SOC_BLE_SUPPORTED + +#include "sdkconfig.h" +#if defined(CONFIG_BLUEDROID_ENABLED) + +#include "BLEDescriptor.h" + +class BLE2901 : public BLEDescriptor { +public: + BLE2901(); + void setDescription(String desc); +}; // BLE2901 + +#endif /* CONFIG_BLUEDROID_ENABLED */ +#endif /* SOC_BLE_SUPPORTED */ +#endif /* COMPONENTS_CPP_UTILS_BLE2901_H_ */ diff --git a/libraries/BLE/src/BLEAdvertising.cpp b/libraries/BLE/src/BLEAdvertising.cpp index 1f2e6cd2887..fe39a69c206 100644 --- a/libraries/BLE/src/BLEAdvertising.cpp +++ b/libraries/BLE/src/BLEAdvertising.cpp @@ -183,7 +183,7 @@ void BLEAdvertising::setScanFilter(bool scanRequestWhitelistOnly, bool connectWh * @brief Set the advertisement data that is to be published in a regular advertisement. * @param [in] advertisementData The data to be advertised. */ -void BLEAdvertising::setAdvertisementData(BLEAdvertisementData &advertisementData) { +bool BLEAdvertising::setAdvertisementData(BLEAdvertisementData &advertisementData) { log_v(">> setAdvertisementData"); esp_err_t errRc = ::esp_ble_gap_config_adv_data_raw((uint8_t *)advertisementData.getPayload().c_str(), advertisementData.getPayload().length()); if (errRc != ESP_OK) { @@ -191,13 +191,14 @@ void BLEAdvertising::setAdvertisementData(BLEAdvertisementData &advertisementDat } m_customAdvData = true; // Set the flag that indicates we are using custom advertising data. log_v("<< setAdvertisementData"); + return ESP_OK == errRc; } // setAdvertisementData /** * @brief Set the advertisement data that is to be published in a scan response. * @param [in] advertisementData The data to be advertised. */ -void BLEAdvertising::setScanResponseData(BLEAdvertisementData &advertisementData) { +bool BLEAdvertising::setScanResponseData(BLEAdvertisementData &advertisementData) { log_v(">> setScanResponseData"); esp_err_t errRc = ::esp_ble_gap_config_scan_rsp_data_raw((uint8_t *)advertisementData.getPayload().c_str(), advertisementData.getPayload().length()); if (errRc != ESP_OK) { @@ -205,6 +206,7 @@ void BLEAdvertising::setScanResponseData(BLEAdvertisementData &advertisementData } m_customScanResponseData = true; // Set the flag that indicates we are using custom scan response data. log_v("<< setScanResponseData"); + return ESP_OK == errRc; } // setScanResponseData /** @@ -212,7 +214,7 @@ void BLEAdvertising::setScanResponseData(BLEAdvertisementData &advertisementData * Start advertising. * @return N/A. */ -void BLEAdvertising::start() { +bool BLEAdvertising::start() { log_v(">> start: customAdvData: %d, customScanResponseData: %d", m_customAdvData, m_customScanResponseData); // We have a vector of service UUIDs that we wish to advertise. In order to use the @@ -225,7 +227,7 @@ void BLEAdvertising::start() { m_advData.p_service_uuid = (uint8_t *)malloc(m_advData.service_uuid_len); if (!m_advData.p_service_uuid) { log_e(">> start failed: out of memory"); - return; + return false; } uint8_t *p = m_advData.p_service_uuid; @@ -250,7 +252,7 @@ void BLEAdvertising::start() { errRc = ::esp_ble_gap_config_adv_data(&m_advData); if (errRc != ESP_OK) { log_e("<< esp_ble_gap_config_adv_data: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; + return false; } } @@ -266,7 +268,7 @@ void BLEAdvertising::start() { errRc = ::esp_ble_gap_config_adv_data(&m_scanRespData); if (errRc != ESP_OK) { log_e("<< esp_ble_gap_config_adv_data (Scan response): rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; + return false; } } @@ -279,9 +281,10 @@ void BLEAdvertising::start() { errRc = ::esp_ble_gap_start_advertising(&m_advParams); if (errRc != ESP_OK) { log_e("<< esp_ble_gap_start_advertising: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; + } else { + log_v("<< start"); } - log_v("<< start"); + return ESP_OK == errRc; } // start /** @@ -289,14 +292,15 @@ void BLEAdvertising::start() { * Stop advertising. * @return N/A. */ -void BLEAdvertising::stop() { +bool BLEAdvertising::stop() { log_v(">> stop"); esp_err_t errRc = ::esp_ble_gap_stop_advertising(); if (errRc != ESP_OK) { log_e("esp_ble_gap_stop_advertising: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; + } else { + log_v("<< stop"); } - log_v("<< stop"); + return ESP_OK == errRc; } // stop /** @@ -305,17 +309,17 @@ void BLEAdvertising::stop() { * @param [in] Bluetooth address type. * Set BLE address. */ - -void BLEAdvertising::setDeviceAddress(esp_bd_addr_t addr, esp_ble_addr_type_t type) { +bool BLEAdvertising::setDeviceAddress(esp_bd_addr_t addr, esp_ble_addr_type_t type) { log_v(">> setPrivateAddress"); m_advParams.own_addr_type = type; esp_err_t errRc = esp_ble_gap_set_rand_addr((uint8_t *)addr); if (errRc != ESP_OK) { log_e("esp_ble_gap_set_rand_addr: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; + } else { + log_v("<< setPrivateAddress"); } - log_v("<< setPrivateAddress"); + return ESP_OK == errRc; } // setPrivateAddress /** @@ -352,7 +356,7 @@ void BLEAdvertisementData::setCompleteServices(BLEUUID uuid) { switch (uuid.bitSize()) { case 16: { - // [Len] [0x02] [LL] [HH] + // [Len] [0x03] [LL] [HH] cdata[0] = 3; cdata[1] = ESP_BLE_AD_TYPE_16SRV_CMPL; // 0x03 addData(String(cdata, 2) + String((char *)&uuid.getNative()->uuid.uuid16, 2)); @@ -361,7 +365,7 @@ void BLEAdvertisementData::setCompleteServices(BLEUUID uuid) { case 32: { - // [Len] [0x04] [LL] [LL] [HH] [HH] + // [Len] [0x05] [LL] [LL] [HH] [HH] cdata[0] = 5; cdata[1] = ESP_BLE_AD_TYPE_32SRV_CMPL; // 0x05 addData(String(cdata, 2) + String((char *)&uuid.getNative()->uuid.uuid32, 4)); @@ -370,7 +374,7 @@ void BLEAdvertisementData::setCompleteServices(BLEUUID uuid) { case 128: { - // [Len] [0x04] [0] [1] ... [15] + // [Len] [0x07] [0] [1] ... [15] cdata[0] = 17; cdata[1] = ESP_BLE_AD_TYPE_128SRV_CMPL; // 0x07 addData(String(cdata, 2) + String((char *)uuid.getNative()->uuid.uuid128, 16)); @@ -453,7 +457,7 @@ void BLEAdvertisementData::setPartialServices(BLEUUID uuid) { case 128: { - // [Len] [0x04] [0] [1] ... [15] + // [Len] [0x06] [0] [1] ... [15] cdata[0] = 17; cdata[1] = ESP_BLE_AD_TYPE_128SRV_PART; // 0x06 addData(String(cdata, 2) + String((char *)&uuid.getNative()->uuid.uuid128, 16)); diff --git a/libraries/BLE/src/BLEAdvertising.h b/libraries/BLE/src/BLEAdvertising.h index 9da70a3d9ca..1e573ac814f 100644 --- a/libraries/BLE/src/BLEAdvertising.h +++ b/libraries/BLE/src/BLEAdvertising.h @@ -54,18 +54,18 @@ class BLEAdvertising { bool removeServiceUUID(int index); bool removeServiceUUID(BLEUUID serviceUUID); bool removeServiceUUID(const char *serviceUUID); - void start(); - void stop(); + bool start(); + bool stop(); void setAppearance(uint16_t appearance); void setAdvertisementType(esp_ble_adv_type_t adv_type); void setAdvertisementChannelMap(esp_ble_adv_channel_t channel_map); void setMaxInterval(uint16_t maxinterval); void setMinInterval(uint16_t mininterval); - void setAdvertisementData(BLEAdvertisementData &advertisementData); + bool setAdvertisementData(BLEAdvertisementData &advertisementData); void setScanFilter(bool scanRequestWhitelistOnly, bool connectWhitelistOnly); - void setScanResponseData(BLEAdvertisementData &advertisementData); + bool setScanResponseData(BLEAdvertisementData &advertisementData); void setPrivateAddress(esp_ble_addr_type_t type = BLE_ADDR_TYPE_RANDOM); - void setDeviceAddress(esp_bd_addr_t addr, esp_ble_addr_type_t type = BLE_ADDR_TYPE_RANDOM); + bool setDeviceAddress(esp_bd_addr_t addr, esp_ble_addr_type_t type = BLE_ADDR_TYPE_RANDOM); void handleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param); void setMinPreferred(uint16_t); diff --git a/libraries/BLE/src/BLECharacteristic.cpp b/libraries/BLE/src/BLECharacteristic.cpp index 1d1bafdda1c..b03d524a6a5 100644 --- a/libraries/BLE/src/BLECharacteristic.cpp +++ b/libraries/BLE/src/BLECharacteristic.cpp @@ -279,9 +279,13 @@ void BLECharacteristic::handleGATTServerEvent(esp_gatts_cb_event_t event, esp_ga log_d(" - Response to write event: New value: handle: %.2x, uuid: %s", getHandle(), getUUID().toString().c_str()); +// The call to BLEUtils::buildHexData() doesn't output anything if the log level is not +// "DEBUG". As it is quite CPU intensive, it is much better to not call it if not needed. +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG char *pHexData = BLEUtils::buildHexData(nullptr, param->write.value, param->write.len); log_d(" - Data: length: %d, data: %s", param->write.len, pHexData); free(pHexData); +#endif if (param->write.need_rsp) { esp_gatt_rsp_t rsp; @@ -390,9 +394,13 @@ void BLECharacteristic::handleGATTServerEvent(esp_gatts_cb_event_t event, esp_ga rsp.attr_value.handle = param->read.handle; rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE; +// The call to BLEUtils::buildHexData() doesn't output anything if the log level is not +// "DEBUG". As it is quite CPU intensive, it is much better to not call it if not needed. +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG char *pHexData = BLEUtils::buildHexData(nullptr, rsp.attr_value.value, rsp.attr_value.len); log_d(" - Data: length=%d, data=%s, offset=%d", rsp.attr_value.len, pHexData, rsp.attr_value.offset); free(pHexData); +#endif esp_err_t errRc = ::esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id, ESP_GATT_OK, &rsp); if (errRc != ESP_OK) { @@ -471,7 +479,20 @@ void BLECharacteristic::notify(bool is_notification) { m_pCallbacks->onNotify(this); // Invoke the notify callback. + // GeneralUtils::hexDump() doesn't output anything if the log level is not + // "VERBOSE". Additionally, it is very CPU intensive, even when it doesn't + // output anything! So it is much better to *not* call it at all if not needed. + // In a simple program which calls BLECharacteristic::notify() every 50 ms, + // the performance gain of this little optimization is 37% in release mode + // (-O3) and 57% in debug mode. + // Of course, the "#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE" guard + // could also be put inside the GeneralUtils::hexDump() function itself. But + // it's better to put it here also, as it is clearer (indicating a verbose log + // thing) and it allows to remove the "m_value.getValue().c_str()" call, which + // is, in itself, quite CPU intensive. +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE GeneralUtils::hexDump((uint8_t *)m_value.getValue().c_str(), m_value.getValue().length()); +#endif if (getService()->getServer()->getConnectedCount() == 0) { log_v("<< notify: No connected clients."); @@ -624,9 +645,13 @@ void BLECharacteristic::setReadProperty(bool value) { * @param [in] length The length of the data in bytes. */ void BLECharacteristic::setValue(uint8_t *data, size_t length) { +// The call to BLEUtils::buildHexData() doesn't output anything if the log level is not +// "VERBOSE". As it is quite CPU intensive, it is much better to not call it if not needed. +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE char *pHex = BLEUtils::buildHexData(nullptr, data, length); log_v(">> setValue: length=%d, data=%s, characteristic UUID=%s", length, pHex, getUUID().toString().c_str()); free(pHex); +#endif if (length > ESP_GATT_MAX_ATTR_LEN) { log_e("Size %d too large, must be no bigger than %d", length, ESP_GATT_MAX_ATTR_LEN); return; diff --git a/libraries/BLE/src/BLEClient.cpp b/libraries/BLE/src/BLEClient.cpp index ee60030a81f..29fa0fbc140 100644 --- a/libraries/BLE/src/BLEClient.cpp +++ b/libraries/BLE/src/BLEClient.cpp @@ -343,7 +343,7 @@ void BLEClient::gattClientEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t BLEUUID uuid = BLEUUID(evtParam->search_res.srvc_id); BLERemoteService *pRemoteService = new BLERemoteService(evtParam->search_res.srvc_id, this, evtParam->search_res.start_handle, evtParam->search_res.end_handle); - m_servicesMap.insert(std::pair(uuid.toString(), pRemoteService)); + m_servicesMap.insert(std::pair(uuid.toString().c_str(), pRemoteService)); m_servicesMapByInstID.insert(std::pair(pRemoteService, evtParam->search_res.srvc_id.inst_id)); break; } // ESP_GATTC_SEARCH_RES_EVT @@ -428,7 +428,7 @@ BLERemoteService *BLEClient::getService(BLEUUID uuid) { if (!m_haveServices) { getServices(); } - String uuidStr = uuid.toString(); + std::string uuidStr = uuid.toString().c_str(); for (auto &myPair : m_servicesMap) { if (myPair.first == uuidStr) { log_v("<< getService: found the service with uuid: %s", uuid.toString().c_str()); @@ -445,7 +445,7 @@ BLERemoteService *BLEClient::getService(BLEUUID uuid) { * services and wait until we have received them all. * @return N/A */ -std::map *BLEClient::getServices() { +std::map *BLEClient::getServices() { /* * Design * ------ diff --git a/libraries/BLE/src/BLEClient.h b/libraries/BLE/src/BLEClient.h index 5820b86349b..ddb932fcd95 100644 --- a/libraries/BLE/src/BLEClient.h +++ b/libraries/BLE/src/BLEClient.h @@ -42,7 +42,7 @@ class BLEClient { void disconnect(); // Disconnect from the remote BLE Server BLEAddress getPeerAddress(); // Get the address of the remote BLE Server int getRssi(); // Get the RSSI of the remote BLE Server - std::map *getServices(); // Get a map of the services offered by the remote BLE Server + std::map *getServices(); // Get a map of the services offered by the remote BLE Server BLERemoteService *getService(const char *uuid); // Get a reference to a specified service offered by the remote BLE server. BLERemoteService *getService(BLEUUID uuid); // Get a reference to a specified service offered by the remote BLE server. String getValue(BLEUUID serviceUUID, BLEUUID characteristicUUID); // Get the value of a given characteristic at a given service. @@ -82,7 +82,7 @@ class BLEClient { FreeRTOS::Semaphore m_semaphoreOpenEvt = FreeRTOS::Semaphore("OpenEvt"); FreeRTOS::Semaphore m_semaphoreSearchCmplEvt = FreeRTOS::Semaphore("SearchCmplEvt"); FreeRTOS::Semaphore m_semaphoreRssiCmplEvt = FreeRTOS::Semaphore("RssiCmplEvt"); - std::map m_servicesMap; + std::map m_servicesMap; std::map m_servicesMapByInstID; void clearServices(); // Clear any existing services. uint16_t m_mtu = 23; diff --git a/libraries/BLE/src/BLERemoteCharacteristic.cpp b/libraries/BLE/src/BLERemoteCharacteristic.cpp index 3e066de347a..60d5108c1fc 100644 --- a/libraries/BLE/src/BLERemoteCharacteristic.cpp +++ b/libraries/BLE/src/BLERemoteCharacteristic.cpp @@ -177,7 +177,7 @@ void BLERemoteCharacteristic::gattClientEventHandler(esp_gattc_cb_event_t event, } // At this point, we have determined that the event is for us, so now we save the value - // and unlock the semaphore to ensure that the requestor of the data can continue. + // and unlock the semaphore to ensure that the requester of the data can continue. if (evtParam->read.status == ESP_GATT_OK) { m_value = String((char *)evtParam->read.value, evtParam->read.value_len); if (m_rawData != nullptr) { @@ -297,7 +297,7 @@ void BLERemoteCharacteristic::retrieveDescriptors() { // We now have a new characteristic ... let us add that to our set of known characteristics BLERemoteDescriptor *pNewRemoteDescriptor = new BLERemoteDescriptor(result.handle, BLEUUID(result.uuid), this); - m_descriptorMap.insert(std::pair(pNewRemoteDescriptor->getUUID().toString(), pNewRemoteDescriptor)); + m_descriptorMap.insert(std::pair(pNewRemoteDescriptor->getUUID().toString().c_str(), pNewRemoteDescriptor)); offset++; } // while true @@ -308,7 +308,7 @@ void BLERemoteCharacteristic::retrieveDescriptors() { /** * @brief Retrieve the map of descriptors keyed by UUID. */ -std::map *BLERemoteCharacteristic::getDescriptors() { +std::map *BLERemoteCharacteristic::getDescriptors() { return &m_descriptorMap; } // getDescriptors @@ -329,7 +329,7 @@ uint16_t BLERemoteCharacteristic::getHandle() { */ BLERemoteDescriptor *BLERemoteCharacteristic::getDescriptor(BLEUUID uuid) { log_v(">> getDescriptor: uuid: %s", uuid.toString().c_str()); - String v = uuid.toString(); + std::string v = uuid.toString().c_str(); for (auto &myPair : m_descriptorMap) { if (myPair.first == v) { log_v("<< getDescriptor: found"); diff --git a/libraries/BLE/src/BLERemoteCharacteristic.h b/libraries/BLE/src/BLERemoteCharacteristic.h index 97a7966ab77..dc63a3bc1a6 100644 --- a/libraries/BLE/src/BLERemoteCharacteristic.h +++ b/libraries/BLE/src/BLERemoteCharacteristic.h @@ -39,7 +39,7 @@ class BLERemoteCharacteristic { bool canWrite(); bool canWriteNoResponse(); BLERemoteDescriptor *getDescriptor(BLEUUID uuid); - std::map *getDescriptors(); + std::map *getDescriptors(); BLERemoteService *getRemoteService(); uint16_t getHandle(); BLEUUID getUUID(); @@ -82,7 +82,7 @@ class BLERemoteCharacteristic { notify_callback m_notifyCallback; // We maintain a map of descriptors owned by this characteristic keyed by a string representation of the UUID. - std::map m_descriptorMap; + std::map m_descriptorMap; }; // BLERemoteCharacteristic #endif /* CONFIG_BLUEDROID_ENABLED */ diff --git a/libraries/BLE/src/BLERemoteDescriptor.cpp b/libraries/BLE/src/BLERemoteDescriptor.cpp index d57f11eb88d..b6d654cf9ec 100644 --- a/libraries/BLE/src/BLERemoteDescriptor.cpp +++ b/libraries/BLE/src/BLERemoteDescriptor.cpp @@ -69,7 +69,7 @@ void BLERemoteDescriptor::gattClientEventHandler(esp_gattc_cb_event_t event, esp } else { m_value = ""; } - // Unlock the semaphore to ensure that the requestor of the data can continue. + // Unlock the semaphore to ensure that the requester of the data can continue. m_semaphoreReadDescrEvt.give(); break; diff --git a/libraries/BLE/src/BLERemoteService.cpp b/libraries/BLE/src/BLERemoteService.cpp index 0ae12e03d21..e4cc31dbb33 100644 --- a/libraries/BLE/src/BLERemoteService.cpp +++ b/libraries/BLE/src/BLERemoteService.cpp @@ -79,8 +79,8 @@ void BLERemoteService::gattClientEventHandler(esp_gattc_cb_event_t event, esp_ga // This is an indication that we now have the characteristic details for a characteristic owned // by this service so remember it. - m_characteristicMap.insert(std::pair( - BLEUUID(evtParam->get_char.char_id.uuid).toString(), + m_characteristicMap.insert(std::pair( + BLEUUID(evtParam->get_char.char_id.uuid).toString().c_str(), new BLERemoteCharacteristic(evtParam->get_char.char_id, evtParam->get_char.char_prop, this) )); @@ -134,7 +134,7 @@ BLERemoteCharacteristic *BLERemoteService::getCharacteristic(BLEUUID uuid) { if (!m_haveCharacteristics) { retrieveCharacteristics(); } - String v = uuid.toString(); + std::string v = uuid.toString().c_str(); for (auto &myPair : m_characteristicMap) { if (myPair.first == v) { return myPair.second; @@ -179,7 +179,9 @@ void BLERemoteService::retrieveCharacteristics() { // We now have a new characteristic ... let us add that to our set of known characteristics BLERemoteCharacteristic *pNewRemoteCharacteristic = new BLERemoteCharacteristic(result.char_handle, BLEUUID(result.uuid), result.properties, this); - m_characteristicMap.insert(std::pair(pNewRemoteCharacteristic->getUUID().toString(), pNewRemoteCharacteristic)); + m_characteristicMap.insert( + std::pair(pNewRemoteCharacteristic->getUUID().toString().c_str(), pNewRemoteCharacteristic) + ); m_characteristicMapByHandle.insert(std::pair(result.char_handle, pNewRemoteCharacteristic)); offset++; // Increment our count of number of descriptors found. } // Loop forever (until we break inside the loop). @@ -192,7 +194,7 @@ void BLERemoteService::retrieveCharacteristics() { * @brief Retrieve a map of all the characteristics of this service. * @return A map of all the characteristics of this service. */ -std::map *BLERemoteService::getCharacteristics() { +std::map *BLERemoteService::getCharacteristics() { log_v(">> getCharacteristics() for service: %s", getUUID().toString().c_str()); // If is possible that we have not read the characteristics associated with the service so do that // now. The request to retrieve the characteristics by calling "retrieveCharacteristics" is a blocking diff --git a/libraries/BLE/src/BLERemoteService.h b/libraries/BLE/src/BLERemoteService.h index 0dbd6823039..49845a0a1e8 100644 --- a/libraries/BLE/src/BLERemoteService.h +++ b/libraries/BLE/src/BLERemoteService.h @@ -34,7 +34,7 @@ class BLERemoteService { BLERemoteCharacteristic *getCharacteristic(const char *uuid); // Get the specified characteristic reference. BLERemoteCharacteristic *getCharacteristic(BLEUUID uuid); // Get the specified characteristic reference. BLERemoteCharacteristic *getCharacteristic(uint16_t uuid); // Get the specified characteristic reference. - std::map *getCharacteristics(); + std::map *getCharacteristics(); std::map *getCharacteristicsByHandle(); // Get the characteristics map. void getCharacteristics(std::map **pCharacteristicMap); @@ -66,7 +66,7 @@ class BLERemoteService { // Properties // We maintain a map of characteristics owned by this service keyed by a string representation of the UUID. - std::map m_characteristicMap; + std::map m_characteristicMap; // We maintain a map of characteristics owned by this service keyed by a handle. std::map m_characteristicMapByHandle; diff --git a/libraries/BLE/src/BLEScan.cpp b/libraries/BLE/src/BLEScan.cpp index 689ce557f29..0a99b46c61d 100644 --- a/libraries/BLE/src/BLEScan.cpp +++ b/libraries/BLE/src/BLEScan.cpp @@ -99,7 +99,7 @@ void BLEScan::handleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_ bool shouldDelete = true; if (!m_wantDuplicates) { - if (m_scanResults.m_vectorAdvertisedDevices.count(advertisedAddress.toString()) != 0) { + if (m_scanResults.m_vectorAdvertisedDevices.count(advertisedAddress.toString().c_str()) != 0) { found = true; } @@ -130,7 +130,8 @@ void BLEScan::handleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_ m_pAdvertisedDeviceCallbacks->onResult(*advertisedDevice); } if (!m_wantDuplicates && !found) { // if no callback and not want duplicate, and not already in vector, record it - m_scanResults.m_vectorAdvertisedDevices.insert(std::pair(advertisedAddress.toString(), advertisedDevice)); + m_scanResults.m_vectorAdvertisedDevices.insert(std::pair(advertisedAddress.toString().c_str(), advertisedDevice) + ); shouldDelete = false; } if (shouldDelete) { @@ -443,8 +444,8 @@ void BLEScan::stop() { // delete peer device from cache after disconnecting, it is required in case we are connecting to devices with not public address void BLEScan::erase(BLEAddress address) { log_i("erase device: %s", address.toString().c_str()); - BLEAdvertisedDevice *advertisedDevice = m_scanResults.m_vectorAdvertisedDevices.find(address.toString())->second; - m_scanResults.m_vectorAdvertisedDevices.erase(address.toString()); + BLEAdvertisedDevice *advertisedDevice = m_scanResults.m_vectorAdvertisedDevices.find(address.toString().c_str())->second; + m_scanResults.m_vectorAdvertisedDevices.erase(address.toString().c_str()); delete advertisedDevice; } diff --git a/libraries/BLE/src/BLEScan.h b/libraries/BLE/src/BLEScan.h index 1c2c0f406a0..080e3b803b2 100644 --- a/libraries/BLE/src/BLEScan.h +++ b/libraries/BLE/src/BLEScan.h @@ -53,7 +53,7 @@ class BLEScanResults { private: friend BLEScan; - std::map m_vectorAdvertisedDevices; + std::map m_vectorAdvertisedDevices; }; /** diff --git a/libraries/BluetoothSerial/examples/DiscoverConnect/DiscoverConnect.ino b/libraries/BluetoothSerial/examples/DiscoverConnect/DiscoverConnect.ino index e9ec101b91e..bd50c6b1d90 100644 --- a/libraries/BluetoothSerial/examples/DiscoverConnect/DiscoverConnect.ino +++ b/libraries/BluetoothSerial/examples/DiscoverConnect/DiscoverConnect.ino @@ -80,7 +80,7 @@ void setup() { Serial.println("Didn't find any devices"); } } else { - Serial.println("Error on discoverAsync f.e. not workin after a \"connect\""); + Serial.println("Error on discoverAsync f.e. not working after a \"connect\""); } } diff --git a/libraries/BluetoothSerial/examples/DiscoverConnect/ci.json b/libraries/BluetoothSerial/examples/DiscoverConnect/ci.json index 1af543242e3..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/DiscoverConnect/ci.json +++ b/libraries/BluetoothSerial/examples/DiscoverConnect/ci.json @@ -1,9 +1,6 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_BT_SPP_ENABLED=y" + ] } diff --git a/libraries/BluetoothSerial/examples/GetLocalMAC/ci.json b/libraries/BluetoothSerial/examples/GetLocalMAC/ci.json index 1af543242e3..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/GetLocalMAC/ci.json +++ b/libraries/BluetoothSerial/examples/GetLocalMAC/ci.json @@ -1,9 +1,6 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_BT_SPP_ENABLED=y" + ] } diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json b/libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json index 1af543242e3..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT/ci.json @@ -1,9 +1,6 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_BT_SPP_ENABLED=y" + ] } diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json b/libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json index 1af543242e3..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json +++ b/libraries/BluetoothSerial/examples/SerialToSerialBTM/ci.json @@ -1,9 +1,6 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_BT_SPP_ENABLED=y" + ] } diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/SerialToSerialBT_Legacy.ino b/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/SerialToSerialBT_Legacy.ino index 343bd79c79b..d184a4ea769 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/SerialToSerialBT_Legacy.ino +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/SerialToSerialBT_Legacy.ino @@ -17,12 +17,6 @@ #error Serial Port Profile for Bluetooth is not available or not enabled. It is only available for the ESP32 chip. #endif -// Check Simple Secure Pairing -#if defined(CONFIG_BT_SSP_ENABLED) -#warning Legacy Pairing is disabled (CONFIG_BT_SSP_ENABLED is enabled. Disable it in menuconfig). -void setup() {} -void loop() {} -#else const char *deviceName = "ESP32_Legacy_example"; BluetoothSerial SerialBT; @@ -62,4 +56,3 @@ void loop() { delay(1); // Feed the watchdog } } -#endif diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json b/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json index 1af543242e3..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT_Legacy/ci.json @@ -1,9 +1,6 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_BT_SPP_ENABLED=y" + ] } diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/SerialToSerialBT_SSP.ino b/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/SerialToSerialBT_SSP.ino index eb0c05e0038..e5d05eed14e 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/SerialToSerialBT_SSP.ino +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/SerialToSerialBT_SSP.ino @@ -22,11 +22,6 @@ #error Serial Port Profile for Bluetooth is not available or not enabled. It is only available for the ESP32 chip. #endif -// Check Simple Secure Pairing -#if !defined(CONFIG_BT_SSP_ENABLED) -#error Simple Secure Pairing for Bluetooth is not available or not enabled. -#endif - const char *deviceName = "ESP32_SSP_example"; // The following lines defines the method of pairing diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json b/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json index 1af543242e3..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json +++ b/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/ci.json @@ -1,9 +1,6 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_BT_SPP_ENABLED=y" + ] } diff --git a/libraries/BluetoothSerial/examples/bt_classic_device_discovery/ci.json b/libraries/BluetoothSerial/examples/bt_classic_device_discovery/ci.json index 1af543242e3..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/bt_classic_device_discovery/ci.json +++ b/libraries/BluetoothSerial/examples/bt_classic_device_discovery/ci.json @@ -1,9 +1,6 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_BT_SPP_ENABLED=y" + ] } diff --git a/libraries/BluetoothSerial/examples/bt_remove_paired_devices/ci.json b/libraries/BluetoothSerial/examples/bt_remove_paired_devices/ci.json index 1af543242e3..b5097688f52 100644 --- a/libraries/BluetoothSerial/examples/bt_remove_paired_devices/ci.json +++ b/libraries/BluetoothSerial/examples/bt_remove_paired_devices/ci.json @@ -1,9 +1,6 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_BT_SPP_ENABLED=y" + ] } diff --git a/libraries/BluetoothSerial/library.properties b/libraries/BluetoothSerial/library.properties index 8581da830d0..0a382410bba 100644 --- a/libraries/BluetoothSerial/library.properties +++ b/libraries/BluetoothSerial/library.properties @@ -1,5 +1,5 @@ name=BluetoothSerial -version=2.0.0 +version=3.2.0 author=Evandro Copercini maintainer=Evandro Copercini sentence=Simple UART to Classical Bluetooth bridge for ESP32 diff --git a/libraries/BluetoothSerial/src/BluetoothSerial.cpp b/libraries/BluetoothSerial/src/BluetoothSerial.cpp index 9eaf7bda816..3d00504c1b1 100644 --- a/libraries/BluetoothSerial/src/BluetoothSerial.cpp +++ b/libraries/BluetoothSerial/src/BluetoothSerial.cpp @@ -71,11 +71,9 @@ static esp_bd_addr_t _peer_bd_addr; static char _remote_name[ESP_BT_GAP_MAX_BDNAME_LEN + 1]; static bool _isRemoteAddressSet; static bool _isMaster; -#ifdef CONFIG_BT_SSP_ENABLED static bool _enableSSP; static bool _IO_CAP_INPUT; static bool _IO_CAP_OUTPUT; -#endif esp_bt_pin_code_t _pin_code = {0}; uint8_t _pin_code_len = 0; // Number of valid Bytes in the esp_bt_pin_code_t array static esp_spp_sec_t _sec_mask; @@ -538,7 +536,6 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa esp_bt_gap_pin_reply(param->pin_req.bda, true, _pin_code_len, _pin_code); } break; -#ifdef CONFIG_BT_SSP_ENABLED case ESP_BT_GAP_CFM_REQ_EVT: // Enum 6 - Security Simple Pairing User Confirmation request. log_i("ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val); if (confirm_request_callback) { @@ -549,13 +546,10 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, false); } break; -#endif case ESP_BT_GAP_KEY_NOTIF_EVT: // Enum 7 - Security Simple Pairing Passkey Notification log_i("ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey); break; - -#ifdef CONFIG_BT_SSP_ENABLED case ESP_BT_GAP_KEY_REQ_EVT: // Enum 8 - Security Simple Pairing Passkey request log_i("ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!"); if (key_request_callback) { @@ -566,7 +560,6 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, false); } break; -#endif case ESP_BT_GAP_READ_RSSI_DELTA_EVT: // Enum 9 - Read rssi event log_i("ESP_BT_GAP_READ_RSSI_DELTA_EVT Read rssi event"); @@ -705,9 +698,8 @@ static bool _init_bt(const char *deviceName, bt_mode mode) { } log_i("device name set"); - esp_bt_dev_set_device_name(deviceName); + esp_bt_gap_set_device_name(deviceName); -#ifdef CONFIG_BT_SSP_ENABLED if (_enableSSP) { log_i("Simple Secure Pairing"); esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; @@ -723,7 +715,6 @@ static bool _init_bt(const char *deviceName, bt_mode mode) { } esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t)); } -#endif // the default BTA_DM_COD_LOUDSPEAKER does not work with the macOS BT stack esp_bt_cod_t cod; @@ -878,7 +869,7 @@ size_t BluetoothSerial::write(const uint8_t *buffer, size_t size) { void BluetoothSerial::flush() { if (_spp_tx_queue != NULL) { while (uxQueueMessagesWaiting(_spp_tx_queue) > 0) { - delay(100); + delay(2); } } } @@ -894,7 +885,6 @@ void BluetoothSerial::memrelease() { esp_bt_mem_release(ESP_BT_MODE_BTDM); } -#ifdef CONFIG_BT_SSP_ENABLED void BluetoothSerial::onConfirmRequest(ConfirmRequestCb cb) { confirm_request_callback = cb; } @@ -906,7 +896,6 @@ void BluetoothSerial::onKeyRequest(KeyRequestCb cb) { void BluetoothSerial::respondPasskey(uint32_t passkey) { esp_bt_gap_ssp_passkey_reply(current_bd_addr, true, passkey); } -#endif void BluetoothSerial::onAuthComplete(AuthCompleteCb cb) { auth_complete_callback = cb; @@ -921,7 +910,6 @@ esp_err_t BluetoothSerial::register_callback(esp_spp_cb_t callback) { return ESP_OK; } -#ifdef CONFIG_BT_SSP_ENABLED // Enable Simple Secure Pairing (using generated PIN) // This must be called before calling begin, otherwise has no effect! void BluetoothSerial::enableSSP() { @@ -957,8 +945,6 @@ void BluetoothSerial::disableSSP() { _enableSSP = false; } -#else - bool BluetoothSerial::setPin(const char *pin, uint8_t pin_code_len) { if (pin_code_len == 0 || pin_code_len > 16) { log_e("PIN code must be 1-16 Bytes long! Called with length %d", pin_code_len); @@ -968,7 +954,6 @@ bool BluetoothSerial::setPin(const char *pin, uint8_t pin_code_len) { memcpy(_pin_code, pin, pin_code_len); return (esp_bt_gap_set_pin(ESP_BT_PIN_TYPE_FIXED, _pin_code_len, _pin_code) == ESP_OK); } -#endif bool BluetoothSerial::connect(String remoteName) { bool retval = false; diff --git a/libraries/BluetoothSerial/src/BluetoothSerial.h b/libraries/BluetoothSerial/src/BluetoothSerial.h index 6b7ba419e00..d59fbf1f714 100644 --- a/libraries/BluetoothSerial/src/BluetoothSerial.h +++ b/libraries/BluetoothSerial/src/BluetoothSerial.h @@ -56,21 +56,16 @@ class BluetoothSerial : public Stream { void onData(BluetoothSerialDataCb cb); esp_err_t register_callback(esp_spp_cb_t callback); -#ifdef CONFIG_BT_SSP_ENABLED void onConfirmRequest(ConfirmRequestCb cb); void onKeyRequest(KeyRequestCb cb); void respondPasskey(uint32_t passkey); -#endif void onAuthComplete(AuthCompleteCb cb); void confirmReply(boolean confirm); -#ifdef CONFIG_BT_SSP_ENABLED void enableSSP(); void enableSSP(bool inputCapability, bool outputCapability); void disableSSP(); -#else bool setPin(const char *pin, uint8_t pin_code_len); -#endif bool connect(String remoteName); bool connect( uint8_t remoteAddress[], int channel = 0, esp_spp_sec_t sec_mask = (ESP_SPP_SEC_ENCRYPT | ESP_SPP_SEC_AUTHENTICATE), diff --git a/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino b/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino index f5de8aa9b57..d956dc14ad3 100644 --- a/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino +++ b/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino @@ -39,7 +39,11 @@ void setup() { // by default DNSServer is started serving any "*" domain name. It will reply // AccessPoint's IP to all DNS request (this is required for Captive Portal detection) - dnsServer.start(); + if (dnsServer.start()) { + Serial.println("Started DNS server in captive portal-mode"); + } else { + Serial.println("Err: Can't start DNS server!"); + } // serve a simple root page server.on("/", handleRoot); diff --git a/libraries/DNSServer/examples/CaptivePortal/ci.json b/libraries/DNSServer/examples/CaptivePortal/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/DNSServer/examples/CaptivePortal/ci.json +++ b/libraries/DNSServer/examples/CaptivePortal/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/DNSServer/library.properties b/libraries/DNSServer/library.properties index bbeb7adf1b5..5e70a6ec03a 100644 --- a/libraries/DNSServer/library.properties +++ b/libraries/DNSServer/library.properties @@ -1,5 +1,5 @@ name=DNSServer -version=2.0.0 +version=3.2.0 author=Kristijan Novoselić maintainer=Kristijan Novoselić, sentence=A simple DNS server for ESP32. diff --git a/libraries/DNSServer/src/DNSServer.cpp b/libraries/DNSServer/src/DNSServer.cpp index 69e41092dc5..28cf89d6ede 100644 --- a/libraries/DNSServer/src/DNSServer.cpp +++ b/libraries/DNSServer/src/DNSServer.cpp @@ -22,10 +22,13 @@ bool DNSServer::start() { #if SOC_WIFI_SUPPORTED if (WiFi.getMode() & WIFI_AP) { _resolvedIP = WiFi.softAPIP(); - return true; + } else { + return false; // won't run if WiFi is not in AP mode, or no WiFi } +#else + return false; // for other non WiFi-AP networking an overloaded method must be used to get device's IP + // start(uint16_t port, const String &domainName, const IPAddress &resolvedIP) #endif - return false; // won't run if WiFi is not in AP mode } _udp.close(); diff --git a/libraries/EEPROM/README.md b/libraries/EEPROM/README.md index 896ca5b3019..577e2ea4eae 100644 --- a/libraries/EEPROM/README.md +++ b/libraries/EEPROM/README.md @@ -1,4 +1,4 @@ ## EEPROM -EEPROM is deprecated. For new applications on ESP32, use Preferences. EEPROM is provided for backwards compatibility with existing Arduino applications. -EEPROM is implemented using a single blob within NVS, so it is a container within a container. As such, it is not going to be a high performance storage method. Preferences will directly use nvs, and store each entry as a single object therein. +EEPROM is deprecated. For new applications on ESP32, use Preferences. EEPROM is provided for backwards compatibility with existing Arduino applications. +EEPROM is implemented using a single blob within NVS, so it is a container within a container. As such, it is not going to be a high performance storage method. Preferences will directly use nvs, and store each entry as a single object therein. diff --git a/libraries/EEPROM/library.properties b/libraries/EEPROM/library.properties index 459c068ad90..c7e48501c04 100644 --- a/libraries/EEPROM/library.properties +++ b/libraries/EEPROM/library.properties @@ -1,5 +1,5 @@ name=EEPROM -version=2.0.0 +version=3.2.0 author=Ivan Grokhotkov maintainer=Paolo Becchi sentence=Enables reading and writing data a sequential, addressable FLASH storage diff --git a/libraries/ESP32/examples/AnalogOut/LEDCFade/LEDCFade.ino b/libraries/ESP32/examples/AnalogOut/LEDCFade/LEDCFade.ino index dc152a63ea4..ea190e4f140 100644 --- a/libraries/ESP32/examples/AnalogOut/LEDCFade/LEDCFade.ino +++ b/libraries/ESP32/examples/AnalogOut/LEDCFade/LEDCFade.ino @@ -21,7 +21,7 @@ #define LEDC_FADE_TIME (3000) bool fade_ended = false; // status of LED fade -bool fade_on = true; +bool fade_in = true; void ARDUINO_ISR_ATTR LED_FADE_ISR() { fade_ended = true; @@ -30,9 +30,6 @@ void ARDUINO_ISR_ATTR LED_FADE_ISR() { void setup() { // Initialize serial communication at 115200 bits per second: Serial.begin(115200); - while (!Serial) { - delay(10); - } // Setup timer with given frequency, resolution and attach it to a led pin with auto-selected channel ledcAttach(LED_PIN, LEDC_BASE_FREQ, LEDC_TIMER_12_BIT); @@ -55,15 +52,15 @@ void loop() { Serial.println("LED fade ended"); fade_ended = false; - // Check if last fade was fade on - if (fade_on) { + // Check what fade should be started next + if (fade_in) { ledcFadeWithInterrupt(LED_PIN, LEDC_START_DUTY, LEDC_TARGET_DUTY, LEDC_FADE_TIME, LED_FADE_ISR); - Serial.println("LED Fade off started."); - fade_on = false; + Serial.println("LED Fade in started."); + fade_in = false; } else { ledcFadeWithInterrupt(LED_PIN, LEDC_TARGET_DUTY, LEDC_START_DUTY, LEDC_FADE_TIME, LED_FADE_ISR); - Serial.println("LED Fade on started."); - fade_on = true; + Serial.println("LED Fade out started."); + fade_in = true; } } } diff --git a/libraries/ESP32/examples/AnalogOut/LEDCSingleChannel/LEDCSingleChannel.ino b/libraries/ESP32/examples/AnalogOut/LEDCSingleChannel/LEDCSingleChannel.ino new file mode 100644 index 00000000000..2317e32a11a --- /dev/null +++ b/libraries/ESP32/examples/AnalogOut/LEDCSingleChannel/LEDCSingleChannel.ino @@ -0,0 +1,50 @@ +/* + LEDC Software Fade on shared channel with multiple pins + + This example shows how to software fade LED + using the ledcWriteChannel function on multiple pins. + This example is useful if you need to control synchronously + multiple LEDs on different pins. + + Code adapted from original Arduino Fade example: + https://www.arduino.cc/en/Tutorial/Fade + + This example code is in the public domain. + */ + +// use 8 bit precision for LEDC timer +#define LEDC_TIMER_8_BIT 8 + +// use 5000 Hz as a LEDC base frequency +#define LEDC_BASE_FREQ 5000 + +// LED pins +#define LED_PIN_1 4 +#define LED_PIN_2 5 + +// LED channel that will be used instead of automatic selection. +#define LEDC_CHANNEL 0 + +int brightness = 0; // how bright the LED is +int fadeAmount = 5; // how many points to fade the LED by + +void setup() { + // Use single LEDC channel 0 for both pins + ledcAttachChannel(LED_PIN_1, LEDC_BASE_FREQ, LEDC_TIMER_8_BIT, LEDC_CHANNEL); + ledcAttachChannel(LED_PIN_2, LEDC_BASE_FREQ, LEDC_TIMER_8_BIT, LEDC_CHANNEL); +} + +void loop() { + // set the brightness on LEDC channel 0 + ledcWriteChannel(LEDC_CHANNEL, brightness); + + // change the brightness for next time through the loop: + brightness = brightness + fadeAmount; + + // reverse the direction of the fading at the ends of the fade: + if (brightness <= 0 || brightness >= 255) { + fadeAmount = -fadeAmount; + } + // wait for 30 milliseconds to see the dimming effect + delay(30); +} diff --git a/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino b/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino index 5c544c934bf..d483e11b1df 100644 --- a/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino +++ b/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino @@ -136,6 +136,7 @@ void setup() { WiFi.begin(ssid, password); WiFi.setSleep(false); + Serial.print("WiFi connecting"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); diff --git a/libraries/ESP32/examples/Camera/CameraWebServer/app_httpd.cpp b/libraries/ESP32/examples/Camera/CameraWebServer/app_httpd.cpp index 9f78de594b7..81d643e37ac 100644 --- a/libraries/ESP32/examples/Camera/CameraWebServer/app_httpd.cpp +++ b/libraries/ESP32/examples/Camera/CameraWebServer/app_httpd.cpp @@ -24,55 +24,6 @@ #include "esp32-hal-log.h" #endif -// Face Detection will not work on boards without (or with disabled) PSRAM -#ifdef BOARD_HAS_PSRAM -// Face Recognition takes upward from 15 seconds per frame on chips other than ESP32S3 -// Makes no sense to have it enabled for them -#if CONFIG_IDF_TARGET_ESP32S3 -#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 1 -#define CONFIG_ESP_FACE_DETECT_ENABLED 1 -#else -#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 0 -#define CONFIG_ESP_FACE_DETECT_ENABLED 0 -#endif -#else -#define CONFIG_ESP_FACE_DETECT_ENABLED 0 -#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 0 -#endif - -#if CONFIG_ESP_FACE_DETECT_ENABLED - -#include -#include "human_face_detect_msr01.hpp" -#include "human_face_detect_mnp01.hpp" - -#define TWO_STAGE 1 /* very large firmware, very slow, reboots when streaming... - -#define FACE_ID_SAVE_NUMBER 7 -#endif - -#define FACE_COLOR_WHITE 0x00FFFFFF -#define FACE_COLOR_BLACK 0x00000000 -#define FACE_COLOR_RED 0x000000FF -#define FACE_COLOR_GREEN 0x0000FF00 -#define FACE_COLOR_BLUE 0x00FF0000 -#define FACE_COLOR_YELLOW (FACE_COLOR_RED | FACE_COLOR_GREEN) -#define FACE_COLOR_CYAN (FACE_COLOR_BLUE | FACE_COLOR_GREEN) -#define FACE_COLOR_PURPLE (FACE_COLOR_BLUE | FACE_COLOR_RED) -#endif - // Enable LED FLASH setting #define CONFIG_LED_ILLUMINATOR_ENABLED 1 @@ -100,32 +51,6 @@ static const char *_STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: % httpd_handle_t stream_httpd = NULL; httpd_handle_t camera_httpd = NULL; -#if CONFIG_ESP_FACE_DETECT_ENABLED - -static int8_t detection_enabled = 0; - -// #if TWO_STAGE -// static HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F); -// static HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5); -// #else -// static HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F); -// #endif - -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED -static int8_t recognition_enabled = 0; -static int8_t is_enrolling = 0; - -#if QUANT_TYPE -// S16 model -FaceRecognition112V1S16 recognizer; -#else -// S8 model -FaceRecognition112V1S8 recognizer; -#endif -#endif - -#endif - typedef struct { size_t size; //number of values used for filtering size_t index; //current value index @@ -166,105 +91,6 @@ static int ra_filter_run(ra_filter_t *filter, int value) { } #endif -#if CONFIG_ESP_FACE_DETECT_ENABLED -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED -static void rgb_print(fb_data_t *fb, uint32_t color, const char *str) { - fb_gfx_print(fb, (fb->width - (strlen(str) * 14)) / 2, 10, color, str); -} - -static int rgb_printf(fb_data_t *fb, uint32_t color, const char *format, ...) { - char loc_buf[64]; - char *temp = loc_buf; - int len; - va_list arg; - va_list copy; - va_start(arg, format); - va_copy(copy, arg); - len = vsnprintf(loc_buf, sizeof(loc_buf), format, arg); - va_end(copy); - if (len >= sizeof(loc_buf)) { - temp = (char *)malloc(len + 1); - if (temp == NULL) { - return 0; - } - } - vsnprintf(temp, len + 1, format, arg); - va_end(arg); - rgb_print(fb, color, temp); - if (len > 64) { - free(temp); - } - return len; -} -#endif -static void draw_face_boxes(fb_data_t *fb, std::list *results, int face_id) { - int x, y, w, h; - uint32_t color = FACE_COLOR_YELLOW; - if (face_id < 0) { - color = FACE_COLOR_RED; - } else if (face_id > 0) { - color = FACE_COLOR_GREEN; - } - if (fb->bytes_per_pixel == 2) { - //color = ((color >> 8) & 0xF800) | ((color >> 3) & 0x07E0) | (color & 0x001F); - color = ((color >> 16) & 0x001F) | ((color >> 3) & 0x07E0) | ((color << 8) & 0xF800); - } - int i = 0; - for (std::list::iterator prediction = results->begin(); prediction != results->end(); prediction++, i++) { - // rectangle box - x = (int)prediction->box[0]; - y = (int)prediction->box[1]; - w = (int)prediction->box[2] - x + 1; - h = (int)prediction->box[3] - y + 1; - if ((x + w) > fb->width) { - w = fb->width - x; - } - if ((y + h) > fb->height) { - h = fb->height - y; - } - fb_gfx_drawFastHLine(fb, x, y, w, color); - fb_gfx_drawFastHLine(fb, x, y + h - 1, w, color); - fb_gfx_drawFastVLine(fb, x, y, h, color); - fb_gfx_drawFastVLine(fb, x + w - 1, y, h, color); -#if TWO_STAGE - // landmarks (left eye, mouth left, nose, right eye, mouth right) - int x0, y0, j; - for (j = 0; j < 10; j += 2) { - x0 = (int)prediction->keypoint[j]; - y0 = (int)prediction->keypoint[j + 1]; - fb_gfx_fillRect(fb, x0, y0, 3, 3, color); - } -#endif - } -} - -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED -static int run_face_recognition(fb_data_t *fb, std::list *results) { - std::vector landmarks = results->front().keypoint; - int id = -1; - - Tensor tensor; - tensor.set_element((uint8_t *)fb->data).set_shape({fb->height, fb->width, 3}).set_auto_free(false); - - int enrolled_count = recognizer.get_enrolled_id_num(); - - if (enrolled_count < FACE_ID_SAVE_NUMBER && is_enrolling) { - id = recognizer.enroll_id(tensor, landmarks, "", true); - log_i("Enrolled ID: %d", id); - rgb_printf(fb, FACE_COLOR_CYAN, "ID[%u]", id); - } - - face_info_t recognize = recognizer.recognize(tensor, landmarks); - if (recognize.id >= 0) { - rgb_printf(fb, FACE_COLOR_GREEN, "ID[%u]: %.2f", recognize.id, recognize.similarity); - } else { - rgb_print(fb, FACE_COLOR_RED, "Intruder Alert!"); - } - return recognize.id; -} -#endif -#endif - #if CONFIG_LED_ILLUMINATOR_ENABLED void enable_led(bool en) { // Turn LED On or Off int duty = en ? led_duty : 0; @@ -359,134 +185,28 @@ static esp_err_t capture_handler(httpd_req_t *req) { snprintf(ts, 32, "%lld.%06ld", fb->timestamp.tv_sec, fb->timestamp.tv_usec); httpd_resp_set_hdr(req, "X-Timestamp", (const char *)ts); -#if CONFIG_ESP_FACE_DETECT_ENABLED - size_t out_len, out_width, out_height; - uint8_t *out_buf; - bool s; #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - bool detected = false; + size_t fb_len = 0; #endif - int face_id = 0; - if (!detection_enabled || fb->width > 400) { -#endif -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - size_t fb_len = 0; -#endif - if (fb->format == PIXFORMAT_JPEG) { + if (fb->format == PIXFORMAT_JPEG) { #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fb_len = fb->len; + fb_len = fb->len; #endif - res = httpd_resp_send(req, (const char *)fb->buf, fb->len); - } else { - jpg_chunking_t jchunk = {req, 0}; - res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk) ? ESP_OK : ESP_FAIL; - httpd_resp_send_chunk(req, NULL, 0); -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fb_len = jchunk.len; -#endif - } - esp_camera_fb_return(fb); -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - int64_t fr_end = esp_timer_get_time(); -#endif - log_i("JPG: %uB %ums", (uint32_t)(fb_len), (uint32_t)((fr_end - fr_start) / 1000)); - return res; -#if CONFIG_ESP_FACE_DETECT_ENABLED - } - - jpg_chunking_t jchunk = {req, 0}; - - if (fb->format == PIXFORMAT_RGB565 -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - && !recognition_enabled -#endif - ) { -#if TWO_STAGE - HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F); - HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5); - std::list &candidates = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}); - std::list &results = s2.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}, candidates); -#else - HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F); - std::list &results = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}); -#endif - if (results.size() > 0) { - fb_data_t rfb; - rfb.width = fb->width; - rfb.height = fb->height; - rfb.data = fb->buf; - rfb.bytes_per_pixel = 2; - rfb.format = FB_RGB565; -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - detected = true; -#endif - draw_face_boxes(&rfb, &results, face_id); - } - s = fmt2jpg_cb(fb->buf, fb->len, fb->width, fb->height, PIXFORMAT_RGB565, 90, jpg_encode_stream, &jchunk); - esp_camera_fb_return(fb); + res = httpd_resp_send(req, (const char *)fb->buf, fb->len); } else { - out_len = fb->width * fb->height * 3; - out_width = fb->width; - out_height = fb->height; - out_buf = (uint8_t *)malloc(out_len); - if (!out_buf) { - log_e("out_buf malloc failed"); - httpd_resp_send_500(req); - return ESP_FAIL; - } - s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf); - esp_camera_fb_return(fb); - if (!s) { - free(out_buf); - log_e("To rgb888 failed"); - httpd_resp_send_500(req); - return ESP_FAIL; - } - - fb_data_t rfb; - rfb.width = out_width; - rfb.height = out_height; - rfb.data = out_buf; - rfb.bytes_per_pixel = 3; - rfb.format = FB_BGR888; - -#if TWO_STAGE - HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F); - HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5); - std::list &candidates = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}); - std::list &results = s2.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}, candidates); -#else - HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F); - std::list &results = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}); -#endif - - if (results.size() > 0) { + jpg_chunking_t jchunk = {req, 0}; + res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk) ? ESP_OK : ESP_FAIL; + httpd_resp_send_chunk(req, NULL, 0); #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - detected = true; -#endif -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - if (recognition_enabled) { - face_id = run_face_recognition(&rfb, &results); - } + fb_len = jchunk.len; #endif - draw_face_boxes(&rfb, &results, face_id); - } - - s = fmt2jpg_cb(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, jpg_encode_stream, &jchunk); - free(out_buf); - } - - if (!s) { - log_e("JPEG compression failed"); - httpd_resp_send_500(req); - return ESP_FAIL; } + esp_camera_fb_return(fb); #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO int64_t fr_end = esp_timer_get_time(); #endif - log_i("FACE: %uB %ums %s%d", (uint32_t)(jchunk.len), (uint32_t)((fr_end - fr_start) / 1000), detected ? "DETECTED " : "", face_id); + log_i("JPG: %uB %ums", (uint32_t)(fb_len), (uint32_t)((fr_end - fr_start) / 1000)); return res; -#endif } static esp_err_t stream_handler(httpd_req_t *req) { @@ -496,26 +216,6 @@ static esp_err_t stream_handler(httpd_req_t *req) { size_t _jpg_buf_len = 0; uint8_t *_jpg_buf = NULL; char *part_buf[128]; -#if CONFIG_ESP_FACE_DETECT_ENABLED -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - bool detected = false; - int64_t fr_ready = 0; - int64_t fr_recognize = 0; - int64_t fr_encode = 0; - int64_t fr_face = 0; - int64_t fr_start = 0; -#endif - int face_id = 0; - size_t out_len = 0, out_width = 0, out_height = 0; - uint8_t *out_buf = NULL; - bool s = false; -#if TWO_STAGE - HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F); - HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5); -#else - HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F); -#endif -#endif static int64_t last_frame = 0; if (!last_frame) { @@ -536,13 +236,6 @@ static esp_err_t stream_handler(httpd_req_t *req) { #endif while (true) { -#if CONFIG_ESP_FACE_DETECT_ENABLED -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - detected = false; -#endif - face_id = 0; -#endif - fb = esp_camera_fb_get(); if (!fb) { log_e("Camera capture failed"); @@ -550,138 +243,18 @@ static esp_err_t stream_handler(httpd_req_t *req) { } else { _timestamp.tv_sec = fb->timestamp.tv_sec; _timestamp.tv_usec = fb->timestamp.tv_usec; -#if CONFIG_ESP_FACE_DETECT_ENABLED -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_start = esp_timer_get_time(); - fr_ready = fr_start; - fr_encode = fr_start; - fr_recognize = fr_start; - fr_face = fr_start; -#endif - if (!detection_enabled || fb->width > 400) { -#endif - if (fb->format != PIXFORMAT_JPEG) { - bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len); - esp_camera_fb_return(fb); - fb = NULL; - if (!jpeg_converted) { - log_e("JPEG compression failed"); - res = ESP_FAIL; - } - } else { - _jpg_buf_len = fb->len; - _jpg_buf = fb->buf; + if (fb->format != PIXFORMAT_JPEG) { + bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len); + esp_camera_fb_return(fb); + fb = NULL; + if (!jpeg_converted) { + log_e("JPEG compression failed"); + res = ESP_FAIL; } -#if CONFIG_ESP_FACE_DETECT_ENABLED } else { - if (fb->format == PIXFORMAT_RGB565 -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - && !recognition_enabled -#endif - ) { -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_ready = esp_timer_get_time(); -#endif -#if TWO_STAGE - std::list &candidates = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}); - std::list &results = s2.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}, candidates); -#else - std::list &results = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}); -#endif -#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_face = esp_timer_get_time(); - fr_recognize = fr_face; -#endif - if (results.size() > 0) { - fb_data_t rfb; - rfb.width = fb->width; - rfb.height = fb->height; - rfb.data = fb->buf; - rfb.bytes_per_pixel = 2; - rfb.format = FB_RGB565; -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - detected = true; -#endif - draw_face_boxes(&rfb, &results, face_id); - } - s = fmt2jpg(fb->buf, fb->len, fb->width, fb->height, PIXFORMAT_RGB565, 80, &_jpg_buf, &_jpg_buf_len); - esp_camera_fb_return(fb); - fb = NULL; - if (!s) { - log_e("fmt2jpg failed"); - res = ESP_FAIL; - } -#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_encode = esp_timer_get_time(); -#endif - } else { - out_len = fb->width * fb->height * 3; - out_width = fb->width; - out_height = fb->height; - out_buf = (uint8_t *)malloc(out_len); - if (!out_buf) { - log_e("out_buf malloc failed"); - res = ESP_FAIL; - } else { - s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf); - esp_camera_fb_return(fb); - fb = NULL; - if (!s) { - free(out_buf); - log_e("To rgb888 failed"); - res = ESP_FAIL; - } else { -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_ready = esp_timer_get_time(); -#endif - - fb_data_t rfb; - rfb.width = out_width; - rfb.height = out_height; - rfb.data = out_buf; - rfb.bytes_per_pixel = 3; - rfb.format = FB_BGR888; - -#if TWO_STAGE - std::list &candidates = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}); - std::list &results = s2.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}, candidates); -#else - std::list &results = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}); -#endif - -#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_face = esp_timer_get_time(); - fr_recognize = fr_face; -#endif - - if (results.size() > 0) { -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - detected = true; -#endif -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - if (recognition_enabled) { - face_id = run_face_recognition(&rfb, &results); -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_recognize = esp_timer_get_time(); -#endif - } -#endif - draw_face_boxes(&rfb, &results, face_id); - } - s = fmt2jpg(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, &_jpg_buf, &_jpg_buf_len); - free(out_buf); - if (!s) { - log_e("fmt2jpg failed"); - res = ESP_FAIL; - } -#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - fr_encode = esp_timer_get_time(); -#endif - } - } - } + _jpg_buf_len = fb->len; + _jpg_buf = fb->buf; } -#endif } if (res == ESP_OK) { res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY)); @@ -707,30 +280,16 @@ static esp_err_t stream_handler(httpd_req_t *req) { } int64_t fr_end = esp_timer_get_time(); -#if CONFIG_ESP_FACE_DETECT_ENABLED && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO - int64_t ready_time = (fr_ready - fr_start) / 1000; - int64_t face_time = (fr_face - fr_ready) / 1000; - int64_t recognize_time = (fr_recognize - fr_face) / 1000; - int64_t encode_time = (fr_encode - fr_recognize) / 1000; - int64_t process_time = (fr_encode - fr_start) / 1000; -#endif - int64_t frame_time = fr_end - last_frame; + last_frame = fr_end; + frame_time /= 1000; #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO uint32_t avg_frame_time = ra_filter_run(&ra_filter, frame_time); #endif log_i( - "MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps)" -#if CONFIG_ESP_FACE_DETECT_ENABLED - ", %u+%u+%u+%u=%u %s%d" -#endif - , - (uint32_t)(_jpg_buf_len), (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time, avg_frame_time, 1000.0 / avg_frame_time -#if CONFIG_ESP_FACE_DETECT_ENABLED - , - (uint32_t)ready_time, (uint32_t)face_time, (uint32_t)recognize_time, (uint32_t)encode_time, (uint32_t)process_time, (detected) ? "DETECTED " : "", face_id -#endif + "MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps)", (uint32_t)(_jpg_buf_len), (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time, avg_frame_time, + 1000.0 / avg_frame_time ); } @@ -841,28 +400,6 @@ static esp_err_t cmd_handler(httpd_req_t *req) { enable_led(true); } } -#endif - -#if CONFIG_ESP_FACE_DETECT_ENABLED - else if (!strcmp(variable, "face_detect")) { - detection_enabled = val; -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - if (!detection_enabled) { - recognition_enabled = 0; - } -#endif - } -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - else if (!strcmp(variable, "face_enroll")) { - is_enrolling = !is_enrolling; - log_i("Enrolling: %s", is_enrolling ? "true" : "false"); - } else if (!strcmp(variable, "face_recognize")) { - recognition_enabled = val; - if (recognition_enabled) { - detection_enabled = val; - } - } -#endif #endif else { log_i("Unknown command: %s", variable); @@ -947,13 +484,6 @@ static esp_err_t status_handler(httpd_req_t *req) { p += sprintf(p, ",\"led_intensity\":%u", led_duty); #else p += sprintf(p, ",\"led_intensity\":%d", -1); -#endif -#if CONFIG_ESP_FACE_DETECT_ENABLED - p += sprintf(p, ",\"face_detect\":%u", detection_enabled); -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - p += sprintf(p, ",\"face_enroll\":%u,", is_enrolling); - p += sprintf(p, "\"face_recognize\":%u", recognition_enabled); -#endif #endif *p++ = '}'; *p++ = 0; @@ -1101,7 +631,7 @@ static esp_err_t win_handler(httpd_req_t *req) { int offsetX = parse_get_var(buf, "offx", 0); int offsetY = parse_get_var(buf, "offy", 0); int totalX = parse_get_var(buf, "tx", 0); - int totalY = parse_get_var(buf, "ty", 0); + int totalY = parse_get_var(buf, "ty", 0); // codespell:ignore totaly int outputX = parse_get_var(buf, "ox", 0); int outputY = parse_get_var(buf, "oy", 0); bool scale = parse_get_var(buf, "scale", 0) == 1; @@ -1110,10 +640,10 @@ static esp_err_t win_handler(httpd_req_t *req) { log_i( "Set Window: Start: %d %d, End: %d %d, Offset: %d %d, Total: %d %d, Output: %d %d, Scale: %u, Binning: %u", startX, startY, endX, endY, offsetX, offsetY, - totalX, totalY, outputX, outputY, scale, binning + totalX, totalY, outputX, outputY, scale, binning // codespell:ignore totaly ); sensor_t *s = esp_camera_sensor_get(); - int res = s->set_res_raw(s, startX, startY, endX, endY, offsetX, offsetY, totalX, totalY, outputX, outputY, scale, binning); + int res = s->set_res_raw(s, startX, startY, endX, endY, offsetX, offsetY, totalX, totalY, outputX, outputY, scale, binning); // codespell:ignore totaly if (res) { return httpd_resp_send_500(req); } @@ -1289,12 +819,6 @@ void startCameraServer() { ra_filter_init(&ra_filter, 20); -#if CONFIG_ESP_FACE_RECOGNITION_ENABLED - recognizer.set_partition(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "fr"); - - // load ids from flash partition - recognizer.set_ids_from_flash(); -#endif log_i("Starting web server on port: '%d'", config.server_port); if (httpd_start(&camera_httpd, &config) == ESP_OK) { httpd_register_uri_handler(camera_httpd, &index_uri); diff --git a/libraries/ESP32/examples/Camera/CameraWebServer/camera_index.h b/libraries/ESP32/examples/Camera/CameraWebServer/camera_index.h index 040f1ec5267..b38e2773af3 100644 --- a/libraries/ESP32/examples/Camera/CameraWebServer/camera_index.h +++ b/libraries/ESP32/examples/Camera/CameraWebServer/camera_index.h @@ -1,971 +1,949 @@ - -//File: index_ov2640.html.gz, Size: 6787 -#define index_ov2640_html_gz_len 6787 -const uint8_t index_ov2640_html_gz[] = { - 0x1F, 0x8B, 0x08, 0x08, 0x23, 0xFC, 0x69, 0x5E, 0x00, 0x03, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x6F, 0x76, 0x32, 0x36, 0x34, 0x30, 0x2E, 0x68, 0x74, 0x6D, - 0x6C, 0x00, 0xED, 0x3D, 0x6B, 0x73, 0xDB, 0x46, 0x92, 0xDF, 0xFD, 0x2B, 0x60, 0x24, 0x6B, 0x92, 0x25, 0x92, 0x22, 0x29, 0x4A, 0x96, 0x15, 0x89, 0x3E, 0x5B, - 0x96, 0x1F, 0xB5, 0x76, 0xE2, 0xB5, 0x12, 0xC7, 0x5B, 0xA9, 0x2D, 0x07, 0x04, 0x86, 0x24, 0x62, 0x10, 0xE0, 0x02, 0xA0, 0x48, 0x26, 0xA5, 0xDF, 0x71, 0x3F, - 0xE8, 0xFE, 0xD8, 0x75, 0xCF, 0x03, 0x18, 0x00, 0x83, 0x07, 0x49, 0x89, 0xF4, 0xFA, 0x8E, 0x4E, 0x45, 0x78, 0x4C, 0xF7, 0xF4, 0xBB, 0x7B, 0x66, 0x30, 0xC0, - 0xF9, 0x43, 0xCB, 0x33, 0xC3, 0xD5, 0x8C, 0x68, 0x93, 0x70, 0xEA, 0x0C, 0x1E, 0x9C, 0xB3, 0x3F, 0x1A, 0xFC, 0xCE, 0x27, 0xC4, 0xB0, 0xD8, 0x21, 0x3D, 0x9D, - 0x92, 0xD0, 0xD0, 0xCC, 0x89, 0xE1, 0x07, 0x24, 0xBC, 0xD0, 0xE7, 0xE1, 0xA8, 0x75, 0xAA, 0xA7, 0x6F, 0xBB, 0xC6, 0x94, 0x5C, 0xE8, 0x37, 0x36, 0x59, 0xCC, - 0x3C, 0x3F, 0xD4, 0x35, 0xD3, 0x73, 0x43, 0xE2, 0x42, 0xF3, 0x85, 0x6D, 0x85, 0x93, 0x0B, 0x8B, 0xDC, 0xD8, 0x26, 0x69, 0xD1, 0x93, 0xA6, 0xED, 0xDA, 0xA1, - 0x6D, 0x38, 0xAD, 0xC0, 0x34, 0x1C, 0x72, 0xD1, 0x95, 0x71, 0x85, 0x76, 0xE8, 0x90, 0xC1, 0xD5, 0xF5, 0xFB, 0xA3, 0x9E, 0xF6, 0xD3, 0xC7, 0x5E, 0xFF, 0xA4, - 0x73, 0x7E, 0xC8, 0xAE, 0xC5, 0x6D, 0x82, 0x70, 0x25, 0x9F, 0xE3, 0x6F, 0xE8, 0x59, 0x2B, 0xED, 0xAF, 0xC4, 0x25, 0xFC, 0x8D, 0x80, 0x88, 0xD6, 0xC8, 0x98, - 0xDA, 0xCE, 0xEA, 0x4C, 0x7B, 0xE6, 0x43, 0x9F, 0xCD, 0xD7, 0xC4, 0xB9, 0x21, 0xA1, 0x6D, 0x1A, 0xCD, 0xC0, 0x70, 0x83, 0x56, 0x40, 0x7C, 0x7B, 0xF4, 0x43, - 0x06, 0x70, 0x68, 0x98, 0x5F, 0xC6, 0xBE, 0x37, 0x77, 0xAD, 0x33, 0xED, 0xBB, 0xEE, 0x29, 0xFE, 0xCB, 0x36, 0x32, 0x3D, 0xC7, 0xF3, 0xE1, 0xFE, 0xD5, 0x4B, - 0xFC, 0x97, 0xBD, 0x4F, 0x7B, 0x0F, 0xEC, 0x3F, 0xC9, 0x99, 0xD6, 0x3D, 0x99, 0x2D, 0x13, 0xF7, 0x6F, 0x1F, 0x24, 0x4E, 0x27, 0xBD, 0x3C, 0xEA, 0x39, 0xFC, - 0x69, 0x31, 0x7C, 0x40, 0xCC, 0xD0, 0xF6, 0xDC, 0xF6, 0xD4, 0xB0, 0x5D, 0x05, 0x26, 0xCB, 0x0E, 0x66, 0x8E, 0x01, 0x32, 0x18, 0x39, 0xA4, 0x10, 0xCF, 0x77, - 0x53, 0xE2, 0xCE, 0x9B, 0x25, 0xD8, 0x10, 0x49, 0xCB, 0xB2, 0x7D, 0xD6, 0xEA, 0x0C, 0xE5, 0x30, 0x9F, 0xBA, 0xA5, 0x68, 0x8B, 0xE8, 0x72, 0x3D, 0x97, 0x28, - 0x04, 0x88, 0x1D, 0x2D, 0x7C, 0x63, 0x86, 0x0D, 0xF0, 0x6F, 0xB6, 0xC9, 0xD4, 0x76, 0x99, 0x51, 0x9D, 0x69, 0x47, 0xFD, 0xCE, 0x6C, 0x59, 0xA2, 0xCA, 0xA3, - 0x13, 0xFC, 0x97, 0x6D, 0x34, 0x33, 0x2C, 0xCB, 0x76, 0xC7, 0x67, 0xDA, 0xA9, 0x12, 0x85, 0xE7, 0x5B, 0xC4, 0x6F, 0xF9, 0x86, 0x65, 0xCF, 0x83, 0x33, 0xAD, - 0xAF, 0x6A, 0x33, 0x35, 0xFC, 0x31, 0xD0, 0x12, 0x7A, 0x40, 0x6C, 0xAB, 0xAB, 0xA4, 0x84, 0x37, 0xF1, 0xED, 0xF1, 0x24, 0x04, 0x95, 0x66, 0xDA, 0xA4, 0x85, - 0xC6, 0x5D, 0xA8, 0x4C, 0x9F, 0x85, 0x72, 0x53, 0x4B, 0xCD, 0x70, 0xEC, 0xB1, 0xDB, 0xB2, 0x43, 0x32, 0x05, 0x76, 0x82, 0xD0, 0x27, 0xA1, 0x39, 0x29, 0x22, - 0x65, 0x64, 0x8F, 0xE7, 0x3E, 0x51, 0x10, 0x12, 0xC9, 0xAD, 0x80, 0x61, 0xB8, 0x99, 0xBD, 0xD5, 0x5A, 0x90, 0xE1, 0x17, 0x3B, 0x6C, 0x71, 0x99, 0x0C, 0xC9, - 0xC8, 0xF3, 0x89, 0xB2, 0xA5, 0x68, 0xE1, 0x78, 0xE6, 0x97, 0x56, 0x10, 0x1A, 0x7E, 0x58, 0x05, 0xA1, 0x31, 0x0A, 0x89, 0x5F, 0x8E, 0x8F, 0xA0, 0x55, 0x94, - 0x63, 0xCB, 0xEF, 0x96, 0x37, 0xB0, 0x5D, 0xC7, 0x76, 0x49, 0x75, 0xF2, 0xF2, 0xFA, 0x4D, 0xA2, 0x63, 0xAD, 0x2A, 0x28, 0xC6, 0x9E, 0x8E, 0x8B, 0xAC, 0x84, - 0xF2, 0x9A, 0xED, 0x8C, 0xFB, 0x4D, 0xB7, 0xD3, 0xF9, 0x5B, 0xF6, 0xE6, 0x84, 0x30, 0x33, 0x35, 0xE6, 0xA1, 0xB7, 0xBD, 0x47, 0x64, 0xDC, 0x2A, 0xC5, 0xC7, - 0x7F, 0x4D, 0x89, 0x65, 0x1B, 0x5A, 0x5D, 0x72, 0xE7, 0xD3, 0x0E, 0xD8, 0x54, 0x43, 0x33, 0x5C, 0x4B, 0xAB, 0x7B, 0xBE, 0x0D, 0x8E, 0x60, 0xD0, 0x70, 0xE3, - 0xC0, 0x15, 0x48, 0x1C, 0x33, 0xD2, 0x50, 0xB0, 0x5C, 0xE0, 0x33, 0xB2, 0x44, 0xD4, 0x6E, 0x83, 0xBF, 0x0A, 0x21, 0x07, 0x7F, 0xA5, 0x0E, 0xA4, 0xE0, 0x91, - 0xA2, 0x2F, 0xD2, 0x97, 0x4C, 0x61, 0x9E, 0xCE, 0xF0, 0x37, 0x35, 0x96, 0xAD, 0x42, 0xDD, 0x89, 0x46, 0x42, 0x87, 0x90, 0x66, 0xCD, 0x3A, 0x34, 0xBD, 0x99, - 0x68, 0x2D, 0x0D, 0xA3, 0x64, 0x43, 0x0D, 0xC3, 0x91, 0xAA, 0x55, 0x8E, 0x3F, 0xD9, 0x28, 0xD6, 0x60, 0x57, 0xCD, 0x6A, 0x1C, 0x3B, 0xD8, 0x3F, 0x95, 0x0D, - 0x31, 0x4E, 0x72, 0xA3, 0x08, 0xFE, 0xAA, 0x47, 0x92, 0x18, 0x59, 0x69, 0x34, 0x51, 0x20, 0xCE, 0x8F, 0x28, 0x19, 0xBC, 0x79, 0xDE, 0xAD, 0xC0, 0x5A, 0x4C, - 0x42, 0xD5, 0xE8, 0xA2, 0x40, 0x5C, 0x44, 0x43, 0x69, 0x94, 0xC1, 0xDF, 0x6D, 0x85, 0x7A, 0xE3, 0xBB, 0xE1, 0x3C, 0x0C, 0x3D, 0x37, 0xD8, 0x2A, 0x45, 0xE5, - 0xF9, 0xD9, 0x1F, 0xF3, 0x20, 0xB4, 0x47, 0xAB, 0x16, 0x77, 0x69, 0xF0, 0xB3, 0x99, 0x01, 0x25, 0xE4, 0x90, 0x84, 0x0B, 0x42, 0x8A, 0xCB, 0x0D, 0xD7, 0xB8, - 0x81, 0xB8, 0x33, 0x1E, 0x3B, 0x2A, 0xDB, 0x33, 0xE7, 0x7E, 0x80, 0x75, 0xDB, 0xCC, 0xB3, 0x01, 0xB1, 0x9F, 0xED, 0x38, 0xE9, 0x83, 0x15, 0x3B, 0x6A, 0x99, - 0x43, 0x45, 0x5F, 0xDE, 0x3C, 0x44, 0x19, 0x2B, 0x35, 0xE1, 0x01, 0x3B, 0x76, 0xB8, 0x52, 0xDE, 0xE3, 0x9E, 0xA8, 0xB8, 0x23, 0x5C, 0xB0, 0x30, 0x2D, 0x24, - 0xE9, 0x3A, 0x33, 0x27, 0xC4, 0xFC, 0x42, 0xAC, 0x83, 0xD2, 0x32, 0xAC, 0xAC, 0x3C, 0x6C, 0xDB, 0xEE, 0x6C, 0x1E, 0xB6, 0xB0, 0x9C, 0x9A, 0xDD, 0x8B, 0xCE, - 0xA9, 0x41, 0x0A, 0x16, 0x7B, 0xBD, 0xA2, 0xA2, 0xE2, 0x78, 0xB6, 0x2C, 0x16, 0x82, 0x4C, 0xEC, 0xC0, 0x31, 0x86, 0xC4, 0x29, 0x22, 0x99, 0x3B, 0x43, 0x4E, - 0xD8, 0xE5, 0xB1, 0x2A, 0xBF, 0x76, 0xA3, 0x94, 0xC5, 0xC9, 0xAB, 0xFF, 0xF8, 0x6F, 0x95, 0xE5, 0x48, 0x8F, 0x9B, 0x89, 0x4B, 0x01, 0x71, 0xC0, 0xC1, 0xF2, - 0x4A, 0x6F, 0x68, 0xB3, 0x00, 0x1A, 0x0A, 0x3B, 0xF0, 0x0D, 0x77, 0x4C, 0x20, 0x16, 0x2C, 0x9B, 0xE2, 0xB0, 0x78, 0x60, 0x50, 0x89, 0x7D, 0x0C, 0xD5, 0xC7, - 0xC5, 0x03, 0x11, 0x16, 0x10, 0x9A, 0x5A, 0x9B, 0x1D, 0x6C, 0x50, 0x95, 0x48, 0xFA, 0x2D, 0x24, 0xA4, 0xAB, 0xB4, 0x0E, 0x56, 0x98, 0x28, 0x3D, 0x27, 0x69, - 0x5B, 0xCA, 0x42, 0xBF, 0x34, 0x34, 0x88, 0x21, 0xDF, 0x68, 0x54, 0x36, 0x68, 0x1C, 0x8D, 0x8E, 0x3A, 0x47, 0xFD, 0xD2, 0xCA, 0x49, 0xC9, 0x65, 0x6A, 0xE0, - 0xA8, 0x08, 0x1D, 0x51, 0x58, 0x29, 0x34, 0x82, 0xC0, 0xB8, 0x51, 0x16, 0xED, 0x5E, 0x60, 0xB3, 0x91, 0x9B, 0x31, 0x0C, 0x60, 0xEC, 0x16, 0x2A, 0x86, 0x5E, - 0xDC, 0xD0, 0x7B, 0x4A, 0xFA, 0x68, 0x49, 0xA7, 0x74, 0x01, 0x21, 0x5E, 0x35, 0xD9, 0x09, 0x0D, 0xA8, 0x9B, 0x48, 0x0A, 0x56, 0x16, 0x95, 0x21, 0x59, 0x86, - 0x2D, 0x8B, 0x98, 0x9E, 0xCF, 0xAA, 0xC1, 0x9C, 0x91, 0x63, 0x4A, 0x91, 0xE5, 0x16, 0x7B, 0x36, 0xF1, 0x6E, 0x88, 0xAF, 0x10, 0x56, 0x4A, 0xA9, 0xFD, 0x27, - 0x7D, 0xAB, 0x02, 0x36, 0x03, 0xD2, 0xA3, 0x52, 0xF6, 0x49, 0x74, 0xBD, 0xAE, 0xD9, 0x2B, 0xF4, 0x63, 0x86, 0xAE, 0x0D, 0x3E, 0x63, 0x0C, 0x1D, 0x62, 0x15, - 0x64, 0x33, 0x8B, 0x8C, 0x8C, 0xB9, 0x13, 0x96, 0x58, 0xA5, 0xD1, 0xC1, 0x7F, 0x45, 0x3D, 0xD2, 0x30, 0xF4, 0x1B, 0xCE, 0x0B, 0x5D, 0xD0, 0xC0, 0xF1, 0x2F, - 0x45, 0x9F, 0xA2, 0xD4, 0x30, 0x66, 0x33, 0x62, 0x40, 0x2B, 0x93, 0xE4, 0xE9, 0xA1, 0xD2, 0x10, 0x43, 0x1D, 0xE7, 0x2B, 0x8D, 0xDB, 0x4B, 0x1D, 0x36, 0x2A, - 0x1E, 0xD7, 0xE2, 0xF9, 0x6C, 0xE4, 0x99, 0x73, 0x55, 0x55, 0x53, 0xCD, 0xF1, 0xB2, 0xF8, 0xCE, 0x84, 0xC8, 0x02, 0xC7, 0xA6, 0xEE, 0x3F, 0x77, 0x5D, 0xD4, - 0x68, 0x2B, 0xF4, 0x81, 0x4D, 0x45, 0x47, 0xD5, 0x04, 0xB7, 0x51, 0x0C, 0x4B, 0x08, 0x36, 0x6F, 0xEE, 0x2A, 0x15, 0xA6, 0x14, 0xE1, 0x34, 0x8A, 0xB4, 0x1A, - 0xC4, 0x10, 0xDB, 0x12, 0xA8, 0xB6, 0x93, 0x4B, 0x38, 0x99, 0x4F, 0x55, 0x75, 0x94, 0xE8, 0xAC, 0x0B, 0x49, 0x9F, 0x75, 0xE7, 0x8F, 0x87, 0x46, 0xBD, 0xD3, - 0xEC, 0x34, 0x8F, 0xE0, 0x7F, 0x8A, 0xF1, 0x4C, 0xB1, 0x71, 0x71, 0xF1, 0xE6, 0x58, 0x5E, 0x2A, 0x44, 0x97, 0x4F, 0x2B, 0xE5, 0x05, 0xFB, 0x52, 0x5D, 0x54, - 0xF7, 0xA4, 0xE4, 0xFC, 0x52, 0xB7, 0x5D, 0x92, 0x87, 0x73, 0x4C, 0x7A, 0x7D, 0x43, 0x54, 0x58, 0xCB, 0xBA, 0x2A, 0x9E, 0x7A, 0x7F, 0xB6, 0x58, 0x11, 0xF2, - 0x7F, 0xDE, 0xDA, 0x25, 0x51, 0x7C, 0xD3, 0x96, 0xBE, 0xB6, 0x5C, 0x82, 0x7D, 0xDB, 0x46, 0x27, 0x5F, 0xEB, 0x2D, 0x5E, 0xF5, 0x01, 0x85, 0x2E, 0x8C, 0x41, - 0x7D, 0x18, 0x8C, 0xE6, 0x56, 0x86, 0x52, 0x9B, 0x0D, 0x64, 0x30, 0xB2, 0x1D, 0xA7, 0xE5, 0x78, 0x8B, 0xF2, 0x4A, 0xA4, 0xD8, 0x92, 0x33, 0x76, 0x5A, 0x6E, - 0xF2, 0x9B, 0x52, 0x3B, 0x87, 0xC8, 0xF5, 0x1F, 0x41, 0xED, 0xB7, 0xED, 0x70, 0x85, 0xAE, 0xB1, 0x59, 0xA2, 0xD8, 0xC0, 0x1E, 0xB7, 0xEB, 0xA8, 0x92, 0x29, - 0xB1, 0x4A, 0xB0, 0x78, 0xD8, 0xB3, 0xB0, 0x43, 0x73, 0xB2, 0xC1, 0xD0, 0x33, 0x1E, 0x18, 0xF9, 0xC4, 0x31, 0xB0, 0x82, 0xDF, 0x68, 0x86, 0xA2, 0x74, 0xF8, - 0x26, 0x83, 0x57, 0xE1, 0x84, 0x8A, 0xEE, 0xEB, 0x99, 0x5D, 0x6A, 0xB3, 0xDA, 0x21, 0x3F, 0x56, 0xAB, 0xCD, 0xBA, 0xA4, 0xDC, 0x4F, 0x7A, 0x86, 0xBA, 0xD1, - 0x1A, 0x11, 0x5D, 0x04, 0xED, 0xB1, 0x4F, 0x56, 0x15, 0x98, 0x69, 0xF2, 0xBF, 0x67, 0x6C, 0xFE, 0x78, 0xF3, 0xA9, 0x12, 0x9A, 0x00, 0xB8, 0x15, 0xB5, 0xFB, - 0x41, 0x85, 0xAE, 0xF3, 0xBB, 0xAC, 0x62, 0x8F, 0xD1, 0xEC, 0xA8, 0xAE, 0x57, 0x08, 0x37, 0x05, 0x29, 0x54, 0x6D, 0xAA, 0x22, 0xFB, 0xAA, 0xC7, 0xF3, 0x64, - 0x14, 0xE6, 0x2C, 0xFE, 0xD0, 0x3A, 0xF5, 0xA8, 0x38, 0xBA, 0xB5, 0xA4, 0xD9, 0x94, 0xD2, 0xC8, 0x11, 0x4D, 0x62, 0xE6, 0x5B, 0x9F, 0x12, 0x33, 0x46, 0xCF, - 0xB5, 0x91, 0xE7, 0xAB, 0x44, 0x94, 0xCF, 0x54, 0xCD, 0xD0, 0x66, 0xCA, 0x53, 0x3E, 0xA8, 0x87, 0x7C, 0xAA, 0xF7, 0x4E, 0x94, 0x6B, 0x2B, 0x05, 0x8D, 0x8B, - 0x48, 0xCB, 0x9D, 0x05, 0xCC, 0xA6, 0xAC, 0xDC, 0x01, 0xB2, 0x1C, 0x8B, 0x94, 0x8A, 0x2A, 0xF6, 0xCA, 0xA2, 0x08, 0x93, 0x9D, 0xC9, 0x2A, 0x34, 0x76, 0x7B, - 0x6A, 0x40, 0xD9, 0x8B, 0xE6, 0x6A, 0x00, 0x46, 0x95, 0xFE, 0xAA, 0x98, 0xBB, 0x34, 0xC7, 0xDA, 0x3D, 0xE9, 0x94, 0x74, 0x69, 0x3A, 0x5E, 0xB0, 0xE5, 0x04, - 0x58, 0xFE, 0xFC, 0x97, 0xF2, 0x4E, 0xA5, 0xD4, 0x5D, 0xE8, 0x53, 0xC5, 0xEE, 0x98, 0x92, 0x79, 0xB7, 0xA3, 0x8C, 0xB4, 0x85, 0xB3, 0x94, 0x74, 0x06, 0x8D, - 0xAE, 0x5F, 0x9E, 0x69, 0x26, 0x51, 0x87, 0xD1, 0xE4, 0x44, 0x5D, 0x95, 0xA9, 0xD2, 0x42, 0x3D, 0x4C, 0x6C, 0xCB, 0x22, 0x85, 0x73, 0xC1, 0x38, 0xE6, 0xAD, - 0x58, 0x3C, 0x20, 0xFD, 0xAA, 0x49, 0xA9, 0x7B, 0x71, 0x8A, 0xC2, 0xC7, 0x1A, 0xBA, 0xF7, 0xED, 0x31, 0x3C, 0xD1, 0xE4, 0xCD, 0xA4, 0x27, 0x4B, 0x91, 0x42, - 0x52, 0x95, 0xCE, 0x1D, 0xCD, 0xB5, 0xA2, 0xC8, 0x40, 0x0E, 0xD8, 0x2A, 0x1B, 0xCD, 0x53, 0x54, 0xD1, 0x85, 0x94, 0x36, 0x5F, 0x5B, 0xE2, 0xCB, 0x80, 0xAD, - 0xBC, 0xD5, 0x95, 0x3B, 0x5C, 0x6A, 0xA3, 0x16, 0x90, 0xEE, 0x37, 0x57, 0x34, 0x7B, 0xAA, 0x8C, 0x0A, 0x88, 0x8C, 0x52, 0x8C, 0x78, 0xB8, 0x2A, 0xD9, 0x6A, - 0x53, 0xE7, 0x38, 0x3F, 0x94, 0x9E, 0x86, 0x3B, 0x3F, 0x8C, 0x1F, 0xDC, 0x3B, 0xC7, 0x47, 0xE2, 0xE4, 0x87, 0xE6, 0x78, 0x3F, 0xA6, 0x63, 0x04, 0xC1, 0x85, - 0x8E, 0x8F, 0x76, 0xE9, 0xC9, 0x67, 0xE8, 0xCE, 0x2D, 0xFB, 0x46, 0xB3, 0xAD, 0x0B, 0xDD, 0xF1, 0xC6, 0x5E, 0xEA, 0x1E, 0xBD, 0xCF, 0xB4, 0x0C, 0x79, 0xEC, - 0x42, 0x4F, 0xAC, 0x2F, 0xEA, 0x14, 0x2A, 0xBE, 0xA4, 0x0F, 0x1E, 0x7D, 0xF7, 0xE4, 0xF1, 0xE3, 0x93, 0x1F, 0x1E, 0xB9, 0xC3, 0x60, 0xC6, 0xFF, 0xFF, 0x33, - 0x5B, 0x8E, 0xFD, 0xE9, 0x63, 0xEF, 0xA4, 0x0F, 0xC3, 0x3D, 0x12, 0x86, 0x60, 0x7A, 0xC1, 0xF9, 0x21, 0x45, 0x9A, 0x22, 0xE4, 0x10, 0x28, 0xC9, 0xA1, 0x8D, - 0x97, 0x3B, 0x2A, 0xF2, 0x44, 0x93, 0x00, 0x32, 0xF8, 0xD0, 0xF0, 0x15, 0x4D, 0x68, 0x33, 0x56, 0x4C, 0xD3, 0x50, 0xA2, 0x53, 0x9D, 0x0C, 0xBD, 0x65, 0x9A, - 0x03, 0xCA, 0x14, 0x57, 0x18, 0x6F, 0x45, 0xAC, 0x3C, 0x84, 0x00, 0x46, 0xC1, 0x71, 0x71, 0x15, 0xDA, 0x28, 0x1B, 0x25, 0x54, 0x80, 0x8D, 0x97, 0xA6, 0xF3, - 0x45, 0xE8, 0x5E, 0x17, 0x4A, 0x71, 0xBD, 0x90, 0x85, 0xCA, 0x9C, 0xAE, 0x12, 0xAC, 0x72, 0x18, 0x69, 0xD9, 0x90, 0x71, 0x01, 0xA2, 0x6D, 0x51, 0xEC, 0xEC, - 0x5A, 0x31, 0x26, 0x8A, 0x4D, 0xD2, 0xAB, 0x00, 0xD6, 0x07, 0x9F, 0x2E, 0xDF, 0xFE, 0x5D, 0x7B, 0xF7, 0xFA, 0x4F, 0xA5, 0x86, 0xCA, 0x88, 0xC2, 0x18, 0x5D, - 0xA1, 0x67, 0x0A, 0xC6, 0xF4, 0x21, 0x64, 0xA2, 0x73, 0xCD, 0x50, 0x0C, 0x98, 0xED, 0x1D, 0xE2, 0x8E, 0xC3, 0xC9, 0x85, 0xDE, 0xD5, 0xF1, 0x91, 0x16, 0x71, - 0xD6, 0xD3, 0x35, 0x8C, 0xDF, 0xF4, 0xE0, 0xC6, 0x70, 0xE6, 0x78, 0xD4, 0xA9, 0xC2, 0x6B, 0xD6, 0xB4, 0x94, 0xCD, 0x78, 0x60, 0x89, 0x64, 0x2C, 0x05, 0xE2, - 0xA4, 0x94, 0xF5, 0xC1, 0x35, 0x09, 0xCF, 0x0F, 0xD9, 0xAD, 0x12, 0xAD, 0x15, 0xF7, 0x0D, 0x9E, 0xCC, 0xCC, 0xA1, 0xC8, 0x84, 0x8A, 0x14, 0x3F, 0xF2, 0x8D, - 0x29, 0x41, 0xA9, 0x54, 0xD2, 0xBC, 0xAC, 0xF5, 0x08, 0x52, 0x1F, 0x7C, 0x20, 0xB4, 0x20, 0x02, 0x32, 0x2A, 0x29, 0xFE, 0x9C, 0xD7, 0xA8, 0x89, 0xFE, 0x23, - 0x7B, 0xE6, 0x6B, 0x52, 0x2D, 0x83, 0x99, 0x79, 0x05, 0xB9, 0x3F, 0x6C, 0xB5, 0xB4, 0xDE, 0xBB, 0xF7, 0x5A, 0xAB, 0x55, 0xA1, 0xB1, 0x37, 0xA3, 0xEE, 0xC4, - 0xF5, 0xDF, 0x3D, 0xD2, 0x07, 0xBF, 0x7C, 0x7A, 0xF5, 0xAC, 0x0E, 0x75, 0x61, 0x67, 0xD9, 0xED, 0x75, 0x3A, 0x8D, 0xF3, 0x43, 0xD6, 0x64, 0x7D, 0x5C, 0x3D, - 0xD0, 0x2B, 0xC5, 0xD5, 0x3B, 0x05, 0x5C, 0x9D, 0x5E, 0x7F, 0x0B, 0x5C, 0x5D, 0x7D, 0xF0, 0xFA, 0x05, 0xC3, 0xF4, 0xB8, 0xB7, 0x0D, 0x51, 0x60, 0xE0, 0x94, - 0x26, 0x20, 0x67, 0xF9, 0xF8, 0xE4, 0x74, 0x73, 0x4C, 0x4F, 0x80, 0xBB, 0x8F, 0x80, 0xE9, 0x14, 0x04, 0x75, 0xB2, 0x8D, 0x9C, 0x4E, 0xF5, 0x01, 0xE2, 0x81, - 0x88, 0xBE, 0xEC, 0x9F, 0x6E, 0x81, 0xE7, 0x31, 0x88, 0x08, 0x11, 0x01, 0x92, 0xE5, 0xD1, 0x36, 0x32, 0x3A, 0xD1, 0x07, 0x97, 0x6F, 0x5E, 0xD6, 0xFB, 0xC0, - 0x58, 0xEF, 0xC9, 0xC9, 0xE6, 0x78, 0x8E, 0xF5, 0xC1, 0x3F, 0x90, 0x20, 0x20, 0x66, 0xD9, 0xEB, 0x6F, 0x41, 0x50, 0x5F, 0x1F, 0x00, 0x3C, 0xE2, 0xD8, 0x18, - 0x05, 0xD8, 0xF5, 0x6B, 0x4A, 0x0C, 0x22, 0xEA, 0x3E, 0xDE, 0x82, 0x2B, 0xB0, 0xEA, 0x7F, 0xA0, 0x78, 0x00, 0xC9, 0xB2, 0xDB, 0xDF, 0xC6, 0xA6, 0x01, 0x11, - 0x25, 0x09, 0x7C, 0x0D, 0x5D, 0x6D, 0x73, 0x4C, 0x60, 0xD3, 0x4F, 0x4E, 0x96, 0x4F, 0x4E, 0xAA, 0x21, 0xC0, 0x18, 0x89, 0xF1, 0xA6, 0x28, 0x8A, 0x16, 0x07, - 0xD9, 0xA2, 0x00, 0xFA, 0xEF, 0x39, 0x0C, 0x8B, 0xC2, 0xD5, 0xDA, 0xE1, 0x93, 0xC3, 0x81, 0x4C, 0xD8, 0x41, 0xB5, 0xC8, 0x29, 0x51, 0x12, 0x3D, 0xA1, 0xA3, - 0x0F, 0xFA, 0x15, 0x32, 0x54, 0xA2, 0x84, 0xA1, 0xB0, 0x09, 0xFA, 0x69, 0xDA, 0x44, 0xCB, 0xC3, 0x84, 0x09, 0x2E, 0x71, 0xA4, 0x4B, 0x11, 0x64, 0xA3, 0xD0, - 0xAC, 0xA0, 0xD5, 0x58, 0xEA, 0x83, 0x93, 0xA3, 0xD2, 0x94, 0xB6, 0xB9, 0x32, 0x86, 0x74, 0x00, 0xEE, 0x92, 0x20, 0x58, 0x5B, 0x1F, 0x31, 0xA8, 0x3E, 0x78, - 0x1E, 0x1D, 0x6F, 0xA3, 0x95, 0x56, 0x6F, 0x0B, 0xB5, 0x48, 0xE4, 0x30, 0xCD, 0xB4, 0x7A, 0x5C, 0x35, 0x71, 0xF1, 0x72, 0xB7, 0x8A, 0x29, 0xA3, 0x76, 0x1B, - 0xBD, 0x60, 0x01, 0xEE, 0x1B, 0x41, 0xB8, 0xB6, 0x56, 0x04, 0x20, 0x44, 0x68, 0x7E, 0xB4, 0x37, 0x8D, 0x44, 0xA4, 0x7C, 0x03, 0xFA, 0x08, 0x8C, 0x70, 0xCE, - 0x9E, 0x85, 0x5A, 0x5B, 0x23, 0x31, 0x28, 0xD4, 0x03, 0xD1, 0xF1, 0xDE, 0xB4, 0x22, 0x91, 0xF3, 0x2D, 0xE8, 0x65, 0x46, 0x4C, 0xDB, 0x70, 0x3E, 0x93, 0xD1, - 0x08, 0x12, 0xD6, 0xFA, 0xBA, 0x49, 0x80, 0x83, 0x7E, 0xD8, 0xB9, 0x76, 0x45, 0xCF, 0xD7, 0xAE, 0xCD, 0x53, 0xE8, 0x36, 0x2F, 0xD0, 0xD3, 0xD9, 0x9B, 0x4F, - 0x52, 0x13, 0x3A, 0x24, 0x62, 0x47, 0xFA, 0xE0, 0x47, 0x2F, 0xA2, 0x73, 0xF3, 0x02, 0xE3, 0x47, 0x32, 0xA6, 0x73, 0xC0, 0xDB, 0x54, 0x3B, 0xAF, 0x7C, 0x63, - 0x45, 0x37, 0x19, 0x6E, 0x53, 0x7C, 0x7D, 0x20, 0x96, 0xF6, 0xB3, 0xED, 0x6E, 0xCE, 0x4C, 0x1F, 0x09, 0x21, 0xC4, 0xDD, 0x0E, 0x0B, 0x94, 0xA4, 0xCF, 0xE1, - 0x60, 0x3B, 0x24, 0x27, 0x38, 0x5E, 0x9D, 0xD9, 0xC6, 0xD7, 0x50, 0x6E, 0x19, 0x8B, 0xE1, 0xDA, 0x6E, 0x01, 0x30, 0xFA, 0xE0, 0xD9, 0xAF, 0xCF, 0xD7, 0x0E, - 0x52, 0x6C, 0x25, 0xB5, 0x8A, 0x85, 0xC7, 0xF3, 0x11, 0xD8, 0x59, 0x66, 0xA2, 0x48, 0xED, 0x39, 0x55, 0x27, 0x8B, 0x14, 0x7C, 0x09, 0x02, 0xE9, 0xC2, 0x93, - 0x2E, 0xB1, 0x59, 0x8D, 0xC7, 0xFB, 0x8B, 0x60, 0x40, 0xC4, 0xE7, 0xB1, 0x61, 0xAF, 0x9F, 0x57, 0x04, 0x20, 0xD5, 0x94, 0xF6, 0x0A, 0x8E, 0x76, 0xA5, 0x2E, - 0xD6, 0xED, 0xDE, 0x74, 0xC6, 0xB9, 0xDE, 0xB7, 0xE2, 0x80, 0x90, 0xA9, 0x67, 0xAD, 0x3F, 0x0D, 0xC4, 0xE1, 0xF4, 0x01, 0x68, 0xED, 0x1D, 0x1C, 0xAC, 0x9D, - 0x65, 0x04, 0x82, 0x7B, 0x4E, 0x2F, 0xCF, 0xE6, 0xA1, 0xB7, 0x4D, 0x66, 0xB9, 0x9E, 0xBB, 0xEE, 0x6A, 0x9B, 0xB4, 0x72, 0xE9, 0x78, 0x73, 0x6B, 0x73, 0x0C, - 0x90, 0x53, 0x7E, 0x1A, 0x8D, 0x6C, 0x73, 0xF3, 0xAC, 0x04, 0x19, 0xE5, 0xB5, 0x37, 0xAD, 0x08, 0x7F, 0xCF, 0x51, 0x9C, 0x98, 0xEB, 0x07, 0x08, 0x62, 0x82, - 0x16, 0xAF, 0x2E, 0xB5, 0xEB, 0xAB, 0x1F, 0xAF, 0x7F, 0xFA, 0xB0, 0x9B, 0xE8, 0x00, 0x7D, 0xEE, 0x29, 0x30, 0x20, 0xB7, 0xFB, 0x8E, 0x09, 0x40, 0x44, 0x6F, - 0x13, 0x3D, 0xF5, 0x98, 0xA2, 0x5E, 0x5C, 0xBF, 0xDF, 0x95, 0x96, 0x7A, 0xFB, 0x53, 0x53, 0xEF, 0x6B, 0xD0, 0xD3, 0x67, 0x87, 0xDC, 0x10, 0x67, 0x03, 0x5D, - 0x31, 0x40, 0xD4, 0x97, 0xF6, 0x16, 0x8F, 0xF6, 0x36, 0x90, 0x8B, 0x48, 0xF9, 0x06, 0x86, 0x71, 0x60, 0x15, 0x9F, 0x29, 0xD1, 0x9B, 0x38, 0x0F, 0x83, 0xD4, - 0x07, 0x57, 0xCB, 0x99, 0x17, 0xCC, 0xFD, 0x8A, 0x09, 0x55, 0xAD, 0x91, 0xCE, 0x56, 0x0A, 0x11, 0xA4, 0x30, 0x8D, 0x74, 0xB8, 0x42, 0x70, 0x91, 0x44, 0x5A, - 0x3F, 0xEB, 0xDF, 0xA9, 0x56, 0x10, 0xF9, 0x7D, 0x2A, 0x66, 0xBC, 0x41, 0xDE, 0x19, 0x63, 0xDE, 0x79, 0x75, 0xB9, 0x9B, 0x50, 0x36, 0xDE, 0x5B, 0xC2, 0x19, - 0xEF, 0x35, 0xE1, 0x68, 0x7C, 0x0D, 0x5B, 0x48, 0x61, 0xC3, 0x41, 0x04, 0x07, 0x84, 0xB1, 0xF3, 0x26, 0x03, 0x08, 0xC9, 0x73, 0xBA, 0xCB, 0x6D, 0x5C, 0x47, - 0x90, 0x91, 0xF4, 0x9C, 0xA3, 0xD8, 0x6F, 0x8E, 0xEF, 0xD4, 0x6B, 0x8E, 0x4A, 0xA9, 0xDD, 0xC6, 0x69, 0x90, 0x13, 0x93, 0xD8, 0x0E, 0x6E, 0x65, 0x5E, 0x57, - 0x21, 0x12, 0x2C, 0xD3, 0x89, 0x76, 0xC9, 0xCE, 0xB6, 0xD1, 0x4D, 0x6F, 0x1B, 0xDD, 0xC8, 0x14, 0x25, 0xD5, 0x73, 0x72, 0x4F, 0x99, 0xA6, 0xDB, 0x3B, 0xBD, - 0x4F, 0xF5, 0x0C, 0x67, 0xEB, 0xC7, 0x34, 0x80, 0xD1, 0x07, 0xCF, 0xDF, 0xEF, 0x26, 0xA6, 0x61, 0x67, 0x15, 0x63, 0xDA, 0x56, 0x11, 0x8C, 0x32, 0xB5, 0xEF, - 0x52, 0x6C, 0xB1, 0x81, 0x36, 0x16, 0x48, 0xF8, 0xAF, 0x3B, 0xD2, 0xC6, 0xA2, 0xBA, 0x36, 0xEE, 0x38, 0xC3, 0x2C, 0xBE, 0x06, 0xFD, 0xF8, 0xC6, 0xE2, 0xF3, - 0x78, 0x6A, 0xAC, 0xAD, 0x23, 0x0E, 0xA7, 0x0F, 0x3E, 0x18, 0x0B, 0xED, 0xD5, 0xBB, 0x67, 0x3B, 0xD1, 0x95, 0xE8, 0x74, 0x3F, 0xFA, 0x8A, 0x58, 0xDE, 0xB7, - 0xCE, 0x1C, 0xE2, 0xAE, 0xEF, 0x54, 0x08, 0xA4, 0x0F, 0xDE, 0x12, 0x37, 0xD0, 0x2E, 0x3D, 0x9F, 0xBF, 0x76, 0x6E, 0x27, 0x5A, 0xA3, 0x3D, 0xEF, 0x47, 0x65, - 0x8C, 0xE9, 0x7D, 0xEB, 0x6B, 0x32, 0xB5, 0x7D, 0xDF, 0xF3, 0xD7, 0x56, 0x19, 0x87, 0xD3, 0x07, 0xAF, 0x5B, 0xEF, 0xE8, 0xD1, 0x4E, 0xD4, 0x25, 0x7A, 0xDD, - 0x8F, 0xC6, 0x22, 0x9E, 0xF7, 0xAD, 0xB4, 0x9B, 0x91, 0x63, 0xCF, 0xD6, 0x56, 0x19, 0x85, 0xD2, 0x07, 0x1F, 0x5B, 0x2F, 0xE1, 0xEF, 0x4E, 0xD4, 0xC5, 0x7A, - 0xDC, 0x8F, 0xB2, 0x38, 0xB7, 0xFB, 0x56, 0x95, 0x65, 0x2E, 0xD6, 0x56, 0x14, 0xC0, 0xE8, 0x83, 0x17, 0x97, 0xBF, 0x6A, 0xF5, 0x17, 0xDE, 0xC2, 0xC5, 0x07, - 0x2E, 0xB5, 0xAB, 0x1F, 0x1B, 0x3B, 0xD1, 0x18, 0x76, 0xBD, 0x1F, 0x7D, 0x51, 0xA6, 0xF7, 0xAD, 0x2D, 0xBA, 0xAF, 0x66, 0x68, 0xAC, 0x1F, 0x0E, 0x05, 0x20, - 0x3E, 0xFB, 0x02, 0x47, 0xDA, 0x73, 0x63, 0x37, 0x01, 0x31, 0xEA, 0x77, 0x17, 0x45, 0x7B, 0xCC, 0xE4, 0xBE, 0xF5, 0xE4, 0x10, 0xAB, 0x82, 0x8A, 0x92, 0x25, - 0x86, 0xF5, 0x19, 0xB7, 0xA8, 0xE0, 0xD6, 0xCD, 0x15, 0xD4, 0x1A, 0x57, 0x2F, 0xB4, 0x37, 0xE2, 0xB4, 0x02, 0x37, 0x1B, 0xCF, 0xD9, 0xE5, 0x0D, 0x6D, 0x93, - 0xF4, 0x24, 0x07, 0xB7, 0xBD, 0xE3, 0xE3, 0xED, 0x86, 0xB7, 0x79, 0xD3, 0xA8, 0xC7, 0xC7, 0xF7, 0xA8, 0x93, 0x91, 0x61, 0x92, 0xCF, 0x16, 0x09, 0x37, 0x79, - 0x18, 0x46, 0x82, 0xD5, 0x07, 0x2F, 0xE1, 0x44, 0x7B, 0x41, 0x4F, 0x76, 0x55, 0x06, 0xCA, 0xFD, 0xEF, 0xC2, 0x93, 0x12, 0xFC, 0xEE, 0xDB, 0x99, 0x28, 0x31, - 0x50, 0x74, 0x7B, 0x63, 0x77, 0xA3, 0xBD, 0x05, 0x09, 0x70, 0xAE, 0xBE, 0x0F, 0xEC, 0x7C, 0xB7, 0x0A, 0x8C, 0x89, 0xD8, 0x99, 0x0E, 0x25, 0xBE, 0x77, 0xA1, - 0x46, 0x79, 0x83, 0x11, 0x7F, 0x33, 0x67, 0x99, 0xA6, 0xF8, 0x46, 0x17, 0x3A, 0x9D, 0x46, 0xC2, 0x56, 0x10, 0xDA, 0x8E, 0xA3, 0x0F, 0x5E, 0x91, 0x50, 0xBB, - 0xC6, 0xC3, 0x8A, 0x3B, 0x5B, 0x24, 0x2C, 0x62, 0x5B, 0x5B, 0xE8, 0x13, 0x63, 0xAA, 0x0F, 0xAE, 0xF1, 0x9D, 0xA5, 0x80, 0x0B, 0xCF, 0xD6, 0x47, 0x46, 0x85, - 0x48, 0x5C, 0xDF, 0x03, 0xA2, 0x22, 0x25, 0xF1, 0x77, 0xA1, 0xE9, 0x9A, 0x38, 0x92, 0xAE, 0x0D, 0xAE, 0x68, 0x63, 0x0D, 0xAD, 0xAC, 0xBC, 0xBB, 0xCA, 0x5B, - 0x6E, 0xE8, 0x1E, 0x3B, 0xDC, 0x34, 0x97, 0x7C, 0xA3, 0x31, 0x68, 0x95, 0xED, 0xA0, 0x1D, 0x9C, 0x07, 0x33, 0xC3, 0x15, 0xCD, 0xE8, 0xF6, 0xD2, 0x05, 0xDF, - 0x2F, 0x38, 0xF4, 0x1C, 0x0B, 0x1A, 0x3E, 0xB3, 0x6E, 0xF0, 0xED, 0x4E, 0x96, 0x76, 0x1D, 0xED, 0x7C, 0x43, 0x10, 0x30, 0x0B, 0x81, 0xA1, 0x44, 0xB7, 0x13, - 0x5F, 0xA0, 0x67, 0x7B, 0x14, 0xF1, 0x7D, 0x38, 0x05, 0xCA, 0xCD, 0xD9, 0xAC, 0xE7, 0x93, 0x71, 0x24, 0x48, 0xD5, 0x1E, 0x4E, 0xE5, 0xD6, 0xBD, 0x0F, 0x64, - 0x6C, 0x07, 0x40, 0xA3, 0x06, 0x66, 0x71, 0x48, 0xB7, 0x3B, 0x31, 0x53, 0xAE, 0xB6, 0x95, 0x4E, 0xEE, 0x92, 0x6F, 0x04, 0x56, 0x6E, 0x90, 0x5C, 0xAB, 0x62, - 0x4C, 0x6F, 0x67, 0x4C, 0x62, 0x2C, 0x33, 0xFA, 0x87, 0xAD, 0xD6, 0xA4, 0x8F, 0x1B, 0xB7, 0x34, 0xC1, 0xDA, 0xF9, 0xE1, 0xA4, 0x5F, 0xB6, 0xE7, 0xA8, 0x74, - 0xD7, 0x1D, 0x70, 0xBA, 0xF1, 0xA6, 0x3B, 0x94, 0xD2, 0x00, 0xA8, 0x69, 0x6A, 0xEF, 0x8C, 0xE0, 0x4B, 0x53, 0xFB, 0x88, 0xF9, 0x7D, 0x87, 0x7B, 0xEF, 0x90, - 0x76, 0xC3, 0xB2, 0xFC, 0xDC, 0xFD, 0x77, 0xFD, 0xC4, 0xFE, 0xBB, 0x13, 0xB1, 0xFF, 0x4E, 0x9A, 0x69, 0x5F, 0x76, 0xBB, 0xDD, 0x2A, 0x9C, 0x57, 0xDC, 0x82, - 0x77, 0x27, 0x2C, 0x4D, 0x41, 0x98, 0x15, 0x59, 0xEA, 0x0B, 0x96, 0xFA, 0x12, 0x4B, 0xA7, 0x77, 0xB9, 0xA9, 0xF0, 0x4E, 0x38, 0xE2, 0xEB, 0xB8, 0x5F, 0x09, - 0x4B, 0x95, 0xF6, 0x49, 0x52, 0xDB, 0xBE, 0xAB, 0x6D, 0x92, 0xB4, 0x49, 0x3A, 0x18, 0x1E, 0x17, 0xC6, 0x42, 0x0A, 0xC2, 0x7C, 0xFE, 0xD5, 0x5D, 0xFA, 0xFC, - 0x78, 0x0B, 0x9F, 0x1F, 0x67, 0x7C, 0x7E, 0x87, 0xCE, 0x2E, 0x08, 0xFF, 0xC6, 0x1C, 0x5E, 0xB0, 0xB5, 0x86, 0xD3, 0x2B, 0xD9, 0xDA, 0xAD, 0x87, 0x44, 0x96, - 0xF0, 0xEA, 0x2E, 0x3D, 0x24, 0xC7, 0x6E, 0x37, 0x32, 0x52, 0x1E, 0x73, 0x06, 0xBB, 0xC9, 0x49, 0xB4, 0x92, 0x92, 0xD5, 0xC9, 0x7B, 0xC7, 0x8D, 0x86, 0x47, - 0x7D, 0x5E, 0x36, 0xDD, 0x85, 0x7A, 0xAA, 0xEF, 0xC7, 0xCE, 0x6D, 0x72, 0x37, 0x45, 0x19, 0xBE, 0x11, 0x61, 0x26, 0x55, 0xB8, 0x95, 0x0B, 0xB3, 0xCB, 0xB7, - 0x7F, 0x5F, 0xAF, 0x16, 0x4B, 0xF7, 0xB4, 0xBB, 0x7A, 0x6C, 0x33, 0x6B, 0x95, 0x05, 0xC6, 0x69, 0x87, 0x88, 0x83, 0x6F, 0x26, 0xE8, 0x7D, 0x8A, 0x38, 0x57, - 0x8C, 0x0D, 0xA5, 0xA0, 0x10, 0x81, 0xE5, 0x0D, 0xFA, 0x68, 0x20, 0xE4, 0x73, 0x96, 0x70, 0x2C, 0xE2, 0x9A, 0xE6, 0x8D, 0x46, 0xF4, 0x73, 0x57, 0x8F, 0x31, - 0x60, 0x04, 0x5F, 0xF0, 0x7A, 0xA7, 0x1B, 0x91, 0xA4, 0x1A, 0xF2, 0xC5, 0x14, 0x46, 0xB4, 0x51, 0x13, 0xE3, 0x86, 0x76, 0x67, 0x22, 0x38, 0x62, 0x22, 0x78, - 0xF1, 0xE6, 0xA3, 0x4A, 0x06, 0xCC, 0xD7, 0x3A, 0x59, 0x11, 0x1C, 0x6D, 0xFE, 0x6E, 0x85, 0x6E, 0x65, 0x69, 0x75, 0x62, 0x69, 0x1D, 0x8D, 0xE2, 0x2D, 0xA2, - 0xDB, 0x84, 0x2C, 0x85, 0x04, 0x8E, 0xD9, 0x43, 0xE0, 0xDA, 0x7B, 0xD9, 0x03, 0x2A, 0xD9, 0xC1, 0xF1, 0x3A, 0x76, 0x60, 0x1D, 0x6D, 0x61, 0x06, 0xC7, 0x39, - 0x66, 0x70, 0x57, 0x32, 0xE8, 0xEB, 0x83, 0xF7, 0x9B, 0x98, 0x41, 0xBF, 0xA2, 0x19, 0x1C, 0x09, 0x33, 0x88, 0xF7, 0x0F, 0xF7, 0xAB, 0x0A, 0x4B, 0xB2, 0x82, - 0xC7, 0x23, 0x7C, 0x6C, 0xE6, 0x71, 0x35, 0x4F, 0xD8, 0x5D, 0xCC, 0x5D, 0xD8, 0xEE, 0xFA, 0xF1, 0xF6, 0x57, 0xDB, 0xB5, 0xBC, 0xC5, 0x7A, 0x21, 0x57, 0xEE, - 0xE8, 0x6B, 0x0F, 0xB7, 0xEB, 0x8D, 0x5A, 0x71, 0x66, 0xA7, 0xB5, 0xC4, 0xCA, 0xDE, 0x0D, 0x3C, 0x5F, 0xCB, 0xBE, 0x39, 0x24, 0xB1, 0x01, 0x51, 0xB4, 0xAE, - 0x56, 0x04, 0x64, 0xB7, 0x5C, 0xBC, 0x79, 0xA9, 0x6D, 0xF0, 0x5A, 0x07, 0x05, 0xB2, 0x2E, 0x7B, 0xF9, 0x85, 0xB6, 0xC1, 0xDB, 0x2F, 0x14, 0xD8, 0x72, 0xB6, - 0xA8, 0xE0, 0x8B, 0x48, 0xB4, 0xCD, 0xDE, 0x44, 0x52, 0xBA, 0x5B, 0x83, 0xB5, 0xDA, 0x3C, 0xA5, 0x44, 0xE3, 0x32, 0xE6, 0xAD, 0x50, 0x63, 0x55, 0xDB, 0x62, - 0x4F, 0x71, 0x4A, 0x06, 0xC0, 0xC1, 0x97, 0x74, 0x37, 0x4B, 0x40, 0xAA, 0x6D, 0x4A, 0x4D, 0x13, 0xB6, 0x46, 0x65, 0xF8, 0xE9, 0x4C, 0x0A, 0x66, 0x51, 0xE7, - 0x6B, 0x06, 0xB3, 0xB8, 0xCE, 0x07, 0x63, 0xDA, 0xFB, 0xE0, 0xE5, 0x9F, 0x0A, 0x96, 0x56, 0x9B, 0xB3, 0x74, 0x74, 0x57, 0x2C, 0x6D, 0x91, 0xAA, 0x22, 0xEB, - 0x0A, 0xBD, 0xD0, 0x70, 0x36, 0x36, 0x2E, 0x06, 0x0D, 0xB6, 0xC5, 0x62, 0xAE, 0x76, 0x0D, 0xAC, 0xEE, 0xD4, 0xC0, 0x04, 0x01, 0xD5, 0x94, 0xD1, 0xCF, 0x2A, - 0xE3, 0xF4, 0x6B, 0xB3, 0x2F, 0xC6, 0x51, 0x55, 0xF3, 0x52, 0x70, 0x74, 0xF2, 0x35, 0x99, 0x97, 0x37, 0x0F, 0xF1, 0xEA, 0xC6, 0xC1, 0x8B, 0x81, 0x63, 0xF0, - 0xA2, 0x47, 0xBB, 0x37, 0xB0, 0x88, 0x82, 0x8D, 0xF5, 0x71, 0x74, 0xA7, 0xAF, 0x3C, 0xBB, 0x8B, 0x08, 0xC6, 0x58, 0xDA, 0xC2, 0xC4, 0x7A, 0xFD, 0x1D, 0x9A, - 0x98, 0xB4, 0xD0, 0xC4, 0xF3, 0x20, 0x2F, 0x60, 0x74, 0xBE, 0x36, 0x10, 0x17, 0x34, 0xEB, 0xAC, 0x24, 0xA9, 0xB3, 0xF2, 0xF9, 0x21, 0x14, 0x85, 0x59, 0x04, - 0x39, 0x74, 0x9E, 0xB3, 0x2F, 0x27, 0xAA, 0x3B, 0x8C, 0xDF, 0x74, 0x48, 0x97, 0xD5, 0xE2, 0x77, 0xEA, 0x46, 0x85, 0x66, 0xFA, 0x5D, 0xBB, 0xA5, 0x6F, 0x15, - 0x3C, 0x37, 0xF8, 0x2B, 0x38, 0x6E, 0x08, 0x5F, 0x03, 0xD4, 0x26, 0x3E, 0x19, 0x5D, 0xE8, 0xDF, 0x45, 0x38, 0xB9, 0xB4, 0xB0, 0x89, 0xAE, 0x41, 0x48, 0x76, - 0x1D, 0xCF, 0xC0, 0x62, 0xD5, 0x98, 0x85, 0x40, 0x69, 0xFB, 0x8F, 0x19, 0x4E, 0xF2, 0x1A, 0xF8, 0xBE, 0x06, 0xA3, 0xDA, 0x4A, 0x33, 0x7D, 0x3B, 0x2F, 0x7F, - 0xB0, 0x06, 0x0F, 0xA3, 0x35, 0xC3, 0xFF, 0xF9, 0xEF, 0xB2, 0xA9, 0x19, 0xFC, 0x7E, 0x66, 0x2C, 0x00, 0x30, 0x23, 0xDF, 0xBC, 0xD0, 0x81, 0x52, 0xDF, 0x0B, - 0xA0, 0x14, 0xB5, 0xC7, 0x76, 0x8E, 0xAA, 0xF2, 0xA4, 0x7D, 0xA8, 0x12, 0x77, 0xAA, 0xB1, 0x62, 0x6C, 0x72, 0x1E, 0x98, 0xBE, 0x3D, 0x83, 0x52, 0xCD, 0xF2, - 0xCC, 0xF9, 0x94, 0xB8, 0x61, 0xDB, 0xB0, 0xAC, 0xAB, 0x1B, 0x38, 0x78, 0x8B, 0x33, 0xCC, 0x20, 0xF9, 0x7A, 0xED, 0xC5, 0x4F, 0xEF, 0x2E, 0xD9, 0x3B, 0x2B, - 0xDF, 0x82, 0xBC, 0x88, 0x55, 0x6B, 0x6A, 0xA3, 0xB9, 0xCB, 0xAA, 0xF7, 0x3A, 0xC1, 0xB6, 0xEC, 0x3B, 0xA6, 0x37, 0x86, 0xAF, 0x0D, 0x8D, 0x80, 0xBC, 0xF6, - 0x82, 0x50, 0xBB, 0xD0, 0x22, 0x8C, 0x8E, 0x67, 0xD2, 0x77, 0xA2, 0xB4, 0x19, 0x5F, 0xBC, 0x25, 0x63, 0xFC, 0x17, 0xDF, 0x81, 0xA6, 0x11, 0xD4, 0x81, 0x56, - 0x3B, 0x3B, 0xED, 0xD6, 0xD0, 0xFE, 0xA2, 0x2E, 0x46, 0xF8, 0x65, 0x52, 0x68, 0x57, 0x9F, 0xFB, 0x4E, 0x53, 0x33, 0x87, 0x0D, 0xF6, 0x9E, 0x51, 0x7A, 0x19, - 0xAF, 0x89, 0x17, 0x50, 0xB7, 0xC3, 0x09, 0x71, 0xEB, 0x31, 0x65, 0xE0, 0x0C, 0x33, 0xCF, 0x0D, 0x12, 0x1F, 0x59, 0xB5, 0x47, 0xF1, 0xF5, 0x36, 0x14, 0xF4, - 0xE1, 0x3C, 0xD0, 0x1E, 0x5E, 0x5C, 0x68, 0x58, 0xE0, 0x26, 0xDE, 0x5F, 0x6A, 0x0E, 0xD3, 0xED, 0x9A, 0x5A, 0xEA, 0xC2, 0xCF, 0x10, 0x1A, 0xA4, 0x37, 0x65, - 0xDF, 0x6A, 0xC4, 0x49, 0xBD, 0xAA, 0x39, 0x02, 0xC0, 0x28, 0x52, 0x6F, 0x24, 0x09, 0xAC, 0x5B, 0x46, 0x68, 0x34, 0x92, 0xEF, 0x4C, 0x85, 0x5E, 0x81, 0x92, - 0xA6, 0x46, 0x6F, 0xC9, 0x2F, 0x70, 0xBD, 0x6D, 0xB4, 0x41, 0x86, 0xC0, 0x6F, 0x04, 0x4D, 0x7C, 0x3F, 0xFD, 0xF5, 0x58, 0x80, 0x6E, 0x75, 0x9B, 0x1A, 0xDE, - 0x49, 0xC2, 0x4A, 0x44, 0x3E, 0x10, 0xD7, 0x84, 0xD0, 0x8A, 0xD1, 0x2A, 0x50, 0x32, 0x74, 0xB7, 0x09, 0x15, 0x41, 0xEC, 0xF9, 0x40, 0xC6, 0x20, 0xB1, 0x71, - 0x93, 0x0F, 0xA0, 0x9B, 0x74, 0xF4, 0xDC, 0x64, 0x41, 0x51, 0xD2, 0xDA, 0xE1, 0x21, 0xB8, 0x34, 0x04, 0x25, 0x02, 0x56, 0x31, 0xAE, 0xD7, 0xF8, 0x02, 0x26, - 0x58, 0x54, 0xAD, 0xB3, 0xAC, 0x1D, 0x00, 0x82, 0x76, 0xE8, 0x5D, 0x87, 0xBE, 0xED, 0x8E, 0x61, 0xE8, 0xD1, 0x88, 0xB1, 0xD1, 0xDB, 0x88, 0x32, 0x75, 0x9F, - 0x5E, 0xA7, 0x9D, 0xA4, 0x6F, 0xD4, 0xF9, 0xF5, 0x83, 0x5A, 0xA3, 0xC6, 0x89, 0xA7, 0xE7, 0x60, 0x6E, 0x75, 0x76, 0xF0, 0x88, 0xD2, 0xD8, 0xD0, 0xCE, 0xCF, - 0x79, 0x37, 0xAC, 0x15, 0x5E, 0x84, 0x46, 0xF4, 0x4F, 0xEA, 0x56, 0x64, 0x8A, 0xBF, 0x7F, 0xFF, 0x97, 0xB0, 0xD9, 0xDB, 0x43, 0xA0, 0xFA, 0x29, 0xCE, 0x20, - 0x7C, 0xFF, 0x17, 0xFC, 0xFF, 0xF6, 0x11, 0x9D, 0x36, 0xF8, 0xFE, 0x2F, 0xFC, 0x73, 0xFB, 0x08, 0x7A, 0x82, 0x63, 0xDA, 0xDF, 0xED, 0xEF, 0x54, 0x0E, 0x59, - 0xE9, 0x8D, 0x73, 0xA5, 0x17, 0x89, 0x6D, 0x6D, 0x9A, 0xC6, 0x05, 0x44, 0xFD, 0x1E, 0xFB, 0x6F, 0xDD, 0xF4, 0x2C, 0x50, 0x4F, 0x08, 0x96, 0x2C, 0x94, 0xEE, - 0x80, 0x4A, 0x84, 0xA0, 0xA2, 0x97, 0x08, 0xDB, 0x23, 0xDA, 0x52, 0xE3, 0xAE, 0x12, 0x1B, 0x88, 0x68, 0x39, 0x33, 0xFC, 0x80, 0xBC, 0x71, 0xC3, 0x7A, 0x98, - 0x70, 0x8A, 0x1C, 0x89, 0x0F, 0x06, 0x09, 0x16, 0xF0, 0x07, 0x70, 0xD0, 0xAE, 0xC6, 0x95, 0x16, 0x19, 0xDB, 0x83, 0xC8, 0x0E, 0x63, 0x4A, 0xD9, 0xCD, 0x1C, - 0x3B, 0xFC, 0x64, 0x3A, 0x5F, 0xEA, 0xF8, 0x5A, 0xD3, 0x74, 0xA8, 0xC8, 0x88, 0x08, 0x1B, 0x3D, 0xC5, 0xFF, 0x81, 0x5C, 0xF0, 0x4F, 0xAE, 0x7E, 0x00, 0x2B, - 0x2B, 0xE1, 0xEB, 0x74, 0x0A, 0xE0, 0xF3, 0xB2, 0xA9, 0xB1, 0x83, 0x15, 0x78, 0x86, 0x6B, 0xE1, 0x39, 0xFE, 0x59, 0x09, 0xED, 0xE1, 0x05, 0x7E, 0x04, 0xD7, - 0x68, 0xCD, 0x8A, 0x97, 0xD8, 0x01, 0xB6, 0xA2, 0x35, 0x06, 0x6D, 0xC5, 0x8E, 0xE0, 0x1A, 0xBE, 0xE2, 0x07, 0x6C, 0xB7, 0xA9, 0x0D, 0x6D, 0xD7, 0xA5, 0x07, - 0x25, 0xD4, 0xC7, 0xA9, 0xFE, 0x69, 0xB0, 0x04, 0x0E, 0x38, 0x69, 0xB7, 0x8F, 0x82, 0x55, 0x74, 0xB6, 0xBA, 0x7D, 0x44, 0xF0, 0x1E, 0x25, 0x12, 0x8E, 0x57, - 0xFC, 0x18, 0xAE, 0x03, 0x7D, 0x78, 0x47, 0x10, 0x4C, 0x2F, 0xAC, 0xE2, 0x0B, 0xD0, 0x22, 0xC4, 0xFB, 0x9C, 0x78, 0x38, 0x5B, 0x45, 0x67, 0x08, 0x4D, 0x61, - 0x39, 0x1B, 0x70, 0xBA, 0x8A, 0x4F, 0xE1, 0x2E, 0x7D, 0x5D, 0x11, 0x12, 0xC1, 0x78, 0xBA, 0x7D, 0xC4, 0x79, 0x82, 0x4B, 0xFC, 0x28, 0x2D, 0x6A, 0x8C, 0x09, - 0x21, 0x8F, 0x22, 0xCF, 0x59, 0x92, 0x96, 0xF2, 0x07, 0xF8, 0xC7, 0x95, 0x43, 0xF0, 0xF0, 0xF9, 0xEA, 0x8D, 0x55, 0xAF, 0xF1, 0x05, 0xD9, 0x1A, 0xC6, 0x30, - 0x19, 0xA6, 0xED, 0xB9, 0xA6, 0x63, 0x9B, 0xE8, 0x28, 0xF5, 0x86, 0x76, 0x31, 0xE0, 0x71, 0x0C, 0x0D, 0x1A, 0x9A, 0xCB, 0x46, 0x9A, 0x8B, 0x5A, 0x2C, 0x29, - 0xD6, 0x1A, 0x6D, 0x6A, 0x87, 0xDC, 0xD6, 0x10, 0x05, 0x77, 0xC1, 0x6A, 0x38, 0xB0, 0xB1, 0x02, 0x47, 0xC6, 0x5B, 0x0A, 0x91, 0xD0, 0xD6, 0x12, 0x16, 0x8A, - 0x46, 0x0E, 0xB5, 0x9D, 0x54, 0x94, 0x2D, 0xF0, 0x6A, 0xE1, 0xC0, 0x0F, 0xD3, 0x0E, 0x0C, 0xAA, 0xF2, 0xC3, 0x7A, 0xED, 0x0A, 0x9F, 0xFB, 0xFF, 0xAD, 0x76, - 0x80, 0x8D, 0x0E, 0x6A, 0xFF, 0x3A, 0xD3, 0x6A, 0x07, 0xB2, 0x27, 0xDF, 0xA6, 0x5D, 0x8E, 0x69, 0x6C, 0x5C, 0x51, 0x63, 0x63, 0x49, 0x63, 0xE3, 0xBB, 0xD5, - 0x98, 0xBC, 0x10, 0xBC, 0x8D, 0xD6, 0xE4, 0x95, 0xD7, 0x02, 0xCD, 0x95, 0xC2, 0x73, 0xA5, 0x71, 0x6D, 0x8D, 0x55, 0xDA, 0xDA, 0x44, 0x4D, 0x2C, 0xC5, 0x81, - 0xF7, 0x10, 0xFF, 0xF5, 0xCF, 0xEF, 0xDE, 0x62, 0xA8, 0x54, 0xAB, 0x2C, 0xD2, 0x58, 0xBA, 0x1C, 0x51, 0x60, 0xC0, 0xDC, 0x99, 0x08, 0xDC, 0x89, 0x1C, 0x7A, - 0x50, 0xD3, 0xEA, 0x14, 0x25, 0x66, 0xD0, 0x12, 0x43, 0xE0, 0x81, 0xB7, 0x9A, 0xEF, 0x62, 0xB0, 0x15, 0xCE, 0x1B, 0x43, 0x15, 0xD8, 0x02, 0x02, 0x54, 0x52, - 0x22, 0xC3, 0x9C, 0x71, 0x18, 0x29, 0x27, 0xEC, 0xDC, 0x45, 0xA8, 0xBF, 0x06, 0x55, 0x83, 0x9A, 0x88, 0xE9, 0x71, 0x6C, 0x0B, 0x4A, 0xA5, 0xC3, 0x23, 0x7F, - 0x25, 0x01, 0xF1, 0x39, 0x6C, 0x85, 0x81, 0x8B, 0x4C, 0x50, 0x09, 0x8D, 0x98, 0xBA, 0xCC, 0xC7, 0xB3, 0x5A, 0x07, 0xCF, 0x4A, 0x81, 0x87, 0x67, 0x9E, 0x4A, - 0x68, 0xF8, 0x44, 0x57, 0x2E, 0x96, 0x6A, 0xC4, 0xF0, 0xC9, 0x25, 0x15, 0x4F, 0x3C, 0xD3, 0x55, 0xE3, 0x89, 0x4F, 0x8A, 0xE4, 0xE3, 0xA9, 0x28, 0x1B, 0x3E, - 0x13, 0xA1, 0xB0, 0xE7, 0x74, 0x35, 0xD2, 0x11, 0xFF, 0x6D, 0x5E, 0x7F, 0x8C, 0x0C, 0x88, 0x16, 0xF1, 0x9F, 0xBD, 0x78, 0xC9, 0xF8, 0xA3, 0xA8, 0x16, 0x89, - 0xA3, 0xCC, 0x06, 0xC4, 0x69, 0x1B, 0x21, 0xC4, 0x27, 0x18, 0xC7, 0x93, 0xA0, 0x8D, 0x15, 0x6E, 0x24, 0xC6, 0xCC, 0xAD, 0xB6, 0x0B, 0x04, 0x50, 0x84, 0x8D, - 0xB3, 0x4E, 0xDA, 0x3C, 0x33, 0xB8, 0xD8, 0xE5, 0x3C, 0x74, 0xEC, 0x6E, 0x0E, 0x46, 0x9E, 0x61, 0x92, 0x10, 0x78, 0x31, 0x0F, 0x1B, 0x1D, 0xC5, 0x48, 0xB8, - 0x7A, 0xC7, 0xC7, 0xD9, 0x3C, 0xC3, 0x3B, 0xE0, 0x5F, 0x4F, 0x43, 0x0C, 0x38, 0x1F, 0x15, 0x0F, 0xCD, 0x4C, 0x28, 0x04, 0xB5, 0x9A, 0x58, 0xB2, 0xAB, 0x9D, - 0x65, 0x2A, 0x6E, 0x80, 0xE0, 0x8B, 0x70, 0xDA, 0x53, 0x46, 0x63, 0xE2, 0x9B, 0x20, 0x43, 0x18, 0x7C, 0x47, 0x9F, 0xFE, 0x62, 0xC8, 0xE8, 0x3E, 0x8A, 0x08, - 0x13, 0xBB, 0x86, 0x03, 0xD7, 0xD4, 0x25, 0xB6, 0xB6, 0xD3, 0xF2, 0x5C, 0xA2, 0xEE, 0x35, 0x51, 0xBF, 0xF3, 0x8E, 0xF8, 0x19, 0x7F, 0x38, 0x3D, 0x06, 0xF3, - 0x49, 0x38, 0xF7, 0x5D, 0x5E, 0xCF, 0x67, 0xEB, 0x1B, 0xE5, 0x50, 0x72, 0x87, 0xB6, 0x79, 0x78, 0xA8, 0x3D, 0x0B, 0x43, 0x03, 0x14, 0x80, 0xEB, 0x94, 0x13, - 0x94, 0x8F, 0x66, 0xF0, 0x49, 0x09, 0xCF, 0x47, 0xA3, 0x64, 0x0F, 0x15, 0x13, 0xE6, 0xB7, 0xF8, 0xA5, 0x34, 0xE1, 0xCE, 0x14, 0x55, 0xFB, 0xDF, 0x73, 0xE2, - 0xAF, 0xAE, 0xA9, 0xC0, 0x3C, 0xFF, 0x99, 0xE3, 0xD4, 0x6B, 0xED, 0x78, 0xD9, 0xB9, 0xC6, 0xC6, 0xE0, 0x6D, 0x40, 0x75, 0x05, 0x7D, 0x80, 0x8E, 0x63, 0x9B, - 0x67, 0xDC, 0x44, 0x7A, 0x87, 0x71, 0xD7, 0x05, 0x57, 0x46, 0x7A, 0xD0, 0x0F, 0x2D, 0x3C, 0xF7, 0x0B, 0x59, 0xCD, 0x67, 0x20, 0xFE, 0x78, 0x18, 0x9F, 0x9A, - 0x58, 0xE0, 0xD2, 0x21, 0x6D, 0x68, 0x79, 0xC9, 0x07, 0x72, 0xDD, 0x23, 0x45, 0xA3, 0x58, 0x05, 0xD4, 0x3A, 0xD1, 0x13, 0xB3, 0x1F, 0x92, 0xB9, 0x7D, 0xA0, - 0x3E, 0x53, 0x4C, 0x81, 0x70, 0x02, 0xB9, 0xF0, 0x44, 0xF2, 0x4A, 0xF5, 0x90, 0x9A, 0x9E, 0xB8, 0x6D, 0x3C, 0x88, 0x23, 0xC3, 0x7C, 0x66, 0x19, 0x21, 0x49, - 0x06, 0x87, 0xC8, 0x16, 0xC4, 0xCD, 0xA9, 0x17, 0x92, 0x54, 0xC4, 0xB0, 0x71, 0x6F, 0x86, 0xE1, 0x7C, 0x8C, 0xAD, 0xF1, 0x5E, 0xDD, 0x5F, 0xE1, 0xE3, 0x6B, - 0xF8, 0x7F, 0x66, 0x0E, 0xA2, 0xDA, 0xB8, 0x39, 0x63, 0x21, 0x51, 0x3C, 0x88, 0xAD, 0x44, 0x96, 0x43, 0x22, 0x2C, 0xF0, 0xFB, 0xA2, 0xA7, 0x87, 0x0F, 0xE9, - 0xD1, 0x83, 0x48, 0x69, 0x22, 0x7A, 0x5C, 0x68, 0xF1, 0x8D, 0x94, 0x82, 0xB3, 0xB8, 0x53, 0x38, 0x04, 0x72, 0x09, 0x03, 0xF3, 0xAD, 0x48, 0xBD, 0x33, 0xA8, - 0x36, 0xD1, 0x16, 0xFE, 0x3F, 0xEA, 0x7F, 0x45, 0x51, 0xFF, 0xFE, 0x42, 0x7C, 0x81, 0x6D, 0xA7, 0x3C, 0x80, 0xC1, 0xA9, 0xA7, 0x05, 0x0F, 0x6A, 0x50, 0xED, - 0x28, 0xE7, 0xFD, 0x78, 0xE8, 0x8E, 0xED, 0x6B, 0x62, 0x5B, 0x8C, 0xE8, 0xD8, 0xB2, 0x50, 0x46, 0x38, 0x7D, 0x8F, 0x13, 0xDC, 0x38, 0xDB, 0x5D, 0xAF, 0xB1, - 0xB5, 0x05, 0x1A, 0x8F, 0x6F, 0xE3, 0x92, 0x64, 0xE2, 0x2D, 0x8A, 0x20, 0x7D, 0x88, 0x3A, 0x37, 0x24, 0x05, 0x1C, 0x41, 0xF3, 0xED, 0x3C, 0xA5, 0x5D, 0x8B, - 0x6D, 0x3F, 0x3C, 0x19, 0x40, 0x03, 0x71, 0x05, 0x40, 0x43, 0x9F, 0x7A, 0x8D, 0x84, 0x96, 0xB8, 0x65, 0x58, 0x05, 0x59, 0x85, 0x88, 0x69, 0x99, 0x97, 0xC4, - 0xCC, 0x42, 0xE9, 0x1A, 0x41, 0x56, 0xBE, 0x0C, 0x10, 0xC9, 0xD3, 0x0B, 0xCD, 0x9D, 0x3B, 0x0E, 0xD8, 0x20, 0xB2, 0x00, 0x36, 0x28, 0xDF, 0x55, 0x86, 0xE8, - 0xFF, 0xDC, 0x78, 0x16, 0x51, 0x9E, 0x90, 0xC0, 0xA3, 0x47, 0x49, 0x6C, 0xB8, 0xC8, 0xC0, 0xCA, 0xF8, 0xA8, 0x37, 0xD6, 0xFE, 0xD2, 0x73, 0x47, 0xF6, 0x38, - 0xCE, 0xB3, 0x9C, 0x24, 0x48, 0xD6, 0x0F, 0x13, 0x82, 0x97, 0x6A, 0x1C, 0x20, 0xC4, 0xB6, 0xA8, 0x80, 0xE8, 0x8B, 0x39, 0x33, 0xB3, 0xB1, 0x4F, 0xA9, 0xD5, - 0xD7, 0x09, 0x7F, 0x65, 0x5F, 0x03, 0xE4, 0x8F, 0xC6, 0x1C, 0x5F, 0x10, 0xF5, 0x4E, 0xD4, 0x95, 0x8C, 0x71, 0x9C, 0xC0, 0x88, 0x8C, 0xA5, 0xE8, 0xC6, 0x1F, - 0xC5, 0x87, 0x2F, 0xAF, 0xE2, 0x2F, 0xD0, 0x92, 0x3F, 0x02, 0x4A, 0x3B, 0x07, 0x34, 0xF8, 0x82, 0x2D, 0x29, 0xB5, 0x67, 0x6B, 0x03, 0xDA, 0x30, 0x07, 0x09, - 0xED, 0x20, 0x8B, 0xA4, 0x90, 0x72, 0xF1, 0xF6, 0x62, 0x85, 0x40, 0x28, 0xBA, 0xC5, 0x10, 0x45, 0x41, 0x7B, 0x85, 0xC3, 0x22, 0x54, 0xA9, 0x9D, 0x8F, 0x0A, - 0x84, 0xCC, 0x11, 0xEB, 0x6C, 0x63, 0x1F, 0x1B, 0xA2, 0x23, 0x72, 0xEE, 0x63, 0xC9, 0xEB, 0xB9, 0x3D, 0x69, 0xA9, 0x4D, 0xD2, 0x99, 0x7E, 0x06, 0x5A, 0xAB, - 0x2B, 0xA8, 0x87, 0xA6, 0xAF, 0xF0, 0x29, 0x81, 0x88, 0x87, 0xE8, 0x42, 0xB2, 0x7C, 0x15, 0x6E, 0x1D, 0x4D, 0x5F, 0xCB, 0x76, 0xC6, 0x92, 0x6C, 0x9C, 0x61, - 0x63, 0x43, 0xBE, 0xA3, 0x9C, 0xD3, 0xD5, 0xE4, 0xEF, 0x0B, 0xCA, 0x99, 0x61, 0xCB, 0x74, 0x53, 0x80, 0x93, 0x2D, 0xEB, 0xA6, 0x91, 0xCE, 0x87, 0x53, 0x3B, - 0x54, 0x20, 0xAC, 0x75, 0x6B, 0xEB, 0x64, 0x2E, 0xD9, 0xCB, 0x59, 0xA4, 0xA4, 0x45, 0x3D, 0x20, 0x4A, 0x4C, 0xC7, 0xD3, 0xEF, 0x71, 0x78, 0xCE, 0xD3, 0x1B, - 0xC3, 0xC7, 0x49, 0x76, 0x54, 0x70, 0x6A, 0xF1, 0x87, 0xA1, 0x60, 0xAB, 0x96, 0x14, 0x45, 0x72, 0xDD, 0x52, 0xAC, 0x15, 0x26, 0xC7, 0x00, 0xF2, 0x62, 0xD9, - 0xEF, 0x3E, 0x01, 0xB8, 0x00, 0x27, 0x35, 0xB4, 0xEF, 0xFF, 0xA2, 0x28, 0x6E, 0xB5, 0x11, 0x44, 0x99, 0x60, 0x42, 0x2C, 0xBA, 0x24, 0x11, 0xE2, 0x27, 0x39, - 0x71, 0xC1, 0x27, 0xB1, 0x4E, 0x79, 0xFB, 0x7B, 0x64, 0x21, 0x51, 0x92, 0x2A, 0x1D, 0xA6, 0xD0, 0xE5, 0xEC, 0xE2, 0x11, 0x0A, 0x2B, 0xEC, 0x15, 0x93, 0x52, - 0xF8, 0x63, 0x11, 0xC8, 0x69, 0x43, 0x35, 0x04, 0xDD, 0xFC, 0x08, 0x75, 0x4F, 0xCA, 0x4C, 0x1B, 0x7C, 0x80, 0x05, 0x1A, 0xB0, 0x44, 0xA8, 0x64, 0x3A, 0xC2, - 0x61, 0x14, 0x13, 0x53, 0x42, 0xC2, 0x8C, 0x19, 0xCE, 0x4B, 0xF9, 0x5A, 0x2F, 0xAF, 0x1F, 0x22, 0x59, 0xFC, 0x11, 0xC0, 0xB0, 0xA8, 0xF1, 0x20, 0x12, 0x43, - 0x16, 0x07, 0x76, 0x20, 0x21, 0x48, 0x88, 0x28, 0x4F, 0x4C, 0xC9, 0xED, 0xD6, 0xB5, 0x38, 0x52, 0xE5, 0x8E, 0xEA, 0x34, 0x39, 0xD3, 0xD2, 0x34, 0x4B, 0xFB, - 0xFD, 0x8D, 0x9A, 0xCC, 0xBF, 0xF8, 0x0C, 0x8C, 0x14, 0xF1, 0x1A, 0xEB, 0x90, 0x93, 0x19, 0x5C, 0x96, 0x90, 0x72, 0x87, 0x65, 0xB6, 0xF8, 0x41, 0x78, 0xA3, - 0xF8, 0xA0, 0x98, 0xCD, 0x0C, 0x2F, 0xE5, 0x5A, 0x30, 0x62, 0x30, 0x71, 0x96, 0x1C, 0xED, 0x49, 0xE2, 0x51, 0xD6, 0x81, 0xB9, 0xE2, 0x62, 0xD6, 0xC5, 0xDC, - 0xF5, 0xC6, 0x26, 0x8B, 0xC2, 0x89, 0x57, 0xFA, 0x1C, 0x02, 0x95, 0x57, 0x0C, 0x70, 0x19, 0x3D, 0x77, 0x52, 0x0A, 0x19, 0x3F, 0xA3, 0x22, 0xE1, 0xA0, 0x0F, - 0xA0, 0x54, 0x5B, 0x17, 0xA1, 0x4D, 0x13, 0xA0, 0x88, 0xB5, 0x1C, 0x36, 0xB1, 0x4B, 0x5D, 0x82, 0x97, 0x53, 0x4F, 0x11, 0xBC, 0xB4, 0x31, 0x5D, 0x82, 0xA6, - 0x7E, 0x5F, 0x0E, 0x2C, 0x3F, 0xED, 0x22, 0xD3, 0x6E, 0xDC, 0x54, 0x00, 0x8E, 0x1F, 0xD1, 0x91, 0x40, 0x45, 0x36, 0x2B, 0x02, 0x8C, 0x5E, 0x8A, 0x52, 0x93, - 0xF4, 0x1B, 0x84, 0xDE, 0x8C, 0x6D, 0xCE, 0x4F, 0x85, 0xA1, 0x05, 0x9D, 0x25, 0x6D, 0xE3, 0xFD, 0x3A, 0x2F, 0xAE, 0x64, 0xD9, 0x26, 0x97, 0x42, 0xE4, 0x4D, - 0xFE, 0xB5, 0x64, 0x65, 0x4C, 0xA7, 0x59, 0x95, 0x3D, 0xA0, 0xA5, 0xB4, 0x03, 0xDF, 0x64, 0xC9, 0x20, 0x7A, 0xA0, 0x05, 0x63, 0x15, 0x1E, 0xFE, 0xCE, 0xFA, - 0xC4, 0xE4, 0x9D, 0xB0, 0xA9, 0x46, 0x29, 0x2D, 0xDE, 0x2C, 0x4D, 0x4A, 0x3C, 0x15, 0xC5, 0xFC, 0x3B, 0xC0, 0x2C, 0xC0, 0x5F, 0x90, 0xF0, 0x40, 0x93, 0xED, - 0x2D, 0x27, 0x28, 0xC7, 0x62, 0xE2, 0x51, 0x30, 0x49, 0xBC, 0x94, 0xC9, 0xD8, 0xD3, 0x50, 0x4F, 0x3F, 0x9B, 0x43, 0x48, 0x5E, 0x2F, 0xC0, 0xF9, 0xC0, 0xDB, - 0x17, 0xF5, 0xC6, 0x6D, 0x11, 0x3B, 0x4C, 0x5C, 0xB1, 0xED, 0x54, 0x25, 0x82, 0xA6, 0x09, 0x35, 0xB6, 0x84, 0x7C, 0xD4, 0xE8, 0x64, 0x87, 0xB9, 0x72, 0xC5, - 0xE0, 0x26, 0x4F, 0xB0, 0x17, 0x59, 0xD1, 0xB2, 0xFA, 0x36, 0x81, 0x20, 0x4E, 0x00, 0x19, 0x62, 0x53, 0x25, 0xAC, 0x64, 0x17, 0xA2, 0x81, 0xA0, 0x5D, 0xF6, - 0xC1, 0x1C, 0xDA, 0x93, 0xD5, 0x7F, 0xAA, 0x5C, 0x64, 0x02, 0x88, 0x9C, 0x29, 0x07, 0x05, 0x3E, 0x45, 0x65, 0x1A, 0xEE, 0x8D, 0x11, 0xC8, 0x4E, 0x63, 0x02, - 0x41, 0x21, 0xE1, 0x7E, 0x53, 0xD7, 0x59, 0x03, 0x9D, 0x3B, 0x00, 0x3B, 0x6B, 0xD3, 0x6D, 0x27, 0x38, 0x8E, 0x41, 0x1B, 0xA0, 0x27, 0x89, 0xDB, 0xEC, 0x43, - 0xD1, 0xE2, 0x3E, 0x3B, 0x63, 0x0D, 0xA2, 0x5E, 0xF0, 0xD3, 0xCC, 0x6D, 0x63, 0x36, 0x23, 0xAE, 0x75, 0x39, 0xB1, 0x1D, 0xAB, 0xCE, 0x40, 0xA3, 0x07, 0x6D, - 0x7C, 0x8D, 0x7E, 0xE6, 0x98, 0x3E, 0xD4, 0xC1, 0xB1, 0x82, 0x37, 0x5F, 0xB2, 0x6B, 0xF5, 0x5A, 0xCF, 0x12, 0xCF, 0xE4, 0xF0, 0x66, 0x6D, 0xCB, 0x37, 0x16, - 0x6F, 0xF0, 0x99, 0x3F, 0x6A, 0x0E, 0xCD, 0x4E, 0xB3, 0xC3, 0x1B, 0x84, 0x50, 0x6C, 0x09, 0x91, 0x23, 0x5E, 0x7C, 0x36, 0xEA, 0x97, 0x0F, 0x6F, 0x63, 0xBC, - 0xA1, 0xF7, 0x82, 0x5D, 0xAA, 0xD7, 0xE8, 0x43, 0x83, 0x87, 0x7F, 0xCC, 0x70, 0xA9, 0x59, 0xA4, 0x19, 0x49, 0x8C, 0xF8, 0x3C, 0x20, 0x8A, 0x8A, 0x35, 0xFF, - 0x41, 0x46, 0x0A, 0x97, 0x5D, 0xC8, 0x13, 0x68, 0xEE, 0x75, 0x15, 0xA8, 0x78, 0x5A, 0x10, 0xC1, 0x91, 0x93, 0x97, 0x30, 0xBC, 0xFD, 0x27, 0x31, 0x7C, 0xD0, - 0xC7, 0x81, 0x56, 0xD7, 0x3B, 0xFA, 0x41, 0x9D, 0x5E, 0x7F, 0x07, 0xEC, 0x4C, 0xEA, 0x8D, 0x83, 0x6E, 0xA3, 0xD1, 0x0E, 0x40, 0x67, 0xA4, 0xDE, 0xEA, 0x89, - 0x26, 0xF0, 0x87, 0xB6, 0x61, 0x9D, 0xE4, 0xDF, 0x7F, 0xED, 0xCD, 0xFD, 0xA0, 0xA8, 0xC1, 0x3B, 0xDB, 0xC5, 0x4C, 0x5C, 0xD4, 0xE4, 0x1A, 0x06, 0x2F, 0xAE, - 0x95, 0x69, 0xA2, 0xD3, 0x87, 0x1C, 0xC5, 0x48, 0x93, 0x3E, 0xFB, 0x05, 0x25, 0xBF, 0x54, 0xEC, 0xF3, 0x7A, 0x93, 0xE0, 0x4C, 0x79, 0x5D, 0xAC, 0x5D, 0xDD, - 0xCA, 0xC6, 0x11, 0x57, 0x74, 0x7C, 0xAE, 0x21, 0xA3, 0xFF, 0x54, 0xC0, 0xE2, 0x35, 0x52, 0x66, 0x0E, 0xBD, 0x4A, 0x19, 0xAA, 0xAC, 0xAF, 0x0A, 0xEB, 0xD1, - 0xE4, 0x44, 0x73, 0x7A, 0x8C, 0x9D, 0xAC, 0x3D, 0x2F, 0xE7, 0xE0, 0xE3, 0x53, 0x11, 0x51, 0xD9, 0x35, 0x1C, 0x70, 0x46, 0xA1, 0x1F, 0x06, 0xA0, 0x45, 0xF9, - 0x08, 0x6E, 0x4B, 0x19, 0x8C, 0x8F, 0x56, 0x4B, 0x00, 0xA4, 0x57, 0x89, 0x4B, 0xB0, 0xD2, 0x28, 0xB8, 0xB0, 0x5E, 0x48, 0xBF, 0xFC, 0x9A, 0xA2, 0x00, 0xAC, - 0x59, 0xCE, 0x15, 0x51, 0x06, 0xDA, 0x35, 0xA2, 0xA0, 0x87, 0x40, 0x7C, 0xD8, 0x26, 0x85, 0xBC, 0x9C, 0x61, 0x7D, 0x76, 0x48, 0x9F, 0x8A, 0x85, 0x79, 0x43, - 0xF9, 0xEC, 0x30, 0xFE, 0x56, 0x32, 0x10, 0xF1, 0x51, 0x81, 0x58, 0x84, 0xA4, 0x58, 0xDE, 0x44, 0x96, 0xB7, 0x98, 0xCE, 0x28, 0x81, 0x90, 0xBF, 0x7D, 0xC0, - 0xC4, 0x45, 0x2A, 0x8A, 0x8B, 0x70, 0x71, 0x21, 0x40, 0x3C, 0xC2, 0x2D, 0x9F, 0x5B, 0x89, 0xEC, 0xFF, 0xD7, 0xE7, 0x31, 0x67, 0x8B, 0x61, 0x21, 0x9D, 0x7C, - 0xEE, 0x42, 0x62, 0xAF, 0x18, 0x20, 0xF1, 0x81, 0x24, 0xC6, 0xD6, 0x62, 0x58, 0x8D, 0x2D, 0x31, 0xF7, 0x81, 0x00, 0x31, 0x5B, 0xEA, 0x19, 0x12, 0xC1, 0x4A, - 0xF4, 0xB2, 0x32, 0xCD, 0x70, 0x2D, 0x2D, 0xFA, 0x4C, 0x76, 0x44, 0x2C, 0x7B, 0xD3, 0x57, 0x69, 0xB9, 0xC9, 0x9A, 0x49, 0x4C, 0x46, 0x73, 0x2C, 0xA5, 0xA0, - 0x51, 0x4B, 0x09, 0x3A, 0xA2, 0xA3, 0x10, 0x5A, 0x34, 0x62, 0x45, 0x63, 0x74, 0x5A, 0x49, 0x58, 0x51, 0xEB, 0xD8, 0x71, 0x62, 0x04, 0x62, 0x8E, 0xE6, 0x38, - 0x3D, 0xA7, 0xC7, 0x06, 0x2F, 0x8C, 0xD9, 0xD4, 0x10, 0x45, 0x6E, 0x10, 0xB1, 0x94, 0x68, 0x13, 0x39, 0x08, 0x83, 0xCF, 0x23, 0xB3, 0x94, 0x14, 0xB6, 0xE6, - 0xA9, 0xBF, 0x77, 0x08, 0xCE, 0x87, 0xF0, 0x7D, 0x8C, 0xB8, 0x07, 0xD1, 0xF3, 0x35, 0xC7, 0x5B, 0x10, 0x5C, 0xBF, 0x14, 0x8F, 0x9B, 0x68, 0x43, 0x02, 0x31, - 0x95, 0xB0, 0x59, 0x2D, 0x8C, 0x41, 0xE1, 0xC4, 0x0E, 0x60, 0x10, 0x8E, 0x9F, 0xB3, 0x24, 0x0F, 0xF5, 0x28, 0x21, 0x96, 0xB2, 0x97, 0x9D, 0xED, 0x4F, 0x88, - 0x93, 0xC1, 0xC4, 0xB2, 0x7C, 0xC8, 0x79, 0xCC, 0x04, 0xA2, 0xA2, 0x79, 0xB4, 0x35, 0x44, 0x18, 0xDD, 0xFE, 0x6A, 0xA5, 0xA8, 0x66, 0xA0, 0x54, 0x90, 0x11, - 0x58, 0x2C, 0xCB, 0x98, 0xD7, 0x8C, 0x34, 0x55, 0x93, 0x95, 0x05, 0x1A, 0xC5, 0x39, 0x7B, 0x65, 0x94, 0xCF, 0xD7, 0x0A, 0x93, 0x38, 0x4B, 0xAC, 0xEC, 0x77, - 0x7E, 0x28, 0x76, 0x16, 0xB0, 0x33, 0x2C, 0x18, 0x07, 0x0F, 0xCE, 0x0F, 0x27, 0xE1, 0xD4, 0x19, 0x3C, 0xF8, 0x5F, 0x94, 0x18, 0xA6, 0xBF, 0xBA, 0xAB, 0x00, - 0x00 +//File: index_ov2640.html.gz, Size: 6687 +#define index_ov2640_html_gz_len 6687 +const unsigned char index_ov2640_html_gz[] = { + 0x1F, 0x8B, 0x08, 0x08, 0xA5, 0xF6, 0xDA, 0x67, 0x00, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x6F, 0x76, 0x32, 0x36, 0x34, 0x30, 0x2E, 0x68, 0x74, 0x6D, + 0x6C, 0x2E, 0x67, 0x7A, 0x00, 0xED, 0x7D, 0x7B, 0x73, 0xDB, 0x36, 0xD6, 0xF7, 0xFF, 0xFD, 0x14, 0x8C, 0xDA, 0xB5, 0xE4, 0xB1, 0x24, 0xDB, 0xB2, 0xE3, 0x24, + 0x5E, 0x5B, 0x79, 0x72, 0x71, 0x93, 0xCE, 0x93, 0xB4, 0xDD, 0xBA, 0x97, 0xEC, 0xEC, 0xEC, 0xA4, 0x94, 0x08, 0x49, 0x6C, 0x28, 0x52, 0x4B, 0x52, 0xBE, 0xB4, + 0xE3, 0xCF, 0xF1, 0x7E, 0xA0, 0xE7, 0x8B, 0xED, 0xEF, 0x00, 0x20, 0x09, 0x92, 0xE0, 0x4D, 0xB2, 0xA5, 0x6C, 0xF7, 0x95, 0x34, 0x12, 0x05, 0x02, 0x07, 0x07, + 0xE7, 0x86, 0x83, 0x83, 0x0B, 0xCF, 0x1E, 0x59, 0xDE, 0x38, 0xBC, 0x5D, 0x30, 0x63, 0x16, 0xCE, 0x9D, 0xE1, 0x17, 0x67, 0xE2, 0xC7, 0xC0, 0xEB, 0x6C, 0xC6, + 0x4C, 0x4B, 0x5C, 0xF2, 0xBF, 0x73, 0x16, 0x9A, 0xC6, 0x78, 0x66, 0xFA, 0x01, 0x0B, 0xCF, 0x5B, 0xCB, 0x70, 0xD2, 0x7B, 0xDA, 0xCA, 0xDE, 0x76, 0xCD, 0x39, + 0x3B, 0x6F, 0x5D, 0xD9, 0xEC, 0x7A, 0xE1, 0xF9, 0x61, 0xCB, 0x18, 0x7B, 0x6E, 0xC8, 0x5C, 0x64, 0xBF, 0xB6, 0xAD, 0x70, 0x76, 0x6E, 0xB1, 0x2B, 0x7B, 0xCC, + 0x7A, 0xFC, 0x4F, 0xD7, 0x76, 0xED, 0xD0, 0x36, 0x9D, 0x5E, 0x30, 0x36, 0x1D, 0x76, 0x7E, 0xA8, 0xC2, 0x0A, 0xED, 0xD0, 0x61, 0xC3, 0x8B, 0xCB, 0xEF, 0x8F, + 0x06, 0xC6, 0x77, 0x3F, 0x0F, 0x4E, 0x8E, 0x0F, 0xCE, 0xF6, 0x45, 0x5A, 0x92, 0x27, 0x08, 0x6F, 0xD5, 0xFF, 0xF4, 0x1A, 0x79, 0xD6, 0xAD, 0xF1, 0x47, 0x2A, + 0x89, 0x5E, 0x13, 0x20, 0xD1, 0x9B, 0x98, 0x73, 0xDB, 0xB9, 0x3D, 0x35, 0x5E, 0xF8, 0xA8, 0xB3, 0xFB, 0x96, 0x39, 0x57, 0x2C, 0xB4, 0xC7, 0x66, 0x37, 0x30, + 0xDD, 0xA0, 0x17, 0x30, 0xDF, 0x9E, 0xFC, 0x35, 0x57, 0x70, 0x64, 0x8E, 0x3F, 0x4D, 0x7D, 0x6F, 0xE9, 0x5A, 0xA7, 0xC6, 0x97, 0x87, 0x4F, 0xE9, 0x9D, 0xCF, + 0x34, 0xF6, 0x1C, 0xCF, 0xC7, 0xFD, 0x8B, 0xAF, 0xE9, 0x9D, 0xBF, 0xCF, 0x6B, 0x0F, 0xEC, 0xDF, 0xD9, 0xA9, 0x71, 0x78, 0xB2, 0xB8, 0x49, 0xDD, 0xBF, 0xFB, + 0x22, 0xF5, 0x77, 0x36, 0x28, 0xC2, 0x5E, 0x96, 0x7F, 0x5A, 0x5E, 0x3E, 0x60, 0xE3, 0xD0, 0xF6, 0xDC, 0xFE, 0xDC, 0xB4, 0x5D, 0x0D, 0x24, 0xCB, 0x0E, 0x16, + 0x8E, 0x09, 0x1A, 0x4C, 0x1C, 0x56, 0x0A, 0xE7, 0xCB, 0x39, 0x73, 0x97, 0xDD, 0x0A, 0x68, 0x04, 0xA4, 0x67, 0xD9, 0xBE, 0xC8, 0x75, 0x4A, 0x74, 0x58, 0xCE, + 0xDD, 0x4A, 0xB0, 0x65, 0x78, 0xB9, 0x9E, 0xCB, 0x34, 0x04, 0xA4, 0x8A, 0xAE, 0x7D, 0x73, 0x41, 0x19, 0xE8, 0x37, 0x9F, 0x65, 0x6E, 0xBB, 0x42, 0xA8, 0x4E, + 0x8D, 0xA3, 0xE3, 0x83, 0xC5, 0x4D, 0x05, 0x2B, 0x8F, 0x4E, 0xE8, 0x9D, 0xCF, 0xB4, 0x30, 0x2D, 0xCB, 0x76, 0xA7, 0xA7, 0x06, 0xE8, 0xAC, 0x01, 0xE1, 0xF9, + 0x16, 0xF3, 0x7B, 0xBE, 0x69, 0xD9, 0xCB, 0xE0, 0xD4, 0x38, 0xD6, 0xE5, 0x99, 0x9B, 0xFE, 0x14, 0xB8, 0x84, 0x1E, 0x90, 0xED, 0x1D, 0x6A, 0x31, 0x91, 0x59, + 0x7C, 0x7B, 0x3A, 0x0B, 0xC1, 0xD2, 0x5C, 0x9E, 0x2C, 0xD1, 0xA4, 0x0A, 0x55, 0xF1, 0xB3, 0x94, 0x6E, 0x7A, 0xAA, 0x99, 0x8E, 0x3D, 0x75, 0x7B, 0x76, 0xC8, + 0xE6, 0x68, 0x4E, 0x10, 0xFA, 0x2C, 0x1C, 0xCF, 0xCA, 0x50, 0x99, 0xD8, 0xD3, 0xA5, 0xCF, 0x34, 0x88, 0xC4, 0x74, 0x2B, 0x69, 0x30, 0x6E, 0xE6, 0x6F, 0xF5, + 0xAE, 0xD9, 0xE8, 0x93, 0x1D, 0xF6, 0x24, 0x4D, 0x46, 0x6C, 0xE2, 0xF9, 0x90, 0x73, 0x4D, 0xCE, 0x28, 0x87, 0xE3, 0x8D, 0x3F, 0xF5, 0x82, 0xD0, 0xF4, 0x41, + 0xBB, 0x6A, 0x80, 0xE6, 0x24, 0x64, 0xD0, 0xCD, 0x2A, 0x78, 0x8C, 0xA4, 0xA2, 0x1A, 0x5A, 0x71, 0xB5, 0x32, 0x83, 0xED, 0x3A, 0xB6, 0xCB, 0xEA, 0xA3, 0x57, + 0x54, 0x6F, 0x1A, 0x9C, 0xC8, 0x55, 0x83, 0x31, 0xF6, 0x7C, 0x5A, 0x26, 0x25, 0xBC, 0xAD, 0xF9, 0xCA, 0xA4, 0xDE, 0x1C, 0x1E, 0x1C, 0xFC, 0x25, 0x7F, 0x73, + 0xC6, 0x84, 0x98, 0x9A, 0xCB, 0xD0, 0x5B, 0x5F, 0x23, 0x72, 0x6A, 0x95, 0x69, 0xC7, 0xFF, 0xCC, 0x99, 0x65, 0x9B, 0x46, 0x47, 0x51, 0xE7, 0xA7, 0x07, 0x90, + 0xA9, 0x5D, 0xC3, 0x74, 0x2D, 0xA3, 0xE3, 0xF9, 0x36, 0x14, 0xC1, 0xE4, 0xE6, 0xC6, 0x41, 0x0A, 0x3A, 0x8E, 0x05, 0xDB, 0xD5, 0x34, 0xB9, 0x44, 0x67, 0x54, + 0x8A, 0xE8, 0xD5, 0xA6, 0xA6, 0xC9, 0xA9, 0xA5, 0x40, 0x9A, 0x36, 0x56, 0xF2, 0xAB, 0x0E, 0xCF, 0x04, 0x61, 0x81, 0x62, 0x19, 0xEF, 0xA2, 0x4C, 0x11, 0x0F, + 0xD1, 0xCD, 0x8E, 0x3B, 0xC8, 0x7A, 0x35, 0x33, 0x7A, 0x06, 0x59, 0xC9, 0x5D, 0x7D, 0x19, 0x09, 0x54, 0xCF, 0xF2, 0xAC, 0x50, 0x34, 0x68, 0xAE, 0xBE, 0xA9, + 0x89, 0xED, 0x10, 0x6F, 0x9D, 0x0C, 0x55, 0x58, 0x91, 0x66, 0x96, 0xA4, 0x81, 0x35, 0x69, 0x64, 0x51, 0x6A, 0x5B, 0x95, 0x46, 0x96, 0xA5, 0x89, 0x75, 0x69, + 0x60, 0x61, 0x6A, 0x59, 0x19, 0xC1, 0xCE, 0x6A, 0x7F, 0xE3, 0xCB, 0xD1, 0x32, 0x0C, 0x3D, 0x37, 0x58, 0xAB, 0x8B, 0x2A, 0xD2, 0xB3, 0xDF, 0x96, 0x41, 0x68, + 0x4F, 0x6E, 0x7B, 0x52, 0xA5, 0xA1, 0x67, 0x0B, 0x13, 0x2E, 0xE4, 0x88, 0x85, 0xD7, 0x8C, 0x95, 0xBB, 0x1B, 0xAE, 0x79, 0x05, 0xBB, 0x33, 0x9D, 0x3A, 0x3A, + 0xD9, 0x1B, 0x2F, 0xFD, 0x80, 0xFC, 0xB6, 0x85, 0x67, 0x03, 0xB0, 0x9F, 0xAF, 0x38, 0xAD, 0x83, 0x35, 0x2B, 0xEA, 0x8D, 0x47, 0x9A, 0xBA, 0xBC, 0x65, 0x48, + 0x34, 0xD6, 0x72, 0xC2, 0x43, 0x73, 0xEC, 0x10, 0xD5, 0x68, 0xEE, 0x49, 0x4D, 0xD4, 0xDC, 0x89, 0x54, 0xB0, 0xB4, 0x5B, 0x48, 0xE3, 0x75, 0x3A, 0x9E, 0xB1, + 0xF1, 0x27, 0x66, 0xED, 0x55, 0xBA, 0x61, 0x55, 0xEE, 0x61, 0xDF, 0x76, 0x17, 0xCB, 0xB0, 0x47, 0xEE, 0xD4, 0xE2, 0x41, 0x78, 0xCE, 0x05, 0x32, 0x6A, 0xE2, + 0x60, 0x50, 0xE6, 0x54, 0x3C, 0x5E, 0xDC, 0x94, 0x13, 0x41, 0x45, 0x76, 0xE8, 0x98, 0x23, 0xE6, 0x94, 0xA1, 0x2C, 0x95, 0xA1, 0xC0, 0xEC, 0x4A, 0x5B, 0x55, + 0xEC, 0xBB, 0x65, 0x7C, 0xD1, 0xE3, 0x27, 0x7F, 0xA9, 0x4D, 0x47, 0x7E, 0xDD, 0x4D, 0x25, 0x05, 0xCC, 0x81, 0x82, 0x15, 0xB9, 0xDE, 0xC8, 0x73, 0x0D, 0x1C, + 0x4A, 0x2B, 0xF0, 0x4D, 0x77, 0xCA, 0x60, 0x0B, 0x6E, 0xBA, 0xD1, 0x65, 0xF9, 0xC0, 0xA0, 0x56, 0xF3, 0xC9, 0x54, 0x83, 0xEC, 0x65, 0x15, 0x0B, 0x83, 0xD0, + 0x35, 0xFA, 0xE2, 0x62, 0x05, 0xAF, 0x44, 0xE1, 0x6F, 0x29, 0x22, 0x87, 0x5A, 0xE9, 0x10, 0x8E, 0x89, 0x56, 0x73, 0xD2, 0xB2, 0xA5, 0x75, 0xF4, 0x2B, 0x4D, + 0x43, 0x34, 0xE4, 0x9B, 0x4C, 0xAA, 0x06, 0x8D, 0x93, 0xC9, 0xD1, 0xC1, 0xD1, 0x71, 0xA5, 0xE7, 0xA4, 0x6D, 0x65, 0x66, 0xE0, 0xA8, 0x31, 0x1D, 0xB1, 0x59, + 0x29, 0x15, 0x82, 0xC0, 0xBC, 0xD2, 0x3A, 0xED, 0x5E, 0x80, 0xF1, 0x37, 0x8D, 0xDC, 0xCC, 0x51, 0x80, 0xB1, 0x5B, 0xA8, 0x19, 0x7A, 0x49, 0x41, 0x1F, 0x68, + 0xF1, 0xE3, 0x2E, 0x9D, 0x56, 0x05, 0x22, 0xF2, 0xEA, 0xD1, 0x4E, 0x71, 0x40, 0x9F, 0x45, 0x61, 0xB0, 0xD6, 0xA9, 0x0C, 0xD9, 0x4D, 0xD8, 0xB3, 0xD8, 0xD8, + 0xF3, 0x85, 0x37, 0x58, 0x30, 0x72, 0xCC, 0x30, 0xB2, 0x5A, 0x62, 0x4F, 0x67, 0xDE, 0x15, 0xF3, 0x35, 0xC4, 0xCA, 0x30, 0xF5, 0xF8, 0xD9, 0xB1, 0x55, 0x03, + 0x9A, 0x89, 0xEE, 0x51, 0x4B, 0xFB, 0x34, 0xB8, 0xC1, 0xE1, 0x78, 0x50, 0xAA, 0xC7, 0x02, 0x5C, 0x1F, 0x3A, 0x63, 0x8E, 0x1C, 0x66, 0x95, 0xF4, 0x66, 0x16, + 0x9B, 0x98, 0x4B, 0x27, 0xAC, 0x90, 0x4A, 0xF3, 0x80, 0xDE, 0x65, 0x35, 0x72, 0x33, 0xF4, 0x0F, 0x8A, 0x0B, 0x9D, 0x73, 0xC3, 0xF1, 0x4F, 0x4D, 0x9D, 0x91, + 0xAB, 0x61, 0x2E, 0x16, 0xCC, 0x44, 0xAE, 0x31, 0x24, 0x51, 0xCF, 0x87, 0x5A, 0x43, 0x0C, 0xBD, 0x9D, 0xAF, 0x35, 0x6E, 0xAF, 0x54, 0xD8, 0xD8, 0x79, 0x6C, + 0xD4, 0xE6, 0xD3, 0x89, 0x37, 0x5E, 0xEA, 0xBC, 0x9A, 0x7A, 0x8A, 0x97, 0x87, 0x77, 0x1A, 0x91, 0x2C, 0x70, 0x6C, 0xAE, 0xFE, 0x4B, 0xD7, 0x25, 0x8E, 0xF6, + 0x42, 0x1F, 0xCD, 0xD4, 0x54, 0x54, 0x8F, 0x70, 0x2B, 0xD9, 0xB0, 0x14, 0x61, 0x8B, 0x62, 0x57, 0x19, 0x33, 0xA5, 0x31, 0xA7, 0xB1, 0xA5, 0x35, 0x60, 0x43, + 0x6C, 0x2B, 0x02, 0xB5, 0x1E, 0x5D, 0xC2, 0xD9, 0x72, 0xAE, 0xF3, 0xA3, 0xA2, 0xCA, 0x0E, 0xD1, 0xE9, 0x8B, 0xEA, 0xFC, 0xE9, 0xC8, 0xEC, 0x1C, 0x74, 0x0F, + 0xBA, 0x47, 0xF8, 0xD2, 0x8C, 0x67, 0xCA, 0x85, 0x4B, 0x92, 0xB7, 0x40, 0xF2, 0x32, 0x26, 0xBA, 0x3A, 0xAC, 0x54, 0x64, 0xEC, 0x2B, 0x79, 0x51, 0x5F, 0x93, + 0xD2, 0xF1, 0xA5, 0xC3, 0x7E, 0x45, 0x3F, 0x5C, 0x20, 0xD2, 0xCD, 0x05, 0x51, 0x23, 0x2D, 0x4D, 0x59, 0x3C, 0xF7, 0x7E, 0x07, 0x31, 0xC9, 0x09, 0xF9, 0xAF, + 0x97, 0x76, 0x85, 0x14, 0x7F, 0x6A, 0x49, 0x6F, 0x4C, 0x97, 0x60, 0xDB, 0xB2, 0x81, 0x00, 0x44, 0x21, 0x7D, 0xA4, 0xD7, 0x07, 0x0C, 0x5D, 0x8C, 0x41, 0x7D, + 0x0C, 0x46, 0x0B, 0x3D, 0x43, 0x25, 0xCF, 0x0A, 0x34, 0x98, 0xD8, 0x8E, 0xD3, 0x73, 0xBC, 0xEB, 0x6A, 0x4F, 0xA4, 0x5C, 0x92, 0x73, 0x72, 0x5A, 0x2D, 0xF2, + 0xAB, 0x62, 0xBB, 0x84, 0xE5, 0xFA, 0x8F, 0xC0, 0xF6, 0xBF, 0xAD, 0x6B, 0x51, 0x54, 0x63, 0xB5, 0x8E, 0x62, 0x05, 0x79, 0x5C, 0xAF, 0xA2, 0x5A, 0xA2, 0x24, + 0x3C, 0xC1, 0xF2, 0x61, 0xCF, 0xB5, 0x8D, 0x70, 0xEC, 0x0A, 0x43, 0xCF, 0x64, 0x60, 0xE4, 0x33, 0x07, 0xE3, 0x8B, 0x2B, 0x4D, 0x3F, 0x5C, 0x23, 0x42, 0x51, + 0x39, 0x7C, 0x53, 0x8B, 0xD7, 0x69, 0x09, 0x27, 0xDD, 0xE7, 0x13, 0x5D, 0xEA, 0x0B, 0xDF, 0xA1, 0xD8, 0x56, 0xEB, 0xC5, 0xBA, 0xC2, 0xDD, 0x4F, 0x6B, 0x86, + 0x3E, 0x53, 0x03, 0x8B, 0x1E, 0x19, 0xED, 0xA9, 0xCF, 0x6E, 0x6B, 0x34, 0xA6, 0x2B, 0x7F, 0x4F, 0x45, 0xFC, 0x78, 0xF5, 0x50, 0x09, 0xEF, 0x00, 0xA4, 0x14, + 0xF5, 0x8F, 0x83, 0x1A, 0x55, 0x17, 0x57, 0x59, 0x47, 0x1E, 0xE3, 0xE8, 0x68, 0xAB, 0x55, 0xC3, 0xDC, 0x94, 0x74, 0xA1, 0x7A, 0x51, 0x8D, 0x7A, 0x5F, 0xFD, + 0x78, 0x9E, 0x4D, 0x50, 0x50, 0x3F, 0x4E, 0x27, 0x3F, 0xF5, 0xA8, 0xDC, 0xBA, 0x45, 0x2C, 0xA2, 0x68, 0x4A, 0xA5, 0xE5, 0x88, 0x83, 0x98, 0xC5, 0xD2, 0xA7, + 0x85, 0x4C, 0xD6, 0xB3, 0x31, 0xF0, 0x62, 0x96, 0x44, 0xEE, 0x33, 0x67, 0x33, 0xF2, 0xCC, 0x65, 0x97, 0x0F, 0xF6, 0xB0, 0x0F, 0x9D, 0x01, 0xC8, 0xA4, 0xE9, + 0x30, 0x4A, 0x32, 0x97, 0x07, 0xD9, 0x0B, 0xA2, 0x80, 0xF9, 0x2E, 0xAB, 0x70, 0x80, 0xAC, 0xDA, 0x22, 0x2D, 0xA3, 0xCA, 0xB5, 0xB2, 0xCC, 0xC2, 0xE4, 0x23, + 0x59, 0xE5, 0x21, 0xCF, 0xB9, 0x09, 0xB7, 0x97, 0xC4, 0x15, 0xAB, 0x0A, 0xB4, 0xFC, 0xAB, 0x23, 0xEE, 0x4A, 0x8C, 0xF5, 0xF0, 0x04, 0x66, 0xA6, 0xB4, 0xCA, + 0xB1, 0xE3, 0x05, 0x6B, 0x06, 0xC0, 0x8A, 0xE3, 0x5F, 0xDA, 0x3B, 0xB5, 0xBA, 0xEE, 0x52, 0x9D, 0x2A, 0x57, 0xC7, 0x0C, 0xCD, 0xE1, 0x14, 0x6B, 0xCD, 0x64, + 0x59, 0x94, 0x92, 0x47, 0xD0, 0xF8, 0xFC, 0x25, 0x26, 0x06, 0x61, 0x39, 0x74, 0x66, 0x34, 0x1D, 0xA8, 0xAB, 0x13, 0x2A, 0x2D, 0xE5, 0xC3, 0xCC, 0xB6, 0x2C, + 0x56, 0x1A, 0x0B, 0xA6, 0x31, 0x6F, 0x4D, 0xE7, 0x81, 0xF0, 0xD7, 0x05, 0xA5, 0x1E, 0x44, 0x29, 0x4A, 0x97, 0x35, 0xA0, 0xA6, 0x87, 0xD5, 0x18, 0xD9, 0xD1, + 0x14, 0x45, 0xD2, 0xD3, 0xAE, 0x48, 0x29, 0xAA, 0x5A, 0xE5, 0x8E, 0x63, 0xAD, 0x44, 0x32, 0xD0, 0x81, 0x72, 0xE5, 0xAD, 0x79, 0x06, 0x2B, 0x3E, 0x91, 0xD2, + 0x97, 0x73, 0x4B, 0x72, 0x1A, 0xB0, 0x57, 0x34, 0xBB, 0x72, 0x8F, 0x53, 0x6D, 0x5C, 0x02, 0xB2, 0xF5, 0x16, 0x92, 0x66, 0x4B, 0x9E, 0x51, 0x09, 0x92, 0x71, + 0x17, 0x13, 0x2D, 0xAE, 0x4A, 0xE7, 0x5A, 0x55, 0x39, 0xCE, 0xF6, 0x95, 0xD5, 0x70, 0x67, 0xFB, 0xC9, 0xC2, 0xBD, 0x33, 0x5A, 0x12, 0xA7, 0x2E, 0x9A, 0x93, + 0xF5, 0x8C, 0x1D, 0x33, 0x08, 0xCE, 0x5B, 0xB4, 0xB4, 0x4B, 0x59, 0x77, 0xC7, 0xB3, 0x58, 0xF6, 0x95, 0x61, 0x5B, 0xE7, 0x2D, 0xC7, 0x9B, 0x7A, 0x99, 0x7B, + 0xFC, 0xBE, 0xE0, 0x32, 0xFA, 0xB1, 0xF3, 0x56, 0x6A, 0x7E, 0xB1, 0xC5, 0x4B, 0x25, 0x49, 0xAD, 0xE1, 0xCE, 0x97, 0xCF, 0x9E, 0x3C, 0x39, 0xF9, 0xEB, 0x8E, + 0x3B, 0x0A, 0x16, 0xF2, 0xFB, 0x47, 0x31, 0x1D, 0x2B, 0xD6, 0xF4, 0xA1, 0x6B, 0x0B, 0x43, 0x88, 0x5E, 0x70, 0xB6, 0xCF, 0x81, 0x66, 0x10, 0xD9, 0x07, 0x26, + 0x05, 0xB8, 0x49, 0x77, 0x47, 0x87, 0x5E, 0x94, 0x25, 0x40, 0x0F, 0x3E, 0x32, 0x7D, 0x4D, 0x16, 0x9E, 0x4D, 0x38, 0xD3, 0xDC, 0x94, 0xB4, 0x38, 0x4F, 0x46, + 0xDE, 0x4D, 0xB6, 0x05, 0xBC, 0x51, 0x92, 0x61, 0x32, 0x17, 0xB3, 0x8A, 0x00, 0xA2, 0x18, 0x2F, 0x4E, 0x93, 0xAB, 0xC8, 0xA3, 0xCD, 0x94, 0x62, 0x01, 0x65, + 0xBE, 0x19, 0x3B, 0x58, 0x7F, 0x20, 0x12, 0x50, 0x95, 0x60, 0x8A, 0xEB, 0x85, 0xC2, 0x54, 0x16, 0x54, 0x95, 0x6A, 0xAA, 0x2C, 0xA3, 0x4C, 0x1B, 0x8A, 0x56, + 0x80, 0xB4, 0x3D, 0x0E, 0x5D, 0xA4, 0x95, 0x43, 0xCA, 0xF2, 0x35, 0x2A, 0xDC, 0x1A, 0x7E, 0x78, 0xF5, 0xEE, 0x7F, 0x8D, 0xF7, 0x6F, 0x7F, 0xD7, 0x72, 0xA8, + 0x0A, 0x29, 0xB2, 0xD1, 0x35, 0x6A, 0x56, 0xF8, 0x11, 0xD1, 0xA4, 0x25, 0x39, 0xC3, 0x21, 0x50, 0x6F, 0xEF, 0x30, 0x77, 0x8A, 0xF5, 0xA3, 0xAD, 0x43, 0xFC, + 0x33, 0x6F, 0xA2, 0x7F, 0x83, 0x96, 0x41, 0xF6, 0x9B, 0x5F, 0x5C, 0x99, 0xCE, 0x92, 0xAE, 0x0E, 0xEA, 0xB4, 0x35, 0x2F, 0x5A, 0xDA, 0x6C, 0xD2, 0xB0, 0xC4, + 0x34, 0x56, 0x0C, 0x71, 0x9A, 0xCA, 0xAD, 0xE1, 0x25, 0x0B, 0xCF, 0xF6, 0xC5, 0xAD, 0x0A, 0xAE, 0x95, 0xD7, 0x0D, 0x4D, 0x16, 0xE2, 0x50, 0x26, 0x42, 0x65, + 0x8C, 0x9F, 0xF8, 0x58, 0x82, 0x4B, 0x54, 0xA9, 0xC5, 0x79, 0x95, 0xEB, 0x71, 0xC9, 0xD6, 0xF0, 0x07, 0xC6, 0x1D, 0x22, 0xA0, 0x51, 0x8B, 0xF1, 0x90, 0x69, + 0xEE, 0xA3, 0xA6, 0xEA, 0x8F, 0xE5, 0x59, 0xCE, 0x49, 0xF5, 0x68, 0x36, 0x0C, 0x84, 0xAB, 0x41, 0xF7, 0x47, 0xBD, 0x9E, 0x31, 0x78, 0xFF, 0xBD, 0xD1, 0xEB, + 0xD5, 0xC8, 0xEC, 0x2D, 0xB8, 0x3A, 0x49, 0xFE, 0x1F, 0x3E, 0x6E, 0x0D, 0x7F, 0xFA, 0xF0, 0xE6, 0x45, 0x07, 0x7E, 0xE1, 0xC1, 0xCD, 0xE1, 0xE0, 0xE0, 0x60, + 0xF7, 0x6C, 0x5F, 0x64, 0x69, 0x0E, 0xEB, 0x18, 0x7C, 0xE5, 0xB0, 0x06, 0x4F, 0x01, 0xEB, 0x60, 0x70, 0xBC, 0x06, 0xAC, 0xA3, 0xD6, 0xF0, 0xED, 0x6B, 0x01, + 0xE9, 0xC9, 0x60, 0x1D, 0xA4, 0x06, 0xD0, 0x4A, 0xC2, 0x09, 0xE8, 0xDC, 0x3C, 0x39, 0x79, 0xBA, 0x06, 0x24, 0x2C, 0xB9, 0xBE, 0xFC, 0x19, 0xA0, 0xB0, 0xC6, + 0xEE, 0x06, 0xD4, 0x5A, 0x03, 0x12, 0x94, 0x8E, 0x00, 0xC1, 0xA6, 0xDF, 0x1C, 0x3F, 0x5D, 0x03, 0xD0, 0x33, 0x10, 0x89, 0x00, 0x01, 0xC8, 0xCD, 0xD1, 0x3A, + 0x54, 0xC2, 0xCA, 0xF4, 0x57, 0xDF, 0x7C, 0xDD, 0x39, 0x46, 0xCB, 0x06, 0xCF, 0x4E, 0x9A, 0xC0, 0x81, 0xEC, 0xA5, 0x41, 0x3D, 0x69, 0x0D, 0x81, 0x0A, 0xA1, + 0x13, 0x41, 0x81, 0x58, 0x0A, 0x19, 0xFD, 0xC9, 0x0D, 0x10, 0xAD, 0xC2, 0x42, 0x77, 0xCC, 0xC9, 0xA2, 0x80, 0x77, 0xC5, 0x7B, 0xB5, 0x15, 0xA4, 0xF6, 0xA4, + 0x35, 0xFC, 0x1B, 0xB5, 0x9B, 0x2A, 0x1A, 0x1C, 0xAF, 0xD1, 0x6E, 0x48, 0x3F, 0xCA, 0x13, 0x8C, 0x95, 0x41, 0x40, 0xE8, 0xDF, 0x72, 0x64, 0x08, 0xD0, 0xE1, + 0x93, 0x46, 0xC4, 0x4B, 0x43, 0x82, 0xC8, 0xFF, 0x8D, 0xB8, 0x00, 0x20, 0x37, 0x87, 0xC7, 0x6B, 0x28, 0x0F, 0x44, 0x1E, 0x8A, 0x03, 0x6D, 0x7E, 0xBA, 0xBA, + 0x88, 0x02, 0x17, 0xDE, 0x2A, 0xD8, 0x05, 0x32, 0x0B, 0xAB, 0x23, 0x03, 0x59, 0x7F, 0x76, 0x72, 0xF3, 0xEC, 0xA4, 0x1E, 0x00, 0xB2, 0xE7, 0x64, 0x1B, 0xCB, + 0x2C, 0x7E, 0x79, 0x87, 0x50, 0x66, 0xEC, 0xFF, 0xB5, 0xC4, 0x10, 0x2E, 0xBC, 0x6D, 0x6C, 0xEA, 0x65, 0x39, 0xD0, 0x44, 0x5C, 0xD4, 0xB3, 0xF2, 0x0A, 0x26, + 0xF1, 0x6A, 0xA2, 0xD6, 0xF0, 0xB8, 0x46, 0x6F, 0x9A, 0x72, 0xB7, 0x78, 0xD9, 0x14, 0xFE, 0xBC, 0x8B, 0x27, 0xC9, 0xA3, 0xCE, 0x1D, 0xDA, 0x70, 0x14, 0x77, + 0xE7, 0xB0, 0x2C, 0x2B, 0x75, 0x23, 0x1A, 0x5C, 0xCD, 0x9B, 0xD6, 0xF0, 0xE4, 0xA8, 0xB2, 0xFB, 0x5D, 0x9D, 0x19, 0x23, 0x1E, 0x2C, 0x70, 0x59, 0x10, 0x34, + 0xE6, 0x47, 0x52, 0xB4, 0x35, 0x7C, 0x19, 0x5F, 0xAF, 0xC3, 0x95, 0xDE, 0x60, 0x0D, 0xB6, 0x28, 0xE8, 0x08, 0xCE, 0xF4, 0xE0, 0x60, 0x71, 0xD6, 0x24, 0x8E, + 0xD6, 0xFD, 0x32, 0xA6, 0x0A, 0xDB, 0x75, 0xF8, 0x42, 0x83, 0x05, 0xDF, 0x0C, 0xA2, 0xB4, 0xFA, 0x5C, 0x89, 0x0A, 0xA2, 0x2F, 0x91, 0x57, 0x5B, 0xE3, 0x48, + 0x8C, 0xCA, 0x9F, 0x80, 0x1F, 0x81, 0x19, 0x2E, 0xC5, 0xBA, 0xAD, 0xC6, 0x1C, 0x49, 0x8A, 0xC2, 0x75, 0x89, 0xAF, 0xB7, 0xC6, 0x15, 0x05, 0x9D, 0x3F, 0x03, + 0x5F, 0x16, 0x6C, 0x8C, 0xBD, 0x71, 0x1F, 0xD9, 0x64, 0x82, 0x0E, 0xAB, 0x39, 0x6F, 0x52, 0xC5, 0xC1, 0x1F, 0xF1, 0xDF, 0xB8, 0xE0, 0xFF, 0x1B, 0x8F, 0x23, + 0x32, 0xE0, 0x56, 0x1F, 0x4C, 0x64, 0x7B, 0x6F, 0x19, 0x50, 0xA7, 0x21, 0x7D, 0x74, 0xD5, 0x1A, 0x7E, 0xEB, 0xC5, 0x78, 0xAE, 0xEE, 0x60, 0x7C, 0xCB, 0xA6, + 0x3C, 0x5E, 0xBD, 0x8E, 0x9F, 0xF3, 0xC6, 0x37, 0x6F, 0xF9, 0x86, 0xC8, 0x75, 0xBC, 0xAE, 0x1F, 0xE0, 0x8F, 0xFE, 0x88, 0x58, 0xDB, 0x3A, 0x3E, 0xE0, 0x1B, + 0x1F, 0xCB, 0xEB, 0xD7, 0x83, 0x02, 0x67, 0xF4, 0x25, 0x2E, 0xD6, 0x03, 0x02, 0xD7, 0xF8, 0x92, 0x2D, 0x6C, 0xF3, 0x73, 0x70, 0xB7, 0xCC, 0xEB, 0x51, 0x63, + 0xB5, 0x40, 0x99, 0xD6, 0xF0, 0xC5, 0x2F, 0x2F, 0x1B, 0x1B, 0x29, 0x31, 0xEB, 0x5B, 0x47, 0xC2, 0x93, 0xD8, 0x09, 0x55, 0x96, 0x0B, 0x6A, 0xE9, 0x35, 0xA7, + 0x6E, 0x60, 0x4B, 0xD3, 0xAE, 0x08, 0x41, 0x3E, 0x49, 0xD6, 0x52, 0x9A, 0x59, 0xAF, 0x8D, 0x0F, 0x67, 0xC1, 0x80, 0xC4, 0xC7, 0x29, 0x42, 0x9A, 0xAB, 0x30, + 0x89, 0x17, 0xE4, 0x9C, 0x32, 0xDE, 0xE0, 0x6A, 0x53, 0xEC, 0x12, 0xD5, 0x6E, 0x8D, 0x67, 0xB2, 0xD5, 0xDB, 0x66, 0x1C, 0x10, 0x99, 0x7B, 0x56, 0xF3, 0x90, + 0x95, 0x2C, 0xD7, 0x1A, 0x82, 0x6B, 0xEF, 0x71, 0xD1, 0xB8, 0x97, 0x89, 0x00, 0x3C, 0x70, 0xF7, 0xF2, 0x02, 0x3B, 0xE5, 0xD6, 0xE9, 0x59, 0x2E, 0xB1, 0x3E, + 0x13, 0x83, 0xB4, 0xD5, 0xBB, 0x95, 0x57, 0x8E, 0xB7, 0xB4, 0x56, 0x87, 0x80, 0x3E, 0xE5, 0xBB, 0xC9, 0x04, 0x5B, 0xF7, 0xD7, 0x8A, 0x2A, 0x78, 0xF3, 0x9A, + 0xE5, 0x1F, 0xD8, 0x8A, 0xB3, 0x71, 0x73, 0x03, 0xC1, 0xC6, 0xE0, 0xE2, 0xC5, 0x2B, 0xE3, 0xF2, 0xE2, 0xDB, 0xCB, 0xEF, 0x7E, 0xD8, 0x8C, 0x75, 0x40, 0x9D, + 0x5B, 0x32, 0x0C, 0xD4, 0xDA, 0xAD, 0x1B, 0x73, 0x36, 0x1E, 0xAC, 0xC2, 0x27, 0x48, 0x3B, 0x31, 0xEA, 0xF5, 0xE5, 0xF7, 0x9B, 0xE2, 0x12, 0x9C, 0xFD, 0x6D, + 0xB1, 0x09, 0x8D, 0xDD, 0x3E, 0x9F, 0x3E, 0x3A, 0xEC, 0x8A, 0x39, 0x2B, 0xF0, 0x4A, 0x14, 0x24, 0x7E, 0x19, 0xEF, 0xE8, 0x6A, 0x6B, 0x03, 0xB9, 0x18, 0x95, + 0x3F, 0xC1, 0x30, 0x0E, 0x52, 0xF1, 0x91, 0x23, 0xBD, 0x8A, 0xF2, 0x88, 0x92, 0xAD, 0xE1, 0xC5, 0x0D, 0x56, 0xC7, 0x60, 0xD3, 0xF6, 0x3A, 0x1C, 0x41, 0x08, + 0x7A, 0x0D, 0x86, 0x44, 0xA8, 0x08, 0x8E, 0x80, 0xFC, 0x9C, 0x21, 0x34, 0xA1, 0xA3, 0xCC, 0xF5, 0x21, 0x62, 0x78, 0x8F, 0x5C, 0x21, 0xE0, 0x0F, 0xC9, 0x98, + 0xE9, 0x0A, 0xFD, 0xCE, 0x94, 0xFA, 0x9D, 0x37, 0xAF, 0x36, 0x63, 0xCA, 0x50, 0xD9, 0x96, 0x2C, 0x19, 0x35, 0x73, 0x7B, 0x86, 0xCC, 0x90, 0xF3, 0xED, 0x11, + 0x15, 0x56, 0x1C, 0x44, 0xC8, 0x82, 0x18, 0x3B, 0xAF, 0x32, 0x80, 0x50, 0x34, 0xE7, 0xF0, 0x66, 0x1D, 0xD5, 0x89, 0xD0, 0x48, 0x6B, 0xCE, 0x51, 0xA2, 0x37, + 0x8F, 0xEF, 0x55, 0x6B, 0x8E, 0x2A, 0xB1, 0x5D, 0x47, 0x69, 0xA8, 0x25, 0x63, 0x66, 0x63, 0xE6, 0x7D, 0xDA, 0x98, 0x21, 0x4A, 0x59, 0xC1, 0x13, 0xE3, 0x95, + 0xF8, 0xB7, 0x0E, 0x6F, 0x06, 0xEB, 0xF0, 0x46, 0xC5, 0x28, 0xCD, 0x9E, 0x93, 0x07, 0xEA, 0x69, 0x68, 0xDE, 0xEC, 0x21, 0xE7, 0x3C, 0x16, 0xCD, 0x6D, 0x1A, + 0xCA, 0x20, 0x30, 0xF4, 0xFD, 0x66, 0x6C, 0x1A, 0x55, 0x56, 0xD3, 0xA6, 0xAD, 0x65, 0xC1, 0x78, 0xA3, 0xB6, 0x3E, 0x8C, 0x5E, 0x81, 0x1B, 0x28, 0x83, 0xE1, + 0xF3, 0x86, 0xB8, 0x41, 0x95, 0x6D, 0xA7, 0x87, 0xE1, 0xCD, 0xDC, 0x36, 0x7F, 0x7C, 0xF3, 0xFA, 0xE3, 0x74, 0x6E, 0x36, 0xE6, 0x91, 0x2C, 0x87, 0xC0, 0xAE, + 0x79, 0x6D, 0xBC, 0x79, 0xFF, 0x62, 0x23, 0xBC, 0x8A, 0x2A, 0xDD, 0x0E, 0xBF, 0xE2, 0x26, 0x6F, 0x9B, 0x67, 0x58, 0x6B, 0xD6, 0x5C, 0xA9, 0xA8, 0x50, 0x6B, + 0xF8, 0x8E, 0xE1, 0x4C, 0x9C, 0x57, 0x9E, 0x2F, 0x8F, 0xC8, 0xDB, 0x08, 0xD7, 0x78, 0xCD, 0xDB, 0x61, 0x99, 0x68, 0xF4, 0xB6, 0xF9, 0x35, 0x9B, 0xDB, 0xBE, + 0xEF, 0xF9, 0x8D, 0x59, 0x26, 0xCB, 0x21, 0x4C, 0xD5, 0x7B, 0xCF, 0xAF, 0x36, 0xC2, 0xAE, 0xA8, 0xD6, 0xED, 0x70, 0x2C, 0x6E, 0xF3, 0xB6, 0x99, 0x76, 0x35, + 0x71, 0xEC, 0x45, 0x63, 0x96, 0xF1, 0x52, 0x58, 0x79, 0xD6, 0xFB, 0x1A, 0xBF, 0x1B, 0x61, 0x97, 0xA8, 0x71, 0x3B, 0xCC, 0x92, 0xAD, 0xDD, 0x36, 0xAB, 0xAC, + 0xF1, 0x75, 0x63, 0x46, 0xA1, 0x4C, 0x6B, 0xF8, 0xFA, 0xD5, 0x2F, 0x46, 0xE7, 0xB5, 0x77, 0x8D, 0x7D, 0x71, 0xBF, 0x33, 0xE3, 0xE2, 0x5B, 0xAC, 0xC0, 0xDA, + 0x00, 0xC7, 0xA8, 0xEA, 0xED, 0xF0, 0x8B, 0x37, 0x7A, 0xDB, 0xDC, 0xE2, 0x7B, 0x80, 0xB0, 0x0C, 0x7E, 0x85, 0xB5, 0x2F, 0xA2, 0x20, 0xAD, 0x7D, 0xC1, 0x95, + 0xF1, 0xD2, 0xDC, 0x8C, 0x41, 0x8C, 0xEB, 0xDD, 0x84, 0xD3, 0x9E, 0x34, 0x72, 0xFB, 0x5E, 0x86, 0x55, 0x83, 0x45, 0x69, 0x17, 0xC3, 0xFA, 0x48, 0xDB, 0x69, + 0x68, 0x9B, 0x29, 0x16, 0xF2, 0xBD, 0xBB, 0x78, 0x6D, 0x7C, 0x13, 0xFD, 0xAD, 0xD1, 0x9A, 0x95, 0x63, 0x76, 0x45, 0x43, 0xDB, 0x34, 0x3E, 0xE9, 0xC1, 0xED, + 0xE0, 0x31, 0x42, 0x0E, 0xEB, 0x0C, 0x6F, 0x8B, 0xC2, 0xA8, 0x8F, 0x1F, 0xAF, 0xC9, 0x13, 0x75, 0x33, 0x86, 0x3C, 0xC5, 0xB0, 0x4A, 0x49, 0xE4, 0xA6, 0x00, + 0x3E, 0x9C, 0xC7, 0xF2, 0x7F, 0x9C, 0x4E, 0xE8, 0x20, 0x84, 0xFD, 0x86, 0x85, 0xC6, 0x25, 0x5D, 0xD6, 0xDC, 0x05, 0xA0, 0x40, 0x89, 0xB6, 0x00, 0xE1, 0xFC, + 0x50, 0x73, 0x8E, 0xB9, 0x3E, 0x3A, 0xDF, 0x11, 0xB0, 0xE8, 0x5F, 0x35, 0xB0, 0xDA, 0xFB, 0x05, 0xF8, 0x06, 0x21, 0xDA, 0xF1, 0x93, 0x3E, 0x8E, 0x15, 0xA2, + 0x2F, 0xB6, 0xFF, 0x0D, 0xCF, 0x70, 0x60, 0x85, 0x1B, 0x65, 0xE3, 0x7B, 0xE3, 0xAE, 0xE5, 0x66, 0xA7, 0x91, 0xE7, 0x58, 0xC8, 0xF8, 0xC2, 0xBA, 0xA2, 0xA3, + 0x69, 0x2C, 0x03, 0x7B, 0x1D, 0xE4, 0xB6, 0x1D, 0x2A, 0x02, 0xDD, 0x89, 0x20, 0x54, 0x10, 0x7B, 0xE6, 0x47, 0xE0, 0xC5, 0x06, 0x2B, 0x3A, 0xCC, 0xA3, 0x84, + 0xDA, 0x05, 0x3B, 0x8D, 0x7C, 0x86, 0xD8, 0x49, 0xB4, 0xC3, 0x44, 0xB3, 0x01, 0x4D, 0xBB, 0xEF, 0xE8, 0x07, 0x36, 0xB5, 0x03, 0xE0, 0x68, 0x80, 0x4F, 0xFB, + 0x7C, 0xAF, 0x86, 0xD0, 0x90, 0x7A, 0xFB, 0x80, 0xD4, 0x2A, 0xE5, 0x2E, 0x46, 0xED, 0xEE, 0xAE, 0x46, 0x5D, 0x48, 0x76, 0x2F, 0x56, 0x1A, 0x62, 0x95, 0x14, + 0x62, 0xF9, 0xF9, 0xEC, 0x98, 0x76, 0x9D, 0x18, 0x51, 0xD3, 0xB0, 0xED, 0xEB, 0xB8, 0x6A, 0xE9, 0x79, 0xE5, 0x96, 0x21, 0xB4, 0x74, 0xE5, 0x1D, 0x43, 0x44, + 0x25, 0x2C, 0x3D, 0x9A, 0x76, 0x8D, 0xF7, 0x66, 0xF0, 0xA9, 0x6B, 0xFC, 0x4C, 0x0A, 0xBF, 0xC1, 0x8D, 0x43, 0x84, 0x3B, 0xF6, 0x32, 0xC6, 0x5D, 0x47, 0x6E, + 0xF3, 0x90, 0x58, 0x5F, 0x1C, 0xFD, 0x43, 0xC4, 0x4D, 0x6C, 0x1E, 0x52, 0x42, 0x6F, 0x37, 0x87, 0xB4, 0x29, 0xE2, 0xDE, 0xF6, 0x0F, 0xDD, 0x4B, 0x93, 0xE6, + 0x20, 0x66, 0xCD, 0x26, 0xE1, 0x9F, 0x68, 0x12, 0x2E, 0xE2, 0x26, 0x3D, 0xBD, 0xCF, 0x1D, 0x51, 0xF7, 0xD2, 0x22, 0x39, 0xB1, 0xF3, 0x99, 0x34, 0xA9, 0xD6, + 0x26, 0x2F, 0x2E, 0xDB, 0xF7, 0xB5, 0xC7, 0x4B, 0x6B, 0x0C, 0x71, 0x2A, 0x43, 0x3D, 0x9D, 0xA7, 0x9E, 0xE6, 0xDE, 0x74, 0x9E, 0x7A, 0xB0, 0x55, 0x75, 0x5E, + 0x96, 0x55, 0x74, 0x7E, 0x83, 0xCA, 0x1E, 0x21, 0xFE, 0x27, 0x53, 0xF8, 0xA8, 0x59, 0x0D, 0x94, 0x5E, 0xDB, 0xAC, 0xCD, 0x6A, 0x48, 0x2C, 0x09, 0x90, 0xCD, + 0xFB, 0xD3, 0x90, 0x02, 0xB9, 0x5D, 0x49, 0x48, 0xA5, 0xCD, 0x19, 0x6E, 0xA6, 0x4F, 0xE2, 0x9E, 0x94, 0xCA, 0x4E, 0x59, 0x3B, 0xED, 0x3C, 0x3A, 0xC2, 0x7E, + 0x19, 0xEE, 0x36, 0xDD, 0x07, 0x7B, 0xEA, 0x6F, 0x26, 0x7D, 0x60, 0xA7, 0x8C, 0x36, 0xBE, 0x2D, 0xE0, 0x07, 0x37, 0x76, 0xCC, 0xB0, 0xBF, 0xB8, 0x99, 0x2F, + 0x96, 0xAD, 0x69, 0x73, 0xFE, 0xD8, 0x6A, 0xD2, 0xAA, 0x12, 0x4C, 0xE2, 0x0E, 0x8B, 0x43, 0xDB, 0xAA, 0x07, 0x1F, 0xE2, 0x96, 0x6B, 0x06, 0xCD, 0x8A, 0x51, + 0x88, 0x8B, 0x15, 0x8D, 0x89, 0xB9, 0x21, 0x94, 0x41, 0x0C, 0x5C, 0x47, 0x76, 0xCD, 0xF0, 0x26, 0x13, 0xFE, 0xAC, 0x9E, 0x27, 0x64, 0x30, 0x82, 0x4F, 0x94, + 0x7E, 0x80, 0xCA, 0x4B, 0x46, 0xC4, 0x09, 0x86, 0x31, 0x6E, 0x5C, 0xC4, 0xA4, 0xA0, 0xDD, 0x1B, 0x09, 0xB0, 0xA0, 0x90, 0x48, 0xF0, 0xFA, 0x9B, 0x9F, 0x75, + 0x34, 0x10, 0xBA, 0x76, 0x90, 0x27, 0x01, 0x36, 0x86, 0xAD, 0xBA, 0x31, 0x1C, 0x19, 0x6A, 0x52, 0x8B, 0x8F, 0x5A, 0x05, 0xB5, 0x8E, 0x26, 0xC9, 0x9E, 0xB1, + 0x75, 0x4C, 0x96, 0x86, 0x02, 0x58, 0x1C, 0x4F, 0xAB, 0x42, 0x8D, 0xEF, 0x55, 0x0D, 0xA8, 0x25, 0x07, 0x18, 0x4B, 0xD7, 0x97, 0x03, 0x0B, 0x24, 0x5B, 0x59, + 0x0C, 0x80, 0xA3, 0x56, 0x0C, 0xEE, 0x8B, 0x06, 0x58, 0x14, 0x4A, 0xCD, 0x6F, 0x2C, 0x06, 0xE8, 0x00, 0x6B, 0x89, 0x01, 0xDA, 0x2E, 0xC4, 0x20, 0xD9, 0x50, + 0x98, 0xAC, 0x18, 0xAA, 0x20, 0x96, 0x22, 0x05, 0x4F, 0x20, 0x05, 0x87, 0x83, 0x27, 0xF5, 0x34, 0x61, 0x73, 0x36, 0xF7, 0x9A, 0xD6, 0x78, 0x34, 0xB5, 0xB7, + 0xBF, 0xD8, 0xAE, 0xE5, 0x5D, 0x37, 0x33, 0xB9, 0x6A, 0x45, 0x9F, 0xBB, 0xB9, 0x6D, 0x36, 0x6A, 0xA5, 0x50, 0x4B, 0x0F, 0x81, 0xA4, 0x4B, 0x84, 0xAD, 0x10, + 0xE4, 0xCC, 0x1F, 0x7B, 0x90, 0xDA, 0x91, 0x14, 0xE5, 0xAE, 0xE7, 0x04, 0xE4, 0xD7, 0x60, 0x7F, 0xF3, 0xB5, 0xB1, 0xC2, 0x8E, 0xF4, 0x82, 0x15, 0xE1, 0xD8, + 0xCB, 0x6C, 0xAC, 0xB0, 0x73, 0xBF, 0xFE, 0x9A, 0x75, 0x3A, 0x45, 0xC1, 0x58, 0xED, 0x18, 0x85, 0xCA, 0xE5, 0xDB, 0x8A, 0xEF, 0xB2, 0x5E, 0xBC, 0x42, 0x68, + 0x2B, 0x7C, 0xAC, 0x7A, 0x7B, 0x6E, 0xB3, 0x02, 0x20, 0x8B, 0x83, 0xA7, 0x58, 0xDE, 0x8E, 0xAB, 0x87, 0xF6, 0x0C, 0x3F, 0x9C, 0x2A, 0xC6, 0x2C, 0xAE, 0xBC, + 0xA1, 0x31, 0x4B, 0xFC, 0x7C, 0x08, 0xD3, 0xD6, 0x07, 0x2F, 0x7F, 0xD7, 0x34, 0x09, 0xF1, 0xDF, 0x55, 0x9B, 0x74, 0x74, 0x5F, 0x4D, 0x5A, 0xA3, 0xAB, 0x8A, + 0xA5, 0x2B, 0xF4, 0x42, 0x3C, 0x9F, 0x70, 0x55, 0xE1, 0x12, 0xA5, 0x21, 0x5B, 0xC2, 0xE6, 0x1A, 0x97, 0x68, 0xEA, 0x46, 0x05, 0x2C, 0x42, 0xA0, 0x1E, 0x33, + 0xE2, 0x48, 0x4B, 0xC2, 0x0C, 0x98, 0x97, 0xCF, 0x4B, 0xBE, 0x44, 0x8B, 0xEA, 0x8A, 0x97, 0xA6, 0x45, 0xB0, 0x66, 0x9F, 0x8F, 0x78, 0xE1, 0x78, 0x32, 0x4A, + 0x5D, 0xD9, 0x78, 0x89, 0xE2, 0x64, 0xBC, 0xF8, 0xD5, 0xE6, 0x05, 0x2C, 0xC6, 0x60, 0x65, 0x7E, 0xE0, 0xC0, 0x93, 0xCF, 0xCC, 0x82, 0x89, 0x26, 0xAD, 0x21, + 0x62, 0x38, 0x36, 0x65, 0x73, 0x22, 0xA6, 0x4C, 0x23, 0xC9, 0x7E, 0x50, 0x3A, 0x30, 0x3C, 0x5A, 0x99, 0x72, 0x68, 0x9A, 0xCC, 0x24, 0xE9, 0x7B, 0xE5, 0xB3, + 0x7D, 0x38, 0x85, 0x9A, 0x23, 0xD7, 0xF4, 0x78, 0x9E, 0x89, 0xC7, 0xBE, 0x15, 0x1C, 0x97, 0x16, 0x1F, 0xD3, 0xC6, 0xE7, 0xB9, 0x92, 0x03, 0x41, 0x63, 0x47, + 0x33, 0x7B, 0x50, 0x68, 0xE5, 0x91, 0x68, 0x67, 0xA6, 0xDC, 0x93, 0x7F, 0x45, 0x73, 0x69, 0x34, 0x29, 0x67, 0xCC, 0x7C, 0x36, 0x39, 0x6F, 0x7D, 0x19, 0xC3, + 0x94, 0xD4, 0xA2, 0x2C, 0x2D, 0x03, 0x26, 0xD9, 0x75, 0x3C, 0x93, 0x9C, 0x55, 0x73, 0x81, 0x7D, 0xFC, 0xAC, 0xFF, 0xDB, 0x82, 0x82, 0xBC, 0xB8, 0x79, 0xB6, + 0x6F, 0xD6, 0x9B, 0xC7, 0xE5, 0x47, 0x8B, 0xCA, 0x99, 0x76, 0xBA, 0x8C, 0x27, 0xF1, 0xFE, 0xEF, 0xFF, 0x55, 0x85, 0x66, 0xE8, 0xE1, 0x7F, 0x09, 0x01, 0x20, + 0x46, 0xFE, 0xF8, 0xBC, 0x05, 0x4C, 0x7D, 0x2F, 0x80, 0x2B, 0x6A, 0x63, 0x92, 0xAE, 0x80, 0x72, 0x05, 0xD4, 0xDE, 0xD7, 0x91, 0x3B, 0x93, 0x59, 0x33, 0x36, + 0x39, 0x0B, 0xC6, 0xBE, 0xBD, 0x80, 0xAB, 0x86, 0xC7, 0x00, 0x2F, 0x71, 0x76, 0x5D, 0xD8, 0x47, 0x44, 0xF5, 0xE2, 0x0A, 0x17, 0xEF, 0x28, 0xC2, 0x0C, 0xCA, + 0x77, 0xDA, 0xAF, 0xBF, 0x7B, 0x4F, 0x07, 0x60, 0x50, 0x1A, 0xE8, 0xC5, 0xAC, 0x76, 0xD7, 0x98, 0x2C, 0x5D, 0xE1, 0xBD, 0x77, 0xB0, 0x6D, 0xC6, 0x0D, 0xC5, + 0x43, 0x18, 0xAF, 0x4C, 0x1F, 0x47, 0x9F, 0x06, 0xEC, 0xAD, 0x17, 0x84, 0xC6, 0x39, 0x08, 0x2C, 0x21, 0xE2, 0x50, 0x47, 0x7E, 0x48, 0x42, 0x5F, 0xB4, 0x4B, + 0xE6, 0x14, 0x0D, 0xFF, 0xC9, 0x77, 0x90, 0x35, 0x2E, 0xB5, 0x67, 0xB4, 0x4F, 0x9F, 0x1E, 0xB6, 0x49, 0xFE, 0xE2, 0x2A, 0x26, 0xF4, 0x58, 0x45, 0xE4, 0xEB, + 0x2C, 0x7D, 0xA7, 0x6B, 0x8C, 0x47, 0xBB, 0xE2, 0x90, 0x44, 0x9E, 0x4C, 0x69, 0xD1, 0xE9, 0xB9, 0xFD, 0x70, 0xC6, 0xDC, 0x4E, 0x82, 0x19, 0x94, 0x61, 0x81, + 0xF9, 0xDC, 0xD4, 0x13, 0x22, 0xED, 0x49, 0x92, 0xDE, 0x87, 0x43, 0x1F, 0xE2, 0xF9, 0x2E, 0x8F, 0xCE, 0xCF, 0x71, 0x6E, 0xE6, 0x41, 0xFA, 0x41, 0x92, 0xE3, + 0x51, 0x36, 0x5F, 0x17, 0xA3, 0xC4, 0x54, 0xC2, 0x8F, 0x30, 0x0D, 0xCA, 0x31, 0xBF, 0x77, 0x06, 0x73, 0x32, 0xE7, 0xCC, 0xC6, 0x05, 0xC8, 0x8A, 0x74, 0x76, + 0xD3, 0x08, 0x76, 0x2C, 0x33, 0x34, 0x65, 0x5B, 0x94, 0x5A, 0x81, 0x49, 0xD7, 0xE0, 0xB7, 0xD4, 0xD3, 0x27, 0xEF, 0x76, 0xFB, 0xA0, 0x21, 0xDA, 0x1B, 0x97, + 0x66, 0xBE, 0x9F, 0x7D, 0xF4, 0x25, 0x4A, 0xF7, 0x0E, 0xBB, 0x06, 0xDD, 0x49, 0x97, 0x55, 0x90, 0x94, 0x57, 0x77, 0x31, 0xD1, 0xCA, 0xC1, 0x6A, 0x40, 0x0A, + 0x70, 0xFC, 0xF0, 0xC9, 0x98, 0xD6, 0xB0, 0x3D, 0x98, 0x04, 0x00, 0xC5, 0x30, 0x11, 0x20, 0x7C, 0xC0, 0x2E, 0x1F, 0x3D, 0x77, 0x85, 0x51, 0x54, 0xB8, 0xB6, + 0xBF, 0x0F, 0x95, 0x86, 0x51, 0x62, 0x90, 0x8A, 0x69, 0xA7, 0x2D, 0x27, 0x30, 0x21, 0x51, 0xED, 0x83, 0x9B, 0xF6, 0x1E, 0x00, 0xE0, 0x44, 0x4C, 0xCC, 0x7D, + 0x63, 0x7A, 0x19, 0x43, 0x8F, 0xDD, 0x04, 0x1A, 0xBF, 0x4D, 0x20, 0x33, 0xF7, 0x79, 0x3A, 0xAF, 0x24, 0x7B, 0xA3, 0x23, 0xD3, 0xF7, 0xDA, 0xBB, 0x6D, 0x89, + 0x3C, 0xFF, 0x0F, 0x71, 0xEB, 0x88, 0x8B, 0x1D, 0x8E, 0xE3, 0xAE, 0x71, 0x76, 0x26, 0xAB, 0x11, 0xB9, 0x28, 0x11, 0x99, 0xF8, 0x4F, 0xE6, 0x56, 0x2C, 0x8A, + 0xBF, 0x7E, 0xF5, 0x47, 0x24, 0xB3, 0x77, 0xFB, 0xC0, 0xFA, 0x39, 0x45, 0x10, 0xBE, 0xFA, 0x03, 0xDF, 0x77, 0x3B, 0x3C, 0x6C, 0xF0, 0xD5, 0x1F, 0xF4, 0x73, + 0xB7, 0x83, 0x9A, 0x70, 0xCD, 0xEB, 0xBB, 0xFB, 0x95, 0xD3, 0x21, 0x4F, 0x3D, 0x44, 0x89, 0x0B, 0xA8, 0x17, 0x93, 0xAD, 0x31, 0x4E, 0x38, 0xF0, 0xBC, 0x10, + 0x29, 0xE0, 0x11, 0xF3, 0x7B, 0x8C, 0xDD, 0xCF, 0x5D, 0x23, 0x84, 0x24, 0x47, 0x4C, 0x77, 0xC0, 0x92, 0x88, 0x50, 0xF1, 0x09, 0xA8, 0xF6, 0x84, 0xE7, 0x34, + 0xA4, 0xAA, 0x24, 0x02, 0x12, 0xE5, 0xC4, 0xC3, 0x2E, 0x02, 0x86, 0x05, 0x28, 0x1D, 0x02, 0x95, 0xC8, 0x5B, 0x01, 0xC5, 0x87, 0xC3, 0x54, 0x13, 0xF8, 0x81, + 0xC4, 0x37, 0x64, 0x33, 0xDA, 0x92, 0x69, 0xB1, 0xB0, 0xC9, 0x5F, 0xC8, 0x61, 0x82, 0xA9, 0xB8, 0x59, 0x20, 0x87, 0x1F, 0x70, 0x1C, 0x63, 0x87, 0xCE, 0x64, + 0xCC, 0x9A, 0x8A, 0x1C, 0x89, 0x28, 0xD3, 0x73, 0xFA, 0x02, 0x5D, 0xE8, 0xA7, 0x90, 0x3F, 0x80, 0x2A, 0x5C, 0xF8, 0x0E, 0x0F, 0x01, 0x7C, 0xBC, 0xE9, 0xC2, + 0x78, 0xD1, 0xC5, 0x2D, 0x34, 0xC3, 0xB5, 0xE8, 0x3F, 0xFD, 0xE0, 0x9F, 0x68, 0x14, 0x25, 0xC8, 0x2B, 0xA4, 0x71, 0x9F, 0x95, 0x92, 0xC4, 0x05, 0xE5, 0xE2, + 0x3E, 0x06, 0xCF, 0x25, 0xAE, 0x90, 0x46, 0x67, 0x7E, 0x40, 0x76, 0xBB, 0xC6, 0xC8, 0x76, 0x5D, 0x7E, 0x51, 0x81, 0x7D, 0xD2, 0xD5, 0x3F, 0x0F, 0x6E, 0xD0, + 0x02, 0x89, 0xDA, 0xDD, 0x4E, 0x70, 0x1B, 0xFF, 0xBB, 0xBD, 0xDB, 0x61, 0x74, 0x8F, 0x23, 0x89, 0x6B, 0xBA, 0xC3, 0x31, 0xBD, 0xDB, 0x01, 0x7E, 0x74, 0x27, + 0x42, 0x98, 0x27, 0xD0, 0xED, 0x08, 0xEF, 0xBB, 0x9D, 0x90, 0xEE, 0x4B, 0xE4, 0xF1, 0x8F, 0x6E, 0xCA, 0x16, 0x20, 0x33, 0x2F, 0x2B, 0x9B, 0x81, 0xBF, 0xBC, + 0xA4, 0x6C, 0x0B, 0x30, 0xE0, 0x0F, 0x74, 0x07, 0x12, 0xA2, 0x4D, 0x77, 0x3B, 0xB2, 0x4D, 0x48, 0x92, 0x57, 0x59, 0x52, 0x93, 0x4D, 0x08, 0xA5, 0x15, 0x79, + 0x29, 0x3A, 0x69, 0xA5, 0xFF, 0x80, 0x7E, 0x5C, 0x38, 0x8C, 0x2E, 0x5F, 0xDE, 0x7E, 0x63, 0x75, 0xDA, 0x72, 0x42, 0xB6, 0x4D, 0x36, 0x4C, 0x2D, 0xD3, 0xF7, + 0xDC, 0xB1, 0x63, 0xE3, 0xF1, 0x31, 0x90, 0xB7, 0x5D, 0xE3, 0x7C, 0x28, 0xED, 0x18, 0x09, 0x34, 0xB2, 0xAB, 0x42, 0x5A, 0x08, 0x3A, 0x9A, 0x52, 0x6C, 0xEF, + 0xF6, 0xB9, 0x1C, 0x4A, 0x59, 0x23, 0x10, 0x52, 0x05, 0xEB, 0xC1, 0xA0, 0xCC, 0x1A, 0x18, 0x39, 0x6D, 0x29, 0x05, 0xC2, 0x73, 0x2B, 0x50, 0x38, 0x18, 0xD5, + 0xD4, 0xA2, 0xA7, 0x48, 0x59, 0xD9, 0x12, 0xAD, 0x8E, 0x14, 0xF8, 0x51, 0x56, 0x81, 0xC1, 0x2A, 0x3F, 0xEC, 0xB4, 0x2F, 0x68, 0x21, 0xF0, 0x3F, 0xDA, 0x7B, + 0x94, 0x69, 0xAF, 0xFD, 0xCF, 0x53, 0xA3, 0xBD, 0xA7, 0x6A, 0xB2, 0xD0, 0x43, 0x45, 0xE5, 0x04, 0xC7, 0x84, 0xE5, 0xAA, 0xE6, 0x98, 0x9C, 0x07, 0xE3, 0x1C, + 0x53, 0xCB, 0xDC, 0x03, 0xC7, 0xD4, 0x89, 0xE0, 0x75, 0xB8, 0xA6, 0xCE, 0xBC, 0x96, 0x70, 0xAE, 0xB2, 0xBC, 0x64, 0x9A, 0xE4, 0x96, 0x6A, 0xDA, 0x63, 0x6E, + 0xAD, 0xC2, 0x26, 0xD1, 0xC5, 0x41, 0x7B, 0x98, 0xFF, 0xF6, 0xC7, 0xF7, 0xEF, 0xC8, 0x54, 0xEA, 0x59, 0x16, 0x73, 0x2C, 0xEB, 0x8E, 0x68, 0x20, 0x50, 0xDF, + 0x99, 0x32, 0xDC, 0xA9, 0x3E, 0x74, 0xAF, 0x6D, 0xA0, 0x0F, 0x45, 0x32, 0xF5, 0xA0, 0x15, 0x82, 0x20, 0x0D, 0x6F, 0x3D, 0xDD, 0x25, 0x63, 0x1B, 0x29, 0x6F, + 0x52, 0xAA, 0x44, 0x16, 0xA8, 0x40, 0x2D, 0x26, 0x0A, 0xC8, 0x39, 0x85, 0x51, 0xFA, 0x84, 0x8D, 0xAB, 0x08, 0xD7, 0xD7, 0xA0, 0xAE, 0x51, 0x8B, 0x6C, 0x7A, + 0x62, 0xDB, 0x64, 0xD1, 0x12, 0xEA, 0x48, 0xCB, 0x5F, 0x8B, 0x40, 0x32, 0x86, 0xAD, 0x11, 0xF0, 0xA8, 0x27, 0xA8, 0x05, 0x26, 0x0A, 0x5D, 0x16, 0xC3, 0xB9, + 0x6D, 0x02, 0xE7, 0x56, 0x03, 0x47, 0xF6, 0x3C, 0xB5, 0xC0, 0xC8, 0x40, 0x57, 0x21, 0x94, 0x7A, 0xC8, 0xC8, 0xE0, 0x92, 0xAE, 0x4D, 0xB2, 0xA7, 0xAB, 0xD7, + 0x26, 0x19, 0x14, 0x29, 0x86, 0x53, 0x93, 0x36, 0x32, 0x12, 0xA1, 0x91, 0xE7, 0xAC, 0x37, 0x02, 0xCB, 0x22, 0x3E, 0xAB, 0xFB, 0x1F, 0x13, 0x13, 0xD6, 0x22, + 0xF9, 0xD9, 0x8A, 0x96, 0x4C, 0xF9, 0xEA, 0x0C, 0x92, 0x70, 0xE6, 0x68, 0x7B, 0x03, 0x3C, 0x72, 0xC0, 0x0C, 0x61, 0x9F, 0x30, 0x8E, 0x67, 0x41, 0x9F, 0x3C, + 0xDC, 0x98, 0x8C, 0xB9, 0x5B, 0x7D, 0x17, 0x08, 0x70, 0x80, 0xBB, 0xA7, 0xD2, 0x8D, 0x4D, 0xC4, 0x33, 0x07, 0x4B, 0x24, 0x17, 0x81, 0x13, 0x77, 0x0B, 0x20, + 0xCA, 0x1E, 0x26, 0x5D, 0x82, 0x12, 0x8B, 0xA0, 0xF1, 0x51, 0x8C, 0x02, 0x0B, 0xAB, 0x98, 0xF3, 0xFD, 0x8C, 0xAC, 0x40, 0x3E, 0xFA, 0x89, 0x20, 0x50, 0x3C, + 0x2A, 0x19, 0x9A, 0x8D, 0xE1, 0x08, 0x1A, 0xED, 0x68, 0xCA, 0xAE, 0x7D, 0x9A, 0xF3, 0xB8, 0x51, 0x42, 0x4E, 0xC2, 0x19, 0xCF, 0x05, 0x8E, 0xA9, 0x07, 0x1A, + 0x8C, 0x30, 0xF8, 0x8E, 0x9F, 0x5B, 0x24, 0x80, 0xF1, 0x85, 0xD5, 0x31, 0x24, 0x91, 0x46, 0x03, 0xD7, 0x4C, 0x92, 0x98, 0xDB, 0xE9, 0xE1, 0x69, 0x04, 0xFA, + 0x5A, 0x53, 0xFE, 0xBB, 0xAC, 0x48, 0xFE, 0x93, 0x2B, 0xBE, 0x93, 0x62, 0x3E, 0x43, 0xE0, 0xC5, 0x95, 0xFE, 0x7C, 0xDE, 0xBF, 0xD1, 0x0E, 0x25, 0x37, 0x28, + 0x9B, 0xFB, 0xFB, 0xC6, 0x8B, 0x30, 0x34, 0xC1, 0x00, 0x9A, 0xA7, 0x9C, 0x11, 0x7D, 0x0C, 0x31, 0x65, 0x4C, 0x11, 0x58, 0x12, 0x4A, 0xB1, 0xA8, 0x18, 0x14, + 0x21, 0xBD, 0xA5, 0xC7, 0x3C, 0x45, 0xEA, 0xCC, 0x41, 0xF5, 0xFF, 0xB5, 0x64, 0xFE, 0xED, 0x25, 0x27, 0x98, 0xE7, 0xBF, 0x70, 0x9C, 0x4E, 0x9B, 0x44, 0x53, + 0x4E, 0x3B, 0x73, 0x1B, 0x8F, 0x4C, 0x00, 0x75, 0x81, 0x3A, 0xC0, 0xE3, 0x44, 0xE6, 0xA3, 0x58, 0x85, 0xE4, 0x3B, 0xC6, 0x5D, 0xE8, 0xAE, 0x39, 0x33, 0xB2, + 0x83, 0x7E, 0xE4, 0xF0, 0xDC, 0x4F, 0xEC, 0x16, 0xA7, 0x18, 0x9C, 0x27, 0xB4, 0x61, 0x99, 0xC0, 0x82, 0xA4, 0x0E, 0xEB, 0x23, 0xE7, 0x2B, 0x39, 0x90, 0x3B, + 0x3C, 0xD2, 0x64, 0x4A, 0x58, 0xC0, 0xA5, 0x93, 0x34, 0x31, 0xFF, 0x14, 0x8C, 0x68, 0x54, 0x96, 0xFD, 0xA7, 0x09, 0x81, 0x48, 0x04, 0x25, 0xF1, 0xA2, 0xCE, + 0x2B, 0x53, 0x43, 0x26, 0x3C, 0x81, 0xE0, 0x44, 0x62, 0x19, 0x96, 0x0B, 0x04, 0x43, 0x58, 0xDA, 0x38, 0xC4, 0xB2, 0x10, 0xDD, 0x9C, 0x7B, 0x21, 0x74, 0x23, + 0x65, 0x31, 0x6C, 0x17, 0x0F, 0xF7, 0x31, 0x1D, 0x5E, 0x6A, 0x03, 0xEA, 0xAF, 0xD1, 0xF1, 0x06, 0xFA, 0x9F, 0x8B, 0x41, 0xD4, 0x1B, 0x37, 0xE7, 0x24, 0x24, + 0xB6, 0x07, 0x89, 0x94, 0xA8, 0x74, 0x48, 0x99, 0x05, 0x79, 0x3F, 0xAA, 0xE9, 0xD1, 0x23, 0x7E, 0x25, 0x53, 0x15, 0xEB, 0x71, 0x2E, 0xB2, 0x08, 0xCE, 0xA4, + 0x19, 0x9C, 0x87, 0x9D, 0x81, 0x11, 0x01, 0x57, 0x20, 0x08, 0xDD, 0x8A, 0xD9, 0xBB, 0x80, 0xB7, 0x49, 0xB2, 0xF0, 0xFF, 0xAD, 0xFE, 0x67, 0x64, 0xF5, 0x1F, + 0xCE, 0xC4, 0xD7, 0x8F, 0xC2, 0x89, 0x72, 0xFA, 0xB0, 0xE0, 0x1E, 0xE2, 0x85, 0xFA, 0xB8, 0x9F, 0x34, 0xDD, 0x89, 0x7C, 0x61, 0xDA, 0x40, 0x20, 0x9D, 0x48, + 0x16, 0xD1, 0x88, 0xC2, 0xF7, 0x14, 0xE0, 0xA6, 0x68, 0x77, 0xA7, 0x2D, 0xE6, 0x16, 0xB8, 0x3D, 0x26, 0x14, 0xA5, 0x4B, 0x32, 0xC3, 0x9C, 0x6D, 0x49, 0x49, + 0x1F, 0x56, 0xE7, 0x8A, 0x65, 0x0A, 0xC7, 0xA5, 0xE5, 0xB3, 0xDA, 0x2B, 0xAB, 0x8E, 0x9E, 0xE9, 0x2E, 0x3B, 0x03, 0x64, 0x88, 0x9F, 0xF2, 0x7E, 0x8E, 0xC7, + 0xC4, 0x71, 0xAD, 0x51, 0xC0, 0x32, 0xFE, 0x98, 0xE6, 0x3A, 0x68, 0x95, 0x02, 0xE6, 0x6E, 0x5E, 0x1A, 0xB2, 0x30, 0xA5, 0x0D, 0x8C, 0xAC, 0x9A, 0x8C, 0x12, + 0xE9, 0xBF, 0xE7, 0x86, 0xBB, 0x74, 0x1C, 0xC8, 0x20, 0x35, 0x01, 0x32, 0xA8, 0xDE, 0xD5, 0x9A, 0xE8, 0xFF, 0x5C, 0x7B, 0x16, 0x63, 0x9E, 0xA2, 0xC0, 0xCE, + 0x4E, 0x1A, 0x1A, 0x4D, 0x32, 0x08, 0x37, 0x3E, 0xAE, 0x4D, 0xE4, 0xC7, 0xCC, 0x0A, 0x66, 0x6E, 0x92, 0x7E, 0x56, 0xA2, 0x84, 0xCE, 0xFA, 0x51, 0x8A, 0xF0, + 0x8A, 0x8F, 0x03, 0x44, 0xF0, 0x5C, 0x33, 0x22, 0x10, 0x3F, 0xA9, 0x2F, 0x17, 0x8D, 0x7D, 0xCE, 0xA5, 0xBE, 0xC3, 0xE4, 0x19, 0x5E, 0xBB, 0xA0, 0x3F, 0x09, + 0x73, 0x92, 0x90, 0x0E, 0x11, 0x64, 0x20, 0xE2, 0x28, 0x26, 0x05, 0x22, 0x35, 0x2C, 0x83, 0x37, 0xB7, 0x50, 0x04, 0x8F, 0x4E, 0xB3, 0x91, 0x27, 0xEA, 0xA8, + 0x4F, 0x30, 0xE4, 0x95, 0x03, 0x0C, 0x9D, 0xB8, 0xA3, 0x74, 0xED, 0x79, 0xDF, 0x80, 0x67, 0x2C, 0x00, 0xC2, 0x2B, 0xC8, 0x03, 0x29, 0xC5, 0x3C, 0x3A, 0xCE, + 0x54, 0x43, 0x10, 0x0E, 0xEE, 0x7A, 0x44, 0xA4, 0xE0, 0xB5, 0xE2, 0xB2, 0x10, 0x94, 0x91, 0xD9, 0xCB, 0x98, 0x03, 0x37, 0xC4, 0xA3, 0xD7, 0x23, 0x98, 0xC8, + 0xFA, 0x86, 0xE6, 0xEE, 0x63, 0xC8, 0x71, 0x42, 0xDA, 0xA9, 0xCC, 0x05, 0x95, 0x55, 0xEE, 0x8B, 0xAE, 0x2F, 0xE9, 0xF7, 0x12, 0xF1, 0xBA, 0xA7, 0x9E, 0xE0, + 0x90, 0xBA, 0x01, 0xAD, 0xBD, 0x5E, 0xB3, 0x13, 0x28, 0x81, 0x29, 0x26, 0x5B, 0xB3, 0x40, 0x97, 0xA3, 0xB9, 0x9D, 0x8C, 0x28, 0x12, 0x80, 0x6D, 0x4C, 0xFA, + 0x35, 0xE8, 0x4F, 0x54, 0xDD, 0x13, 0xF6, 0x8B, 0xBB, 0xDA, 0x00, 0x94, 0x0A, 0x92, 0xF3, 0x63, 0xF3, 0x3D, 0xE7, 0x39, 0xE6, 0x1B, 0x29, 0xF4, 0x4D, 0x0C, + 0xCE, 0x4C, 0xC9, 0x08, 0x10, 0x62, 0x2E, 0x91, 0x83, 0x48, 0xCF, 0x26, 0x46, 0x33, 0x78, 0x69, 0xCF, 0x5C, 0x9D, 0xC2, 0xFA, 0xD5, 0x67, 0x28, 0x07, 0x04, + 0xB0, 0x96, 0xF7, 0xAB, 0x3F, 0x38, 0x88, 0x3B, 0x63, 0x02, 0xDD, 0x0F, 0x66, 0xCC, 0xE2, 0x13, 0x05, 0x98, 0x2A, 0x3C, 0xC5, 0xAD, 0xCC, 0xEC, 0xE1, 0xDD, + 0xAF, 0xB1, 0x84, 0xC4, 0x5D, 0x47, 0xE5, 0xE0, 0x81, 0x4F, 0x32, 0x97, 0x8F, 0x1B, 0x84, 0xBB, 0xAD, 0x09, 0x15, 0xC5, 0x1A, 0x87, 0x1C, 0xE2, 0xD1, 0xE4, + 0xDF, 0xC2, 0x1B, 0xC9, 0x88, 0x29, 0x3C, 0x6F, 0x3E, 0xEC, 0x01, 0x07, 0xAC, 0xC8, 0x80, 0x09, 0x1E, 0xD1, 0xE0, 0x46, 0x90, 0x29, 0x45, 0x61, 0xD1, 0x18, + 0xD9, 0x96, 0xEA, 0x19, 0x58, 0xD9, 0xAB, 0xC7, 0xB4, 0xF8, 0x2D, 0xC0, 0x60, 0x45, 0x14, 0x96, 0x53, 0x92, 0x59, 0x18, 0x54, 0x81, 0x02, 0x20, 0x45, 0xA2, + 0x22, 0x32, 0xA5, 0x77, 0x16, 0x4B, 0x7A, 0x95, 0x8E, 0xB5, 0x22, 0x6B, 0x1C, 0x0D, 0x49, 0x04, 0xE3, 0xD8, 0x3F, 0xB8, 0xC8, 0xFC, 0x53, 0xC6, 0x45, 0x14, + 0x3B, 0x14, 0x5D, 0xD6, 0x42, 0x27, 0x37, 0xE4, 0xAB, 0x40, 0xE5, 0x1E, 0x9D, 0x5F, 0x65, 0xEC, 0xC7, 0xE1, 0xC1, 0xC5, 0xCC, 0x0D, 0xFA, 0x54, 0x0F, 0x4D, + 0x3F, 0xC2, 0x4B, 0x8F, 0xC1, 0x14, 0xF2, 0x68, 0xBD, 0xB3, 0x42, 0x72, 0x09, 0xE9, 0x12, 0xEA, 0x7A, 0x65, 0x33, 0xF2, 0xAE, 0x4A, 0x02, 0x95, 0xB4, 0x3A, + 0x80, 0xD3, 0x2B, 0x29, 0x40, 0xAB, 0x10, 0xC4, 0x6A, 0x90, 0xCA, 0x92, 0xC9, 0xCA, 0x11, 0x05, 0x06, 0x5F, 0x16, 0x52, 0x6F, 0xB6, 0x82, 0x67, 0x4D, 0x15, + 0x25, 0xA8, 0xD5, 0x65, 0x53, 0x9B, 0xB9, 0x95, 0xF2, 0x5C, 0x73, 0xAB, 0x8B, 0xAB, 0xAB, 0x48, 0xD4, 0xDA, 0xB1, 0x28, 0xA5, 0x46, 0x08, 0x39, 0x5E, 0xFA, + 0xA2, 0x14, 0x8D, 0xFA, 0xA3, 0xB2, 0x82, 0xF1, 0xE9, 0x03, 0x28, 0xA7, 0xB4, 0xD8, 0x5B, 0x88, 0x5D, 0xE8, 0x19, 0x43, 0x82, 0xE5, 0xE0, 0x88, 0x3E, 0xC2, + 0x8C, 0x79, 0x8B, 0x8E, 0x74, 0x5A, 0x54, 0xEA, 0xA4, 0xA7, 0x18, 0xD4, 0xDD, 0xEC, 0x64, 0xE1, 0xD5, 0x98, 0x1F, 0xDD, 0xD2, 0xD6, 0x40, 0xBC, 0xEE, 0x63, + 0x41, 0x8C, 0x30, 0xE7, 0xF1, 0x42, 0x11, 0xB2, 0x36, 0x74, 0xF9, 0xAB, 0xA8, 0x93, 0xBA, 0xDF, 0x94, 0x54, 0x08, 0x29, 0x2B, 0xC3, 0xC5, 0x5B, 0x64, 0x51, + 0x49, 0x42, 0x3C, 0x42, 0x43, 0x03, 0xB2, 0xE3, 0xF2, 0x24, 0x00, 0x0A, 0xC1, 0x27, 0x12, 0x53, 0x60, 0x56, 0x13, 0x32, 0x49, 0x3B, 0x96, 0x46, 0x5E, 0xE9, + 0x8B, 0xC4, 0x2A, 0xA3, 0xE7, 0x1F, 0xC7, 0x23, 0x74, 0x3F, 0xAF, 0xA1, 0x3E, 0xD0, 0xD7, 0xEB, 0xCE, 0x2E, 0xFA, 0xA0, 0xE2, 0xE6, 0x08, 0x72, 0x25, 0xB2, + 0x53, 0x17, 0x09, 0x6E, 0xE8, 0xF5, 0xD0, 0x52, 0xF4, 0xD1, 0x83, 0x53, 0x45, 0xFE, 0x82, 0x8F, 0x38, 0xC8, 0x6D, 0x2E, 0x22, 0x2C, 0x39, 0xEA, 0x19, 0xD2, + 0x0A, 0xBF, 0x31, 0x05, 0x20, 0x31, 0xE1, 0x39, 0x64, 0x33, 0xAE, 0xA1, 0x22, 0x17, 0x51, 0x86, 0x18, 0xF7, 0x58, 0x0F, 0x0A, 0x30, 0xA7, 0x85, 0x45, 0x63, + 0xD3, 0xBD, 0x32, 0x03, 0x55, 0xDE, 0xC7, 0x80, 0x15, 0x32, 0x29, 0xF2, 0x1D, 0xAC, 0xF7, 0xA2, 0x0C, 0x2D, 0x29, 0xBB, 0xE2, 0x5F, 0x9F, 0xEF, 0xC4, 0x20, + 0xD7, 0x9E, 0xD8, 0xC7, 0xFF, 0xA4, 0x6E, 0x8B, 0x07, 0xBF, 0x46, 0xF7, 0xC5, 0x3F, 0x91, 0x21, 0xAE, 0x85, 0x1E, 0xB5, 0xDA, 0x37, 0x17, 0x0B, 0xCC, 0xB0, + 0xBF, 0x9A, 0xD9, 0x8E, 0xD5, 0x11, 0x45, 0xE3, 0xB5, 0x27, 0xC0, 0x8C, 0x56, 0x51, 0xF1, 0x75, 0x0E, 0x12, 0x2A, 0x14, 0x91, 0xAF, 0xAC, 0xC2, 0xEA, 0xA0, + 0xF6, 0x00, 0x43, 0x35, 0x59, 0xA5, 0x48, 0xEA, 0x5B, 0x38, 0x04, 0xED, 0x1B, 0x5A, 0x06, 0xC7, 0x39, 0xD9, 0x3D, 0xE8, 0x1E, 0xC8, 0x0C, 0x21, 0x3C, 0x9D, + 0x88, 0x5A, 0x04, 0x97, 0x96, 0x0B, 0xFD, 0xF4, 0x03, 0xC9, 0xB8, 0x84, 0x1B, 0x7A, 0x90, 0x2F, 0x4A, 0xEA, 0xB4, 0xF9, 0x3A, 0xBA, 0xFD, 0xDF, 0x16, 0x34, + 0xFB, 0x1A, 0xD9, 0x78, 0x85, 0x8C, 0xB4, 0x44, 0x8E, 0x48, 0x25, 0xB2, 0x47, 0x19, 0x38, 0x50, 0x24, 0xBB, 0x30, 0xD2, 0x24, 0xA9, 0x91, 0x9E, 0xA7, 0x8A, + 0x46, 0x0B, 0xE8, 0xA8, 0x38, 0xB5, 0xE4, 0x6B, 0x8C, 0xF8, 0xFE, 0xCE, 0x4C, 0x1F, 0xFC, 0xD8, 0x33, 0x3A, 0xD8, 0x56, 0xB0, 0xD7, 0xE1, 0xE9, 0xEF, 0xD1, + 0x9C, 0x59, 0x67, 0x77, 0xEF, 0x70, 0x77, 0x97, 0x1E, 0xAC, 0x3E, 0x66, 0x9D, 0xDE, 0x20, 0xCA, 0x82, 0x1F, 0x9E, 0x47, 0x54, 0x52, 0x7C, 0xFF, 0xAD, 0x87, + 0x67, 0x08, 0x97, 0x65, 0x78, 0x6F, 0xBB, 0xD4, 0x0D, 0x96, 0x65, 0xB9, 0x64, 0x20, 0xAC, 0x95, 0xCB, 0xD2, 0xE2, 0xEB, 0xFE, 0xA2, 0xC1, 0x17, 0x5F, 0x0E, + 0x05, 0x7F, 0x5B, 0xF1, 0xB4, 0xA5, 0xB3, 0x87, 0x35, 0x50, 0x9E, 0x8F, 0x1B, 0x6A, 0x28, 0x43, 0x92, 0x3B, 0x71, 0xA7, 0xE4, 0xF0, 0x3B, 0xC7, 0xFF, 0x8C, + 0xAD, 0x91, 0x0E, 0x4A, 0x2E, 0xAC, 0x5C, 0xC7, 0x07, 0xD4, 0x3A, 0x37, 0xA5, 0xCE, 0x60, 0x3A, 0xF6, 0x9A, 0x1D, 0x76, 0xA6, 0x1D, 0xBF, 0x57, 0x4B, 0xA8, + 0xE7, 0x3C, 0x32, 0x86, 0x22, 0x8D, 0xC6, 0x60, 0xB1, 0xD5, 0xC6, 0x98, 0xAC, 0xAC, 0x2B, 0xC1, 0x6D, 0xA5, 0xF3, 0x91, 0x03, 0xB8, 0x8A, 0x02, 0xCA, 0x71, + 0xBB, 0x4A, 0x59, 0x65, 0x60, 0x58, 0xDA, 0x59, 0x67, 0x0F, 0x88, 0xE5, 0x20, 0x00, 0x35, 0xDF, 0x72, 0x35, 0x6E, 0x21, 0xDB, 0x8F, 0x7C, 0x82, 0x00, 0x64, + 0xAF, 0xA8, 0x90, 0x1C, 0x33, 0x29, 0xD6, 0xAA, 0x60, 0xA4, 0x9B, 0x1F, 0xE5, 0x66, 0xCC, 0x58, 0xD1, 0xE8, 0x36, 0x3F, 0xB2, 0x8D, 0xCD, 0x1B, 0x68, 0x1D, + 0x1D, 0xBC, 0x9D, 0x90, 0x90, 0x95, 0xD3, 0x9B, 0xA9, 0xF4, 0x8E, 0x46, 0xF8, 0x15, 0x25, 0xD4, 0xF3, 0xC1, 0x05, 0xB9, 0x58, 0x4D, 0x72, 0x31, 0x49, 0x2E, + 0x2A, 0x90, 0x0C, 0x2F, 0xAB, 0xC3, 0x0D, 0xB1, 0xFC, 0xFF, 0xF2, 0x32, 0x69, 0xD9, 0xF5, 0xA8, 0x14, 0x4F, 0x39, 0x9C, 0x57, 0x9A, 0x57, 0x5E, 0x20, 0xF5, + 0x10, 0x11, 0xD1, 0xAC, 0xEB, 0x51, 0xBD, 0x66, 0x45, 0xE1, 0x00, 0x2A, 0x90, 0x34, 0x4B, 0x1F, 0x34, 0x88, 0x9A, 0xF2, 0x9A, 0x85, 0x72, 0x07, 0x9B, 0xE9, + 0x5A, 0x46, 0xFC, 0xD8, 0xDB, 0x18, 0xD9, 0x38, 0xA5, 0x0C, 0xE7, 0x38, 0x93, 0xF0, 0xBC, 0xE2, 0xBF, 0xB5, 0xD0, 0x8E, 0x73, 0x27, 0x22, 0x9C, 0x00, 0x88, + 0x42, 0x15, 0x98, 0x5B, 0x48, 0x07, 0x9C, 0x84, 0x0F, 0x6F, 0x71, 0xEC, 0x33, 0x9E, 0xBA, 0x9A, 0x01, 0x87, 0x56, 0x7A, 0x53, 0x17, 0x90, 0x52, 0x79, 0x84, + 0xA8, 0x0A, 0x6B, 0x11, 0xAF, 0x29, 0x96, 0x2B, 0x88, 0xC5, 0x3F, 0xF1, 0xC0, 0x71, 0x1C, 0x4C, 0x11, 0xCE, 0x9D, 0xE1, 0x17, 0xFF, 0x06, 0x6E, 0xDA, 0x6F, + 0xC1, 0x5F, 0xA4, 0x00, 0x00 }; -//File: index_ov3660.html.gz, Size: 8887 -#define index_ov3660_html_gz_len 8887 -const uint8_t index_ov3660_html_gz[] = { - 0x1F, 0x8B, 0x08, 0x08, 0xA3, 0xFA, 0x69, 0x5E, 0x00, 0x03, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x6F, 0x76, 0x33, 0x36, 0x36, 0x30, 0x2E, 0x68, 0x74, 0x6D, - 0x6C, 0x00, 0xED, 0x3D, 0x69, 0x73, 0xDB, 0x46, 0xB2, 0xDF, 0xFD, 0x2B, 0x60, 0x24, 0x6B, 0x51, 0x65, 0x91, 0xE2, 0xAD, 0x23, 0x12, 0xFD, 0x6C, 0x59, 0xB1, - 0x53, 0x1B, 0x67, 0xBD, 0x71, 0xE2, 0x24, 0xB5, 0xB5, 0xE5, 0x80, 0xC4, 0x90, 0x44, 0x0C, 0x02, 0x5C, 0x00, 0xD4, 0x91, 0x94, 0x7E, 0xC7, 0xFB, 0x41, 0xEF, - 0x8F, 0xBD, 0xEE, 0x39, 0x70, 0x71, 0x00, 0x0C, 0x00, 0x11, 0x52, 0xF2, 0x1E, 0x5D, 0x65, 0xE1, 0x98, 0xEE, 0xE9, 0x7B, 0x7A, 0x7A, 0x06, 0xC0, 0xD9, 0x53, - 0xD3, 0x9D, 0x05, 0xB7, 0x6B, 0xA2, 0x2D, 0x83, 0x95, 0x3D, 0x79, 0x72, 0xC6, 0xFE, 0x68, 0xF0, 0x3B, 0x5B, 0x12, 0xC3, 0x64, 0x87, 0xF4, 0x74, 0x45, 0x02, - 0x43, 0x9B, 0x2D, 0x0D, 0xCF, 0x27, 0xC1, 0xB9, 0xBE, 0x09, 0xE6, 0xED, 0x63, 0x3D, 0x7D, 0xDB, 0x31, 0x56, 0xE4, 0x5C, 0xBF, 0xB2, 0xC8, 0xF5, 0xDA, 0xF5, - 0x02, 0x5D, 0x9B, 0xB9, 0x4E, 0x40, 0x1C, 0x68, 0x7E, 0x6D, 0x99, 0xC1, 0xF2, 0xDC, 0x24, 0x57, 0xD6, 0x8C, 0xB4, 0xE9, 0xC9, 0x81, 0xE5, 0x58, 0x81, 0x65, - 0xD8, 0x6D, 0x7F, 0x66, 0xD8, 0xE4, 0xBC, 0x17, 0xC7, 0x15, 0x58, 0x81, 0x4D, 0x26, 0x97, 0x1F, 0xDE, 0x0F, 0xFA, 0xDA, 0x3F, 0x3E, 0x0E, 0xC6, 0xE3, 0xEE, - 0xD9, 0x21, 0xBB, 0x16, 0xB5, 0xF1, 0x83, 0xDB, 0xF8, 0x39, 0xFE, 0xA6, 0xAE, 0x79, 0xAB, 0xFD, 0x91, 0xB8, 0x84, 0xBF, 0x39, 0x10, 0xD1, 0x9E, 0x1B, 0x2B, - 0xCB, 0xBE, 0x3D, 0xD5, 0x5E, 0x7A, 0xD0, 0xE7, 0xC1, 0x5B, 0x62, 0x5F, 0x91, 0xC0, 0x9A, 0x19, 0x07, 0xBE, 0xE1, 0xF8, 0x6D, 0x9F, 0x78, 0xD6, 0xFC, 0xAB, - 0x2D, 0xC0, 0xA9, 0x31, 0xFB, 0xBC, 0xF0, 0xDC, 0x8D, 0x63, 0x9E, 0x6A, 0x5F, 0xF4, 0x8E, 0xF1, 0xDF, 0x76, 0xA3, 0x99, 0x6B, 0xBB, 0x1E, 0xDC, 0xBF, 0xFC, - 0x1A, 0xFF, 0x6D, 0xDF, 0xA7, 0xBD, 0xFB, 0xD6, 0xEF, 0xE4, 0x54, 0xEB, 0x8D, 0xD7, 0x37, 0x89, 0xFB, 0x77, 0x4F, 0x12, 0xA7, 0xCB, 0x7E, 0x16, 0xF5, 0x1C, - 0xFE, 0x38, 0x1F, 0xDE, 0x27, 0xB3, 0xC0, 0x72, 0x9D, 0xCE, 0xCA, 0xB0, 0x1C, 0x09, 0x26, 0xD3, 0xF2, 0xD7, 0xB6, 0x01, 0x32, 0x98, 0xDB, 0x24, 0x17, 0xCF, - 0x17, 0x2B, 0xE2, 0x6C, 0x0E, 0x0A, 0xB0, 0x21, 0x92, 0xB6, 0x69, 0x79, 0xAC, 0xD5, 0x29, 0xCA, 0x61, 0xB3, 0x72, 0x0A, 0xD1, 0xE6, 0xD1, 0xE5, 0xB8, 0x0E, - 0x91, 0x08, 0x10, 0x3B, 0xBA, 0xF6, 0x8C, 0x35, 0x36, 0xC0, 0xBF, 0xDB, 0x4D, 0x56, 0x96, 0xC3, 0x8C, 0xEA, 0x54, 0x1B, 0x0C, 0xBB, 0xEB, 0x9B, 0x02, 0x55, - 0x0E, 0xC6, 0xF8, 0x6F, 0xBB, 0xD1, 0xDA, 0x30, 0x4D, 0xCB, 0x59, 0x9C, 0x6A, 0xC7, 0x52, 0x14, 0xAE, 0x67, 0x12, 0xAF, 0xED, 0x19, 0xA6, 0xB5, 0xF1, 0x4F, - 0xB5, 0xA1, 0xAC, 0xCD, 0xCA, 0xF0, 0x16, 0x40, 0x4B, 0xE0, 0x02, 0xB1, 0xED, 0x9E, 0x94, 0x12, 0xDE, 0xC4, 0xB3, 0x16, 0xCB, 0x00, 0x54, 0xBA, 0xD5, 0x26, - 0x2D, 0x34, 0xEE, 0x42, 0x45, 0xFA, 0xCC, 0x95, 0x9B, 0x5C, 0x6A, 0x86, 0x6D, 0x2D, 0x9C, 0xB6, 0x15, 0x90, 0x15, 0xB0, 0xE3, 0x07, 0x1E, 0x09, 0x66, 0xCB, - 0x3C, 0x52, 0xE6, 0xD6, 0x62, 0xE3, 0x11, 0x09, 0x21, 0xA1, 0xDC, 0x72, 0x18, 0x86, 0x9B, 0xDB, 0xB7, 0xDA, 0xD7, 0x64, 0xFA, 0xD9, 0x0A, 0xDA, 0x5C, 0x26, - 0x53, 0x32, 0x77, 0x3D, 0x22, 0x6D, 0x29, 0x5A, 0xD8, 0xEE, 0xEC, 0x73, 0xDB, 0x0F, 0x0C, 0x2F, 0x50, 0x41, 0x68, 0xCC, 0x03, 0xE2, 0x15, 0xE3, 0x23, 0x68, - 0x15, 0xC5, 0xD8, 0xB2, 0xBB, 0xE5, 0x0D, 0x2C, 0xC7, 0xB6, 0x1C, 0xA2, 0x4E, 0x5E, 0x56, 0xBF, 0x49, 0x74, 0xAC, 0x95, 0x82, 0x62, 0xAC, 0xD5, 0x22, 0xCF, - 0x4A, 0x28, 0xAF, 0xDB, 0x9D, 0x71, 0xBF, 0xE9, 0x75, 0xBB, 0x7F, 0xDB, 0xBE, 0xB9, 0x24, 0xCC, 0x4C, 0x8D, 0x4D, 0xE0, 0xD6, 0xF7, 0x88, 0x2D, 0xB7, 0x4A, - 0xF1, 0xF1, 0x5F, 0x2B, 0x62, 0x5A, 0x86, 0xD6, 0x8A, 0xB9, 0xF3, 0x71, 0x17, 0x6C, 0x6A, 0x5F, 0x33, 0x1C, 0x53, 0x6B, 0xB9, 0x9E, 0x05, 0x8E, 0x60, 0xD0, - 0x70, 0x63, 0xC3, 0x15, 0x18, 0x38, 0xD6, 0x64, 0x5F, 0xC2, 0x72, 0x8E, 0xCF, 0xC4, 0x25, 0x22, 0x77, 0x1B, 0xFC, 0x29, 0x84, 0x1C, 0xFC, 0x15, 0x3A, 0x90, - 0x84, 0x47, 0x8A, 0x3E, 0x4F, 0x5F, 0x71, 0x0A, 0xB3, 0x74, 0x86, 0xBF, 0x95, 0x71, 0xD3, 0xCE, 0xD5, 0x9D, 0x68, 0x24, 0x74, 0x08, 0xC3, 0xEC, 0xAC, 0x05, - 0x4D, 0xAF, 0x96, 0x5A, 0x5B, 0xC3, 0x28, 0xB9, 0x2F, 0x87, 0xE1, 0x48, 0xE5, 0x2A, 0xC7, 0x5F, 0xDC, 0x28, 0x4A, 0xB0, 0x2B, 0x67, 0x35, 0x8A, 0x1D, 0xEC, - 0x9F, 0xCC, 0x86, 0x18, 0x27, 0x99, 0x51, 0x04, 0x7F, 0xEA, 0x91, 0x24, 0x42, 0x56, 0x18, 0x4D, 0x24, 0x88, 0xB3, 0x23, 0xCA, 0x16, 0xDE, 0x2C, 0xEF, 0x96, - 0x60, 0xCD, 0x27, 0x41, 0x35, 0xBA, 0x48, 0x10, 0xE7, 0xD1, 0x50, 0x18, 0x65, 0xF0, 0x77, 0xA7, 0x90, 0x6F, 0x7C, 0x31, 0xDD, 0x04, 0x81, 0xEB, 0xF8, 0xB5, - 0x86, 0xA8, 0x2C, 0x3F, 0xFB, 0x6D, 0xE3, 0x07, 0xD6, 0xFC, 0xB6, 0xCD, 0x5D, 0x1A, 0xFC, 0x6C, 0x6D, 0x40, 0x0A, 0x39, 0x25, 0xC1, 0x35, 0x21, 0xF9, 0xE9, - 0x86, 0x63, 0x5C, 0x41, 0xDC, 0x59, 0x2C, 0x6C, 0x99, 0xED, 0xCD, 0x36, 0x9E, 0x8F, 0x79, 0xDB, 0xDA, 0xB5, 0x00, 0xB1, 0xB7, 0xDD, 0x71, 0xD2, 0x07, 0x15, - 0x3B, 0x6A, 0xCF, 0xA6, 0x92, 0xBE, 0xDC, 0x4D, 0x80, 0x32, 0x96, 0x6A, 0xC2, 0x05, 0x76, 0xAC, 0xE0, 0x56, 0x7A, 0x8F, 0x7B, 0xA2, 0xE4, 0x8E, 0x70, 0xC1, - 0xDC, 0x61, 0x21, 0x49, 0xD7, 0xE9, 0x6C, 0x49, 0x66, 0x9F, 0x89, 0xF9, 0xBC, 0x30, 0x0D, 0x2B, 0x4A, 0x0F, 0x3B, 0x96, 0xB3, 0xDE, 0x04, 0x6D, 0x4C, 0xA7, - 0xD6, 0x3B, 0xD1, 0x39, 0x35, 0x48, 0xC1, 0x62, 0xBF, 0x9F, 0x97, 0x54, 0x8C, 0xD6, 0x37, 0xF9, 0x42, 0x88, 0x13, 0x3B, 0xB1, 0x8D, 0x29, 0xB1, 0xF3, 0x48, - 0xE6, 0xCE, 0x90, 0x11, 0x76, 0x79, 0xAC, 0xCA, 0xCE, 0xDD, 0x28, 0x65, 0xD1, 0xE0, 0x35, 0x3C, 0xFA, 0x9B, 0xB2, 0x1C, 0xE9, 0xF1, 0x41, 0xE2, 0x92, 0x4F, - 0x6C, 0x70, 0xB0, 0xAC, 0xD4, 0x1B, 0xDA, 0x5C, 0x03, 0x0D, 0xB9, 0x1D, 0x78, 0x86, 0xB3, 0x20, 0x10, 0x0B, 0x6E, 0x0E, 0xC4, 0x61, 0xFE, 0xC4, 0x40, 0x89, - 0x7D, 0x0C, 0xD5, 0xA3, 0xFC, 0x89, 0x08, 0x0B, 0x08, 0x07, 0x5A, 0x87, 0x1D, 0x54, 0xC8, 0x4A, 0x62, 0xFA, 0xCD, 0x25, 0xA4, 0x27, 0xB5, 0x0E, 0x96, 0x98, - 0x48, 0x3D, 0x27, 0x69, 0x5B, 0xD2, 0x44, 0xBF, 0x30, 0x34, 0x88, 0x29, 0xDF, 0x7C, 0x5E, 0x34, 0x69, 0x9C, 0xCF, 0x07, 0xDD, 0xC1, 0xB0, 0x30, 0x73, 0x92, - 0x72, 0x99, 0x9A, 0x38, 0x4A, 0x42, 0x47, 0x18, 0x56, 0x72, 0x8D, 0xC0, 0x37, 0xAE, 0xA4, 0x49, 0xBB, 0xEB, 0x5B, 0x6C, 0xE6, 0x66, 0x4C, 0x7D, 0x98, 0xBB, - 0x05, 0x92, 0xA9, 0x17, 0x37, 0xF4, 0xBE, 0x94, 0x3E, 0x9A, 0xD2, 0x49, 0x5D, 0x40, 0x88, 0x57, 0x4E, 0x76, 0x42, 0x03, 0xF2, 0x26, 0x31, 0x05, 0x4B, 0x93, - 0xCA, 0x80, 0xDC, 0x04, 0x6D, 0x93, 0xCC, 0x5C, 0x8F, 0x65, 0x83, 0x19, 0x33, 0xC7, 0x94, 0x22, 0x8B, 0x2D, 0xF6, 0x74, 0xE9, 0x5E, 0x11, 0x4F, 0x22, 0xAC, - 0x94, 0x52, 0x87, 0x27, 0x43, 0x53, 0x01, 0x9B, 0x01, 0xC3, 0xA3, 0x54, 0xF6, 0x49, 0x74, 0xFD, 0xDE, 0xAC, 0x9F, 0xEB, 0xC7, 0x0C, 0x5D, 0x07, 0x7C, 0xC6, - 0x98, 0xDA, 0xC4, 0xCC, 0x19, 0xCD, 0x4C, 0x32, 0x37, 0x36, 0x76, 0x50, 0x60, 0x95, 0x46, 0x17, 0xFF, 0xE5, 0xF5, 0x48, 0xC3, 0xD0, 0xBF, 0xB0, 0x2E, 0x74, - 0x4E, 0x03, 0xC7, 0xBF, 0x25, 0x7D, 0x8A, 0x54, 0xC3, 0x58, 0xAF, 0x89, 0x01, 0xAD, 0x66, 0x24, 0x4B, 0x0F, 0x4A, 0x53, 0x0C, 0x79, 0x9C, 0x57, 0x9A, 0xB7, - 0x17, 0x3A, 0x6C, 0x98, 0x3C, 0x96, 0xE2, 0xF9, 0x74, 0xEE, 0xCE, 0x36, 0xB2, 0xAC, 0x46, 0xCD, 0xF1, 0xB6, 0xF1, 0x9D, 0x0A, 0x91, 0xF9, 0xB6, 0x45, 0xDD, - 0x7F, 0xE3, 0x38, 0xA8, 0xD1, 0x76, 0xE0, 0x01, 0x9B, 0x92, 0x8E, 0xD4, 0x04, 0x57, 0x29, 0x86, 0x25, 0x04, 0x9B, 0x55, 0xBB, 0x4A, 0x85, 0x29, 0x49, 0x38, - 0x0D, 0x23, 0xAD, 0x06, 0x31, 0xC4, 0x32, 0x05, 0xAA, 0x7A, 0x72, 0x09, 0x96, 0x9B, 0x95, 0x2C, 0x8F, 0x12, 0x9D, 0xF5, 0x60, 0xD0, 0x67, 0xDD, 0x79, 0x8B, - 0xA9, 0xD1, 0xEA, 0x1E, 0x74, 0x0F, 0x06, 0xF0, 0x9F, 0x64, 0x3E, 0x93, 0x6F, 0x5C, 0x5C, 0xBC, 0x19, 0x96, 0x97, 0x0A, 0xD1, 0xC5, 0x65, 0xA5, 0xAC, 0x60, - 0x5F, 0xA8, 0x0B, 0x75, 0x4F, 0x4A, 0xD6, 0x97, 0x7A, 0x9D, 0x82, 0x71, 0x38, 0xC3, 0xA4, 0xCB, 0x1B, 0xA2, 0xC4, 0x5A, 0xCA, 0xAA, 0x78, 0xE5, 0xFE, 0xDE, - 0x66, 0x49, 0xC8, 0xFF, 0x79, 0x6B, 0x8F, 0x89, 0xE2, 0x2F, 0x6D, 0xE9, 0xA5, 0xE5, 0xE2, 0x3F, 0xB4, 0x6D, 0x74, 0xB3, 0xB5, 0xDE, 0xE6, 0x59, 0x1F, 0x50, - 0xE8, 0xC0, 0x1C, 0xD4, 0x83, 0xC9, 0x68, 0x66, 0x66, 0x18, 0x6B, 0x53, 0x41, 0x06, 0x73, 0xCB, 0xB6, 0xDB, 0xB6, 0x7B, 0x5D, 0x9C, 0x89, 0xE4, 0x5B, 0xF2, - 0x96, 0x9D, 0x16, 0x9B, 0x7C, 0x55, 0x6A, 0x37, 0x10, 0xB9, 0xFE, 0x14, 0xD4, 0xFE, 0xB5, 0x1D, 0x2E, 0xD7, 0x35, 0xAA, 0x0D, 0x14, 0x15, 0xEC, 0xB1, 0x5E, - 0x47, 0x4A, 0xA6, 0xC4, 0x32, 0xC1, 0xFC, 0x69, 0xCF, 0xB5, 0x15, 0xCC, 0x96, 0x15, 0xA6, 0x9E, 0xD1, 0xC4, 0xC8, 0x23, 0xB6, 0x81, 0x19, 0x7C, 0xA5, 0x0A, - 0x45, 0xE1, 0xF4, 0x2D, 0x0E, 0xAE, 0xC2, 0x09, 0x15, 0xDD, 0xE3, 0xA9, 0x2E, 0x75, 0x58, 0xEE, 0x90, 0x1D, 0xAB, 0xE5, 0x66, 0x5D, 0x90, 0xEE, 0x27, 0x3D, - 0x43, 0xDE, 0xA8, 0x44, 0x44, 0x17, 0x41, 0x7B, 0xE1, 0x91, 0x5B, 0x05, 0x66, 0x0E, 0xF8, 0xDF, 0x53, 0x56, 0x3F, 0xAE, 0x5E, 0x2A, 0xA1, 0x03, 0x00, 0xB7, - 0xA2, 0xCE, 0xD0, 0x57, 0xE8, 0x3A, 0xBB, 0x4B, 0x15, 0x7B, 0x0C, 0xAB, 0xA3, 0xBA, 0xAE, 0x10, 0x6E, 0x72, 0x86, 0x50, 0xB9, 0xA9, 0x8A, 0xD1, 0x57, 0x3E, - 0x9F, 0x27, 0xF3, 0x20, 0x63, 0xF1, 0x87, 0xE6, 0xA9, 0x83, 0xFC, 0xE8, 0xD6, 0x8E, 0x55, 0x53, 0x0A, 0x23, 0x47, 0x58, 0xC4, 0xCC, 0xB6, 0x3E, 0x29, 0x66, - 0x8C, 0x9E, 0xA5, 0x91, 0x67, 0xAB, 0x44, 0xA4, 0xCF, 0x54, 0xCD, 0xD0, 0x66, 0xC5, 0x87, 0x7C, 0x50, 0x0F, 0xF9, 0xB9, 0xD5, 0x1F, 0x4B, 0xD7, 0x56, 0x72, - 0x1A, 0xE7, 0x91, 0x96, 0x59, 0x05, 0xDC, 0x1E, 0xB2, 0x32, 0x27, 0xC8, 0xF1, 0x58, 0x24, 0x55, 0x54, 0xBE, 0x57, 0xE6, 0x45, 0x98, 0xED, 0x4A, 0x56, 0xAE, - 0xB1, 0x5B, 0x2B, 0x03, 0xD2, 0x5E, 0x34, 0x57, 0x03, 0x30, 0xCA, 0xF4, 0xA7, 0x62, 0xEE, 0xB1, 0x1A, 0x6B, 0x6F, 0xDC, 0x2D, 0xE8, 0x72, 0x66, 0xBB, 0x7E, - 0xCD, 0x02, 0x58, 0x76, 0xFD, 0x4B, 0x7A, 0x47, 0x69, 0xE8, 0xCE, 0xF5, 0xA9, 0x7C, 0x77, 0x4C, 0xC9, 0xBC, 0xD7, 0x95, 0x46, 0xDA, 0xDC, 0x2A, 0x25, 0xAD, - 0xA0, 0xD1, 0xF5, 0xCB, 0x53, 0x6D, 0x46, 0xE4, 0x61, 0x34, 0x59, 0xA8, 0x53, 0x29, 0x95, 0xE6, 0xEA, 0x61, 0x69, 0x99, 0x26, 0xC9, 0xAD, 0x05, 0xE3, 0x9C, - 0x57, 0x31, 0x79, 0x40, 0xFA, 0x65, 0x45, 0xA9, 0x9D, 0x38, 0x45, 0xEE, 0xB6, 0x86, 0xDE, 0xAE, 0x3D, 0x86, 0x0F, 0x34, 0x59, 0x95, 0xF4, 0x64, 0x2A, 0x92, - 0x4B, 0xAA, 0xD4, 0xB9, 0xC3, 0x5A, 0x2B, 0x8A, 0x0C, 0xE4, 0x80, 0xAD, 0xB6, 0xA3, 0x79, 0x8A, 0x2A, 0xBA, 0x90, 0xD2, 0xE1, 0x6B, 0x4B, 0x7C, 0x19, 0xB0, - 0x9D, 0xB5, 0xBA, 0x72, 0x8F, 0x4B, 0x6D, 0xD4, 0x02, 0xD2, 0xFD, 0x66, 0x8A, 0xE6, 0x81, 0x32, 0xA3, 0x1C, 0x22, 0xC3, 0x21, 0x46, 0x6C, 0xAE, 0x4A, 0xB6, - 0x2A, 0xEB, 0x1C, 0xE1, 0xF9, 0xD9, 0x61, 0x6C, 0x3B, 0xDC, 0xD9, 0x61, 0xB4, 0x73, 0xEF, 0x0C, 0xF7, 0xC4, 0xC5, 0x77, 0xCD, 0xF1, 0x8E, 0x66, 0xB6, 0xE1, - 0xFB, 0xE7, 0x3A, 0xEE, 0xED, 0xD2, 0x93, 0x9B, 0xE8, 0xCE, 0x4C, 0xEB, 0x4A, 0xB3, 0xCC, 0x73, 0xDD, 0x76, 0x17, 0x6E, 0xEA, 0x1E, 0xBD, 0xCF, 0xD4, 0x0C, - 0x03, 0xD9, 0xB9, 0x9E, 0x58, 0x60, 0xD4, 0x29, 0x54, 0x74, 0x49, 0x9F, 0x3C, 0xFB, 0xE2, 0xE4, 0xE8, 0x68, 0xFC, 0xD5, 0x33, 0x67, 0xEA, 0xAF, 0xF9, 0xFF, - 0x3F, 0xB0, 0xF5, 0x58, 0xB6, 0xA9, 0x0F, 0xC6, 0xB6, 0x20, 0x00, 0xDB, 0xF3, 0xCF, 0x0E, 0x29, 0xD2, 0x14, 0x21, 0x87, 0x40, 0x49, 0x06, 0x6D, 0x3C, 0xDF, - 0x91, 0x91, 0x27, 0x9A, 0xF8, 0x30, 0x84, 0x4F, 0x0D, 0x4F, 0xD2, 0x84, 0x36, 0x63, 0xD9, 0x34, 0x8D, 0x25, 0x3A, 0x55, 0xCA, 0xD4, 0xBD, 0x49, 0x73, 0x40, - 0x99, 0xE2, 0x1A, 0xE3, 0xAD, 0x88, 0x99, 0x85, 0x10, 0xC0, 0x28, 0x38, 0xAE, 0xAE, 0x42, 0x1B, 0x69, 0xA3, 0x84, 0x0A, 0xB0, 0xF1, 0xCD, 0xCC, 0xFE, 0x2C, - 0x94, 0xAF, 0x0B, 0xA5, 0x38, 0x6E, 0xC0, 0x62, 0x65, 0x46, 0x57, 0x09, 0x56, 0x39, 0x4C, 0x6C, 0xDD, 0x90, 0x71, 0x01, 0xA2, 0x6D, 0x53, 0xEC, 0xEC, 0x5A, - 0x3E, 0x26, 0x8A, 0x2D, 0xA6, 0x57, 0x01, 0xAC, 0x4F, 0x7E, 0xBE, 0xF8, 0xF6, 0xEF, 0xDA, 0xBB, 0xB7, 0xBF, 0x4B, 0x35, 0x54, 0x44, 0x14, 0x06, 0x69, 0x85, - 0x9E, 0x29, 0x18, 0xD3, 0x87, 0x90, 0x89, 0xCE, 0x35, 0x43, 0x31, 0xE0, 0x70, 0x6F, 0x13, 0x67, 0x11, 0x2C, 0xCF, 0xF5, 0x9E, 0x8E, 0x7B, 0x5A, 0xC4, 0x59, - 0x5F, 0xD7, 0x30, 0x80, 0xD3, 0x83, 0x2B, 0xC3, 0xDE, 0xE0, 0x51, 0x57, 0x85, 0xD7, 0x6D, 0xD3, 0x92, 0x36, 0xE3, 0x91, 0x25, 0x94, 0x71, 0x2C, 0x12, 0x27, - 0xA5, 0xAC, 0x4F, 0x3E, 0x90, 0xE0, 0xEC, 0x90, 0xDD, 0x2A, 0xD0, 0x5A, 0x7E, 0xDF, 0xE0, 0xC9, 0xCC, 0x1C, 0xF2, 0x4C, 0x28, 0x4F, 0xF1, 0x73, 0xCF, 0x58, - 0x11, 0x94, 0x8A, 0x92, 0xE6, 0xE3, 0x5A, 0x0F, 0x21, 0xF5, 0xC9, 0xF7, 0x84, 0x66, 0x44, 0x40, 0x86, 0x92, 0xE2, 0xCF, 0x78, 0x92, 0x9A, 0xE8, 0x3F, 0xB4, - 0x67, 0xBE, 0x28, 0xD5, 0x36, 0x98, 0x99, 0x2B, 0xC8, 0xFD, 0x69, 0xBB, 0xAD, 0x0D, 0xDE, 0xBD, 0xD7, 0xDA, 0x6D, 0x85, 0xC6, 0xEE, 0x9A, 0xBA, 0x13, 0xD7, - 0x7F, 0xEF, 0x48, 0x9F, 0xFC, 0xF3, 0xE7, 0x37, 0x2F, 0x5B, 0xFD, 0xEE, 0xF0, 0xF8, 0xA6, 0x37, 0x1A, 0x0F, 0xF7, 0xCF, 0x0E, 0x59, 0x93, 0xF2, 0xB8, 0xC6, - 0xFA, 0xE4, 0x3D, 0x12, 0xD2, 0x3A, 0x1E, 0x0F, 0xEB, 0xE2, 0x1A, 0x21, 0xAE, 0xB7, 0xAF, 0x5B, 0x47, 0xFD, 0xEE, 0x4D, 0xAF, 0x7F, 0xDC, 0xAD, 0x81, 0x6A, - 0xA8, 0x4F, 0xBE, 0x06, 0x4C, 0xBD, 0x13, 0x44, 0xD5, 0x2D, 0x87, 0x0A, 0x45, 0xDB, 0xAF, 0x28, 0xDA, 0x81, 0x3E, 0xF9, 0x11, 0x45, 0x0B, 0x39, 0x37, 0xF2, - 0xD0, 0xAD, 0xC3, 0x43, 0x1F, 0x5C, 0x86, 0xE2, 0x02, 0x51, 0x00, 0x13, 0xFD, 0x3A, 0xA2, 0xED, 0xE9, 0x13, 0x14, 0x07, 0x62, 0x02, 0xE9, 0xD6, 0x40, 0x04, - 0xB1, 0x83, 0xD2, 0x04, 0xE4, 0xDC, 0x1C, 0x8D, 0x8F, 0xAB, 0x63, 0x3A, 0x01, 0xEE, 0x3E, 0x02, 0xA6, 0x63, 0x10, 0xD4, 0xB8, 0x8E, 0x9C, 0x8E, 0xF5, 0x09, - 0xE2, 0x19, 0x0F, 0xBB, 0x37, 0xC3, 0x3A, 0x36, 0x03, 0x5E, 0xF1, 0x16, 0x11, 0x01, 0x92, 0x9B, 0x41, 0x1D, 0x19, 0x81, 0x4B, 0x5C, 0x7C, 0xF3, 0x75, 0x6B, - 0x08, 0x8C, 0xF5, 0x4F, 0xC6, 0xD5, 0xF1, 0x80, 0x3B, 0xFC, 0x13, 0x09, 0x02, 0x62, 0x6E, 0xFA, 0xC3, 0x1A, 0x04, 0x81, 0x33, 0x00, 0x3C, 0xE2, 0xA8, 0x8C, - 0x02, 0xEC, 0xFA, 0x2D, 0x25, 0x06, 0x11, 0xF5, 0x8E, 0x6A, 0x70, 0x05, 0x56, 0xFD, 0x4F, 0x14, 0x0F, 0x20, 0xB9, 0xE9, 0x0D, 0xEB, 0xD8, 0x34, 0x20, 0xA2, - 0x24, 0x81, 0xAF, 0xA1, 0xAB, 0x55, 0xC7, 0x04, 0x36, 0x7D, 0x32, 0xBE, 0x39, 0x19, 0xAB, 0x21, 0xC0, 0xE1, 0x07, 0x43, 0x79, 0xDE, 0x00, 0x95, 0x3F, 0x7E, - 0xE5, 0x8D, 0x4D, 0xFF, 0xD9, 0xC0, 0x94, 0x33, 0xB8, 0x2D, 0x3D, 0x32, 0x71, 0x38, 0x90, 0x09, 0x3B, 0x50, 0x1B, 0x94, 0x62, 0x94, 0x84, 0xBB, 0x9F, 0xF4, - 0xC9, 0x50, 0x61, 0xF0, 0x4F, 0x64, 0x87, 0x14, 0x36, 0x41, 0x3F, 0xCD, 0x48, 0xD0, 0xF2, 0x30, 0x17, 0x01, 0x97, 0x18, 0xE8, 0xB1, 0x08, 0x52, 0x69, 0xD4, - 0x93, 0xD0, 0x6A, 0xDC, 0xE8, 0x93, 0xF1, 0xA0, 0x30, 0x5B, 0xA8, 0xAE, 0x8C, 0x29, 0x2D, 0x6E, 0x38, 0xC4, 0xF7, 0x4B, 0xEB, 0x23, 0x02, 0xD5, 0x27, 0xAF, - 0xC2, 0xE3, 0x3A, 0x5A, 0x69, 0x17, 0x71, 0x4A, 0x61, 0x33, 0xD4, 0x12, 0x23, 0x87, 0x69, 0xA6, 0x3D, 0xE0, 0xAA, 0x89, 0x34, 0x73, 0xBF, 0x8A, 0xD9, 0xA5, - 0x5E, 0x70, 0x6E, 0xE3, 0x19, 0x7E, 0x50, 0x5A, 0x2B, 0x02, 0x10, 0x22, 0x34, 0x3F, 0x7A, 0x30, 0x8D, 0x84, 0xA4, 0xFC, 0x05, 0xF4, 0xE1, 0x1B, 0xC1, 0x86, - 0xED, 0x33, 0x2B, 0xAD, 0x91, 0x08, 0x14, 0xF2, 0x81, 0xF0, 0xB8, 0x96, 0x56, 0xEA, 0x84, 0xAF, 0x18, 0x39, 0x5C, 0x2F, 0x22, 0x84, 0x0D, 0x77, 0xA4, 0x97, - 0x22, 0x6A, 0x6B, 0xE9, 0x65, 0x69, 0x78, 0xEB, 0x4A, 0xE1, 0x2B, 0x84, 0x04, 0xAD, 0x88, 0xC3, 0x07, 0x73, 0x95, 0x88, 0x98, 0xBF, 0x80, 0xAF, 0x98, 0xC4, - 0x71, 0x2D, 0xBF, 0xFC, 0xD4, 0x93, 0xC3, 0xE9, 0x93, 0xD7, 0xA4, 0xFD, 0x1D, 0x1E, 0xD5, 0x51, 0xC7, 0xCB, 0x4D, 0xE0, 0xD6, 0x50, 0x88, 0xA0, 0x85, 0xA9, - 0xA3, 0xCB, 0xB5, 0x71, 0xBC, 0x23, 0x6D, 0x1C, 0xEF, 0x50, 0x1B, 0x06, 0xF9, 0x64, 0x93, 0x2B, 0x62, 0x97, 0x56, 0x87, 0x00, 0xD4, 0x27, 0x97, 0x37, 0x6B, - 0xD7, 0xC7, 0xA7, 0x77, 0xBE, 0xC5, 0xF3, 0x5A, 0x4E, 0x32, 0xAA, 0xA1, 0x93, 0x90, 0x20, 0xEE, 0x23, 0x23, 0xAE, 0x95, 0xD1, 0x8E, 0xB4, 0x52, 0x44, 0x6B, - 0x1D, 0xAD, 0x2C, 0x0C, 0xCB, 0x99, 0x11, 0xCB, 0xC6, 0x27, 0x09, 0xCA, 0x2A, 0x26, 0x06, 0xAB, 0x4F, 0xDE, 0x44, 0x27, 0x75, 0x14, 0xD3, 0xAD, 0xA1, 0x97, - 0x38, 0x3D, 0x49, 0x7F, 0x19, 0xC1, 0xAC, 0x7C, 0x47, 0xBA, 0xE9, 0xF5, 0x76, 0x39, 0xAA, 0xAC, 0xC9, 0xCC, 0x32, 0xEC, 0x4F, 0x64, 0x3E, 0x87, 0x69, 0x50, - 0xF9, 0xA1, 0x25, 0x01, 0x0E, 0xE3, 0x0B, 0x3B, 0xD7, 0x2E, 0xE9, 0x79, 0xE9, 0x62, 0x5A, 0x0A, 0x5D, 0xF5, 0x8A, 0x5A, 0x7A, 0x4E, 0xC8, 0x97, 0x95, 0x09, - 0xAD, 0x61, 0xB2, 0x23, 0x7D, 0xF2, 0x9D, 0x1B, 0xD2, 0x59, 0x7D, 0xDA, 0xFA, 0x1D, 0x59, 0xD0, 0x55, 0xDB, 0x3A, 0x73, 0xE8, 0x37, 0x9E, 0x71, 0x4B, 0x5F, - 0x0B, 0x50, 0x67, 0x4A, 0xFF, 0x3D, 0x31, 0xB5, 0x1F, 0x2C, 0xA7, 0x3A, 0x33, 0x43, 0x24, 0x84, 0x10, 0xA7, 0x1E, 0x96, 0x11, 0x4C, 0x91, 0xE0, 0xA0, 0x1E, - 0x92, 0x31, 0x16, 0x98, 0xD7, 0x96, 0xF1, 0x18, 0x26, 0xF1, 0xC6, 0xF5, 0xB4, 0xFC, 0x80, 0x72, 0x3D, 0x85, 0x71, 0xF9, 0xA7, 0x57, 0xDA, 0x25, 0xDD, 0x67, - 0x5C, 0x3A, 0x5C, 0xB1, 0x2D, 0x50, 0x2A, 0x86, 0x1E, 0xAD, 0x23, 0x60, 0x9F, 0x5B, 0x0B, 0x3C, 0x72, 0x07, 0x52, 0x5D, 0xE4, 0x91, 0xB0, 0x27, 0x08, 0xA4, - 0x3B, 0x46, 0xF4, 0x18, 0xB7, 0x6A, 0x3C, 0xEE, 0x30, 0x15, 0x9B, 0x5D, 0x97, 0x4F, 0xC3, 0x66, 0xD7, 0xA0, 0x26, 0xF3, 0x0A, 0xB7, 0xA0, 0x9B, 0x1A, 0xE8, - 0xAB, 0x11, 0x45, 0x61, 0xAF, 0x0F, 0xA3, 0x28, 0xCA, 0xEF, 0x43, 0x2B, 0x0A, 0xAC, 0xE5, 0x13, 0x8E, 0xA3, 0x55, 0x9C, 0x8A, 0x02, 0xEA, 0x93, 0x77, 0x86, - 0xB3, 0x81, 0x41, 0xA6, 0x29, 0x85, 0x85, 0x1D, 0x3F, 0x98, 0x7B, 0x71, 0xBE, 0x1F, 0x5A, 0x75, 0x40, 0xC8, 0xCA, 0x35, 0xCB, 0x4F, 0x77, 0x38, 0x1C, 0x0B, - 0x89, 0xEF, 0xE0, 0xA8, 0x74, 0x62, 0x20, 0x30, 0xEC, 0x38, 0x23, 0x60, 0x53, 0xA9, 0xEA, 0xC9, 0xC0, 0x87, 0x8D, 0xE3, 0xDC, 0xD6, 0xC9, 0x04, 0x2E, 0x6C, - 0x77, 0x63, 0x56, 0xC7, 0x00, 0x69, 0xC0, 0x3F, 0xE6, 0x73, 0x6B, 0x56, 0x3D, 0x91, 0x80, 0x24, 0xE0, 0xAD, 0xBB, 0x52, 0x84, 0xDF, 0xF1, 0xC0, 0x4B, 0x66, - 0x15, 0x66, 0x72, 0x33, 0xD0, 0xE2, 0xE5, 0x45, 0xA3, 0x03, 0x2F, 0xF4, 0xF9, 0x40, 0x91, 0x01, 0xB9, 0x7D, 0xE8, 0xA0, 0x00, 0x44, 0x7C, 0xA2, 0xC6, 0x53, - 0x45, 0x59, 0x0C, 0x32, 0x8C, 0xE8, 0x62, 0xFA, 0xFD, 0x50, 0xF3, 0xBB, 0x88, 0xA2, 0xE4, 0xEC, 0xAE, 0x37, 0x1A, 0x8C, 0xC3, 0xE9, 0xDD, 0xA0, 0x7F, 0xBF, - 0x13, 0x3C, 0x44, 0xBE, 0x5B, 0xFD, 0xF4, 0xAB, 0xA8, 0x06, 0xA2, 0xD1, 0x77, 0xB8, 0xCE, 0x50, 0x22, 0x60, 0xD7, 0x77, 0xA4, 0xFE, 0xC3, 0x79, 0x52, 0xFF, - 0x11, 0xB8, 0xD2, 0xA2, 0x42, 0xC4, 0x5B, 0x60, 0xC4, 0x7B, 0x73, 0xD1, 0x8C, 0x86, 0x16, 0x0F, 0x16, 0xEA, 0x16, 0x0F, 0x1A, 0xEA, 0x34, 0xBE, 0x43, 0x4D, - 0x48, 0xA1, 0x62, 0x06, 0xCB, 0x01, 0x59, 0x2D, 0xAB, 0x4E, 0x90, 0xEB, 0xDD, 0xD4, 0x89, 0x72, 0x82, 0x8C, 0x64, 0x90, 0x1B, 0x47, 0xAB, 0x22, 0xA3, 0xFB, - 0x5D, 0xD6, 0x1D, 0x16, 0x51, 0x5B, 0xC7, 0x69, 0x3C, 0xE3, 0xFA, 0xD3, 0x62, 0x65, 0x94, 0x56, 0x06, 0x87, 0x03, 0x5D, 0xBC, 0x7B, 0xD9, 0x64, 0xBA, 0x20, - 0xFA, 0x7D, 0x18, 0x3F, 0x0A, 0xB9, 0x7E, 0xE8, 0x58, 0x67, 0x13, 0xA7, 0x7C, 0xB0, 0x43, 0x20, 0x7D, 0xF2, 0x2D, 0x71, 0x7C, 0xED, 0xC2, 0xF5, 0xF8, 0xBB, - 0x18, 0x1B, 0xD1, 0x1A, 0xED, 0xF9, 0x61, 0x54, 0xC6, 0x98, 0x7E, 0x68, 0x7D, 0x2D, 0x57, 0x96, 0xE7, 0xB9, 0x5E, 0x69, 0x95, 0x71, 0x38, 0x98, 0x56, 0xB4, - 0xDF, 0xD1, 0xA3, 0x46, 0xD4, 0x25, 0x7A, 0x7D, 0x18, 0x8D, 0x85, 0x3C, 0x3F, 0xB4, 0xD2, 0xAE, 0xE6, 0xB6, 0xB5, 0x2E, 0xAD, 0x32, 0x0A, 0xA5, 0x4F, 0x3E, - 0xB6, 0xBF, 0x86, 0xBF, 0x8D, 0xA8, 0x8B, 0xF5, 0xF8, 0x30, 0xCA, 0xE2, 0xDC, 0x3E, 0xB4, 0xAA, 0xA6, 0xEB, 0xF2, 0xE1, 0x10, 0x60, 0xF4, 0xC9, 0xAB, 0xF7, - 0xCD, 0xE4, 0x7E, 0xD8, 0x99, 0xA2, 0x86, 0x6A, 0xE9, 0x83, 0x32, 0xF5, 0xD0, 0xDA, 0xB8, 0xAE, 0xA0, 0x8D, 0x6B, 0x24, 0xFC, 0xA7, 0x86, 0xB4, 0x71, 0xAD, - 0xAE, 0x8D, 0x7B, 0xF6, 0x97, 0xEB, 0xC7, 0xA0, 0x1F, 0xFA, 0xB0, 0xDF, 0xD4, 0x28, 0x3F, 0x1C, 0x09, 0x40, 0xDC, 0x34, 0x06, 0x47, 0xDA, 0x2B, 0xA3, 0x99, - 0x01, 0x29, 0xEC, 0xB7, 0x09, 0x17, 0x8A, 0x98, 0x7C, 0x68, 0x3D, 0xD9, 0xC4, 0xAC, 0x90, 0xE4, 0x99, 0x9F, 0xF0, 0xC9, 0x39, 0x7C, 0xA2, 0xFC, 0x16, 0xB2, - 0xBD, 0xCB, 0xD7, 0xDA, 0x37, 0xE2, 0xF4, 0xA1, 0x0A, 0x43, 0x49, 0x9A, 0x92, 0xF3, 0xA6, 0xFE, 0x68, 0x57, 0xDB, 0x32, 0x00, 0xF3, 0x0E, 0x75, 0x33, 0x37, - 0x66, 0xE4, 0x93, 0x49, 0x82, 0x2A, 0xEB, 0xFE, 0x31, 0x58, 0x7D, 0xF2, 0x35, 0x9C, 0x68, 0xAF, 0xE9, 0x49, 0x53, 0xE9, 0x78, 0xBC, 0xFF, 0x26, 0x3C, 0x2A, - 0xC1, 0xEF, 0x43, 0x3B, 0x15, 0x25, 0x06, 0x26, 0x3F, 0xEE, 0xC2, 0xA9, 0xF4, 0xDC, 0x53, 0x02, 0x9C, 0xAB, 0xEF, 0x7B, 0x76, 0xDE, 0xAC, 0x02, 0x23, 0x22, - 0x1A, 0xD3, 0x61, 0x8C, 0xEF, 0x26, 0xD4, 0x18, 0x7F, 0xF8, 0x91, 0xBF, 0x36, 0xB8, 0x48, 0x53, 0xFC, 0x21, 0x3C, 0xBA, 0xDD, 0x88, 0x04, 0x6D, 0x3F, 0xB0, - 0x6C, 0x5B, 0x9F, 0xBC, 0x21, 0x81, 0xF6, 0x01, 0x0F, 0x15, 0x9F, 0xBA, 0x8B, 0x61, 0x11, 0xCF, 0xDC, 0x06, 0x1E, 0x31, 0x56, 0xFA, 0xE4, 0x03, 0xBE, 0x50, - 0x19, 0x70, 0xE1, 0x59, 0x79, 0x64, 0x54, 0x88, 0xC4, 0xF1, 0x5C, 0x20, 0x2A, 0x54, 0x12, 0x7F, 0x51, 0xA3, 0xAE, 0x89, 0xA3, 0xD8, 0xB5, 0xC9, 0x25, 0x6D, - 0xAC, 0xA1, 0x95, 0x15, 0x77, 0x17, 0x7F, 0x1C, 0x30, 0xDF, 0x39, 0xE8, 0x03, 0xC0, 0xF8, 0x44, 0x6F, 0xF2, 0x7D, 0xEB, 0xA0, 0x56, 0xF6, 0x7C, 0xFF, 0xE4, - 0xCC, 0x5F, 0x1B, 0x8E, 0x68, 0x46, 0x1F, 0x7E, 0xBF, 0xE6, 0x4F, 0x33, 0x4F, 0x5D, 0xDB, 0xFC, 0x2A, 0xB6, 0xF0, 0xFF, 0x21, 0x7C, 0x2C, 0x17, 0x41, 0xC0, - 0x2E, 0x04, 0x86, 0x02, 0xE5, 0x2E, 0x3D, 0x81, 0x9E, 0x3D, 0x41, 0x8D, 0x6F, 0xEB, 0xCA, 0xD1, 0x6E, 0xC6, 0x93, 0xC4, 0x1E, 0x59, 0x84, 0x92, 0x94, 0x3D, - 0x61, 0x2E, 0x7D, 0xAE, 0xF8, 0x7B, 0xB2, 0xB0, 0x7C, 0xA0, 0x51, 0x03, 0xBB, 0x38, 0xA4, 0xCF, 0x62, 0x32, 0x5B, 0x56, 0x7B, 0xCE, 0x37, 0xDE, 0x25, 0x7F, - 0x4D, 0x81, 0xF4, 0xF1, 0xED, 0x52, 0xA9, 0x63, 0xFA, 0x59, 0xEB, 0x24, 0xC6, 0x22, 0xAB, 0x7F, 0xDA, 0x6E, 0x2F, 0x87, 0xF8, 0x54, 0xA9, 0x26, 0x58, 0x3B, - 0x3B, 0x5C, 0x0E, 0x8B, 0x9E, 0xDA, 0x2B, 0x7C, 0x24, 0x18, 0x38, 0xAD, 0xFC, 0x44, 0x30, 0x4A, 0x69, 0x02, 0xD4, 0x1C, 0x68, 0xEF, 0x0C, 0xFF, 0xF3, 0x81, - 0xF6, 0x11, 0x87, 0xF8, 0x06, 0x1F, 0x0C, 0x46, 0xDA, 0x0D, 0xD3, 0xF4, 0x32, 0x1F, 0x0E, 0x1E, 0x26, 0x1E, 0x0E, 0x1E, 0x8B, 0x87, 0x83, 0xA3, 0x95, 0xAA, - 0xEE, 0xCD, 0xA0, 0xDB, 0x3D, 0x56, 0x61, 0x5D, 0xF1, 0x01, 0xE1, 0x7B, 0xE1, 0x69, 0x05, 0xD2, 0x54, 0xE4, 0x69, 0x28, 0x78, 0x8A, 0x6D, 0xD8, 0xBF, 0x99, - 0xCF, 0x1F, 0x1B, 0x47, 0x7C, 0xC9, 0xB0, 0x3A, 0x4B, 0xDD, 0x7E, 0xD3, 0x4F, 0x71, 0x53, 0xE3, 0xBE, 0xAF, 0x87, 0xB8, 0x69, 0x93, 0x74, 0x34, 0x1C, 0xE5, - 0x06, 0x43, 0x0A, 0xC2, 0x9C, 0xFE, 0xCD, 0x7D, 0x3A, 0xFD, 0xA2, 0x86, 0xD3, 0x2F, 0xB6, 0x9C, 0xBE, 0x41, 0x6F, 0x17, 0x84, 0xFF, 0xD5, 0x3C, 0x5E, 0xF0, - 0x55, 0xC2, 0xEB, 0xA5, 0x7C, 0x75, 0xBB, 0xF7, 0xEA, 0xF7, 0x85, 0x4E, 0x12, 0x1A, 0xC3, 0x9B, 0xFB, 0x74, 0x92, 0x0C, 0xD3, 0xAD, 0x64, 0xA7, 0x3C, 0xEC, - 0x4C, 0x9A, 0x19, 0x97, 0x68, 0x36, 0x15, 0x57, 0x28, 0xEF, 0x1D, 0x1F, 0xD7, 0x1D, 0x0C, 0x79, 0xEA, 0x74, 0x1F, 0xEA, 0x51, 0x7F, 0x61, 0x44, 0x66, 0x93, - 0xFB, 0x49, 0xCC, 0xD6, 0xB1, 0x14, 0x57, 0x39, 0x31, 0x7B, 0xFF, 0xED, 0xB7, 0xE5, 0x72, 0xB1, 0x78, 0x2F, 0x8F, 0x24, 0x17, 0xCB, 0x2D, 0x53, 0xDF, 0xAE, - 0xE1, 0x06, 0x52, 0x5D, 0xC9, 0x74, 0x23, 0x70, 0x7D, 0xF2, 0x8A, 0x1E, 0x6B, 0x31, 0x89, 0x95, 0x32, 0x5E, 0xE5, 0x59, 0x27, 0x05, 0x8C, 0xD5, 0xB1, 0x23, - 0x12, 0xD2, 0xBA, 0x51, 0xC4, 0x95, 0x53, 0xBB, 0x8E, 0xB1, 0xA7, 0xCE, 0x54, 0x6D, 0x9F, 0xA0, 0x4D, 0x8A, 0x52, 0xE1, 0xD5, 0xC6, 0xAE, 0xAC, 0x36, 0x0E, - 0xAB, 0x4F, 0xDE, 0xC1, 0x64, 0xDC, 0x5A, 0xDB, 0x16, 0xCC, 0x3C, 0x5A, 0x5D, 0xAD, 0xAD, 0x0D, 0x7A, 0xFB, 0x0D, 0x8E, 0x91, 0x82, 0x8C, 0x92, 0x6F, 0xCB, - 0xE9, 0x45, 0x0F, 0xB3, 0x0D, 0xEE, 0xE9, 0x75, 0x39, 0x75, 0x15, 0xE2, 0xB9, 0x6E, 0x50, 0x59, 0x1B, 0x02, 0x18, 0x12, 0x15, 0x38, 0xD2, 0x22, 0x9D, 0xA8, - 0xAB, 0x22, 0xB6, 0xB5, 0x36, 0xC2, 0xA6, 0xA6, 0x0E, 0xA5, 0x8D, 0xB4, 0xB8, 0x3F, 0x45, 0x75, 0x07, 0xAA, 0x04, 0x6B, 0x4F, 0x9F, 0xF4, 0x4B, 0x60, 0x28, - 0xDE, 0x87, 0xCA, 0x5A, 0xD5, 0x77, 0x22, 0xFF, 0xB6, 0x7A, 0xEC, 0xE3, 0xB0, 0x90, 0x76, 0xDF, 0x42, 0xAA, 0xBB, 0xD2, 0x5E, 0x43, 0x5F, 0xD4, 0x89, 0x7A, - 0xA3, 0x26, 0x9D, 0x48, 0x90, 0x51, 0xDD, 0x89, 0x7A, 0x8F, 0xC3, 0x87, 0x50, 0x1F, 0x6B, 0x8F, 0x54, 0xD6, 0x07, 0x87, 0xD5, 0x27, 0xEF, 0x3D, 0x82, 0xCA, - 0xA8, 0xE4, 0x3D, 0x21, 0x92, 0x6A, 0xCE, 0x73, 0x0F, 0x8E, 0xD2, 0xEB, 0x8C, 0xEA, 0xE1, 0xE8, 0x97, 0x73, 0x36, 0x09, 0x86, 0x81, 0x3C, 0x08, 0x0C, 0x1E, - 0xA7, 0x0B, 0x13, 0xDB, 0x1C, 0x55, 0x77, 0x62, 0x01, 0x8D, 0xB3, 0x67, 0x38, 0xAC, 0x6C, 0x38, 0x31, 0x44, 0x8F, 0x2A, 0xEE, 0xD6, 0xC4, 0x70, 0x1F, 0xC6, - 0x34, 0xE9, 0x97, 0x32, 0xE9, 0x66, 0x4C, 0x67, 0x8D, 0x2F, 0x17, 0x24, 0x6A, 0x7B, 0x3E, 0x29, 0xB2, 0x78, 0xA4, 0x61, 0xB0, 0x10, 0x69, 0xE8, 0xEB, 0x05, - 0xE9, 0x5E, 0xF7, 0x46, 0x73, 0x5E, 0x41, 0xC0, 0xF6, 0x32, 0x4B, 0xF9, 0xAD, 0x01, 0x31, 0xE6, 0x64, 0x29, 0x70, 0xC8, 0xEB, 0x63, 0xCB, 0x7F, 0x29, 0x61, - 0x95, 0xC7, 0x0A, 0x0E, 0xCC, 0x55, 0x18, 0x0E, 0xDD, 0xCD, 0xE6, 0xBF, 0x21, 0x15, 0x35, 0xC6, 0xEE, 0x06, 0x13, 0xE0, 0xD8, 0xB2, 0x11, 0x55, 0x00, 0x0B, - 0x9A, 0x01, 0x9B, 0xF1, 0x95, 0x58, 0x09, 0xCA, 0x6C, 0x72, 0x3F, 0xF3, 0xFC, 0x6B, 0xCB, 0x29, 0x3F, 0xCF, 0xFF, 0xC9, 0x72, 0x4C, 0xF7, 0xBA, 0xDC, 0x54, - 0x3F, 0xDE, 0xD1, 0x9F, 0x60, 0xAA, 0x4F, 0x07, 0x4B, 0x5C, 0x2C, 0x6C, 0x7B, 0x44, 0xED, 0xA5, 0x33, 0x69, 0x21, 0x33, 0xE8, 0x1B, 0x5C, 0x6A, 0x03, 0x14, - 0xBE, 0x46, 0x97, 0x1E, 0x77, 0xED, 0x2F, 0x3F, 0x9F, 0xC6, 0x93, 0x5D, 0x4E, 0x81, 0x9A, 0xC3, 0x0C, 0x25, 0x85, 0xC7, 0x07, 0xAF, 0xA5, 0xFE, 0xB2, 0xCD, - 0xCF, 0xED, 0x83, 0xF3, 0x73, 0x1F, 0x01, 0x99, 0x38, 0x66, 0x65, 0xCB, 0x42, 0xD8, 0xC8, 0xAE, 0x2E, 0x1D, 0xB3, 0x51, 0xAB, 0x62, 0xBD, 0x57, 0xD6, 0x41, - 0xBF, 0x7B, 0x74, 0xF2, 0xB8, 0xCC, 0x0A, 0x19, 0xAA, 0x61, 0x54, 0xBD, 0xD1, 0xF0, 0xE8, 0xF1, 0xD8, 0x95, 0x3B, 0x9F, 0xB3, 0x15, 0xAE, 0x6A, 0xA6, 0xC5, - 0xC1, 0x6F, 0xE8, 0xA3, 0xB4, 0x3E, 0x69, 0x36, 0x5E, 0x85, 0x9D, 0xAB, 0xE9, 0x62, 0x20, 0xD1, 0xC5, 0xF8, 0x71, 0x99, 0x16, 0xE7, 0x48, 0xD5, 0xBA, 0x24, - 0x1C, 0xDD, 0x13, 0x43, 0xF7, 0x61, 0x5A, 0x81, 0x1B, 0x18, 0x76, 0x65, 0xCB, 0x62, 0xD0, 0x60, 0x58, 0x3F, 0xE0, 0x81, 0xF6, 0x01, 0xF8, 0x6C, 0xD4, 0xB8, - 0x44, 0xFF, 0xD5, 0x03, 0xD7, 0xA0, 0xFB, 0xC8, 0xC6, 0x43, 0xC6, 0x52, 0xAD, 0xD0, 0x35, 0x1E, 0x3E, 0x1E, 0xFB, 0x72, 0x37, 0x01, 0x5E, 0xAD, 0x1C, 0xBA, - 0x18, 0x38, 0x86, 0x2E, 0x7A, 0xD4, 0xBC, 0x89, 0x85, 0x14, 0xD4, 0x18, 0x1C, 0x87, 0x0F, 0xBF, 0x7E, 0xFD, 0x8B, 0x84, 0xA7, 0x5A, 0x46, 0x36, 0x78, 0x2C, - 0x41, 0x6C, 0x66, 0x28, 0xBF, 0x88, 0x8D, 0x22, 0x8B, 0x67, 0xF3, 0x0C, 0x16, 0xE6, 0x70, 0xEC, 0xA0, 0xD1, 0x0A, 0x86, 0xE8, 0xFC, 0xDE, 0x97, 0xEC, 0x42, - 0xAE, 0x1E, 0x53, 0xBD, 0x62, 0x6A, 0x39, 0x4E, 0x55, 0x35, 0x71, 0x58, 0x7D, 0xF2, 0x8A, 0x1D, 0x34, 0xBB, 0xB8, 0xCA, 0x3B, 0xBF, 0xFF, 0x95, 0x55, 0xC1, - 0x55, 0xD3, 0x6A, 0x4A, 0x15, 0x31, 0xBC, 0xF0, 0x4B, 0x11, 0x3A, 0xDF, 0xAD, 0x18, 0x7D, 0x39, 0xE2, 0xF1, 0x94, 0x34, 0x16, 0xC6, 0x0A, 0x9F, 0x30, 0x2E, - 0x5B, 0xD4, 0x78, 0x83, 0x60, 0xE5, 0x6A, 0x1A, 0xC9, 0x9E, 0x1E, 0x77, 0x55, 0x63, 0x92, 0x7C, 0xB5, 0x24, 0x10, 0xDE, 0x9E, 0x5A, 0x86, 0x8F, 0x4F, 0xE3, - 0xC3, 0xB1, 0xF6, 0x0A, 0x8E, 0xB5, 0xF7, 0xF6, 0x26, 0x7C, 0x37, 0xAE, 0xCC, 0x21, 0xE2, 0x3B, 0x9B, 0x22, 0x0C, 0x59, 0xDB, 0xD7, 0xE9, 0x86, 0x2E, 0xFE, - 0x14, 0x16, 0x1C, 0xE3, 0x3E, 0xA6, 0xD1, 0xF0, 0xB8, 0xAB, 0x6B, 0x2C, 0x2B, 0xE6, 0xCF, 0x90, 0xF8, 0x9F, 0xE9, 0x06, 0xA7, 0x5E, 0x48, 0xA0, 0xCC, 0x01, - 0xE2, 0xF4, 0x86, 0x04, 0x52, 0xFB, 0xAD, 0xB3, 0xEF, 0x68, 0x5B, 0x22, 0x3D, 0x21, 0x8E, 0xAE, 0xD4, 0x10, 0x12, 0x2F, 0xC3, 0x64, 0xED, 0x55, 0x9E, 0x86, - 0x91, 0x0B, 0xA2, 0x27, 0x15, 0x04, 0xEE, 0xF3, 0xBA, 0x5F, 0x9E, 0xFA, 0x82, 0xA7, 0x9E, 0x1A, 0x4F, 0xFD, 0x1A, 0x3C, 0xF5, 0x1B, 0xE2, 0x69, 0x20, 0x78, - 0xEA, 0xAB, 0xF1, 0x34, 0xA8, 0xC1, 0xD3, 0xA0, 0x21, 0x9E, 0x86, 0x82, 0xA7, 0x81, 0x1A, 0x4F, 0xC3, 0x1A, 0x3C, 0x0D, 0x1B, 0xE2, 0x69, 0x24, 0x78, 0x1A, - 0xAA, 0xF1, 0x34, 0xAA, 0xC1, 0xD3, 0xA8, 0x21, 0x9E, 0xC6, 0x82, 0xA7, 0x91, 0x1A, 0x4F, 0xE3, 0x1A, 0x3C, 0x8D, 0x1B, 0xE2, 0xE9, 0x48, 0xF0, 0x34, 0x56, - 0xE3, 0xE9, 0xA8, 0x06, 0x4F, 0x47, 0x0D, 0xF1, 0x74, 0x2C, 0x78, 0x3A, 0x52, 0xE3, 0xE9, 0xB8, 0x06, 0x4F, 0xC7, 0x0D, 0xF1, 0x74, 0x22, 0x78, 0x3A, 0x56, - 0xE3, 0xE9, 0xA4, 0x06, 0x4F, 0x27, 0x0D, 0xF1, 0x84, 0x8B, 0x72, 0x8C, 0xA9, 0x13, 0xC5, 0x41, 0xB7, 0x5B, 0x83, 0x2B, 0xA3, 0x29, 0xAE, 0xC2, 0x54, 0xA2, - 0xA7, 0x9A, 0x4B, 0xD4, 0x49, 0x26, 0xA6, 0x4D, 0xB1, 0x15, 0x65, 0x13, 0x8A, 0xE9, 0x44, 0xAF, 0x4E, 0x3E, 0x31, 0x6B, 0x8A, 0xAD, 0x30, 0xA1, 0xE8, 0x29, - 0x66, 0x14, 0xBD, 0x3A, 0x29, 0x85, 0xD9, 0x14, 0x5B, 0x61, 0x4E, 0xD1, 0x53, 0x4C, 0x2A, 0x7A, 0x75, 0xB2, 0x0A, 0xD2, 0x14, 0x5B, 0x61, 0x5A, 0xD1, 0x53, - 0xCC, 0x2B, 0x7A, 0x75, 0x12, 0x8B, 0x79, 0x53, 0x6C, 0x85, 0x99, 0x45, 0x4F, 0x31, 0xB5, 0xE8, 0xD5, 0xC8, 0x2D, 0x4E, 0xE4, 0x13, 0xB1, 0x7B, 0x65, 0x8B, - 0x04, 0x7C, 0x8A, 0x1C, 0x4D, 0xDA, 0x94, 0x1E, 0x3D, 0xE1, 0x40, 0xF8, 0x6C, 0x14, 0x13, 0xC8, 0x85, 0xEB, 0xCC, 0xAD, 0x45, 0x58, 0x64, 0x78, 0x34, 0x4F, - 0x49, 0xF8, 0xB1, 0xB7, 0xF2, 0x2A, 0x17, 0x1A, 0x3E, 0xBC, 0xBE, 0x2C, 0x57, 0x66, 0x88, 0xF7, 0xF2, 0x27, 0x2A, 0x32, 0x00, 0xD9, 0xFD, 0xF8, 0x27, 0x02, - 0x94, 0xEA, 0x0A, 0x14, 0xA8, 0x4C, 0x45, 0x61, 0x14, 0xAF, 0x28, 0x8C, 0x95, 0x2B, 0x0A, 0x8C, 0xB8, 0xDD, 0xD4, 0x12, 0x00, 0xF7, 0x80, 0x7D, 0xD7, 0x40, - 0x9D, 0xE9, 0x41, 0x75, 0xA6, 0x47, 0x65, 0x98, 0x1E, 0x54, 0x61, 0xBA, 0xC2, 0xD3, 0x8D, 0x8A, 0x72, 0x02, 0x7A, 0xBF, 0xB6, 0x6E, 0x88, 0xA9, 0xFD, 0xA2, - 0x2E, 0xAA, 0x5E, 0x75, 0x51, 0x1D, 0x95, 0x11, 0x55, 0x6F, 0x87, 0xF6, 0x31, 0x12, 0x7C, 0xFF, 0xA8, 0xCE, 0xF7, 0xA8, 0x3A, 0xDF, 0x83, 0x32, 0x7C, 0x8F, - 0x76, 0xC8, 0xF7, 0x50, 0xF0, 0xFD, 0x51, 0x9D, 0xEF, 0x61, 0x75, 0xBE, 0x87, 0x65, 0xF8, 0x1E, 0xEE, 0x90, 0xEF, 0x3E, 0x04, 0x9B, 0x1F, 0x3F, 0x6A, 0x3F, - 0x2C, 0x3D, 0xE2, 0x2F, 0x8B, 0x2B, 0x71, 0x0C, 0xA2, 0xEA, 0xD8, 0x3E, 0x6A, 0x60, 0xEE, 0x86, 0x14, 0x0E, 0xE2, 0x3C, 0x15, 0xE6, 0xCD, 0x0C, 0x42, 0xE5, - 0xC3, 0x41, 0x72, 0x9E, 0xE4, 0x33, 0xB7, 0x9E, 0x2A, 0x53, 0xBB, 0x8B, 0x61, 0xC7, 0xFA, 0xE4, 0xED, 0xA6, 0xC4, 0xF8, 0x76, 0x5C, 0xDD, 0x9E, 0xD5, 0x2B, - 0xE6, 0x8C, 0xAE, 0x9D, 0xD9, 0xF3, 0x09, 0xE5, 0x19, 0xF2, 0x32, 0x5F, 0x41, 0xED, 0xD5, 0xAB, 0x10, 0xA3, 0x06, 0xAA, 0xE4, 0x18, 0xE9, 0x8F, 0x18, 0x3B, - 0x3F, 0x22, 0x43, 0x1A, 0x64, 0x2C, 0x25, 0x06, 0xA3, 0xA3, 0x92, 0xDA, 0x3C, 0xAE, 0x18, 0x9D, 0x90, 0xC6, 0x9D, 0xA9, 0x13, 0xA7, 0x1E, 0x28, 0x80, 0x8F, - 0x15, 0x04, 0x30, 0xAE, 0x2E, 0x80, 0x52, 0x99, 0x0B, 0xD2, 0xB8, 0x3B, 0x01, 0x74, 0x99, 0x00, 0x3E, 0x44, 0x6F, 0xA6, 0xCE, 0x31, 0xE8, 0x1A, 0x15, 0xA8, - 0x51, 0x03, 0x6B, 0x24, 0x18, 0x69, 0x7B, 0xC2, 0xA2, 0x81, 0xA3, 0x72, 0x0A, 0xED, 0x97, 0xCD, 0xAF, 0xE4, 0xC5, 0x4F, 0x85, 0xFC, 0x7B, 0x97, 0x09, 0x56, - 0xBF, 0x2B, 0x2C, 0xBA, 0xBC, 0x00, 0xBA, 0xD5, 0x05, 0xD0, 0x2B, 0x25, 0x80, 0xEE, 0xE3, 0x4A, 0xC6, 0xC7, 0xDB, 0x1F, 0x13, 0x2E, 0x96, 0x56, 0x59, 0xF7, - 0x8F, 0x8D, 0x66, 0xFD, 0x32, 0xC2, 0xDA, 0xA9, 0xF7, 0x0F, 0x22, 0xCE, 0xB5, 0x5F, 0xB4, 0xE4, 0xD6, 0xD7, 0xBC, 0x38, 0x50, 0xBD, 0x08, 0x38, 0x6A, 0x60, - 0xBD, 0x0A, 0x29, 0x3C, 0x91, 0x70, 0x56, 0x32, 0xC0, 0x9F, 0x54, 0x77, 0x87, 0x52, 0x1A, 0x46, 0x5A, 0x77, 0xA7, 0xE2, 0x51, 0x42, 0x10, 0xEC, 0x43, 0xE6, - 0x2A, 0x2A, 0xAE, 0x5E, 0x39, 0x1C, 0x35, 0xB0, 0xD4, 0x85, 0x14, 0x1E, 0x4B, 0x38, 0x2B, 0xA9, 0xE2, 0xB2, 0x29, 0xE9, 0x71, 0xC5, 0xA9, 0x65, 0x6F, 0x97, - 0x39, 0x29, 0x56, 0xBB, 0x63, 0x82, 0x88, 0x7F, 0x65, 0x22, 0x4F, 0xC1, 0xD5, 0x2B, 0xDE, 0xA3, 0x9A, 0xEB, 0xB3, 0xBB, 0x8B, 0xE4, 0x47, 0xB2, 0x4F, 0x90, - 0x17, 0xDB, 0x41, 0xD9, 0x5C, 0xB6, 0x5B, 0x71, 0xE0, 0xDB, 0x69, 0x2A, 0x0B, 0xBD, 0x43, 0xD6, 0xB3, 0xCD, 0x7D, 0x8E, 0x09, 0x54, 0x5F, 0x79, 0x1B, 0x35, - 0xB0, 0x3D, 0x04, 0x29, 0xEC, 0xEB, 0x93, 0x8F, 0x25, 0x99, 0xAA, 0x53, 0x3F, 0xA8, 0xBC, 0x3F, 0xA4, 0xB9, 0xD2, 0xFB, 0x6C, 0x75, 0x53, 0xBE, 0xF4, 0x7E, - 0xF1, 0xEE, 0xE7, 0x72, 0xA5, 0xF7, 0x78, 0x2F, 0xCD, 0x95, 0xDE, 0xAB, 0xD9, 0x4C, 0xA9, 0x8D, 0xB2, 0xC0, 0x18, 0xBE, 0x3F, 0x62, 0x66, 0xF9, 0xB4, 0x4B, - 0x10, 0x8C, 0xF6, 0x5E, 0x9C, 0x86, 0x22, 0x8A, 0x3D, 0xB1, 0x9F, 0x6C, 0x9F, 0x67, 0x3D, 0x83, 0x9C, 0xB0, 0xA0, 0xB6, 0x11, 0x76, 0xFB, 0x75, 0x28, 0x9D, - 0x31, 0xFF, 0x10, 0x57, 0x8D, 0x47, 0xEB, 0xB3, 0x5E, 0x1A, 0xD0, 0x39, 0x2A, 0x89, 0x7B, 0xE7, 0x8F, 0xDC, 0x4F, 0x52, 0x8A, 0xEA, 0x51, 0xFD, 0xF4, 0xF0, - 0x5C, 0xB9, 0x4E, 0x4E, 0xC1, 0xCA, 0x44, 0xF3, 0x41, 0xBC, 0xD4, 0xA2, 0x1E, 0xCD, 0x19, 0x79, 0xBB, 0x89, 0xE6, 0x88, 0x3B, 0xC1, 0x7B, 0x89, 0xAC, 0x86, - 0xC1, 0x96, 0x13, 0x80, 0x7C, 0x13, 0x85, 0x82, 0x00, 0xB2, 0x24, 0x70, 0x2F, 0x22, 0xE8, 0x53, 0x09, 0xF4, 0x53, 0xDA, 0xCF, 0x08, 0xFC, 0xB4, 0x7D, 0xD5, - 0xB8, 0x3F, 0x68, 0xA0, 0x36, 0x81, 0xE2, 0x4A, 0x70, 0x54, 0x52, 0xA7, 0xE5, 0x16, 0x07, 0x13, 0x3A, 0x2D, 0x67, 0xD4, 0x3B, 0x5B, 0x1D, 0x04, 0xE4, 0x03, - 0x2A, 0x80, 0x81, 0xB2, 0x4A, 0xAB, 0x4F, 0x33, 0x07, 0x0D, 0xE4, 0x27, 0x28, 0xAD, 0x04, 0x47, 0x25, 0x55, 0x5A, 0x6E, 0xE9, 0x33, 0xA1, 0x52, 0xF5, 0xF9, - 0x25, 0x27, 0x72, 0x67, 0x2A, 0x1D, 0x52, 0x01, 0x0C, 0x95, 0x55, 0x5A, 0x7D, 0xD6, 0x31, 0x68, 0x60, 0xF7, 0x2E, 0x4A, 0x2B, 0xC1, 0x51, 0x49, 0x95, 0x96, - 0x5B, 0xB2, 0x4B, 0xA8, 0x54, 0x7D, 0x3E, 0xC9, 0x89, 0xDC, 0x99, 0x4A, 0x47, 0x54, 0x00, 0x23, 0x65, 0x95, 0x56, 0xAF, 0x14, 0x0C, 0x1A, 0x28, 0x06, 0xA1, - 0xB4, 0x12, 0x1C, 0x95, 0x54, 0x69, 0xB9, 0xD5, 0xE7, 0x84, 0x4A, 0xD5, 0xD7, 0x39, 0x38, 0x91, 0x3B, 0x53, 0xE9, 0x98, 0x0A, 0x60, 0xAC, 0xAC, 0xD2, 0xEA, - 0xFB, 0xAB, 0x06, 0x0D, 0xEC, 0xDD, 0x46, 0x69, 0x25, 0x38, 0x2A, 0xA9, 0xD2, 0x72, 0xA5, 0xDB, 0x84, 0x4A, 0xD5, 0x57, 0x6E, 0x38, 0x91, 0x3B, 0x53, 0xE9, - 0x11, 0x15, 0xC0, 0x91, 0xB2, 0x4A, 0xAB, 0x6F, 0x5D, 0x1F, 0x34, 0x50, 0xCF, 0x43, 0x69, 0x25, 0x38, 0x2A, 0xA9, 0xD2, 0x72, 0x15, 0x9C, 0x84, 0x4A, 0xD5, - 0xF7, 0x4E, 0x71, 0x22, 0x77, 0xA6, 0xD2, 0x63, 0x2A, 0x80, 0x63, 0x65, 0x95, 0x56, 0xDF, 0xB9, 0x3F, 0x68, 0x60, 0xE7, 0x3E, 0x4A, 0x2B, 0xC1, 0x51, 0x49, - 0x95, 0x96, 0xAB, 0xCD, 0x26, 0x54, 0xAA, 0xBE, 0xDD, 0x89, 0x13, 0xB9, 0x33, 0x95, 0x9E, 0x50, 0x01, 0x9C, 0x28, 0xAB, 0xB4, 0xFA, 0x96, 0x81, 0x41, 0x03, - 0x9B, 0x5F, 0x50, 0x5A, 0xDD, 0x38, 0x47, 0x25, 0x55, 0x5A, 0x6E, 0x81, 0x71, 0x90, 0xB1, 0xF5, 0x45, 0x41, 0xA5, 0x59, 0x0B, 0x8C, 0x8F, 0xA0, 0x7E, 0x67, - 0x5C, 0x4F, 0x2B, 0x7C, 0xFA, 0xE5, 0xE5, 0x4F, 0xAF, 0xB2, 0x0B, 0xFB, 0x99, 0x55, 0xBC, 0x44, 0x5F, 0x8F, 0xBD, 0x8C, 0x17, 0x97, 0x17, 0x12, 0x0E, 0x5A, - 0x66, 0x2F, 0x4D, 0xD4, 0xB6, 0x98, 0xCF, 0xB7, 0x34, 0x06, 0x5C, 0xC2, 0xD2, 0x06, 0xC3, 0xAE, 0x3C, 0x69, 0x29, 0xB0, 0x34, 0x4E, 0xE5, 0x6E, 0x82, 0x07, - 0x22, 0x87, 0xB9, 0x38, 0xF2, 0xFE, 0xBD, 0xD2, 0x9A, 0x0E, 0x03, 0x48, 0x86, 0x8F, 0x61, 0xF7, 0x44, 0x31, 0x7E, 0x80, 0x0C, 0xB2, 0x36, 0xC6, 0xDF, 0x63, - 0x00, 0x41, 0x1A, 0x07, 0x8C, 0xA9, 0x37, 0xCA, 0x4C, 0xA5, 0xAB, 0x00, 0xA5, 0x98, 0xCA, 0xAA, 0xEC, 0xDC, 0x33, 0x53, 0x43, 0xC6, 0x54, 0x8E, 0x93, 0xA6, - 0x98, 0x4A, 0xCF, 0x83, 0x4B, 0x31, 0x95, 0x35, 0x11, 0x8E, 0x98, 0x7A, 0x0C, 0x81, 0x8E, 0xCC, 0x8C, 0xC5, 0xAC, 0x42, 0xA8, 0xBB, 0xBC, 0x38, 0x7C, 0xF9, - 0xE6, 0x42, 0xA3, 0x4B, 0x9A, 0xAE, 0x5D, 0x32, 0xE2, 0x25, 0x3B, 0xFD, 0x53, 0xC5, 0x3C, 0x4A, 0x7A, 0x2C, 0xEA, 0xBD, 0xB9, 0x50, 0x0D, 0x78, 0x1C, 0xB2, - 0x4C, 0xC8, 0x1B, 0x75, 0x07, 0x55, 0x2A, 0x84, 0x21, 0x91, 0x3B, 0x0A, 0x7A, 0x14, 0x7D, 0x3F, 0x92, 0xC1, 0x65, 0x39, 0x19, 0x94, 0xAA, 0x92, 0x26, 0x65, - 0x50, 0x22, 0xEC, 0x0B, 0x22, 0x77, 0x29, 0x03, 0x8C, 0x92, 0x97, 0x17, 0xDA, 0xFB, 0xBF, 0x6B, 0x97, 0x37, 0x6B, 0xD7, 0xDF, 0x78, 0xA4, 0x30, 0xAA, 0x70, - 0xB8, 0x64, 0x5C, 0x19, 0x8F, 0x46, 0x03, 0xD5, 0xC0, 0x32, 0xCA, 0x1E, 0x02, 0xE6, 0xDD, 0x7B, 0x8C, 0x97, 0x94, 0xD0, 0x61, 0xC8, 0xE0, 0xF7, 0x04, 0x34, - 0xAD, 0x14, 0x37, 0x39, 0x60, 0x92, 0xC3, 0x5E, 0x17, 0xB7, 0x57, 0x2B, 0x32, 0x28, 0xCF, 0x28, 0x07, 0xF7, 0x3A, 0x1C, 0x50, 0x2A, 0x47, 0x21, 0x7B, 0x1F, - 0x7F, 0xF8, 0xA0, 0xC6, 0x58, 0xBA, 0x8E, 0x56, 0x4E, 0x75, 0x59, 0x8F, 0x8C, 0xDE, 0xD3, 0xA0, 0x20, 0xBD, 0x71, 0x76, 0x08, 0xA1, 0x77, 0x1B, 0x26, 0x43, - 0x92, 0x67, 0x73, 0x6B, 0x01, 0x76, 0x2C, 0xEF, 0x83, 0x8A, 0x96, 0xBD, 0xEC, 0x14, 0xBF, 0x51, 0xD9, 0x9E, 0x41, 0xF4, 0x07, 0x93, 0x40, 0xA7, 0x13, 0x02, - 0x5F, 0x19, 0x0B, 0x12, 0x5D, 0xD7, 0x58, 0x6C, 0xCF, 0x8B, 0xD9, 0x06, 0x43, 0x68, 0x5C, 0x11, 0xFE, 0x41, 0x4D, 0x6D, 0xE9, 0x91, 0xF9, 0xB9, 0xFE, 0x45, - 0x88, 0x93, 0x3F, 0x95, 0x87, 0x4D, 0x74, 0xCD, 0x74, 0xAF, 0x1D, 0xDB, 0x35, 0x70, 0x3C, 0x30, 0xD6, 0x01, 0x50, 0xDA, 0xF9, 0x6D, 0x8D, 0x2F, 0xBE, 0x32, - 0xF0, 0x21, 0x2E, 0x23, 0xA7, 0x9F, 0x98, 0x55, 0xCC, 0x6C, 0xD7, 0x17, 0xB3, 0x39, 0x3C, 0x0C, 0x3F, 0xC0, 0xF9, 0x3F, 0xFF, 0x5D, 0xB4, 0x83, 0xC0, 0x5A, - 0x2D, 0x62, 0x02, 0xD0, 0x35, 0xDF, 0x9B, 0x9D, 0xEB, 0x40, 0xA9, 0xE7, 0xFA, 0xBE, 0xEB, 0x59, 0x0B, 0x2B, 0x43, 0x3B, 0x59, 0xD2, 0x3E, 0x94, 0x89, 0x3B, - 0xD5, 0x58, 0xA2, 0xF8, 0x33, 0x7F, 0xE6, 0x59, 0xEB, 0x60, 0xF2, 0xC4, 0x74, 0x67, 0x9B, 0x15, 0x71, 0x82, 0x8E, 0x61, 0x9A, 0x97, 0x57, 0x70, 0xF0, 0x2D, - 0x7E, 0xAC, 0x0D, 0x24, 0xDF, 0xDA, 0x7B, 0xFD, 0x8F, 0x77, 0x38, 0x3A, 0xE3, 0x35, 0x90, 0x17, 0x31, 0xF7, 0x0E, 0xB4, 0xF9, 0xC6, 0x61, 0x03, 0x64, 0x8B, - 0x60, 0xDB, 0x7D, 0xED, 0x0F, 0xC0, 0x78, 0x65, 0x78, 0xDA, 0xD4, 0xF0, 0xC9, 0x5B, 0xD7, 0x0F, 0xB4, 0x73, 0x2D, 0xC4, 0x68, 0xBB, 0x33, 0xBA, 0x9D, 0xA3, - 0xC3, 0xF8, 0xE2, 0x2D, 0x19, 0xE3, 0x3F, 0x7A, 0x36, 0x34, 0x0D, 0xA1, 0x9E, 0x6B, 0x7B, 0xA7, 0xC7, 0xBD, 0x3D, 0xB4, 0xDD, 0xB0, 0x8B, 0x39, 0x81, 0xE8, - 0x0F, 0xED, 0x5A, 0x1B, 0xCF, 0x3E, 0xD0, 0x66, 0xD3, 0xFD, 0x3F, 0x28, 0xF5, 0xF4, 0x32, 0x5E, 0xDB, 0xE7, 0xCC, 0x74, 0x82, 0x25, 0x71, 0x5A, 0x11, 0x65, - 0x1E, 0xF1, 0xD7, 0xAE, 0xE3, 0x13, 0x46, 0x1C, 0xFB, 0x59, 0xF3, 0xE8, 0x7A, 0xC7, 0x0F, 0x8C, 0x60, 0xE3, 0x6B, 0x4F, 0xCF, 0xCF, 0xB5, 0x7E, 0xB7, 0x1B, - 0x6F, 0xA6, 0x41, 0x37, 0xE9, 0x76, 0x07, 0x5A, 0xEA, 0xC2, 0x0F, 0xE4, 0x26, 0xD8, 0xFF, 0x2A, 0x84, 0xB9, 0xD3, 0x88, 0xED, 0x93, 0x04, 0x92, 0x10, 0x00, - 0x5F, 0x27, 0xD7, 0xDA, 0x4F, 0x12, 0xD8, 0x32, 0x8D, 0xC0, 0xD8, 0xFF, 0x23, 0xA1, 0x2F, 0xE8, 0x15, 0x28, 0x39, 0xD0, 0xE8, 0xAD, 0xAF, 0x62, 0xB7, 0xEE, - 0xF6, 0x3B, 0x20, 0x43, 0xE0, 0x37, 0x84, 0x26, 0x9E, 0x97, 0xA4, 0x98, 0x42, 0xB7, 0x7B, 0x07, 0x1A, 0xDE, 0x49, 0xC2, 0xC6, 0x88, 0x7C, 0x22, 0xAE, 0x09, - 0xA1, 0xE5, 0xA3, 0x95, 0xA0, 0x64, 0xE8, 0xEE, 0x12, 0x2A, 0x82, 0x38, 0xF4, 0x3D, 0x59, 0x80, 0xC4, 0x16, 0x07, 0x3C, 0x2C, 0x1D, 0xD0, 0x98, 0x74, 0xC0, - 0xC2, 0x59, 0x4C, 0x6B, 0xE0, 0xD0, 0xBE, 0x6B, 0x13, 0xB0, 0x89, 0x45, 0x6B, 0x8F, 0x7F, 0x0A, 0x14, 0xEC, 0x69, 0xAF, 0x7B, 0xB3, 0xF7, 0x1C, 0xC0, 0x3B, - 0x81, 0xFB, 0x21, 0xF0, 0x2C, 0x67, 0xD1, 0xEA, 0x8D, 0xF7, 0x23, 0x5C, 0xF4, 0x36, 0x22, 0x4C, 0xDD, 0xA7, 0xD7, 0x69, 0x17, 0xE9, 0x1B, 0x2D, 0x7E, 0xFD, - 0xF9, 0xDE, 0xFE, 0x1E, 0x27, 0x9D, 0x9E, 0x83, 0xB1, 0xB5, 0xD8, 0xC1, 0x33, 0x4A, 0xE1, 0xBE, 0x76, 0x76, 0xC6, 0xBB, 0x61, 0xAD, 0xF0, 0x22, 0x34, 0xA2, - 0x7F, 0x52, 0xB7, 0x42, 0x43, 0xFC, 0xF5, 0xCB, 0x3F, 0x84, 0xC5, 0xDE, 0x1D, 0x02, 0xD5, 0x2F, 0x30, 0x2E, 0x7F, 0xF9, 0x07, 0xFC, 0x7F, 0xF7, 0x8C, 0x86, - 0xE2, 0x2F, 0xFF, 0xC0, 0x3F, 0x77, 0xCF, 0xA0, 0x27, 0x38, 0xA6, 0xFD, 0xDD, 0xFD, 0x4A, 0xA5, 0xB0, 0x2D, 0xBB, 0x45, 0xA6, 0xEC, 0x42, 0xA1, 0x95, 0xA6, - 0x69, 0x91, 0x43, 0xD4, 0xAF, 0x91, 0xF7, 0xB6, 0x66, 0xAE, 0x09, 0xCA, 0x09, 0xC0, 0x8E, 0x85, 0xCA, 0x6D, 0x50, 0x89, 0x10, 0x54, 0x57, 0xA8, 0xDC, 0x9A, - 0xD3, 0x96, 0x1A, 0x77, 0x94, 0xC8, 0x3C, 0x44, 0xCB, 0xB5, 0xE1, 0xF9, 0xE4, 0x1B, 0x27, 0x68, 0x05, 0x09, 0x97, 0xC8, 0x90, 0xF8, 0x64, 0x92, 0x60, 0x01, - 0x7F, 0x00, 0x07, 0xED, 0xF6, 0xB8, 0xD2, 0x42, 0x53, 0x7B, 0x12, 0x5A, 0x61, 0x44, 0x29, 0xBB, 0x99, 0x61, 0x85, 0x3F, 0xCF, 0xEC, 0xCF, 0xAD, 0x1B, 0xF8, - 0x2F, 0x1D, 0x28, 0xB6, 0x44, 0x84, 0x8D, 0x5E, 0xE0, 0x7F, 0x20, 0x17, 0xFC, 0x93, 0xA9, 0x1F, 0xC0, 0xFA, 0xDE, 0xB6, 0x5B, 0xEC, 0xB3, 0x5F, 0xA0, 0x9A, - 0x0D, 0x04, 0x21, 0xFF, 0x16, 0xC3, 0x81, 0xEB, 0x06, 0x9F, 0x0E, 0xB4, 0xB5, 0x07, 0x84, 0xD1, 0x2F, 0x7D, 0xC0, 0x31, 0x20, 0x22, 0x0E, 0xFB, 0x5B, 0x48, - 0xC1, 0xDA, 0xB6, 0x5F, 0x30, 0xAC, 0x40, 0x02, 0x3B, 0x00, 0x4D, 0x6D, 0xD0, 0x62, 0xE0, 0xFF, 0xBB, 0x67, 0xD0, 0x09, 0x1C, 0xC2, 0xFF, 0x77, 0xCF, 0xB0, - 0x2B, 0xD4, 0x25, 0xF6, 0x78, 0xF7, 0x0C, 0x7A, 0x84, 0x13, 0xF8, 0x1F, 0xDA, 0x60, 0xBF, 0xD8, 0x0A, 0xFF, 0xC2, 0x1D, 0xDA, 0x3F, 0xDE, 0xA4, 0x07, 0xEC, - 0x02, 0x3F, 0xCD, 0x63, 0x90, 0xBD, 0xE9, 0xBE, 0x45, 0xDF, 0x3C, 0xFE, 0xE9, 0x06, 0xD8, 0xA1, 0x07, 0xB7, 0xE0, 0xF8, 0x8E, 0x89, 0xE7, 0xF8, 0xE7, 0x56, - 0x98, 0x27, 0x5E, 0xE0, 0x47, 0x70, 0x8D, 0xBE, 0x9D, 0x15, 0x2F, 0xB1, 0x03, 0x6C, 0x45, 0xDF, 0xA5, 0x49, 0x5B, 0xB1, 0x23, 0xB8, 0xC6, 0xDF, 0xC0, 0x78, - 0xA0, 0xF1, 0x77, 0xFC, 0x15, 0x0A, 0x27, 0x7A, 0x07, 0xDF, 0x0B, 0xFF, 0x06, 0x19, 0x64, 0xA4, 0xA1, 0x54, 0xC2, 0xB3, 0xDB, 0xBB, 0x67, 0x04, 0xEF, 0x51, - 0x22, 0xE1, 0xF8, 0x96, 0x1F, 0xC3, 0x75, 0xA0, 0x0F, 0xEF, 0x08, 0x82, 0xE9, 0x85, 0xDB, 0xE8, 0x02, 0xB4, 0x08, 0xF0, 0x3E, 0x27, 0x1E, 0xCE, 0x6E, 0xC3, - 0x33, 0x84, 0xA6, 0xB0, 0x9C, 0x0D, 0x38, 0xBD, 0x8D, 0x4E, 0xE1, 0x2E, 0xF2, 0x82, 0x0A, 0xE0, 0x3C, 0xDD, 0x3D, 0xE3, 0x3C, 0xA1, 0x16, 0xD9, 0x51, 0x5A, - 0xD4, 0x18, 0xF4, 0x02, 0x1E, 0x24, 0x5F, 0xB1, 0x1C, 0x24, 0x36, 0x3C, 0x42, 0x00, 0xB8, 0xB4, 0x09, 0x1E, 0xBE, 0xBA, 0xFD, 0xC6, 0x6C, 0xED, 0xF1, 0x4F, - 0xB7, 0xEE, 0x61, 0x88, 0x8E, 0xC3, 0x74, 0x5C, 0x67, 0x66, 0x5B, 0x33, 0x8C, 0x04, 0xAD, 0x7D, 0xED, 0x7C, 0xC2, 0xC3, 0x34, 0x7A, 0x2C, 0x34, 0x8F, 0x7B, - 0x61, 0x26, 0x6A, 0x8F, 0x7F, 0x7C, 0x74, 0x6F, 0xBF, 0x43, 0x1D, 0x8D, 0x3B, 0x13, 0xA2, 0xE0, 0x31, 0x46, 0x0D, 0x07, 0x36, 0x96, 0xE0, 0xD8, 0x0A, 0x07, - 0xB9, 0x48, 0x68, 0xEB, 0x18, 0x16, 0x8A, 0x26, 0x3E, 0x92, 0x74, 0x53, 0x83, 0x48, 0x4E, 0xD8, 0x12, 0x11, 0xEA, 0x69, 0x3A, 0x42, 0x81, 0xAA, 0xBC, 0xA0, - 0xB5, 0x77, 0xE9, 0x79, 0xAE, 0xF7, 0xAF, 0xBD, 0xE7, 0xD8, 0xE8, 0xF9, 0xDE, 0xBF, 0x4F, 0xB5, 0xBD, 0xE7, 0xF1, 0x50, 0x75, 0x97, 0x8E, 0x29, 0x4C, 0x63, - 0x0B, 0x45, 0x8D, 0x2D, 0x62, 0x1A, 0x5B, 0xDC, 0xAF, 0xC6, 0xE2, 0x9F, 0x8C, 0xAD, 0xA3, 0xB5, 0xF8, 0x27, 0x5A, 0x73, 0x34, 0x57, 0x08, 0xCF, 0x95, 0xC6, - 0xB5, 0xB5, 0x90, 0x69, 0xAB, 0x8A, 0x9A, 0xD8, 0x18, 0x0E, 0xDE, 0x43, 0xBC, 0xB7, 0x3F, 0xBC, 0xFB, 0x16, 0xC7, 0x02, 0xB9, 0xCA, 0x42, 0x8D, 0xA5, 0xB3, - 0x2D, 0x09, 0x06, 0x4C, 0x0E, 0x12, 0x23, 0x53, 0x22, 0x49, 0x78, 0xBE, 0xA7, 0xB5, 0x28, 0x4A, 0x4C, 0x11, 0x0A, 0x0C, 0x81, 0x8F, 0x2C, 0x6A, 0xBE, 0x8B, - 0xA3, 0x89, 0x70, 0xDE, 0x08, 0x2A, 0xC7, 0x16, 0x10, 0x40, 0x49, 0x89, 0x0C, 0xF3, 0x96, 0xC3, 0xC4, 0x06, 0xBD, 0xC6, 0x5D, 0x84, 0xFA, 0xAB, 0xAF, 0x1A, - 0xD4, 0x44, 0x4C, 0x8F, 0x62, 0x9B, 0x5F, 0x28, 0x1D, 0x1E, 0xF9, 0x95, 0x04, 0xC4, 0x3F, 0x05, 0x22, 0x31, 0x70, 0x3E, 0x62, 0x94, 0xC0, 0x72, 0x2B, 0xC1, - 0x42, 0x47, 0x1A, 0x25, 0x1C, 0xF4, 0xF3, 0x11, 0x19, 0x18, 0xD4, 0xA8, 0xA0, 0xDF, 0x6B, 0x90, 0x60, 0x10, 0x63, 0x9A, 0x12, 0x12, 0xF1, 0xAD, 0x81, 0x6C, - 0x3C, 0x6A, 0xC4, 0x88, 0x37, 0xFC, 0x4B, 0xF0, 0xF0, 0x31, 0x54, 0x09, 0x0D, 0x7F, 0x3B, 0x7D, 0x26, 0x16, 0x35, 0x62, 0xF8, 0x0B, 0xE1, 0x65, 0x3C, 0xF1, - 0x31, 0x5B, 0x8D, 0x27, 0xFE, 0x1E, 0xF3, 0x6C, 0x3C, 0x8A, 0xB2, 0xE1, 0xEF, 0x0E, 0x97, 0x59, 0x1D, 0x4B, 0x11, 0x72, 0x1D, 0x83, 0x35, 0x01, 0x60, 0x5E, - 0x96, 0x7E, 0xD1, 0x3B, 0xED, 0x46, 0x18, 0x78, 0x46, 0x91, 0x87, 0x81, 0x37, 0x49, 0x63, 0x10, 0xD1, 0xE1, 0x01, 0x72, 0xBB, 0x87, 0x88, 0x42, 0x90, 0xA3, - 0xAB, 0x45, 0x21, 0x48, 0xBB, 0x45, 0xF8, 0x09, 0x61, 0x32, 0xC2, 0x0F, 0x2D, 0x68, 0xB0, 0x2F, 0x18, 0xE7, 0xC9, 0x3F, 0xFC, 0x20, 0xB0, 0x4C, 0x89, 0x88, - 0x03, 0xD2, 0x79, 0x25, 0x4B, 0xE2, 0xDF, 0xBE, 0x4D, 0x19, 0x12, 0x2D, 0x96, 0xDC, 0xFA, 0x6A, 0xA1, 0xEB, 0xD6, 0xCF, 0xC0, 0x40, 0xE7, 0x0E, 0x6A, 0xB9, - 0x19, 0xFF, 0x58, 0xAC, 0x04, 0x09, 0xCC, 0x39, 0x94, 0x50, 0xF0, 0x2F, 0x66, 0xCA, 0x18, 0xA1, 0x1F, 0x54, 0x54, 0x62, 0x45, 0x7C, 0x3C, 0x51, 0x46, 0x07, - 0x9D, 0xDE, 0xE4, 0x29, 0x85, 0x7F, 0xA2, 0x2E, 0x4B, 0x23, 0x6B, 0xD5, 0x21, 0x57, 0x7C, 0x8E, 0x4D, 0x32, 0xEC, 0x56, 0x9C, 0x15, 0x3E, 0xCC, 0x10, 0xBD, - 0xF8, 0x28, 0xE6, 0xE2, 0xC4, 0x96, 0xA6, 0xA2, 0xC4, 0xEE, 0x18, 0x01, 0x24, 0x47, 0xD3, 0x4D, 0x40, 0xFC, 0x0E, 0xD6, 0x0F, 0x42, 0xE1, 0x6C, 0xDD, 0xEA, - 0x38, 0x40, 0x00, 0x45, 0xB8, 0x1F, 0x8F, 0x55, 0x2C, 0x70, 0x6C, 0xE1, 0x62, 0x97, 0xB3, 0xD0, 0xB1, 0xBB, 0x19, 0x18, 0x79, 0x7A, 0x9B, 0x84, 0xC0, 0x8B, - 0x59, 0xD8, 0x68, 0x8D, 0x28, 0x86, 0xAB, 0x3F, 0x1A, 0x6D, 0x27, 0xB9, 0xBC, 0x03, 0xB6, 0xAC, 0x84, 0x02, 0xE9, 0x60, 0x89, 0x3E, 0x2A, 0x7B, 0xCD, 0x60, - 0x16, 0xAA, 0xED, 0x89, 0x35, 0xA5, 0xBD, 0xD3, 0xAD, 0x7A, 0x06, 0x40, 0x70, 0xAB, 0xD2, 0x5E, 0x30, 0x1A, 0x4F, 0xA3, 0x62, 0x89, 0xA6, 0x4D, 0x3D, 0x62, - 0x7C, 0xFE, 0x2A, 0x81, 0x8C, 0x56, 0xFF, 0x43, 0x4C, 0xEC, 0x1A, 0x16, 0x05, 0x53, 0x97, 0xD8, 0x13, 0x37, 0x6D, 0xD7, 0x21, 0xF2, 0x5E, 0x13, 0xD5, 0x11, - 0xDE, 0x11, 0x3F, 0x33, 0xC9, 0xDC, 0xD8, 0xD8, 0x41, 0x04, 0xE6, 0x91, 0x60, 0xE3, 0x39, 0xBC, 0x5A, 0xB2, 0x3D, 0xB9, 0x92, 0x96, 0xE9, 0x1A, 0xB4, 0xCD, - 0xC3, 0x43, 0xED, 0x65, 0x10, 0x18, 0xA0, 0x00, 0x5C, 0x66, 0x5D, 0xA2, 0x7C, 0x34, 0x83, 0x17, 0x7C, 0x5D, 0x0F, 0x8D, 0x12, 0xEB, 0xCF, 0x1E, 0x70, 0x4D, - 0xBD, 0xD1, 0x07, 0x10, 0xE1, 0xA4, 0x14, 0x55, 0xE7, 0x3F, 0x1B, 0xE2, 0xDD, 0x7E, 0xA0, 0x02, 0x73, 0xBD, 0x97, 0xE0, 0x8B, 0x7B, 0x9D, 0x68, 0xA9, 0x64, - 0x8F, 0xD5, 0x37, 0x3B, 0x80, 0xEA, 0x12, 0xFA, 0x00, 0x1D, 0x47, 0x36, 0xCF, 0xB8, 0x09, 0xF5, 0xAE, 0x9D, 0x9F, 0x9F, 0x73, 0x65, 0xA4, 0x0B, 0xAA, 0xD0, - 0xC2, 0x75, 0x3E, 0x93, 0xDB, 0xCD, 0x1A, 0xC4, 0x1F, 0x95, 0x48, 0x53, 0x45, 0x5B, 0x2E, 0x1D, 0xD2, 0x81, 0x96, 0x17, 0xBC, 0x4C, 0xD6, 0x1B, 0x48, 0x1A, - 0x45, 0x2A, 0xA0, 0xD6, 0x89, 0x9E, 0xF8, 0xD5, 0x56, 0xA3, 0xBB, 0x27, 0xF2, 0x33, 0x49, 0x79, 0x99, 0x13, 0xC8, 0x85, 0x27, 0x86, 0xAE, 0x54, 0x0F, 0x4F, - 0x92, 0xA8, 0xEE, 0xF6, 0x9F, 0x44, 0x91, 0x61, 0xB3, 0x36, 0x8D, 0x80, 0x24, 0x83, 0x43, 0x68, 0x0B, 0xE2, 0xE6, 0xCA, 0x0D, 0x48, 0x2A, 0x62, 0x58, 0x8E, - 0x15, 0x58, 0x86, 0xFD, 0x31, 0xB2, 0xC6, 0x9D, 0xBA, 0xBF, 0xC4, 0xC7, 0x4B, 0xF8, 0xFF, 0x56, 0x85, 0x57, 0xAD, 0x2A, 0xB9, 0x65, 0x21, 0x61, 0x3C, 0x88, - 0xAC, 0x24, 0x2E, 0x87, 0x44, 0x58, 0xE0, 0xF7, 0x45, 0x4F, 0x4F, 0x9F, 0xD2, 0xA3, 0x27, 0xA1, 0xD2, 0x44, 0xF4, 0x38, 0xD7, 0xA2, 0x1B, 0x29, 0x05, 0x6F, - 0xE3, 0x4E, 0xE1, 0x10, 0xC8, 0x63, 0x18, 0x98, 0x6F, 0x85, 0xEA, 0x5D, 0xC3, 0x54, 0x17, 0x6D, 0xE1, 0xFF, 0xA3, 0xFE, 0x23, 0x8A, 0xFA, 0xBB, 0x0B, 0xF1, - 0x39, 0xB6, 0x9D, 0xF2, 0x00, 0x06, 0x27, 0x5F, 0x74, 0x79, 0xBE, 0x77, 0xA0, 0xC9, 0x57, 0x55, 0x52, 0x69, 0xC5, 0xD2, 0x32, 0x19, 0xC9, 0x91, 0x5D, 0xA1, - 0x84, 0x70, 0x61, 0x14, 0x97, 0x0E, 0x71, 0x1D, 0xB1, 0xB5, 0xC7, 0x56, 0x6D, 0x69, 0x34, 0xBE, 0x8B, 0x12, 0x92, 0xA5, 0x7B, 0x9D, 0x07, 0xE9, 0x41, 0xCC, - 0xB9, 0x22, 0x29, 0xE0, 0x10, 0xDA, 0xB4, 0x7C, 0x63, 0x6A, 0x17, 0x77, 0xCD, 0xDB, 0x99, 0x7C, 0x28, 0x80, 0x06, 0xE2, 0x0A, 0x80, 0x06, 0x1E, 0xF5, 0x99, - 0x18, 0x5A, 0xE2, 0x14, 0x61, 0x15, 0x64, 0xE5, 0x22, 0x9E, 0x1B, 0xE0, 0xC4, 0x49, 0xCC, 0x2C, 0x90, 0x96, 0x08, 0xB1, 0xF1, 0xCB, 0x00, 0x91, 0x3C, 0x3D, - 0xD7, 0x9C, 0x8D, 0x6D, 0x83, 0x05, 0x22, 0x0B, 0x60, 0x81, 0xF1, 0xBB, 0xD2, 0x00, 0xFD, 0xE7, 0x8D, 0x66, 0x21, 0xE5, 0x09, 0x09, 0x3C, 0x7B, 0x96, 0xC4, - 0x86, 0xCB, 0xB7, 0x2C, 0x35, 0x0F, 0x7B, 0x63, 0xED, 0xD9, 0xDB, 0x74, 0xA3, 0x51, 0x96, 0x93, 0x04, 0x43, 0xF5, 0xD3, 0x84, 0xE0, 0x63, 0x19, 0x0E, 0x10, - 0x62, 0x99, 0x54, 0x40, 0xB8, 0x49, 0x43, 0xDF, 0x5A, 0xE9, 0x7A, 0x41, 0xAD, 0xBE, 0x45, 0xF8, 0x1E, 0x9D, 0x7D, 0x90, 0x3F, 0x1A, 0x73, 0x74, 0x41, 0x64, - 0x3B, 0x61, 0x57, 0x71, 0x8C, 0x8B, 0x04, 0x46, 0x64, 0x2C, 0x45, 0x37, 0xFE, 0x68, 0x07, 0xD0, 0x14, 0x77, 0xC8, 0xC4, 0x06, 0xEF, 0xED, 0xD1, 0x9F, 0x76, - 0xBC, 0xDD, 0x30, 0x97, 0x82, 0xEB, 0xE9, 0xA7, 0x05, 0x34, 0x97, 0x31, 0x46, 0xD1, 0x5D, 0x4F, 0x91, 0x25, 0x4A, 0x02, 0x1C, 0xE6, 0xA1, 0x9A, 0x1B, 0x33, - 0xF2, 0xC9, 0x23, 0x33, 0x77, 0xE1, 0x58, 0xBF, 0x13, 0x19, 0x42, 0xE6, 0x50, 0x2D, 0xE2, 0x78, 0xAE, 0x98, 0x66, 0x23, 0x72, 0xEE, 0x2B, 0xC9, 0xEB, 0x99, - 0x3D, 0x69, 0x3A, 0xB8, 0xD5, 0x27, 0x0B, 0x37, 0x1F, 0xF8, 0x56, 0x70, 0xBB, 0xDD, 0xCF, 0x44, 0x6B, 0xF7, 0x04, 0xF5, 0xD0, 0xF4, 0x0D, 0x6E, 0xD0, 0x09, - 0x79, 0x08, 0x2F, 0x24, 0x93, 0x50, 0xE1, 0x9E, 0xE1, 0x0A, 0x58, 0xDC, 0x5E, 0xD8, 0x50, 0x19, 0x8D, 0x93, 0x91, 0x41, 0xDE, 0xD3, 0xC8, 0xD1, 0xC3, 0x61, - 0x43, 0x1A, 0xDF, 0x6B, 0x0E, 0x1A, 0x39, 0x38, 0xD9, 0xC6, 0x97, 0x34, 0xD2, 0xCD, 0x74, 0x65, 0x05, 0x12, 0x84, 0x7B, 0xBD, 0xBD, 0x32, 0xE3, 0x4F, 0xDC, - 0x5B, 0x59, 0xC4, 0xA3, 0xA9, 0x39, 0x20, 0x4A, 0xAC, 0xE8, 0xCD, 0xD8, 0x06, 0xCF, 0x17, 0x30, 0xFD, 0xC6, 0x75, 0x3A, 0x54, 0x70, 0x6A, 0x81, 0x9C, 0xA1, - 0x60, 0xFB, 0x3A, 0x28, 0x8A, 0xE4, 0xCE, 0x0E, 0xB1, 0x9B, 0x22, 0x99, 0xC9, 0xC7, 0x37, 0x14, 0xFC, 0xEA, 0x11, 0x80, 0xF3, 0xB1, 0x9A, 0xA8, 0x7D, 0xF9, - 0x07, 0x45, 0x71, 0xA7, 0xCD, 0x21, 0x5A, 0xF8, 0x4B, 0x62, 0xD2, 0xCA, 0x57, 0xB0, 0xF1, 0x4F, 0x35, 0x5C, 0x14, 0x4F, 0xEC, 0xE4, 0xB8, 0xFB, 0x35, 0xB4, - 0x90, 0x70, 0xB0, 0x29, 0x9C, 0x6C, 0xD0, 0x0D, 0x3F, 0xF9, 0xF3, 0x0C, 0x96, 0x9E, 0x4B, 0x0A, 0x4B, 0xF8, 0x63, 0x91, 0xC4, 0xEE, 0x40, 0x4E, 0x03, 0xDD, - 0x7C, 0x07, 0xD9, 0x4B, 0xCA, 0x4C, 0xF7, 0xF9, 0x34, 0x09, 0x34, 0x60, 0x8A, 0x90, 0xC7, 0x74, 0x84, 0x93, 0x21, 0x26, 0xA6, 0x84, 0x84, 0x19, 0x33, 0x9C, - 0x97, 0xE2, 0xDD, 0x30, 0x3C, 0x0B, 0x08, 0x65, 0xF1, 0x9B, 0x0F, 0x93, 0x9B, 0xFD, 0x27, 0xA1, 0x18, 0xB6, 0x71, 0x60, 0x07, 0x31, 0x04, 0x09, 0x11, 0x65, - 0x89, 0x89, 0x1B, 0x4D, 0x72, 0x5E, 0x96, 0x23, 0x33, 0xF6, 0x8B, 0x8D, 0x99, 0x74, 0xC0, 0xA4, 0x3D, 0xFF, 0x8B, 0x1A, 0xCD, 0xBF, 0x0F, 0xD8, 0x20, 0x1B, - 0x8B, 0x79, 0xFB, 0x65, 0x08, 0xDA, 0x9A, 0x24, 0x16, 0x12, 0x73, 0x6F, 0xE9, 0xB2, 0xF8, 0x41, 0x80, 0xA3, 0xF8, 0x20, 0x29, 0xDD, 0x9A, 0x26, 0xC6, 0x73, - 0xBA, 0x90, 0x41, 0x89, 0x6C, 0x62, 0x73, 0x3C, 0x21, 0x1E, 0x69, 0x3E, 0x97, 0x29, 0x2E, 0x66, 0x5F, 0xCC, 0x61, 0xAF, 0x2C, 0x72, 0x9D, 0x5B, 0x37, 0xA5, - 0x7B, 0xB5, 0xA8, 0xBC, 0x22, 0x80, 0x8B, 0x70, 0x6F, 0x5E, 0x21, 0x64, 0xB4, 0x8F, 0x2F, 0x86, 0x83, 0x6E, 0xD2, 0x53, 0x5B, 0x5C, 0xA5, 0x4D, 0x13, 0xA0, - 0x88, 0xB5, 0x18, 0x56, 0xEC, 0xDB, 0x4E, 0x93, 0x1F, 0x1F, 0x7C, 0xF2, 0xE0, 0xE9, 0x28, 0xC7, 0x1A, 0xC7, 0xA0, 0xA9, 0xE7, 0x17, 0x03, 0xC7, 0x77, 0x04, - 0xC6, 0x69, 0x37, 0xAE, 0x14, 0x80, 0xA3, 0x6D, 0x8C, 0x31, 0x50, 0x31, 0x9E, 0xE5, 0x01, 0x42, 0x1B, 0xB6, 0x4D, 0x75, 0x2F, 0xA6, 0x5F, 0x3F, 0x70, 0xD7, - 0x1F, 0x28, 0x21, 0xA9, 0x40, 0x74, 0x4D, 0x17, 0x07, 0x3A, 0x78, 0xBF, 0xC5, 0xD3, 0xA4, 0xB8, 0x6C, 0x93, 0xEB, 0xA9, 0x1F, 0x70, 0xE5, 0x40, 0x63, 0x78, - 0xF6, 0x92, 0x39, 0x2E, 0x5D, 0x54, 0x90, 0xF6, 0x80, 0x96, 0xD2, 0xF1, 0xBD, 0x19, 0x1B, 0x0E, 0xC2, 0x4D, 0x7F, 0x18, 0xAD, 0xF0, 0xF0, 0x57, 0xD6, 0x27, - 0x0E, 0xDF, 0x09, 0x9B, 0xDA, 0x2F, 0xA4, 0xC5, 0x5D, 0xA7, 0x49, 0x89, 0x4A, 0x4A, 0xCC, 0xBF, 0x7D, 0x1C, 0x07, 0xD8, 0xD0, 0x87, 0x11, 0x33, 0x66, 0x6F, - 0x19, 0x61, 0x39, 0x12, 0x13, 0x8F, 0x83, 0x49, 0xE2, 0x63, 0x63, 0x19, 0xDB, 0x31, 0xFA, 0xE2, 0xD3, 0x6C, 0x0A, 0xC3, 0xD7, 0x6B, 0x70, 0x3E, 0xF0, 0xF6, - 0xEB, 0xD6, 0xFE, 0x5D, 0x1E, 0x3B, 0x4C, 0x5C, 0x91, 0xED, 0xA8, 0x12, 0x41, 0x07, 0x0A, 0x39, 0xB6, 0x84, 0x7C, 0xE4, 0xE8, 0xE2, 0x0E, 0x73, 0xE9, 0x88, - 0x69, 0x4A, 0x96, 0x60, 0xCF, 0xB7, 0x45, 0xCB, 0x32, 0xD5, 0x04, 0x82, 0x68, 0x08, 0xD8, 0x22, 0x36, 0x95, 0xA8, 0xC6, 0xEC, 0x42, 0x34, 0x10, 0xB4, 0xC7, - 0x7D, 0x30, 0x83, 0xF6, 0x64, 0x1E, 0x9F, 0x4A, 0x18, 0x99, 0x00, 0x42, 0x67, 0xCA, 0x59, 0xC2, 0x99, 0x19, 0xCE, 0x95, 0x91, 0x58, 0xC2, 0x99, 0x01, 0x41, - 0x01, 0xE1, 0x7E, 0xD3, 0xD2, 0x59, 0x03, 0x9D, 0x3B, 0x00, 0x3B, 0xEB, 0xD0, 0x87, 0x61, 0x70, 0x46, 0x82, 0x36, 0x40, 0x4F, 0x12, 0xB7, 0x97, 0x84, 0xBE, - 0x80, 0x90, 0xDF, 0x67, 0x67, 0xAC, 0x41, 0xD8, 0xCB, 0xD4, 0x35, 0x6F, 0x3B, 0xC6, 0x7A, 0x4D, 0x1C, 0xF3, 0x62, 0x69, 0xD9, 0x66, 0x8B, 0x81, 0xC6, 0xD6, - 0x31, 0x30, 0x2C, 0x12, 0xBA, 0xF5, 0x8D, 0x63, 0x05, 0x6F, 0xBE, 0x60, 0xD7, 0x5A, 0x7B, 0x7D, 0x53, 0xEC, 0x5C, 0xE4, 0xCD, 0x3A, 0xA6, 0x67, 0x5C, 0x7F, - 0x83, 0xFB, 0xA2, 0xA9, 0x39, 0x1C, 0x74, 0x0F, 0xBA, 0xBC, 0x41, 0x00, 0xE9, 0x96, 0x10, 0x39, 0xE2, 0xC5, 0xFD, 0xA3, 0x3F, 0x7E, 0xFF, 0x6D, 0x84, 0x37, - 0x70, 0x5F, 0xB3, 0x4B, 0xAD, 0x3D, 0xBA, 0xB1, 0xFA, 0xF0, 0xB7, 0x35, 0xEE, 0x57, 0x11, 0xC3, 0x4C, 0x4C, 0x8C, 0xB8, 0x67, 0x1A, 0x45, 0xC5, 0x9A, 0x7F, - 0x15, 0x47, 0x0A, 0x97, 0x1D, 0x18, 0x27, 0xD0, 0xDC, 0x5B, 0x32, 0x50, 0xB1, 0xA3, 0x1A, 0xC1, 0x91, 0x93, 0xAF, 0x61, 0xA2, 0xFA, 0x0B, 0x31, 0x3C, 0xD0, - 0xC7, 0x73, 0xAD, 0xA5, 0x77, 0xF5, 0xE7, 0x2D, 0x7A, 0xFD, 0x1D, 0xB0, 0xB3, 0x6C, 0xED, 0x3F, 0xEF, 0xED, 0xEF, 0x77, 0x7C, 0xD0, 0x19, 0x69, 0xB5, 0xFB, - 0xA2, 0x09, 0xFC, 0xA1, 0x6D, 0x58, 0x27, 0xD9, 0xF7, 0xDF, 0xBA, 0x1B, 0xCF, 0xCF, 0x6B, 0xF0, 0xCE, 0x72, 0x70, 0x24, 0xCE, 0x6B, 0xF2, 0x01, 0xA6, 0x2F, - 0x8E, 0xB9, 0xD5, 0x44, 0xA7, 0x1B, 0xC1, 0xC5, 0x9C, 0x91, 0xEE, 0x8F, 0x85, 0xA4, 0x3F, 0x96, 0xEE, 0xF3, 0x8C, 0x93, 0x60, 0xC5, 0xBB, 0x25, 0x96, 0xA5, - 0xEE, 0xE2, 0xC6, 0x11, 0xE5, 0x74, 0xBC, 0x6A, 0xB0, 0xA5, 0xFF, 0x54, 0xC0, 0xE2, 0x59, 0xD2, 0x56, 0x2D, 0x5C, 0x25, 0x11, 0x95, 0x66, 0x58, 0xB9, 0x19, - 0x69, 0xB2, 0x60, 0x9C, 0x9E, 0x2D, 0x27, 0xB3, 0xCF, 0x8B, 0x0D, 0xF8, 0xF8, 0x4A, 0x44, 0x54, 0x76, 0x0D, 0xA7, 0x9C, 0x61, 0xE8, 0x87, 0x29, 0x68, 0xDE, - 0x78, 0x04, 0xB7, 0x63, 0x23, 0x18, 0x9F, 0xAF, 0x16, 0x00, 0xD0, 0x49, 0x6A, 0x38, 0x8A, 0x69, 0x08, 0xB5, 0x4D, 0xB6, 0x24, 0x44, 0x40, 0xBB, 0xFD, 0x30, - 0x62, 0x21, 0x10, 0x9F, 0x75, 0x45, 0xBA, 0xDB, 0x9E, 0x5D, 0xA7, 0x03, 0xD6, 0xD6, 0xAC, 0xFA, 0x2E, 0xA6, 0x2D, 0xF1, 0x70, 0x4E, 0xC4, 0x0F, 0xC9, 0x67, - 0x9E, 0xC4, 0x99, 0x17, 0x55, 0x82, 0x02, 0x88, 0x4F, 0x34, 0xC7, 0x8F, 0xB3, 0x4F, 0x14, 0xD9, 0x27, 0x9C, 0x7D, 0x04, 0x88, 0x26, 0x9C, 0xC5, 0x25, 0x8B, - 0xD0, 0x18, 0x7F, 0x7A, 0x15, 0x71, 0x76, 0x3D, 0xCD, 0xA5, 0x93, 0x97, 0x12, 0x62, 0xEC, 0xE5, 0x03, 0x40, 0xFB, 0x15, 0xF8, 0x43, 0x9C, 0xAD, 0xEB, 0xA9, - 0x1A, 0x5B, 0xA2, 0x14, 0x81, 0x00, 0x11, 0x5B, 0xF2, 0x82, 0x85, 0x60, 0xE5, 0x35, 0x09, 0xF8, 0x23, 0x7C, 0x86, 0x63, 0x6A, 0x73, 0xCF, 0x58, 0x11, 0xFC, - 0x62, 0x7B, 0x48, 0xAC, 0x49, 0xEF, 0x17, 0xE6, 0x7E, 0xAC, 0x59, 0x8C, 0xC9, 0xB0, 0xE4, 0x51, 0x08, 0x1A, 0xB6, 0x8C, 0x41, 0x87, 0x74, 0xE4, 0x42, 0x8B, - 0x46, 0x2C, 0x83, 0x0B, 0x4F, 0x95, 0x84, 0x15, 0xB6, 0x8E, 0x1C, 0x21, 0x42, 0x20, 0x4A, 0x26, 0xA3, 0x74, 0xA9, 0x8C, 0xCD, 0x24, 0x18, 0xB3, 0xA9, 0xF9, - 0x42, 0xBC, 0x41, 0xC8, 0x52, 0xA2, 0x4D, 0xE8, 0x20, 0x0C, 0x3E, 0x8B, 0xCC, 0x42, 0x52, 0xD8, 0x42, 0xA2, 0xFE, 0xDE, 0x26, 0x58, 0x9E, 0xE0, 0x2F, 0x65, - 0xBC, 0xF8, 0xE6, 0x6B, 0xCD, 0xF5, 0x34, 0xDB, 0xBD, 0x26, 0xB8, 0x28, 0x28, 0x36, 0x90, 0x69, 0x53, 0x02, 0x01, 0x8E, 0xB0, 0x22, 0x13, 0xEE, 0x8F, 0x09, - 0x96, 0x96, 0x0F, 0x73, 0x62, 0x7C, 0x75, 0x28, 0x79, 0xAA, 0x87, 0xA3, 0x53, 0x21, 0x7B, 0xDB, 0x25, 0xF4, 0x84, 0x38, 0x19, 0x4C, 0x24, 0xCB, 0xA7, 0x9C, - 0xC7, 0xAD, 0xC0, 0x92, 0x57, 0xD6, 0x2A, 0x21, 0xC2, 0xF0, 0xF6, 0xA3, 0x95, 0xA2, 0x9C, 0x81, 0x42, 0x41, 0x86, 0x60, 0x91, 0x2C, 0x23, 0x5E, 0xB7, 0xA4, - 0x29, 0xAB, 0x1D, 0xE6, 0x68, 0x14, 0x4B, 0xE1, 0xD2, 0x68, 0x9E, 0xAD, 0x15, 0x26, 0x71, 0x36, 0xCA, 0xB1, 0xDF, 0xD9, 0xA1, 0x78, 0x14, 0x8A, 0x9D, 0x61, - 0xF6, 0x36, 0x79, 0x72, 0x76, 0xB8, 0x0C, 0x56, 0xF6, 0xE4, 0xC9, 0xFF, 0x02, 0x49, 0x60, 0xC8, 0xA8, 0x55, 0x0C, 0x01, 0x00 +//File: index_ov3660.html.gz, Size: 8636 +#define index_ov3660_html_gz_len 8636 +const unsigned char index_ov3660_html_gz[] = { + 0x1F, 0x8B, 0x08, 0x08, 0xD3, 0xA3, 0x7B, 0x67, 0x00, 0x03, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x6F, 0x76, 0x33, 0x36, 0x36, 0x30, 0x2E, 0x68, 0x74, 0x6D, + 0x6C, 0x00, 0xED, 0x3D, 0x69, 0x73, 0xDB, 0x46, 0xB2, 0xDF, 0xFD, 0x2B, 0x60, 0x66, 0xD7, 0xA2, 0xCA, 0x22, 0x45, 0xF0, 0xD2, 0x61, 0x89, 0x7E, 0xB6, 0xAC, + 0xD8, 0xA9, 0xB5, 0xB3, 0xDE, 0x28, 0x71, 0x92, 0xDA, 0xDA, 0x72, 0x40, 0x62, 0x48, 0x22, 0x06, 0x01, 0x2E, 0x00, 0xEA, 0x58, 0x97, 0x7E, 0xC7, 0xFB, 0x41, + 0xEF, 0x8F, 0xBD, 0xEE, 0x39, 0x70, 0x71, 0x00, 0x0C, 0x00, 0x92, 0x52, 0xF2, 0x1E, 0x5D, 0x65, 0xE1, 0x98, 0xEE, 0xE9, 0x7B, 0x7A, 0x7A, 0x06, 0xC0, 0xD9, + 0x53, 0xD3, 0x9D, 0x04, 0x77, 0x4B, 0xA2, 0xCD, 0x83, 0x85, 0x3D, 0x7A, 0x72, 0xC6, 0xFE, 0x68, 0xF0, 0x3B, 0x9B, 0x13, 0xC3, 0x64, 0x87, 0xF4, 0x74, 0x41, + 0x02, 0x43, 0x9B, 0xCC, 0x0D, 0xCF, 0x27, 0xC1, 0x79, 0x63, 0x15, 0x4C, 0x5B, 0xC7, 0x8D, 0xF4, 0x6D, 0xC7, 0x58, 0x90, 0xF3, 0xC6, 0xB5, 0x45, 0x6E, 0x96, + 0xAE, 0x17, 0x34, 0xB4, 0x89, 0xEB, 0x04, 0xC4, 0x81, 0xE6, 0x37, 0x96, 0x19, 0xCC, 0xCF, 0x4D, 0x72, 0x6D, 0x4D, 0x48, 0x8B, 0x9E, 0x1C, 0x58, 0x8E, 0x15, + 0x58, 0x86, 0xDD, 0xF2, 0x27, 0x86, 0x4D, 0xCE, 0xF5, 0x38, 0xAE, 0xC0, 0x0A, 0x6C, 0x32, 0xBA, 0xBC, 0xFA, 0xD8, 0xEB, 0x6A, 0x7F, 0xFF, 0xD4, 0x1B, 0x0E, + 0x3B, 0x67, 0x87, 0xEC, 0x5A, 0xD4, 0xC6, 0x0F, 0xEE, 0xE2, 0xE7, 0xF8, 0x1B, 0xBB, 0xE6, 0x9D, 0xF6, 0x35, 0x71, 0x09, 0x7F, 0x53, 0x20, 0xA2, 0x35, 0x35, + 0x16, 0x96, 0x7D, 0x77, 0xAA, 0xBD, 0xF2, 0xA0, 0xCF, 0x83, 0x77, 0xC4, 0xBE, 0x26, 0x81, 0x35, 0x31, 0x0E, 0x7C, 0xC3, 0xF1, 0x5B, 0x3E, 0xF1, 0xAC, 0xE9, + 0x8B, 0x35, 0xC0, 0xB1, 0x31, 0xF9, 0x32, 0xF3, 0xDC, 0x95, 0x63, 0x9E, 0x6A, 0xDF, 0xE8, 0xC7, 0xF8, 0x6F, 0xBD, 0xD1, 0xC4, 0xB5, 0x5D, 0x0F, 0xEE, 0x5F, + 0x7E, 0x8B, 0xFF, 0xD6, 0xEF, 0xD3, 0xDE, 0x7D, 0xEB, 0x3F, 0xE4, 0x54, 0xD3, 0x87, 0xCB, 0xDB, 0xC4, 0xFD, 0xFB, 0x27, 0x89, 0xD3, 0x79, 0x37, 0x8B, 0x7A, + 0x0E, 0x7F, 0x9C, 0x0F, 0xEF, 0x93, 0x49, 0x60, 0xB9, 0x4E, 0x7B, 0x61, 0x58, 0x8E, 0x04, 0x93, 0x69, 0xF9, 0x4B, 0xDB, 0x00, 0x19, 0x4C, 0x6D, 0x92, 0x8B, + 0xE7, 0x9B, 0x05, 0x71, 0x56, 0x07, 0x05, 0xD8, 0x10, 0x49, 0xCB, 0xB4, 0x3C, 0xD6, 0xEA, 0x14, 0xE5, 0xB0, 0x5A, 0x38, 0x85, 0x68, 0xF3, 0xE8, 0x72, 0x5C, + 0x87, 0x48, 0x04, 0x88, 0x1D, 0xDD, 0x78, 0xC6, 0x12, 0x1B, 0xE0, 0xDF, 0xF5, 0x26, 0x0B, 0xCB, 0x61, 0x46, 0x75, 0xAA, 0xF5, 0xFA, 0x9D, 0xE5, 0x6D, 0x81, + 0x2A, 0x7B, 0x43, 0xFC, 0xB7, 0xDE, 0x68, 0x69, 0x98, 0xA6, 0xE5, 0xCC, 0x4E, 0xB5, 0x63, 0x29, 0x0A, 0xD7, 0x33, 0x89, 0xD7, 0xF2, 0x0C, 0xD3, 0x5A, 0xF9, + 0xA7, 0x5A, 0x5F, 0xD6, 0x66, 0x61, 0x78, 0x33, 0xA0, 0x25, 0x70, 0x81, 0xD8, 0x96, 0x2E, 0xA5, 0x84, 0x37, 0xF1, 0xAC, 0xD9, 0x3C, 0x00, 0x95, 0xAE, 0xB5, + 0x49, 0x0B, 0x8D, 0xBB, 0x50, 0x91, 0x3E, 0x73, 0xE5, 0x26, 0x97, 0x9A, 0x61, 0x5B, 0x33, 0xA7, 0x65, 0x05, 0x64, 0x01, 0xEC, 0xF8, 0x81, 0x47, 0x82, 0xC9, + 0x3C, 0x8F, 0x94, 0xA9, 0x35, 0x5B, 0x79, 0x44, 0x42, 0x48, 0x28, 0xB7, 0x1C, 0x86, 0xE1, 0xE6, 0xFA, 0xAD, 0xD6, 0x0D, 0x19, 0x7F, 0xB1, 0x82, 0x16, 0x97, + 0xC9, 0x98, 0x4C, 0x5D, 0x8F, 0x48, 0x5B, 0x8A, 0x16, 0xB6, 0x3B, 0xF9, 0xD2, 0xF2, 0x03, 0xC3, 0x0B, 0x54, 0x10, 0x1A, 0xD3, 0x80, 0x78, 0xC5, 0xF8, 0x08, + 0x5A, 0x45, 0x31, 0xB6, 0xEC, 0x6E, 0x79, 0x03, 0xCB, 0xB1, 0x2D, 0x87, 0xA8, 0x93, 0x97, 0xD5, 0x6F, 0x12, 0x1D, 0x6B, 0xA5, 0xA0, 0x18, 0x6B, 0x31, 0xCB, + 0xB3, 0x12, 0xCA, 0xEB, 0x7A, 0x67, 0xDC, 0x6F, 0xF4, 0x4E, 0xE7, 0xAF, 0xEB, 0x37, 0xE7, 0x84, 0x99, 0xA9, 0xB1, 0x0A, 0xDC, 0xFA, 0x1E, 0xB1, 0xE6, 0x56, + 0x29, 0x3E, 0xFE, 0x6B, 0x41, 0x4C, 0xCB, 0xD0, 0x9A, 0x31, 0x77, 0x3E, 0xEE, 0x80, 0x4D, 0xED, 0x6B, 0x86, 0x63, 0x6A, 0x4D, 0xD7, 0xB3, 0xC0, 0x11, 0x0C, + 0x1A, 0x6E, 0x6C, 0xB8, 0x02, 0x03, 0xC7, 0x92, 0xEC, 0x4B, 0x58, 0xCE, 0xF1, 0x99, 0xB8, 0x44, 0xE4, 0x6E, 0x83, 0x3F, 0x85, 0x90, 0x83, 0xBF, 0x42, 0x07, + 0x92, 0xF0, 0x48, 0xD1, 0xE7, 0xE9, 0x2B, 0x4E, 0x61, 0x96, 0xCE, 0xF0, 0xB7, 0x30, 0x6E, 0x5B, 0xB9, 0xBA, 0x13, 0x8D, 0x84, 0x0E, 0x61, 0x98, 0x9D, 0x34, + 0xA1, 0xE9, 0xF5, 0x5C, 0x6B, 0x69, 0x18, 0x25, 0xF7, 0xE5, 0x30, 0x1C, 0xA9, 0x5C, 0xE5, 0xF8, 0x8B, 0x1B, 0x45, 0x09, 0x76, 0xE5, 0xAC, 0x46, 0xB1, 0x83, + 0xFD, 0x93, 0xD9, 0x10, 0xE3, 0x24, 0x33, 0x8A, 0xE0, 0x4F, 0x3D, 0x92, 0x44, 0xC8, 0x0A, 0xA3, 0x89, 0x04, 0x71, 0x76, 0x44, 0x59, 0xC3, 0x9B, 0xE5, 0xDD, + 0x12, 0xAC, 0xF9, 0x24, 0xA8, 0x46, 0x17, 0x09, 0xE2, 0x3C, 0x1A, 0x0A, 0xA3, 0x0C, 0xFE, 0xEE, 0x15, 0xF2, 0x8D, 0x6F, 0xC6, 0xAB, 0x20, 0x70, 0x1D, 0xBF, + 0xD6, 0x10, 0x95, 0xE5, 0x67, 0xBF, 0xAF, 0xFC, 0xC0, 0x9A, 0xDE, 0xB5, 0xB8, 0x4B, 0x83, 0x9F, 0x2D, 0x0D, 0x48, 0x21, 0xC7, 0x24, 0xB8, 0x21, 0x24, 0x3F, + 0xDD, 0x70, 0x8C, 0x6B, 0x88, 0x3B, 0xB3, 0x99, 0x2D, 0xB3, 0xBD, 0xC9, 0xCA, 0xF3, 0x31, 0x6F, 0x5B, 0xBA, 0x16, 0x20, 0xF6, 0xD6, 0x3B, 0x4E, 0xFA, 0xA0, + 0x62, 0x47, 0xAD, 0xC9, 0x58, 0xD2, 0x97, 0xBB, 0x0A, 0x50, 0xC6, 0x52, 0x4D, 0xB8, 0xC0, 0x8E, 0x15, 0xDC, 0x49, 0xEF, 0x71, 0x4F, 0x94, 0xDC, 0x11, 0x2E, + 0x98, 0x3B, 0x2C, 0x24, 0xE9, 0x3A, 0x9D, 0xCC, 0xC9, 0xE4, 0x0B, 0x31, 0x9F, 0x17, 0xA6, 0x61, 0x45, 0xE9, 0x61, 0xDB, 0x72, 0x96, 0xAB, 0xA0, 0x85, 0xE9, + 0xD4, 0x72, 0x2B, 0x3A, 0xA7, 0x06, 0x29, 0x58, 0xEC, 0x76, 0xF3, 0x92, 0x8A, 0xC1, 0xF2, 0x36, 0x5F, 0x08, 0x71, 0x62, 0x47, 0xB6, 0x31, 0x26, 0x76, 0x1E, + 0xC9, 0xDC, 0x19, 0x32, 0xC2, 0x2E, 0x8F, 0x55, 0xD9, 0xB9, 0x1B, 0xA5, 0x2C, 0x1A, 0xBC, 0xFA, 0x47, 0x7F, 0x55, 0x96, 0x23, 0x3D, 0x3E, 0x48, 0x5C, 0xF2, + 0x89, 0x0D, 0x0E, 0x96, 0x95, 0x7A, 0x43, 0x9B, 0x1B, 0xA0, 0x21, 0xB7, 0x03, 0xCF, 0x70, 0x66, 0x04, 0x62, 0xC1, 0xED, 0x81, 0x38, 0xCC, 0x9F, 0x18, 0x28, + 0xB1, 0x8F, 0xA1, 0x7A, 0x90, 0x3F, 0x11, 0x61, 0x01, 0xE1, 0x40, 0x6B, 0xB3, 0x83, 0x0A, 0x59, 0x49, 0x4C, 0xBF, 0xB9, 0x84, 0xE8, 0x52, 0xEB, 0x60, 0x89, + 0x89, 0xD4, 0x73, 0x92, 0xB6, 0x25, 0x4D, 0xF4, 0x0B, 0x43, 0x83, 0x98, 0xF2, 0x4D, 0xA7, 0x45, 0x93, 0xC6, 0xE9, 0xB4, 0xD7, 0xE9, 0xF5, 0x0B, 0x33, 0x27, + 0x29, 0x97, 0xA9, 0x89, 0xA3, 0x24, 0x74, 0x84, 0x61, 0x25, 0xD7, 0x08, 0x7C, 0xE3, 0x5A, 0x9A, 0xB4, 0xBB, 0xBE, 0xC5, 0x66, 0x6E, 0xC6, 0xD8, 0x87, 0xB9, + 0x5B, 0x20, 0x99, 0x7A, 0x71, 0x43, 0xEF, 0x4A, 0xE9, 0xA3, 0x29, 0x9D, 0xD4, 0x05, 0x84, 0x78, 0xE5, 0x64, 0x27, 0x34, 0x20, 0x6F, 0x12, 0x53, 0xB0, 0x34, + 0xA9, 0x0C, 0xC8, 0x6D, 0xD0, 0x32, 0xC9, 0xC4, 0xF5, 0x58, 0x36, 0x98, 0x31, 0x73, 0x4C, 0x29, 0xB2, 0xD8, 0x62, 0x4F, 0xE7, 0xEE, 0x35, 0xF1, 0x24, 0xC2, + 0x4A, 0x29, 0xB5, 0x7F, 0xD2, 0x37, 0x15, 0xB0, 0x19, 0x30, 0x3C, 0x4A, 0x65, 0x9F, 0x44, 0xD7, 0xD5, 0x27, 0xDD, 0x5C, 0x3F, 0x66, 0xE8, 0xDA, 0xE0, 0x33, + 0xC6, 0xD8, 0x26, 0x66, 0xCE, 0x68, 0x66, 0x92, 0xA9, 0xB1, 0xB2, 0x83, 0x02, 0xAB, 0x34, 0x3A, 0xF8, 0x2F, 0xAF, 0x47, 0x1A, 0x86, 0xFE, 0x89, 0x75, 0xA1, + 0x73, 0x1A, 0x38, 0xFE, 0x25, 0xE9, 0x53, 0xA4, 0x1A, 0xC6, 0x72, 0x49, 0x0C, 0x68, 0x35, 0x21, 0x59, 0x7A, 0x50, 0x9A, 0x62, 0xC8, 0xE3, 0xBC, 0xD2, 0xBC, + 0xBD, 0xD0, 0x61, 0xC3, 0xE4, 0xB1, 0x14, 0xCF, 0xA7, 0x53, 0x77, 0xB2, 0x92, 0x65, 0x35, 0x6A, 0x8E, 0xB7, 0x8E, 0xEF, 0x54, 0x88, 0xCC, 0xB7, 0x2D, 0xEA, + 0xFE, 0x2B, 0xC7, 0x41, 0x8D, 0xB6, 0x02, 0x0F, 0xD8, 0x94, 0x74, 0xA4, 0x26, 0xB8, 0x4A, 0x31, 0x2C, 0x21, 0xD8, 0xAC, 0xDA, 0x55, 0x2A, 0x4C, 0x49, 0xC2, + 0x69, 0x18, 0x69, 0x35, 0x88, 0x21, 0x96, 0x29, 0x50, 0xD5, 0x93, 0x4B, 0x30, 0x5F, 0x2D, 0x64, 0x79, 0x94, 0xE8, 0x4C, 0x87, 0x41, 0x9F, 0x75, 0xE7, 0xCD, + 0xC6, 0x46, 0xB3, 0x73, 0xD0, 0x39, 0xE8, 0xC1, 0x7F, 0x92, 0xF9, 0x4C, 0xBE, 0x71, 0x71, 0xF1, 0x66, 0x58, 0x5E, 0x2A, 0x44, 0x17, 0x97, 0x95, 0xB2, 0x82, + 0x7D, 0xA1, 0x2E, 0xD4, 0x3D, 0x29, 0x59, 0x5F, 0xD2, 0xDB, 0x05, 0xE3, 0x70, 0x86, 0x49, 0x97, 0x37, 0x44, 0x89, 0xB5, 0x94, 0x55, 0xF1, 0xC2, 0xFD, 0x4F, + 0x8B, 0x25, 0x21, 0xFF, 0xE7, 0xAD, 0x3D, 0x26, 0x8A, 0x3F, 0xB5, 0xA5, 0x97, 0x96, 0x8B, 0xFF, 0xD0, 0xB6, 0xD1, 0xC9, 0xD6, 0x7A, 0x8B, 0x67, 0x7D, 0x40, + 0xA1, 0x03, 0x73, 0x50, 0x0F, 0x26, 0xA3, 0x99, 0x99, 0x61, 0xAC, 0x4D, 0x05, 0x19, 0x4C, 0x2D, 0xDB, 0x6E, 0xD9, 0xEE, 0x4D, 0x71, 0x26, 0x92, 0x6F, 0xC9, + 0x6B, 0x76, 0x5A, 0x6C, 0xF2, 0x55, 0xA9, 0x5D, 0x41, 0xE4, 0xFA, 0x43, 0x50, 0xFB, 0xE7, 0x76, 0xB8, 0x5C, 0xD7, 0xA8, 0x36, 0x50, 0x54, 0xB0, 0xC7, 0x7A, + 0x1D, 0x29, 0x99, 0x12, 0xCB, 0x04, 0xF3, 0xA7, 0x3D, 0x37, 0x56, 0x30, 0x99, 0x57, 0x98, 0x7A, 0x46, 0x13, 0x23, 0x8F, 0xD8, 0x06, 0x66, 0xF0, 0x95, 0x2A, + 0x14, 0x85, 0xD3, 0xB7, 0x38, 0xB8, 0x0A, 0x27, 0x54, 0x74, 0x8F, 0xA7, 0xBA, 0xD4, 0x66, 0xB9, 0x43, 0x76, 0xAC, 0x96, 0x9B, 0x75, 0x41, 0xBA, 0x9F, 0xF4, + 0x0C, 0x79, 0xA3, 0x12, 0x11, 0x5D, 0x04, 0xED, 0x99, 0x47, 0xEE, 0x14, 0x98, 0x39, 0xE0, 0x7F, 0x4F, 0x59, 0xFD, 0xB8, 0x7A, 0xA9, 0x84, 0x0E, 0x00, 0xDC, + 0x8A, 0xDA, 0x7D, 0x5F, 0xA1, 0xEB, 0xEC, 0x2E, 0x55, 0xEC, 0x31, 0xAC, 0x8E, 0x36, 0x1A, 0x0A, 0xE1, 0x26, 0x67, 0x08, 0x95, 0x9B, 0xAA, 0x18, 0x7D, 0xE5, + 0xF3, 0x79, 0x32, 0x0D, 0x32, 0x16, 0x7F, 0x68, 0x9E, 0xDA, 0xCB, 0x8F, 0x6E, 0xAD, 0x58, 0x35, 0xA5, 0x30, 0x72, 0x84, 0x45, 0xCC, 0x6C, 0xEB, 0x93, 0x62, + 0xC6, 0xE8, 0x59, 0x1A, 0x79, 0xB6, 0x4A, 0x44, 0xFA, 0x4C, 0xD5, 0x0C, 0x6D, 0x16, 0x7C, 0xC8, 0x07, 0xF5, 0x90, 0x5F, 0x9A, 0xDD, 0xA1, 0x74, 0x6D, 0x25, + 0xA7, 0x71, 0x1E, 0x69, 0x99, 0x55, 0xC0, 0xF5, 0x21, 0x2B, 0x73, 0x82, 0x1C, 0x8F, 0x45, 0x52, 0x45, 0xE5, 0x7B, 0x65, 0x5E, 0x84, 0x59, 0xAF, 0x64, 0xE5, + 0x1A, 0xBB, 0xB5, 0x30, 0x20, 0xED, 0x45, 0x73, 0x35, 0x00, 0xA3, 0x4C, 0x7F, 0x2A, 0xE6, 0x1E, 0xAB, 0xB1, 0xEA, 0xC3, 0x4E, 0x41, 0x97, 0x13, 0xDB, 0xF5, + 0x6B, 0x16, 0xC0, 0xB2, 0xEB, 0x5F, 0xD2, 0x3B, 0x4A, 0x43, 0x77, 0xAE, 0x4F, 0xE5, 0xBB, 0x63, 0x4A, 0xE6, 0x7A, 0x47, 0x1A, 0x69, 0x73, 0xAB, 0x94, 0xB4, + 0x82, 0x46, 0xD7, 0x2F, 0x4F, 0xB5, 0x09, 0x91, 0x87, 0xD1, 0x64, 0xA1, 0x4E, 0xA5, 0x54, 0x9A, 0xAB, 0x87, 0xB9, 0x65, 0x9A, 0x24, 0xB7, 0x16, 0x8C, 0x73, + 0x5E, 0xC5, 0xE4, 0x01, 0xE9, 0x97, 0x15, 0xA5, 0xB6, 0xE2, 0x14, 0xB9, 0xDB, 0x1A, 0xF4, 0x6D, 0x7B, 0x0C, 0x1F, 0x68, 0xB2, 0x2A, 0xE9, 0xC9, 0x54, 0x24, + 0x97, 0x54, 0xA9, 0x73, 0x87, 0xB5, 0x56, 0x14, 0x19, 0xC8, 0x01, 0x5B, 0xAD, 0x47, 0xF3, 0x14, 0x55, 0x74, 0x21, 0xA5, 0xCD, 0xD7, 0x96, 0xF8, 0x32, 0x60, + 0x2B, 0x6B, 0x75, 0x65, 0x83, 0x4B, 0x6D, 0xD4, 0x02, 0xD2, 0xFD, 0x66, 0x8A, 0xE6, 0x81, 0x32, 0xA3, 0x1C, 0x22, 0xC3, 0x21, 0x46, 0x6C, 0xAE, 0x4A, 0xB6, + 0x2A, 0xEB, 0x1C, 0xE1, 0xF9, 0xD9, 0x61, 0x6C, 0x3B, 0xDC, 0xD9, 0x61, 0xB4, 0x73, 0xEF, 0x0C, 0xF7, 0xC4, 0xC5, 0x77, 0xCD, 0xF1, 0x8E, 0x26, 0xB6, 0xE1, + 0xFB, 0xE7, 0x0D, 0xDC, 0xDB, 0xD5, 0x48, 0x6E, 0xA2, 0x3B, 0x33, 0xAD, 0x6B, 0xCD, 0x32, 0xCF, 0x1B, 0xB6, 0x3B, 0x73, 0x53, 0xF7, 0xE8, 0x7D, 0xA6, 0x66, + 0x18, 0xC8, 0xCE, 0x1B, 0x89, 0x05, 0xC6, 0x06, 0x85, 0x8A, 0x2E, 0x35, 0x46, 0xCF, 0xBE, 0x39, 0x39, 0x3A, 0x1A, 0xBE, 0x78, 0xE6, 0x8C, 0xFD, 0x25, 0xFF, + 0xFF, 0x47, 0xB6, 0x1E, 0xCB, 0x36, 0xF5, 0xC1, 0xD8, 0x16, 0x04, 0x60, 0x7B, 0xFE, 0xD9, 0x21, 0x45, 0x9A, 0x22, 0xE4, 0x10, 0x28, 0xC9, 0xA0, 0x8D, 0xE7, + 0x3B, 0x32, 0xF2, 0x44, 0x13, 0x1F, 0x86, 0xF0, 0xB1, 0xE1, 0x49, 0x9A, 0xD0, 0x66, 0x2C, 0x9B, 0xA6, 0xB1, 0xA4, 0x41, 0x95, 0x32, 0x76, 0x6F, 0xD3, 0x1C, + 0x50, 0xA6, 0xB8, 0xC6, 0x78, 0x2B, 0x62, 0x66, 0x21, 0x04, 0x30, 0x0A, 0x8E, 0xAB, 0xAB, 0xD0, 0x46, 0xDA, 0x28, 0xA1, 0x02, 0x6C, 0x7C, 0x3B, 0xB1, 0xBF, + 0x08, 0xE5, 0x37, 0x84, 0x52, 0x1C, 0x37, 0x60, 0xB1, 0x32, 0xA3, 0xAB, 0x04, 0xAB, 0x1C, 0x26, 0xB6, 0x6E, 0xC8, 0xB8, 0x00, 0xD1, 0xB6, 0x28, 0x76, 0x76, + 0x2D, 0x1F, 0x13, 0xC5, 0x16, 0xD3, 0xAB, 0x00, 0x6E, 0x8C, 0x7E, 0xB9, 0x78, 0xFF, 0x37, 0xED, 0xC3, 0xBB, 0xFF, 0x48, 0x35, 0x54, 0x44, 0x14, 0x06, 0x69, + 0x85, 0x9E, 0x29, 0x18, 0xD3, 0x87, 0x90, 0x49, 0x83, 0x6B, 0x86, 0x62, 0xC0, 0xE1, 0xDE, 0x26, 0xCE, 0x2C, 0x98, 0x9F, 0x37, 0xF4, 0x06, 0xEE, 0x69, 0x11, + 0x67, 0xDD, 0x86, 0x86, 0x01, 0x9C, 0x1E, 0x5C, 0x1B, 0xF6, 0x0A, 0x8F, 0x3A, 0x2A, 0xBC, 0xAE, 0x9B, 0x96, 0xB4, 0x19, 0x8F, 0x2C, 0xA1, 0x8C, 0x63, 0x91, + 0x38, 0x29, 0xE5, 0xC6, 0xE8, 0x8A, 0x04, 0x67, 0x87, 0xEC, 0x56, 0x81, 0xD6, 0xF2, 0xFB, 0x06, 0x4F, 0x66, 0xE6, 0x90, 0x67, 0x42, 0x79, 0x8A, 0x9F, 0x7A, + 0xC6, 0x82, 0xA0, 0x54, 0x94, 0x34, 0x1F, 0xD7, 0x7A, 0x08, 0xD9, 0x18, 0xFD, 0x40, 0x68, 0x46, 0x04, 0x64, 0x28, 0x29, 0xFE, 0x8C, 0x27, 0xA9, 0x89, 0xFE, + 0x43, 0x7B, 0xE6, 0x8B, 0x52, 0x2D, 0x83, 0x99, 0xB9, 0x82, 0xDC, 0x9F, 0xB6, 0x5A, 0x5A, 0xEF, 0xC3, 0x47, 0xAD, 0xD5, 0x52, 0x68, 0xEC, 0x2E, 0xA9, 0x3B, + 0x71, 0xFD, 0xEB, 0x27, 0x8D, 0xD1, 0x3F, 0x7E, 0x79, 0xFB, 0xAA, 0xD9, 0xED, 0xF4, 0x8F, 0x6F, 0xF5, 0xC1, 0xB0, 0xBF, 0x7F, 0x76, 0xC8, 0x9A, 0x94, 0xC7, + 0x75, 0xDC, 0x18, 0x7D, 0x44, 0x42, 0x9A, 0xC7, 0xC3, 0x7E, 0x5D, 0x5C, 0x47, 0x88, 0xEB, 0xDD, 0x9B, 0xE6, 0x51, 0xB7, 0x73, 0xAB, 0x77, 0x8F, 0x3B, 0x35, + 0x50, 0x0D, 0x1B, 0xA3, 0x6F, 0x01, 0x93, 0x7E, 0x82, 0xA8, 0x3A, 0xE5, 0x50, 0xA1, 0x68, 0xBB, 0x15, 0x45, 0x3B, 0x68, 0x8C, 0x7E, 0x42, 0xD1, 0x42, 0xCE, + 0x8D, 0x3C, 0x74, 0xEA, 0xF0, 0xD0, 0x07, 0x97, 0xA1, 0xB8, 0x40, 0x14, 0xC0, 0x44, 0xB7, 0x8E, 0x68, 0x7B, 0x8D, 0x11, 0x8A, 0x03, 0x31, 0x81, 0x74, 0x6B, + 0x20, 0xEA, 0x42, 0xC0, 0x43, 0x9A, 0x80, 0x9C, 0xDB, 0xA3, 0xE1, 0x71, 0x0D, 0x4C, 0x3A, 0xB0, 0xF7, 0x09, 0x50, 0x1D, 0x83, 0xA4, 0x86, 0xB5, 0x04, 0x05, + 0xF1, 0x0C, 0x11, 0x0D, 0xFB, 0x9D, 0xDB, 0x7E, 0x1D, 0xAB, 0x01, 0xBF, 0x78, 0x87, 0x88, 0x00, 0xC9, 0x6D, 0xAF, 0x8E, 0x94, 0xC0, 0x29, 0x2E, 0xBE, 0xFB, + 0xB6, 0xD9, 0x07, 0xCE, 0xBA, 0x27, 0xC3, 0xEA, 0x78, 0xC0, 0x21, 0x80, 0x0E, 0xA4, 0xA5, 0x32, 0x0A, 0x70, 0x84, 0x7F, 0x20, 0x4F, 0x88, 0xA7, 0xDB, 0xAF, + 0xC1, 0x13, 0x58, 0x36, 0xC0, 0x23, 0x8E, 0xCA, 0x28, 0xC0, 0xA0, 0xDF, 0x51, 0x62, 0x10, 0x91, 0x7E, 0x54, 0x43, 0x30, 0x60, 0xCE, 0xFF, 0x40, 0x09, 0x03, + 0x92, 0x5B, 0xBD, 0x5F, 0xC3, 0x31, 0xC0, 0x9C, 0xC1, 0x29, 0x30, 0xDA, 0x54, 0x37, 0x3F, 0xA0, 0x85, 0x72, 0x05, 0x3E, 0x8F, 0x2E, 0x5F, 0x9D, 0x18, 0xB0, + 0xE3, 0x93, 0xE1, 0xED, 0xC9, 0x50, 0x0D, 0x01, 0x0E, 0x83, 0x38, 0xA4, 0xE4, 0x0D, 0x94, 0xF9, 0xE3, 0x68, 0xDE, 0x18, 0xF9, 0xEF, 0x15, 0x4C, 0x7D, 0x83, + 0xBB, 0xD2, 0x23, 0x24, 0x87, 0x03, 0x99, 0xB0, 0x03, 0xB5, 0xC1, 0x31, 0x46, 0x49, 0xB8, 0x0B, 0xAB, 0x31, 0xEA, 0x2B, 0x24, 0x21, 0x89, 0x2C, 0x95, 0xC2, + 0x26, 0xE8, 0xA7, 0x99, 0x11, 0x5A, 0x1E, 0xE6, 0x44, 0xE0, 0x0D, 0xBD, 0x46, 0x2C, 0x6A, 0x54, 0x1A, 0x7D, 0x25, 0xB4, 0x1A, 0xB7, 0x8D, 0xD1, 0xB0, 0x57, + 0x98, 0xB5, 0x54, 0x57, 0xC6, 0x98, 0x16, 0x59, 0x1C, 0xE2, 0xFB, 0xA5, 0xF5, 0x11, 0x81, 0x36, 0x46, 0xAF, 0xC3, 0xE3, 0x3A, 0x5A, 0x69, 0x15, 0x71, 0x4A, + 0x61, 0x33, 0xD4, 0x12, 0x23, 0x87, 0x69, 0xA6, 0xD5, 0xE3, 0xAA, 0x89, 0x34, 0xB3, 0x59, 0xC5, 0x6C, 0x53, 0x2F, 0x38, 0xC7, 0xF2, 0x0C, 0x3F, 0x28, 0xAD, + 0x15, 0x01, 0x08, 0xE3, 0x04, 0x3F, 0x7A, 0x30, 0x8D, 0x84, 0xA4, 0xFC, 0x09, 0xF4, 0xE1, 0x1B, 0xC1, 0x8A, 0xED, 0x77, 0x2B, 0xAD, 0x91, 0x08, 0x14, 0xD2, + 0x92, 0xF0, 0xB8, 0x96, 0x56, 0xEA, 0x84, 0xAF, 0x18, 0x39, 0x5C, 0x2F, 0x22, 0x84, 0xF5, 0xB7, 0xA4, 0x97, 0x22, 0x6A, 0x6B, 0xE9, 0x65, 0x6E, 0x78, 0xCB, + 0x4A, 0xE1, 0x2B, 0x84, 0x04, 0xAD, 0x88, 0xC3, 0x07, 0x73, 0x95, 0x88, 0x98, 0x3F, 0x81, 0xAF, 0x98, 0xC4, 0x71, 0x2D, 0xBF, 0xFC, 0x14, 0x98, 0xC3, 0x35, + 0x46, 0x6F, 0x48, 0xEB, 0x7B, 0x3C, 0xAA, 0xA3, 0x8E, 0x57, 0xAB, 0xC0, 0xAD, 0xA1, 0x10, 0x41, 0x0B, 0x53, 0x47, 0x87, 0x6B, 0xE3, 0x78, 0x4B, 0xDA, 0x38, + 0xDE, 0xA2, 0x36, 0x0C, 0xF2, 0xD9, 0x26, 0xD7, 0xC4, 0x2E, 0xAD, 0x0E, 0x01, 0xD8, 0x18, 0x5D, 0xDE, 0x2E, 0x5D, 0x1F, 0x9F, 0x22, 0x7A, 0x8F, 0xE7, 0xB5, + 0x9C, 0x64, 0x50, 0x43, 0x27, 0x21, 0x41, 0xDC, 0x47, 0x06, 0x5C, 0x2B, 0x83, 0x2D, 0x69, 0xA5, 0x88, 0xD6, 0x3A, 0x5A, 0x99, 0x19, 0x96, 0x33, 0x21, 0x96, + 0x8D, 0x4F, 0x34, 0x94, 0x55, 0x4C, 0x0C, 0xB6, 0x31, 0x7A, 0x1B, 0x9D, 0xD4, 0x51, 0x4C, 0xA7, 0x86, 0x5E, 0xE2, 0xF4, 0x24, 0xFD, 0x65, 0x00, 0x53, 0xF1, + 0x2D, 0xE9, 0x46, 0xD7, 0xB7, 0x39, 0xAA, 0x2C, 0xC9, 0xC4, 0x32, 0xEC, 0xCF, 0x64, 0x3A, 0x85, 0x69, 0x50, 0xF9, 0xA1, 0x25, 0x01, 0x0E, 0xE3, 0x0B, 0x3B, + 0xD7, 0x2E, 0xE9, 0x79, 0xE9, 0xA2, 0x5E, 0x0A, 0x5D, 0xF5, 0xCA, 0x5E, 0x7A, 0x4E, 0xC8, 0x97, 0xB7, 0x09, 0xAD, 0xA5, 0xB2, 0xA3, 0xC6, 0xE8, 0x7B, 0x37, + 0xA4, 0xB3, 0xFA, 0xB4, 0xF5, 0x7B, 0x32, 0xA3, 0xAB, 0xC7, 0x75, 0x66, 0xCF, 0x6F, 0x3D, 0xE3, 0x8E, 0xBE, 0x9E, 0xA0, 0xCE, 0x5C, 0xFE, 0x07, 0x62, 0x6A, + 0x3F, 0x5A, 0x4E, 0x75, 0x66, 0xFA, 0x48, 0x08, 0x21, 0x4E, 0x3D, 0x2C, 0x03, 0x98, 0x22, 0xC1, 0x41, 0x3D, 0x24, 0x43, 0x2C, 0x74, 0x2F, 0x2D, 0xE3, 0x31, + 0x4C, 0xE2, 0x8D, 0x9B, 0x71, 0xF9, 0x01, 0xE5, 0x66, 0x0C, 0xE3, 0xF2, 0xCF, 0xAF, 0xB5, 0x4B, 0xBA, 0xDF, 0xB9, 0x74, 0xB8, 0x62, 0x5B, 0xB1, 0x54, 0x0C, + 0x3D, 0x5A, 0xCF, 0xC0, 0x3E, 0xD7, 0x16, 0x9A, 0xE4, 0x0E, 0xA4, 0xBA, 0xD8, 0x24, 0x61, 0x4F, 0x10, 0x48, 0x77, 0xAE, 0x34, 0x62, 0xDC, 0xAA, 0xF1, 0xB8, + 0xC5, 0x54, 0x6C, 0x72, 0x53, 0x3E, 0x0D, 0x9B, 0xDC, 0x80, 0x9A, 0xCC, 0x6B, 0xDC, 0x0A, 0x6F, 0x6A, 0xA0, 0xAF, 0x9D, 0x28, 0x0A, 0x7B, 0x7D, 0x18, 0x45, + 0x51, 0x7E, 0x1F, 0x5A, 0x51, 0x60, 0x2D, 0x9F, 0x71, 0x1C, 0xAD, 0xE2, 0x54, 0x14, 0xB0, 0x31, 0xFA, 0x60, 0x38, 0x2B, 0x18, 0x64, 0x76, 0xA5, 0xB0, 0xB0, + 0xE3, 0x07, 0x73, 0x2F, 0xCE, 0xF7, 0x43, 0xAB, 0x0E, 0x08, 0x59, 0xB8, 0x66, 0xF9, 0xE9, 0x0E, 0x87, 0x63, 0x21, 0xF1, 0x03, 0x1C, 0x95, 0x4E, 0x0C, 0x04, + 0x86, 0x2D, 0x67, 0x04, 0x6C, 0x2A, 0x55, 0x3D, 0x19, 0xB8, 0x5A, 0x39, 0xCE, 0x5D, 0x9D, 0x4C, 0xE0, 0xC2, 0x76, 0x57, 0x66, 0x75, 0x0C, 0x90, 0x06, 0xFC, + 0x7D, 0x3A, 0xB5, 0x26, 0xD5, 0x13, 0x09, 0x5C, 0x5E, 0x70, 0x17, 0x8A, 0xF0, 0x5B, 0x1E, 0x78, 0xC9, 0xA4, 0xC2, 0x4C, 0x6E, 0x02, 0x5A, 0xBC, 0xBC, 0xD8, + 0xE9, 0xC0, 0x0B, 0x7D, 0x3E, 0x50, 0x64, 0x40, 0x6E, 0x1F, 0x3A, 0x28, 0x00, 0x11, 0x9F, 0xA9, 0xF1, 0x54, 0x51, 0x16, 0x83, 0x0C, 0x23, 0xBA, 0x98, 0x7E, + 0x3F, 0xD4, 0xFC, 0x2E, 0xA2, 0x28, 0x39, 0xBB, 0xD3, 0x07, 0xBD, 0x61, 0x38, 0xBD, 0xEB, 0x75, 0x37, 0x3B, 0xC1, 0x43, 0xE4, 0xDB, 0xD5, 0x4F, 0xB7, 0x8A, + 0x6A, 0x20, 0x1A, 0x7D, 0x8F, 0xEB, 0x0C, 0x25, 0x02, 0x76, 0x7D, 0x47, 0xEA, 0x3E, 0x9C, 0x27, 0x75, 0x1F, 0x81, 0x2B, 0xCD, 0x2A, 0x44, 0xBC, 0x19, 0x46, + 0xBC, 0xB7, 0x17, 0xBB, 0xD1, 0xD0, 0xEC, 0xC1, 0x42, 0xDD, 0xEC, 0x41, 0x43, 0x9D, 0xC6, 0x77, 0xCA, 0x09, 0x29, 0x54, 0xCC, 0x60, 0x39, 0x20, 0xAB, 0x65, + 0xD5, 0x09, 0x72, 0xFA, 0x6D, 0x9D, 0x28, 0x27, 0xC8, 0x48, 0x06, 0xB9, 0x61, 0xB4, 0x2A, 0x32, 0xD8, 0xEC, 0xB2, 0x6E, 0xBF, 0x88, 0xDA, 0x3A, 0x4E, 0xE3, + 0x19, 0x37, 0x9F, 0x67, 0x0B, 0xA3, 0xB4, 0x32, 0x38, 0x1C, 0xE8, 0xE2, 0xC3, 0xAB, 0x5D, 0xA6, 0x0B, 0xA2, 0xDF, 0x87, 0xF1, 0xA3, 0x90, 0xEB, 0x87, 0x8E, + 0x75, 0x36, 0x71, 0xCA, 0x07, 0x3B, 0x04, 0x6A, 0x8C, 0xDE, 0x13, 0xC7, 0xD7, 0x2E, 0x5C, 0x8F, 0xBF, 0x13, 0x72, 0x27, 0x5A, 0xA3, 0x3D, 0x3F, 0x8C, 0xCA, + 0x18, 0xD3, 0x0F, 0xAD, 0xAF, 0xF9, 0xC2, 0xF2, 0x3C, 0xD7, 0x2B, 0xAD, 0x32, 0x0E, 0x07, 0xD3, 0x8A, 0xD6, 0x07, 0x7A, 0xB4, 0x13, 0x75, 0x89, 0x5E, 0x1F, + 0x46, 0x63, 0x21, 0xCF, 0x0F, 0xAD, 0xB4, 0xEB, 0xA9, 0x6D, 0x2D, 0x4B, 0xAB, 0x8C, 0x42, 0x35, 0x46, 0x9F, 0x5A, 0xDF, 0xC2, 0xDF, 0x9D, 0xA8, 0x8B, 0xF5, + 0xF8, 0x30, 0xCA, 0xE2, 0xDC, 0x3E, 0xB4, 0xAA, 0xC6, 0xCB, 0xF2, 0xE1, 0x10, 0x60, 0x1A, 0xA3, 0xD7, 0x1F, 0x77, 0x93, 0xFB, 0x61, 0x67, 0x8A, 0x1A, 0xAA, + 0xA5, 0x0F, 0xCA, 0xD4, 0x43, 0x6B, 0xE3, 0xA6, 0x82, 0x36, 0x6E, 0x90, 0xF0, 0x9F, 0x77, 0xA4, 0x8D, 0x1B, 0x75, 0x6D, 0x6C, 0xD8, 0x5F, 0x6E, 0x1E, 0x83, + 0x7E, 0xE8, 0x43, 0x87, 0x63, 0xA3, 0xFC, 0x70, 0x24, 0x00, 0x71, 0xD3, 0x18, 0x1C, 0x69, 0xAF, 0x8D, 0xDD, 0x0C, 0x48, 0x61, 0xBF, 0xBB, 0x70, 0xA1, 0x88, + 0xC9, 0x87, 0xD6, 0x93, 0x4D, 0xCC, 0x0A, 0x49, 0x9E, 0xF9, 0x19, 0x9F, 0xE0, 0xC3, 0x27, 0xDB, 0xEF, 0x20, 0xDB, 0xBB, 0x7C, 0xA3, 0x7D, 0x27, 0x4E, 0x1F, + 0xAA, 0x30, 0x94, 0xA4, 0x29, 0x39, 0x6F, 0xEA, 0x0E, 0xB6, 0xB5, 0x2D, 0x03, 0x30, 0xD7, 0xD4, 0x4D, 0xFC, 0x21, 0x30, 0xFE, 0xFA, 0xD4, 0x22, 0x52, 0xF8, + 0xC3, 0x48, 0x74, 0xBB, 0x03, 0x09, 0x5A, 0x7E, 0x60, 0xD9, 0x36, 0x4C, 0x92, 0x48, 0xA0, 0x5D, 0xE1, 0xA1, 0xE2, 0xD3, 0x47, 0x31, 0x2C, 0xE2, 0xD9, 0xC3, + 0xC0, 0x23, 0xC6, 0xA2, 0x31, 0xBA, 0xC2, 0x17, 0xCB, 0x02, 0x2E, 0x3C, 0x2B, 0x46, 0x16, 0x7F, 0x4E, 0x29, 0xDF, 0x04, 0xE9, 0x93, 0x89, 0xF8, 0xA8, 0x61, + 0xF2, 0x45, 0xD0, 0xE0, 0x03, 0xEC, 0xC1, 0xE3, 0xD1, 0x99, 0xBF, 0x34, 0x1C, 0xD1, 0x8C, 0x3E, 0x95, 0x7B, 0xC3, 0x1F, 0xB3, 0x1C, 0xBB, 0xB6, 0xF9, 0x22, + 0xB6, 0x12, 0x78, 0x15, 0x3E, 0x2F, 0x88, 0x20, 0xE0, 0x44, 0x02, 0x43, 0x81, 0xB4, 0xE7, 0x9E, 0x40, 0xCF, 0x1E, 0xED, 0xC4, 0xD7, 0x08, 0xE5, 0x88, 0x3B, + 0xE3, 0x11, 0x47, 0x8F, 0xCC, 0x42, 0x2B, 0x92, 0x3D, 0xFA, 0x2A, 0x7D, 0xE0, 0xF1, 0x07, 0x32, 0xB3, 0x7C, 0xA0, 0x51, 0x03, 0x45, 0x1D, 0xD2, 0x87, 0xC4, + 0x98, 0xA3, 0xA8, 0x3D, 0x80, 0x18, 0xEF, 0x92, 0x3F, 0x3F, 0x2D, 0x7D, 0xAE, 0xB4, 0xD4, 0x58, 0x92, 0x7E, 0x08, 0x34, 0x89, 0xB1, 0xC8, 0x0C, 0x9F, 0xB6, + 0x5A, 0xF3, 0x3E, 0x3E, 0xEE, 0xA6, 0x09, 0xD6, 0xCE, 0x0E, 0xE7, 0xFD, 0xA2, 0xC7, 0x89, 0x0A, 0x9F, 0x55, 0x04, 0x4E, 0x2B, 0x3F, 0xAA, 0x88, 0x52, 0x1A, + 0x01, 0x35, 0x07, 0xDA, 0x07, 0xC3, 0xFF, 0x72, 0xA0, 0x7D, 0x42, 0x9F, 0xDF, 0xE1, 0x13, 0x8B, 0x48, 0xBB, 0x61, 0x9A, 0x5E, 0xE6, 0x53, 0x8B, 0xFD, 0xC4, + 0x53, 0x8B, 0x43, 0xF1, 0xD4, 0x62, 0x54, 0xBA, 0xEE, 0xDC, 0xF6, 0x3A, 0x9D, 0x63, 0x15, 0xD6, 0x15, 0x9F, 0x5C, 0xDC, 0x08, 0x4F, 0x0B, 0x90, 0xA6, 0x22, + 0x4F, 0x7D, 0xC1, 0x53, 0x6C, 0x07, 0xEF, 0xED, 0x74, 0xFA, 0xD8, 0x38, 0xE2, 0x6B, 0x08, 0xD5, 0x59, 0xEA, 0x74, 0x77, 0xFD, 0x78, 0x29, 0x35, 0xEE, 0x4D, + 0x3D, 0x5D, 0x4A, 0x9B, 0xA4, 0xA3, 0xE1, 0x20, 0x37, 0x18, 0x52, 0x10, 0xE6, 0xF4, 0x6F, 0x37, 0xE9, 0xF4, 0xB3, 0x1A, 0x4E, 0x3F, 0x5B, 0x73, 0xFA, 0x1D, + 0x7A, 0xBB, 0x20, 0xFC, 0xCF, 0xE6, 0xF1, 0x82, 0xAF, 0x12, 0x5E, 0x2F, 0xE5, 0xAB, 0xD3, 0xD9, 0xA8, 0xDF, 0x17, 0x3A, 0x49, 0x68, 0x0C, 0x6F, 0x37, 0xE9, + 0x24, 0x19, 0xA6, 0x5B, 0xC9, 0x4E, 0x79, 0xD8, 0x19, 0xED, 0x66, 0x5C, 0xA2, 0xD9, 0x54, 0x5C, 0xA1, 0xBC, 0x77, 0x7C, 0x7E, 0xAF, 0xD7, 0xE7, 0xA9, 0xD3, + 0x26, 0xD4, 0xA3, 0xFE, 0x24, 0x7B, 0x66, 0x93, 0xCD, 0x24, 0x66, 0x4B, 0x48, 0x84, 0x4B, 0x27, 0x66, 0x1F, 0xDF, 0xBF, 0x2F, 0x97, 0x8B, 0xC5, 0x7B, 0x79, + 0x24, 0xB9, 0x58, 0x6E, 0xDD, 0xEA, 0x6E, 0x09, 0x37, 0x90, 0xEA, 0x4A, 0xA6, 0x1B, 0x81, 0x37, 0x46, 0xAF, 0xE9, 0xB1, 0x16, 0x93, 0x58, 0x29, 0xE3, 0x55, + 0x9E, 0x96, 0x53, 0xC0, 0x58, 0x61, 0x2B, 0x22, 0x21, 0xAD, 0x1B, 0x45, 0x5C, 0x39, 0xC5, 0xAC, 0x18, 0x7B, 0xEA, 0x4C, 0xD5, 0xF6, 0x09, 0xDA, 0xA4, 0x28, + 0x15, 0x5E, 0xAC, 0xEC, 0xCA, 0x6A, 0xE3, 0xB0, 0x8D, 0xD1, 0x07, 0x98, 0xE3, 0x5A, 0x4B, 0xDB, 0x82, 0x99, 0x47, 0xB3, 0xA3, 0xB5, 0xB4, 0x9E, 0xBE, 0xBF, + 0xC3, 0x31, 0x52, 0x90, 0x51, 0xF2, 0x35, 0x1E, 0x7A, 0xF4, 0x74, 0x4B, 0x6F, 0x43, 0xEF, 0xF1, 0xA8, 0xAB, 0x10, 0xCF, 0x75, 0x83, 0xCA, 0xDA, 0x10, 0xC0, + 0x90, 0xA8, 0xC0, 0x91, 0x16, 0xE9, 0x44, 0x5D, 0x15, 0xB1, 0xBD, 0x76, 0x11, 0x36, 0x35, 0x75, 0x28, 0xED, 0xAC, 0xC3, 0x05, 0x6B, 0xD5, 0x2D, 0x69, 0x12, + 0xAC, 0x7A, 0x63, 0xD4, 0x2D, 0x81, 0xA1, 0x78, 0x63, 0x1A, 0x6B, 0x55, 0xDF, 0x89, 0xFC, 0xBB, 0xEA, 0xB1, 0x8F, 0xC3, 0x42, 0xDA, 0x7D, 0x07, 0xA9, 0xEE, + 0x42, 0x7B, 0x03, 0x7D, 0x51, 0x27, 0xD2, 0x07, 0xBB, 0x74, 0x22, 0x41, 0x46, 0x75, 0x27, 0xD2, 0x1F, 0x87, 0x0F, 0xA1, 0x3E, 0x96, 0x1E, 0xA9, 0xAC, 0x0F, + 0x0E, 0xDB, 0x18, 0x7D, 0xF4, 0x08, 0x2A, 0xA3, 0x92, 0xF7, 0x84, 0x48, 0xAA, 0x39, 0xCF, 0x06, 0x1C, 0x45, 0x6F, 0x0F, 0xEA, 0xE1, 0xE8, 0x96, 0x73, 0x36, + 0x09, 0x86, 0x9E, 0x3C, 0x08, 0xF4, 0x1E, 0xA7, 0x0B, 0x13, 0xDB, 0x1C, 0x54, 0x77, 0x62, 0x01, 0x8D, 0xB3, 0x67, 0x38, 0xAC, 0x6C, 0x38, 0x31, 0x44, 0x8F, + 0x2A, 0xEE, 0xD6, 0xC4, 0xB0, 0x09, 0x63, 0x1A, 0x75, 0x4B, 0x99, 0xF4, 0x6E, 0x4C, 0x67, 0x89, 0x6F, 0x3D, 0x23, 0x6A, 0x9B, 0xC0, 0x28, 0xB2, 0x78, 0xA4, + 0x61, 0xB0, 0x10, 0x69, 0xE8, 0x7B, 0xCF, 0xE8, 0xE6, 0xD7, 0x9D, 0xE6, 0xBC, 0x82, 0x80, 0xF5, 0xD5, 0xA8, 0xF2, 0x6B, 0x85, 0x31, 0xE6, 0x64, 0x29, 0x70, + 0xC8, 0xEB, 0x63, 0xCB, 0x7F, 0x29, 0x61, 0x95, 0xC7, 0x0A, 0x0E, 0xCC, 0x55, 0x18, 0x0E, 0xDD, 0xBB, 0xCD, 0x7F, 0x43, 0x2A, 0x6A, 0x8C, 0xDD, 0x3B, 0x4C, + 0x80, 0x63, 0x8B, 0x42, 0x54, 0x01, 0x2C, 0x68, 0x06, 0x6C, 0xC6, 0x57, 0x62, 0x25, 0x28, 0xB3, 0xC9, 0x66, 0xE6, 0xF9, 0x37, 0x96, 0x53, 0x7E, 0x9E, 0xFF, + 0xB3, 0xE5, 0x98, 0xEE, 0x4D, 0xB9, 0xA9, 0x7E, 0xBC, 0xA3, 0x3F, 0xC0, 0x54, 0x9F, 0x0E, 0x96, 0xB8, 0x7A, 0xD7, 0xF2, 0x88, 0xDA, 0x5B, 0x28, 0xD2, 0x42, + 0x66, 0xD0, 0xB7, 0xB8, 0xD4, 0x06, 0x28, 0x7C, 0x8D, 0xAE, 0x05, 0x6E, 0xDB, 0x5F, 0x7E, 0x39, 0x8D, 0x27, 0xBB, 0x9C, 0x02, 0x35, 0x87, 0xE9, 0x4B, 0x0A, + 0x8F, 0x0F, 0x5E, 0x4B, 0xFD, 0x75, 0x9D, 0x9F, 0xBB, 0x07, 0xE7, 0x67, 0x13, 0x01, 0x99, 0x38, 0x66, 0x65, 0xCB, 0x42, 0xD8, 0xC8, 0xAE, 0x2E, 0x1D, 0x73, + 0xA7, 0x56, 0xC5, 0x7A, 0xAF, 0xAC, 0x83, 0x6E, 0xE7, 0xE8, 0xE4, 0x71, 0x99, 0x15, 0x32, 0x54, 0xC3, 0xA8, 0xF4, 0x41, 0xFF, 0xE8, 0xF1, 0xD8, 0x95, 0x3B, + 0x9D, 0xB2, 0x15, 0xAE, 0x6A, 0xA6, 0xC5, 0xC1, 0x6F, 0xE9, 0xB3, 0x75, 0x3E, 0xD9, 0x6D, 0xBC, 0x0A, 0x3B, 0x57, 0xD3, 0x45, 0x4F, 0xA2, 0x8B, 0xE1, 0xE3, + 0x32, 0x2D, 0xCE, 0x91, 0xAA, 0x75, 0x49, 0x38, 0xDA, 0x10, 0x43, 0x9B, 0x30, 0xAD, 0xC0, 0x0D, 0x0C, 0xBB, 0xB2, 0x65, 0x31, 0x68, 0x30, 0xAC, 0x1F, 0xF1, + 0x40, 0xBB, 0x02, 0x3E, 0x77, 0x6A, 0x5C, 0xA2, 0xFF, 0xEA, 0x81, 0xAB, 0xD7, 0x79, 0x64, 0xE3, 0x21, 0x63, 0xA9, 0x56, 0xE8, 0x1A, 0xF6, 0x1F, 0x8F, 0x7D, + 0xB9, 0xAB, 0x00, 0xAF, 0x56, 0x0E, 0x5D, 0x0C, 0x1C, 0x43, 0x17, 0x3D, 0xDA, 0xBD, 0x89, 0x85, 0x14, 0xD4, 0x18, 0x1C, 0xFB, 0x0F, 0xBF, 0x7E, 0xFD, 0xAB, + 0x84, 0xA7, 0x5A, 0x46, 0xD6, 0x7B, 0x2C, 0x41, 0x6C, 0x62, 0x28, 0xBF, 0x99, 0x89, 0x22, 0x8B, 0x67, 0xF3, 0x0C, 0x16, 0xE6, 0x70, 0xEC, 0x60, 0xA7, 0x15, + 0x0C, 0xD1, 0xF9, 0xC6, 0x97, 0xEC, 0x42, 0xAE, 0x1E, 0x53, 0xBD, 0x62, 0x6C, 0x39, 0x4E, 0x55, 0x35, 0x71, 0xD8, 0xC6, 0xE8, 0x35, 0x3B, 0xD8, 0xED, 0xE2, + 0x2A, 0xEF, 0x7C, 0xF3, 0x2B, 0xAB, 0x82, 0xAB, 0x5D, 0xAB, 0x29, 0x55, 0xC4, 0xF0, 0xC2, 0x57, 0xD8, 0x37, 0xF8, 0x6E, 0xC5, 0xE8, 0x95, 0xF6, 0x8F, 0xA7, + 0xA4, 0x31, 0x33, 0x16, 0xF8, 0xC8, 0x61, 0xD9, 0xA2, 0xC6, 0x5B, 0x04, 0x2B, 0x57, 0xD3, 0x48, 0xF6, 0xF4, 0xB8, 0xAB, 0x1A, 0xA3, 0xE4, 0xBB, 0xE6, 0x80, + 0xF0, 0xD6, 0xD8, 0x32, 0x7C, 0x7C, 0x3C, 0x17, 0x8E, 0xB5, 0xD7, 0x70, 0xAC, 0x7D, 0xB4, 0x57, 0xE1, 0xCB, 0x32, 0x65, 0x0E, 0x11, 0xDF, 0xD9, 0x14, 0x61, + 0xC8, 0xDA, 0xE5, 0x4F, 0x37, 0x74, 0xF1, 0xC7, 0x32, 0xE0, 0x18, 0xF7, 0x31, 0x0D, 0xFA, 0xC7, 0x9D, 0x86, 0xC6, 0xB2, 0x62, 0xBE, 0xA9, 0xDC, 0xFF, 0x42, + 0x37, 0x38, 0xE9, 0x21, 0x81, 0x32, 0x07, 0x88, 0xD3, 0x1B, 0x12, 0x48, 0xED, 0xB7, 0xCE, 0xBE, 0xA3, 0x75, 0x89, 0xE8, 0x42, 0x1C, 0x1D, 0xA9, 0x21, 0x24, + 0xDE, 0x8E, 0xC7, 0xDA, 0xAB, 0x6C, 0x8F, 0x97, 0x0B, 0x42, 0x97, 0x0A, 0x02, 0xF7, 0x79, 0x6D, 0x96, 0xA7, 0xAE, 0xE0, 0x49, 0x57, 0xE3, 0xA9, 0x5B, 0x83, + 0xA7, 0xEE, 0x8E, 0x78, 0xEA, 0x09, 0x9E, 0xBA, 0x6A, 0x3C, 0xF5, 0x6A, 0xF0, 0xD4, 0xDB, 0x11, 0x4F, 0x7D, 0xC1, 0x53, 0x4F, 0x8D, 0xA7, 0x7E, 0x0D, 0x9E, + 0xFA, 0x3B, 0xE2, 0x69, 0x20, 0x78, 0xEA, 0xAB, 0xF1, 0x34, 0xA8, 0xC1, 0xD3, 0x60, 0x47, 0x3C, 0x0D, 0x05, 0x4F, 0x03, 0x35, 0x9E, 0x86, 0x35, 0x78, 0x1A, + 0xEE, 0x88, 0xA7, 0x23, 0xC1, 0xD3, 0x50, 0x8D, 0xA7, 0xA3, 0x1A, 0x3C, 0x1D, 0xED, 0x88, 0xA7, 0x63, 0xC1, 0xD3, 0x91, 0x1A, 0x4F, 0xC7, 0x35, 0x78, 0x3A, + 0xDE, 0x11, 0x4F, 0x27, 0x82, 0xA7, 0x63, 0x35, 0x9E, 0x4E, 0x6A, 0xF0, 0x74, 0xB2, 0x23, 0x9E, 0x70, 0x51, 0x8E, 0x31, 0x75, 0xA2, 0x38, 0xE8, 0x76, 0x6A, + 0x70, 0x65, 0xEC, 0x8A, 0xAB, 0x30, 0x95, 0xD0, 0x55, 0x73, 0x89, 0x3A, 0xC9, 0xC4, 0x78, 0x57, 0x6C, 0x45, 0xD9, 0x84, 0x62, 0x3A, 0xA1, 0xD7, 0xC9, 0x27, + 0x26, 0xBB, 0x62, 0x2B, 0x4C, 0x28, 0x74, 0xC5, 0x8C, 0x42, 0xAF, 0x93, 0x52, 0x98, 0xBB, 0x62, 0x2B, 0xCC, 0x29, 0x74, 0xC5, 0xA4, 0x42, 0xAF, 0x93, 0x55, + 0x90, 0x5D, 0xB1, 0x15, 0xA6, 0x15, 0xBA, 0x62, 0x5E, 0xA1, 0xD7, 0x49, 0x2C, 0xA6, 0xBB, 0x62, 0x2B, 0xCC, 0x2C, 0x74, 0xC5, 0xD4, 0x42, 0xAF, 0x91, 0x5B, + 0x9C, 0xC8, 0x27, 0x62, 0x1B, 0x65, 0x8B, 0x04, 0x7C, 0x8A, 0x1C, 0x4D, 0xDA, 0x94, 0x1E, 0x3D, 0xE1, 0x40, 0xF8, 0x6C, 0x14, 0x13, 0xC8, 0x85, 0xEB, 0x4C, + 0xAD, 0x59, 0x58, 0x64, 0x78, 0x34, 0x4F, 0x49, 0xF8, 0xB1, 0xD7, 0x74, 0x2A, 0x17, 0x1A, 0xAE, 0xDE, 0x5C, 0x96, 0x2B, 0x33, 0xC4, 0x7B, 0xF9, 0x03, 0x15, + 0x19, 0x80, 0xEC, 0x6E, 0xFC, 0x9D, 0xE1, 0x4A, 0x75, 0x05, 0x0A, 0x54, 0xA6, 0xA2, 0x30, 0x88, 0x57, 0x14, 0x86, 0xCA, 0x15, 0x05, 0x46, 0xDC, 0x76, 0x6A, + 0x09, 0x80, 0xBB, 0xC7, 0x5E, 0x74, 0xAE, 0xCE, 0x74, 0xAF, 0x3A, 0xD3, 0x83, 0x32, 0x4C, 0xF7, 0xAA, 0x30, 0x5D, 0xE1, 0xE9, 0x46, 0x45, 0x39, 0x01, 0xBD, + 0xDF, 0x5A, 0xB7, 0xC4, 0xD4, 0x7E, 0x55, 0x17, 0x95, 0x5E, 0x5D, 0x54, 0x47, 0x65, 0x44, 0xA5, 0x6F, 0xD1, 0x3E, 0x06, 0x82, 0xEF, 0x9F, 0xD4, 0xF9, 0x1E, + 0x54, 0xE7, 0xBB, 0x57, 0x86, 0xEF, 0xC1, 0x16, 0xF9, 0xEE, 0x0B, 0xBE, 0x3F, 0xA9, 0xF3, 0xDD, 0xAF, 0xCE, 0x77, 0xBF, 0x0C, 0xDF, 0xFD, 0x2D, 0xF2, 0xDD, + 0x85, 0x60, 0xF3, 0xD3, 0x27, 0xED, 0xC7, 0xB9, 0x47, 0xFC, 0x79, 0x71, 0x25, 0x8E, 0x41, 0x54, 0x1D, 0xDB, 0x07, 0x3B, 0x98, 0xBB, 0x21, 0x85, 0xBD, 0x38, + 0x4F, 0x85, 0x79, 0x33, 0x83, 0x50, 0xF9, 0x92, 0x88, 0x9C, 0x27, 0xF9, 0xCC, 0x4D, 0x57, 0x65, 0x6A, 0x7B, 0x31, 0xEC, 0xB8, 0x31, 0x7A, 0xB7, 0x2A, 0x31, + 0xBE, 0x1D, 0x57, 0xB7, 0x67, 0xF5, 0x8A, 0x39, 0xA3, 0x6B, 0x6B, 0xF6, 0x7C, 0x42, 0x79, 0x86, 0xBC, 0xCC, 0x57, 0x50, 0x7B, 0xF5, 0x2A, 0xC4, 0x60, 0x07, + 0x55, 0x72, 0x8C, 0xF4, 0x47, 0x8C, 0x9D, 0x9F, 0x90, 0x21, 0x0D, 0x32, 0x96, 0x12, 0x83, 0xD1, 0x51, 0x49, 0x6D, 0x1E, 0x57, 0x8C, 0x4E, 0x48, 0xE3, 0xD6, + 0xD4, 0x89, 0x53, 0x0F, 0x14, 0xC0, 0xA7, 0x0A, 0x02, 0x18, 0x56, 0x17, 0x40, 0xA9, 0xCC, 0x05, 0x69, 0xDC, 0x9E, 0x00, 0x3A, 0x4C, 0x00, 0x57, 0xD1, 0xAB, + 0x6A, 0x73, 0x0C, 0xBA, 0x46, 0x05, 0x6A, 0xB0, 0x83, 0x35, 0x12, 0x8C, 0xB4, 0xBA, 0xB0, 0x68, 0xE0, 0xA8, 0x9C, 0x42, 0xBB, 0x65, 0xF3, 0x2B, 0x79, 0xF1, + 0x53, 0x21, 0xFF, 0xDE, 0x66, 0x82, 0xD5, 0xED, 0x08, 0x8B, 0x2E, 0x2F, 0x80, 0x4E, 0x75, 0x01, 0xE8, 0xA5, 0x04, 0xD0, 0x79, 0x5C, 0xC9, 0xF8, 0x70, 0xFD, + 0xEB, 0xA2, 0xC5, 0xD2, 0x2A, 0xEB, 0xFE, 0xB1, 0xD1, 0xAC, 0x5B, 0x46, 0x58, 0x5B, 0xF5, 0xFE, 0x5E, 0xC4, 0xB9, 0xF6, 0xAB, 0x96, 0xDC, 0xFA, 0x9A, 0x17, + 0x07, 0xAA, 0x17, 0x01, 0x07, 0x3B, 0x58, 0xAF, 0x42, 0x0A, 0x4F, 0x24, 0x9C, 0x95, 0x0C, 0xF0, 0x27, 0xD5, 0xDD, 0xA1, 0x94, 0x86, 0x91, 0xD6, 0xED, 0xA9, + 0x78, 0x90, 0x10, 0x04, 0xFB, 0xB2, 0xB1, 0x8A, 0x8A, 0xAB, 0x57, 0x0E, 0x07, 0x3B, 0x58, 0xEA, 0x42, 0x0A, 0x8F, 0x25, 0x9C, 0x95, 0x54, 0x71, 0xD9, 0x94, + 0xF4, 0xB8, 0xE2, 0xD4, 0x52, 0xDF, 0x66, 0x4E, 0x8A, 0xD5, 0xEE, 0x98, 0x20, 0xE2, 0xAF, 0x9D, 0xCF, 0x53, 0x70, 0xF5, 0x8A, 0xF7, 0xA0, 0xE6, 0xFA, 0xEC, + 0xF6, 0x22, 0xF9, 0x91, 0xEC, 0x9B, 0xC4, 0xC5, 0x76, 0x50, 0x36, 0x97, 0xED, 0x54, 0x1C, 0xF8, 0xB6, 0x9A, 0xCA, 0x42, 0xEF, 0x90, 0xF5, 0xAC, 0x73, 0x9F, + 0x63, 0x02, 0xD5, 0x57, 0xDE, 0x06, 0x3B, 0xD8, 0x1E, 0x82, 0x14, 0x76, 0x1B, 0xA3, 0x4F, 0x25, 0x99, 0xAA, 0x53, 0x3F, 0xA8, 0xBC, 0x3F, 0x64, 0x77, 0xA5, + 0xF7, 0xC9, 0xE2, 0xB6, 0x7C, 0xE9, 0xFD, 0xE2, 0xC3, 0x2F, 0xE5, 0x4A, 0xEF, 0xF1, 0x5E, 0x76, 0x57, 0x7A, 0xAF, 0x66, 0x33, 0xA5, 0x36, 0xCA, 0x02, 0x63, + 0xF8, 0xFE, 0x88, 0x89, 0xE5, 0xD3, 0x2E, 0x41, 0x30, 0xDA, 0x47, 0x71, 0x1A, 0x8A, 0x28, 0xF6, 0xC4, 0x7E, 0xB2, 0x7D, 0x9E, 0xF5, 0xF4, 0x72, 0xC2, 0x82, + 0xDA, 0x46, 0xD8, 0xF5, 0xD7, 0xA1, 0xB4, 0x87, 0xFC, 0xCB, 0x3C, 0x35, 0x1E, 0xAD, 0xCF, 0x7A, 0x69, 0x40, 0xFB, 0xA8, 0x24, 0xEE, 0xAD, 0x3F, 0x72, 0x3F, + 0x4A, 0x29, 0x4A, 0xA7, 0xFA, 0xD1, 0xF1, 0x5C, 0xB9, 0x4E, 0x4E, 0xC1, 0xCA, 0x44, 0xF3, 0x5E, 0xBC, 0xD4, 0xA2, 0x1E, 0xCD, 0x19, 0x79, 0xDB, 0x89, 0xE6, + 0x88, 0x3B, 0xC1, 0x7B, 0x89, 0xAC, 0x86, 0xC1, 0x96, 0x13, 0x80, 0x7C, 0x13, 0x85, 0x82, 0x00, 0xB2, 0x24, 0xB0, 0x11, 0x11, 0x74, 0xA9, 0x04, 0xBA, 0x29, + 0xED, 0x67, 0x04, 0x7E, 0xDA, 0xBE, 0x6A, 0xDC, 0xEF, 0xED, 0xA0, 0x36, 0x81, 0xE2, 0x4A, 0x70, 0x54, 0x52, 0xA7, 0xE5, 0x16, 0x07, 0x13, 0x3A, 0x2D, 0x67, + 0xD4, 0x5B, 0x5B, 0x1D, 0x04, 0xE4, 0x3D, 0x2A, 0x80, 0x9E, 0xB2, 0x4A, 0xAB, 0x4F, 0x33, 0x7B, 0x3B, 0xC8, 0x4F, 0x50, 0x5A, 0x09, 0x8E, 0x4A, 0xAA, 0xB4, + 0xDC, 0xD2, 0x67, 0x42, 0xA5, 0xEA, 0xF3, 0x4B, 0x4E, 0xE4, 0xD6, 0x54, 0xDA, 0xA7, 0x02, 0xE8, 0x2B, 0xAB, 0xB4, 0xFA, 0xAC, 0xA3, 0xB7, 0x83, 0xDD, 0xBB, + 0x28, 0xAD, 0x04, 0x47, 0x25, 0x55, 0x5A, 0x6E, 0xC9, 0x2E, 0xA1, 0x52, 0xF5, 0xF9, 0x24, 0x27, 0x72, 0x6B, 0x2A, 0x1D, 0x50, 0x01, 0x0C, 0x94, 0x55, 0x5A, + 0xBD, 0x52, 0xD0, 0xDB, 0x41, 0x31, 0x08, 0xA5, 0x95, 0xE0, 0xA8, 0xA4, 0x4A, 0xCB, 0xAD, 0x3E, 0x27, 0x54, 0xAA, 0xBE, 0xCE, 0xC1, 0x89, 0xDC, 0x9A, 0x4A, + 0x87, 0x54, 0x00, 0x43, 0x65, 0x95, 0x56, 0xDF, 0x5F, 0xD5, 0xDB, 0xC1, 0xDE, 0x6D, 0x94, 0x56, 0x82, 0xA3, 0x92, 0x2A, 0x2D, 0x57, 0xBA, 0x4D, 0xA8, 0x54, + 0x7D, 0xE5, 0x86, 0x13, 0xB9, 0x35, 0x95, 0x1E, 0x51, 0x01, 0x1C, 0x29, 0xAB, 0xB4, 0xFA, 0xD6, 0xF5, 0xDE, 0x0E, 0xEA, 0x79, 0x28, 0xAD, 0x04, 0x47, 0x25, + 0x55, 0x5A, 0xAE, 0x82, 0x93, 0x50, 0xA9, 0xFA, 0xDE, 0x29, 0x4E, 0xE4, 0xD6, 0x54, 0x7A, 0x4C, 0x05, 0x70, 0xAC, 0xAC, 0xD2, 0xEA, 0x3B, 0xF7, 0x7B, 0x3B, + 0xD8, 0xB9, 0x8F, 0xD2, 0x4A, 0x70, 0x54, 0x52, 0xA5, 0xE5, 0x6A, 0xB3, 0x09, 0x95, 0xAA, 0x6F, 0x77, 0xE2, 0x44, 0x6E, 0x4D, 0xA5, 0x27, 0x54, 0x00, 0x27, + 0xCA, 0x2A, 0xAD, 0xBE, 0x65, 0xA0, 0xB7, 0x83, 0xCD, 0x2F, 0x28, 0xAD, 0x4E, 0x9C, 0xA3, 0x92, 0x2A, 0x2D, 0xB7, 0xC0, 0xD8, 0xCB, 0xD8, 0xFA, 0xA2, 0xA0, + 0xD2, 0xAC, 0x05, 0xC6, 0x47, 0x50, 0xBF, 0x33, 0x6E, 0xC6, 0x15, 0x3E, 0xFD, 0xF2, 0xEA, 0xE7, 0xD7, 0xD9, 0x85, 0xFD, 0xCC, 0x2A, 0x5E, 0xA2, 0xAF, 0xC7, + 0x5E, 0xC6, 0x8B, 0xCB, 0x0B, 0x09, 0xD7, 0xC3, 0x2F, 0x86, 0xAF, 0x31, 0x9F, 0x6F, 0x69, 0x0C, 0xB8, 0x84, 0xA5, 0xF5, 0xFA, 0x1D, 0x79, 0xD2, 0x52, 0x60, + 0x69, 0x9C, 0xCA, 0xED, 0x04, 0x0F, 0x44, 0x0E, 0x73, 0x71, 0xE4, 0xFD, 0x07, 0xA5, 0x35, 0x1D, 0x06, 0x90, 0x0C, 0x1F, 0xFD, 0xCE, 0x89, 0x62, 0xFC, 0x00, + 0x19, 0x64, 0x6D, 0x8C, 0xDF, 0x60, 0x00, 0x41, 0x1A, 0x7B, 0x8C, 0xA9, 0xB7, 0xCA, 0x4C, 0xA5, 0xAB, 0x00, 0xA5, 0x98, 0xCA, 0xAA, 0xEC, 0x6C, 0x98, 0xA9, + 0x3E, 0x63, 0x2A, 0xC7, 0x49, 0x53, 0x4C, 0xA5, 0xE7, 0xC1, 0xA5, 0x98, 0xCA, 0x9A, 0x08, 0x47, 0x4C, 0x3D, 0x86, 0x40, 0x47, 0x26, 0xF4, 0x53, 0xE2, 0xA5, + 0x43, 0xDD, 0xE5, 0xC5, 0xE1, 0xAB, 0xB7, 0x17, 0x1A, 0x5D, 0xD2, 0x74, 0xED, 0x92, 0x11, 0x2F, 0xD9, 0xE9, 0x1F, 0x2A, 0xE6, 0x51, 0xD2, 0x63, 0x51, 0x2F, + 0xFA, 0xDE, 0x7B, 0x51, 0xC0, 0xE3, 0x90, 0x65, 0x42, 0xDE, 0xA0, 0xD3, 0xAB, 0x52, 0x21, 0x0C, 0x89, 0xDC, 0x52, 0xD0, 0xA3, 0xE8, 0xBB, 0x91, 0x0C, 0x2E, + 0xCB, 0xC9, 0xA0, 0x54, 0x95, 0x34, 0x29, 0x83, 0x12, 0x61, 0x5F, 0x10, 0xB9, 0x4D, 0x19, 0x60, 0x94, 0xBC, 0xBC, 0xD0, 0x3E, 0xFE, 0x4D, 0xBB, 0xBC, 0x5D, + 0xBA, 0xFE, 0xCA, 0x23, 0x85, 0x51, 0x85, 0xC3, 0xA5, 0x3E, 0xF8, 0x3E, 0x18, 0xF4, 0x54, 0x03, 0xCB, 0x20, 0x7B, 0x08, 0x98, 0x76, 0x36, 0x18, 0x2F, 0x29, + 0xA1, 0xFD, 0x90, 0xC1, 0x1F, 0x08, 0x68, 0x5A, 0x29, 0x6E, 0x72, 0xC0, 0x24, 0x87, 0x7A, 0x07, 0xB7, 0x57, 0x2B, 0x32, 0x28, 0xCF, 0x28, 0x7B, 0x1B, 0x1D, + 0x0E, 0x28, 0x95, 0x83, 0x90, 0xBD, 0x4F, 0x3F, 0x5E, 0xA9, 0x31, 0x96, 0xAE, 0xA3, 0x95, 0x53, 0x5D, 0xD6, 0x23, 0xA3, 0x1B, 0x1A, 0x14, 0xA4, 0x37, 0xCE, + 0x0E, 0x21, 0xF4, 0xAE, 0xC3, 0x64, 0x48, 0xF2, 0x6C, 0x6A, 0xCD, 0xC0, 0x8E, 0xE5, 0x7D, 0x50, 0xD1, 0xB2, 0x97, 0x9D, 0xE2, 0x47, 0x23, 0x5B, 0x13, 0x88, + 0xFE, 0x60, 0x12, 0xE8, 0x74, 0x42, 0xE0, 0x0B, 0x63, 0x46, 0xA2, 0xEB, 0x1A, 0x8B, 0xED, 0x79, 0x31, 0xDB, 0x60, 0x08, 0x8D, 0x6B, 0xC2, 0xBF, 0x70, 0xA9, + 0xCD, 0x3D, 0x32, 0x3D, 0x6F, 0x7C, 0x13, 0xE2, 0xE4, 0x4F, 0xE5, 0x61, 0x93, 0x86, 0x66, 0xBA, 0x37, 0x8E, 0xED, 0x1A, 0x38, 0x1E, 0x18, 0xCB, 0x00, 0x28, + 0x6D, 0xFF, 0xBE, 0xC4, 0x17, 0x5F, 0x19, 0xF8, 0x10, 0x97, 0x91, 0xD3, 0x4F, 0xCC, 0x2A, 0x26, 0xB6, 0xEB, 0x8B, 0xD9, 0x1C, 0x1E, 0x86, 0x5F, 0xC4, 0xFC, + 0x9F, 0xFF, 0x2E, 0xDA, 0x41, 0x60, 0x2D, 0x66, 0x31, 0x01, 0x34, 0x34, 0xDF, 0x9B, 0x9C, 0x37, 0x80, 0x52, 0xCF, 0xF5, 0x7D, 0xD7, 0xB3, 0x66, 0x56, 0x86, + 0x76, 0xB2, 0xA4, 0x7D, 0x28, 0x13, 0x77, 0xAA, 0xB1, 0x44, 0xF1, 0x67, 0xFE, 0xC4, 0xB3, 0x96, 0xC1, 0xE8, 0x89, 0xE9, 0x4E, 0x56, 0x0B, 0xE2, 0x04, 0x6D, + 0xC3, 0x34, 0x2F, 0xAF, 0xE1, 0xE0, 0x3D, 0x7E, 0xAC, 0x0D, 0x24, 0xDF, 0xDC, 0x7B, 0xF3, 0xF7, 0x0F, 0x38, 0x3A, 0xE3, 0x35, 0x90, 0x17, 0x31, 0xF7, 0x0E, + 0xB4, 0xE9, 0xCA, 0x61, 0x03, 0x64, 0x93, 0x60, 0xDB, 0x7D, 0xED, 0x2B, 0x60, 0xBC, 0x36, 0x3C, 0x6D, 0x6C, 0xF8, 0xE4, 0x9D, 0xEB, 0x07, 0xDA, 0xB9, 0x16, + 0x62, 0xB4, 0xDD, 0x09, 0xDD, 0xCE, 0xD1, 0x66, 0x7C, 0xF1, 0x96, 0x8C, 0xF1, 0x9F, 0x3C, 0x1B, 0x9A, 0x86, 0x50, 0xCF, 0xB5, 0xBD, 0xD3, 0x63, 0x7D, 0x0F, + 0x6D, 0x37, 0xEC, 0x62, 0x4A, 0x20, 0xFA, 0x43, 0xBB, 0xE6, 0xCA, 0xB3, 0x0F, 0xB4, 0xC9, 0x78, 0xFF, 0x2B, 0xA5, 0x9E, 0x5E, 0xC6, 0x6B, 0xFB, 0x9C, 0x99, + 0x76, 0x30, 0x27, 0x4E, 0x33, 0xA2, 0xCC, 0x23, 0xFE, 0xD2, 0x75, 0x7C, 0xC2, 0x88, 0x63, 0x3F, 0x6B, 0x1A, 0x5D, 0x6F, 0xFB, 0x81, 0x11, 0xAC, 0x7C, 0xED, + 0xE9, 0xF9, 0xB9, 0xD6, 0xED, 0x74, 0xE2, 0xCD, 0x34, 0xE8, 0x26, 0xDD, 0xEE, 0x40, 0x4B, 0x5D, 0xF8, 0x91, 0xDC, 0x06, 0xFB, 0x2F, 0x42, 0x98, 0x7B, 0x8D, + 0xD8, 0x3E, 0x49, 0x20, 0x09, 0x01, 0xF0, 0x75, 0x72, 0xCD, 0xFD, 0x24, 0x81, 0x4D, 0xD3, 0x08, 0x8C, 0xFD, 0xAF, 0x09, 0x7D, 0x41, 0xAF, 0x40, 0xC9, 0x81, + 0x46, 0x6F, 0xBD, 0x88, 0xDD, 0xBA, 0xDF, 0x6F, 0x83, 0x0C, 0x81, 0xDF, 0x10, 0x9A, 0x78, 0x5E, 0x92, 0x62, 0x0A, 0xDD, 0xD2, 0x0F, 0x34, 0xBC, 0x93, 0x84, + 0x8D, 0x11, 0xF9, 0x44, 0x5C, 0x13, 0x42, 0xCB, 0x47, 0x2B, 0x41, 0xC9, 0xD0, 0xDD, 0x27, 0x54, 0x04, 0x71, 0xE8, 0x07, 0x32, 0x03, 0x89, 0xCD, 0x0E, 0x78, + 0x58, 0x3A, 0xA0, 0x31, 0xE9, 0x80, 0x85, 0xB3, 0x98, 0xD6, 0xC0, 0xA1, 0x7D, 0xD7, 0x26, 0x60, 0x13, 0xB3, 0xE6, 0x1E, 0xFF, 0x14, 0x28, 0xD8, 0xD3, 0x5E, + 0xE7, 0x76, 0xEF, 0x39, 0x80, 0xB7, 0x03, 0xF7, 0x2A, 0xF0, 0x2C, 0x67, 0xD6, 0xD4, 0x87, 0xFB, 0x11, 0x2E, 0x7A, 0x1B, 0x11, 0xA6, 0xEE, 0xD3, 0xEB, 0xB4, + 0x8B, 0xF4, 0x8D, 0x26, 0xBF, 0xFE, 0x7C, 0x6F, 0x7F, 0x8F, 0x93, 0x4E, 0xCF, 0xC1, 0xD8, 0x9A, 0xEC, 0xE0, 0x19, 0xA5, 0x70, 0x5F, 0x3B, 0x3B, 0xE3, 0xDD, + 0xB0, 0x56, 0x78, 0x11, 0x1A, 0xD1, 0x3F, 0xA9, 0x5B, 0xA1, 0x21, 0xFE, 0xF6, 0x97, 0xAF, 0xC2, 0x62, 0xEF, 0x0F, 0x81, 0xEA, 0x97, 0x18, 0x97, 0xFF, 0xF2, + 0x15, 0xFE, 0xBF, 0x7F, 0x46, 0x43, 0xF1, 0x5F, 0xBE, 0xE2, 0x9F, 0xFB, 0x67, 0xD0, 0x13, 0x1C, 0xD3, 0xFE, 0xEE, 0x7F, 0xA3, 0x52, 0x58, 0x97, 0xDD, 0x2C, + 0x53, 0x76, 0xA1, 0xD0, 0x4A, 0xD3, 0x34, 0xCB, 0x21, 0xEA, 0xB7, 0xC8, 0x7B, 0x9B, 0x13, 0xD7, 0x04, 0xE5, 0x04, 0x60, 0xC7, 0x42, 0xE5, 0x36, 0xA8, 0x44, + 0x08, 0xAA, 0x23, 0x54, 0x6E, 0x4D, 0x69, 0x4B, 0x8D, 0x3B, 0x4A, 0x64, 0x1E, 0xA2, 0xE5, 0xD2, 0xF0, 0x7C, 0xF2, 0x9D, 0x13, 0x34, 0x83, 0x84, 0x4B, 0x64, + 0x48, 0x7C, 0x34, 0x4A, 0xB0, 0x80, 0x3F, 0x80, 0x83, 0x76, 0x7B, 0x5C, 0x69, 0xA1, 0xA9, 0x3D, 0x09, 0xAD, 0x30, 0xA2, 0x94, 0xDD, 0xCC, 0xB0, 0xC2, 0x5F, + 0x26, 0xF6, 0x97, 0xE6, 0x2D, 0xFC, 0x97, 0x0E, 0x14, 0x6B, 0x22, 0xC2, 0x46, 0x2F, 0xF1, 0x3F, 0x90, 0x0B, 0xFE, 0xC9, 0xD4, 0x0F, 0x60, 0xFD, 0x68, 0xDB, + 0x4D, 0xF6, 0xD9, 0x2F, 0x50, 0xCD, 0x0A, 0x82, 0x90, 0x7F, 0x87, 0xE1, 0xC0, 0x75, 0x83, 0xCF, 0x07, 0xDA, 0xD2, 0x03, 0xC2, 0xE8, 0x97, 0x3E, 0xE0, 0x18, + 0x10, 0x11, 0x87, 0xFD, 0x2D, 0xA4, 0x60, 0x69, 0xDB, 0x2F, 0x19, 0x56, 0x20, 0x81, 0x1D, 0x80, 0xA6, 0x56, 0x68, 0x31, 0xF0, 0xFF, 0xFD, 0x33, 0xE8, 0x04, + 0x0E, 0xE1, 0xFF, 0xFB, 0x67, 0xD8, 0x15, 0xEA, 0x12, 0x7B, 0xBC, 0x7F, 0x06, 0x3D, 0xC2, 0x09, 0xFC, 0x0F, 0x6D, 0xB0, 0x5F, 0x6C, 0x85, 0x7F, 0xE1, 0x0E, + 0xED, 0x1F, 0x6F, 0xD2, 0x03, 0x76, 0x81, 0x9F, 0xE6, 0x31, 0xC8, 0xDE, 0x74, 0xDF, 0xA4, 0x6F, 0x1E, 0xFF, 0x7C, 0x0B, 0xEC, 0xD0, 0x83, 0x3B, 0x70, 0x7C, + 0xC7, 0xC4, 0x73, 0xFC, 0x73, 0x27, 0xCC, 0x13, 0x2F, 0xF0, 0x23, 0xB8, 0x46, 0xDF, 0xCE, 0x8A, 0x97, 0xD8, 0x01, 0xB6, 0xA2, 0xEF, 0xD2, 0xA4, 0xAD, 0xD8, + 0x11, 0x5C, 0xE3, 0x6F, 0x60, 0x3C, 0xD0, 0xF8, 0x3B, 0xFE, 0x0A, 0x85, 0x13, 0xBD, 0x83, 0xEF, 0xA5, 0x7F, 0x8B, 0x0C, 0x32, 0xD2, 0x50, 0x2A, 0xE1, 0xD9, + 0xDD, 0xFD, 0x33, 0x82, 0xF7, 0x28, 0x91, 0x70, 0x7C, 0xC7, 0x8F, 0xE1, 0x3A, 0xD0, 0x87, 0x77, 0x04, 0xC1, 0xF4, 0xC2, 0x5D, 0x74, 0x01, 0x5A, 0x04, 0x78, + 0x9F, 0x13, 0x0F, 0x67, 0x77, 0xE1, 0x19, 0x42, 0x53, 0x58, 0xCE, 0x06, 0x9C, 0xDE, 0x45, 0xA7, 0x70, 0x17, 0x79, 0x41, 0x05, 0x70, 0x9E, 0xEE, 0x9F, 0x71, + 0x9E, 0x50, 0x8B, 0xEC, 0x28, 0x2D, 0x6A, 0x0C, 0x7A, 0x01, 0x0F, 0x92, 0xAF, 0x59, 0x0E, 0x12, 0x1B, 0x1E, 0x21, 0x00, 0x5C, 0xDA, 0x04, 0x0F, 0x5F, 0xDF, + 0x7D, 0x67, 0x36, 0xF7, 0xF8, 0xA7, 0x5B, 0xF7, 0x30, 0x44, 0xC7, 0x61, 0xDA, 0xAE, 0x33, 0xB1, 0xAD, 0x09, 0x46, 0x82, 0xE6, 0xBE, 0x76, 0x3E, 0xE2, 0x61, + 0x1A, 0x3D, 0x16, 0x9A, 0xC7, 0xBD, 0x30, 0x13, 0xB5, 0xC7, 0x3F, 0x3E, 0xBA, 0xB7, 0xDF, 0xA6, 0x8E, 0xC6, 0x9D, 0x09, 0x51, 0xF0, 0x18, 0xA3, 0x86, 0x03, + 0x1B, 0x4B, 0x70, 0xAC, 0x85, 0x83, 0x5C, 0x24, 0xB4, 0x75, 0x0C, 0x0B, 0x45, 0x13, 0x1F, 0x49, 0x3A, 0xA9, 0x41, 0x24, 0x27, 0x6C, 0x89, 0x08, 0xF5, 0x34, + 0x1D, 0xA1, 0x40, 0x55, 0x5E, 0xD0, 0xDC, 0xBB, 0xF4, 0x3C, 0xD7, 0xFB, 0xE7, 0xDE, 0x73, 0x6C, 0xF4, 0x7C, 0xEF, 0x5F, 0xA7, 0xDA, 0xDE, 0xF3, 0x78, 0xA8, + 0xBA, 0x4F, 0xC7, 0x14, 0xA6, 0xB1, 0x99, 0xA2, 0xC6, 0x66, 0x31, 0x8D, 0xCD, 0x36, 0xAB, 0xB1, 0xF8, 0x27, 0x63, 0xEB, 0x68, 0x2D, 0xFE, 0x89, 0xD6, 0x1C, + 0xCD, 0x15, 0xC2, 0x73, 0xA5, 0x71, 0x6D, 0xCD, 0x64, 0xDA, 0xAA, 0xA2, 0x26, 0x36, 0x86, 0x83, 0xF7, 0x10, 0xEF, 0xDD, 0x8F, 0x1F, 0xDE, 0xE3, 0x58, 0x20, + 0x57, 0x59, 0xA8, 0xB1, 0x74, 0xB6, 0x25, 0xC1, 0x80, 0xC9, 0x41, 0x62, 0x64, 0x4A, 0x24, 0x09, 0xCF, 0xF7, 0xB4, 0x26, 0x45, 0x89, 0x29, 0x42, 0x81, 0x21, + 0xF0, 0x91, 0x45, 0xCD, 0x77, 0x71, 0x34, 0x11, 0xCE, 0x1B, 0x41, 0xE5, 0xD8, 0x02, 0x02, 0x28, 0x29, 0x91, 0x61, 0x5E, 0x73, 0x98, 0xD8, 0xA0, 0xB7, 0x73, + 0x17, 0xA1, 0xFE, 0xEA, 0xAB, 0x06, 0x35, 0x11, 0xD3, 0xA3, 0xD8, 0xE6, 0x17, 0x4A, 0x87, 0x47, 0x7E, 0x25, 0x01, 0xF1, 0x4F, 0x81, 0x48, 0x0C, 0x9C, 0x8F, + 0x18, 0x25, 0xB0, 0xDC, 0x49, 0xB0, 0xD0, 0x91, 0x46, 0x09, 0x07, 0xFD, 0x7C, 0x44, 0x06, 0x06, 0x35, 0x2A, 0xE8, 0xF7, 0x1A, 0x24, 0x18, 0xC4, 0x98, 0xA6, + 0x84, 0x44, 0x7C, 0x6B, 0x20, 0x1B, 0x8F, 0x1A, 0x31, 0xE2, 0x0D, 0xFF, 0x12, 0x3C, 0x7C, 0x0C, 0x55, 0x42, 0xC3, 0xDF, 0x4E, 0x9F, 0x89, 0x45, 0x8D, 0x18, + 0xFE, 0x42, 0x78, 0x19, 0x4F, 0x7C, 0xCC, 0x56, 0xE3, 0x89, 0xBF, 0xC7, 0x3C, 0x1B, 0x8F, 0xA2, 0x6C, 0xF8, 0xBB, 0xC3, 0x65, 0x56, 0xC7, 0x52, 0x84, 0x5C, + 0xC7, 0x60, 0x4D, 0x00, 0x98, 0x97, 0xA5, 0x5F, 0xEA, 0xA7, 0x9D, 0x08, 0x03, 0xCF, 0x28, 0xF2, 0x30, 0xF0, 0x26, 0x69, 0x0C, 0x22, 0x3A, 0x3C, 0x40, 0x6E, + 0xF7, 0x10, 0x51, 0x08, 0x72, 0x74, 0xB5, 0x28, 0x04, 0x69, 0xB7, 0x08, 0x3F, 0x21, 0x4C, 0x46, 0xF8, 0xA1, 0x05, 0x0D, 0xF6, 0x05, 0xE3, 0x3C, 0xF9, 0x87, + 0x1F, 0x04, 0x96, 0x29, 0x11, 0x71, 0x40, 0x3A, 0xAF, 0x64, 0x49, 0xFC, 0xDB, 0xB7, 0x29, 0x43, 0xA2, 0xC5, 0x92, 0x3B, 0x5F, 0x2D, 0x74, 0xDD, 0xF9, 0x19, + 0x18, 0xE8, 0xDC, 0x41, 0x2D, 0x37, 0xE3, 0x1F, 0x8B, 0x95, 0x20, 0x81, 0x39, 0x87, 0x12, 0x0A, 0xFE, 0xC5, 0x4C, 0x19, 0x23, 0xF4, 0x83, 0x8A, 0x4A, 0xAC, + 0x88, 0x8F, 0x27, 0xCA, 0xE8, 0xA0, 0xD3, 0x9B, 0x3C, 0xA5, 0xF0, 0x4F, 0xD4, 0x65, 0x69, 0x64, 0xA9, 0x3A, 0xE4, 0x8A, 0xCF, 0xB1, 0x49, 0x86, 0xDD, 0x8A, + 0xB3, 0xC2, 0x87, 0x19, 0xA2, 0x67, 0x9F, 0xC4, 0x5C, 0x9C, 0xD8, 0xD2, 0x54, 0x94, 0xD8, 0x6D, 0x23, 0x80, 0xE4, 0x68, 0xBC, 0x0A, 0x88, 0xDF, 0xC6, 0xFA, + 0x41, 0x28, 0x9C, 0xB5, 0x5B, 0x6D, 0x07, 0x08, 0xA0, 0x08, 0xF7, 0xE3, 0xB1, 0x8A, 0x05, 0x8E, 0x35, 0x5C, 0xEC, 0x72, 0x16, 0x3A, 0x76, 0x37, 0x03, 0x23, + 0x4F, 0x6F, 0x93, 0x10, 0x78, 0x31, 0x0B, 0x1B, 0xAD, 0x11, 0xC5, 0x70, 0x75, 0x07, 0x83, 0xF5, 0x24, 0x97, 0x77, 0xC0, 0x96, 0x95, 0x50, 0x20, 0x6D, 0x2C, + 0xD1, 0x47, 0x65, 0xAF, 0x09, 0xCC, 0x42, 0xB5, 0x3D, 0xB1, 0xA6, 0xB4, 0x77, 0xBA, 0x56, 0xCF, 0x00, 0x08, 0x6E, 0x55, 0xDA, 0x4B, 0x46, 0xE3, 0x69, 0x54, + 0x2C, 0xD1, 0xB4, 0xB1, 0x47, 0x8C, 0x2F, 0x2F, 0x12, 0xC8, 0x68, 0xF5, 0x3F, 0xC4, 0xC4, 0xAE, 0x61, 0x51, 0x30, 0x75, 0x89, 0x3D, 0x71, 0xD3, 0x72, 0x1D, + 0x22, 0xEF, 0x35, 0x51, 0x1D, 0xE1, 0x1D, 0xF1, 0x33, 0x93, 0x4C, 0x8D, 0x95, 0x1D, 0x44, 0x60, 0x1E, 0x09, 0x56, 0x9E, 0xC3, 0xAB, 0x25, 0xEB, 0x93, 0x2B, + 0x69, 0x99, 0x6E, 0x87, 0xB6, 0x79, 0x78, 0xA8, 0xBD, 0x0A, 0x02, 0x03, 0x14, 0x80, 0xCB, 0xAC, 0x73, 0x94, 0x8F, 0x66, 0xF0, 0x82, 0xAF, 0xEB, 0xA1, 0x51, + 0x62, 0xFD, 0xD9, 0x03, 0xAE, 0xA9, 0x37, 0xFA, 0x00, 0x22, 0x9C, 0x94, 0xA2, 0x6A, 0xFF, 0x7B, 0x45, 0xBC, 0xBB, 0x2B, 0x2A, 0x30, 0xD7, 0x7B, 0x05, 0xBE, + 0xB8, 0xD7, 0x8E, 0x96, 0x4A, 0xF6, 0x58, 0x7D, 0xB3, 0x0D, 0xA8, 0x2E, 0xA1, 0x0F, 0xD0, 0x71, 0x64, 0xF3, 0x8C, 0x9B, 0x50, 0xEF, 0xDA, 0xF9, 0xF9, 0x39, + 0x57, 0x46, 0xBA, 0xA0, 0x0A, 0x2D, 0x5C, 0xE7, 0x0B, 0xB9, 0x5B, 0x2D, 0x41, 0xFC, 0x51, 0x89, 0x34, 0x55, 0xB4, 0xE5, 0xD2, 0x21, 0x6D, 0x68, 0x79, 0xC1, + 0xCB, 0x64, 0x7A, 0x4F, 0xD2, 0x28, 0x52, 0x01, 0xB5, 0x4E, 0xF4, 0xC4, 0x17, 0x6B, 0x8D, 0xEE, 0x9F, 0xC8, 0xCF, 0x24, 0xE5, 0x65, 0x4E, 0x20, 0x17, 0x9E, + 0x18, 0xBA, 0x52, 0x3D, 0x3C, 0x49, 0xA2, 0xBA, 0xDF, 0x7F, 0x12, 0x45, 0x86, 0xD5, 0xD2, 0x34, 0x02, 0x92, 0x0C, 0x0E, 0xA1, 0x2D, 0x88, 0x9B, 0x0B, 0x37, + 0x20, 0xA9, 0x88, 0x61, 0x39, 0x56, 0x60, 0x19, 0xF6, 0xA7, 0xC8, 0x1A, 0xB7, 0xEA, 0xFE, 0x12, 0x1F, 0x2F, 0xE1, 0xFF, 0x6B, 0x15, 0x5E, 0xB5, 0xAA, 0xE4, + 0x9A, 0x85, 0x84, 0xF1, 0x20, 0xB2, 0x92, 0xB8, 0x1C, 0x12, 0x61, 0x81, 0xDF, 0x17, 0x3D, 0x3D, 0x7D, 0x4A, 0x8F, 0x9E, 0x84, 0x4A, 0x13, 0xD1, 0xE3, 0x5C, + 0x8B, 0x6E, 0xA4, 0x14, 0xBC, 0x8E, 0x3B, 0x85, 0x43, 0x20, 0x8F, 0x61, 0x60, 0xBE, 0x15, 0xAA, 0x77, 0x09, 0x53, 0x5D, 0xB4, 0x85, 0xFF, 0x8F, 0xFA, 0x8F, + 0x28, 0xEA, 0x6F, 0x2F, 0xC4, 0xE7, 0xD8, 0x76, 0xCA, 0x03, 0x18, 0x9C, 0x7C, 0xD1, 0xE5, 0xF9, 0xDE, 0x81, 0x26, 0x5F, 0x55, 0x49, 0xA5, 0x15, 0x73, 0xCB, + 0x64, 0x24, 0x47, 0x76, 0x85, 0x12, 0xC2, 0x85, 0x51, 0x5C, 0x3A, 0xC4, 0x75, 0xC4, 0xE6, 0x1E, 0x5B, 0xB5, 0xA5, 0xD1, 0xF8, 0x3E, 0x4A, 0x48, 0xE6, 0xEE, + 0x4D, 0x1E, 0xA4, 0x07, 0x31, 0xE7, 0x9A, 0xA4, 0x80, 0x43, 0x68, 0xD3, 0xF2, 0x8D, 0xB1, 0x5D, 0xDC, 0x35, 0x6F, 0x67, 0xF2, 0xA1, 0x00, 0x1A, 0x88, 0x2B, + 0x00, 0x1A, 0x78, 0xD4, 0x67, 0x62, 0x68, 0x89, 0x53, 0x84, 0x55, 0x90, 0x95, 0x8B, 0x78, 0x6A, 0x80, 0x13, 0x27, 0x31, 0xB3, 0x40, 0x5A, 0x22, 0xC4, 0xC6, + 0x2F, 0x03, 0x44, 0xF2, 0xF4, 0x5C, 0x73, 0x56, 0xB6, 0x0D, 0x16, 0x88, 0x2C, 0x80, 0x05, 0xC6, 0xEF, 0x4A, 0x03, 0xF4, 0x1F, 0x37, 0x9A, 0x85, 0x94, 0x27, + 0x24, 0xF0, 0xEC, 0x59, 0x12, 0x1B, 0x2E, 0xDF, 0xB2, 0xD4, 0x3C, 0xEC, 0x8D, 0xB5, 0x67, 0x6F, 0xD3, 0x8D, 0x46, 0x59, 0x4E, 0x12, 0x0C, 0xD5, 0x4F, 0x13, + 0x82, 0x8F, 0x65, 0x38, 0x40, 0x88, 0x65, 0x52, 0x01, 0xE1, 0x26, 0x8D, 0xC6, 0xDA, 0x4A, 0xD7, 0x4B, 0x6A, 0xF5, 0x4D, 0xC2, 0xF7, 0xE8, 0xEC, 0x83, 0xFC, + 0xD1, 0x98, 0xA3, 0x0B, 0x22, 0xDB, 0x09, 0xBB, 0x8A, 0x63, 0x9C, 0x25, 0x30, 0x22, 0x63, 0x29, 0xBA, 0xF1, 0x47, 0x3B, 0x80, 0xA6, 0xB8, 0x43, 0x26, 0x36, + 0x78, 0xAF, 0x8F, 0xFE, 0xB4, 0xE3, 0xF5, 0x86, 0xB9, 0x14, 0xDC, 0x8C, 0x3F, 0xCF, 0xA0, 0xB9, 0x8C, 0x31, 0x8A, 0xEE, 0x66, 0x8C, 0x2C, 0x51, 0x12, 0xE0, + 0x30, 0x13, 0x95, 0xD6, 0x00, 0x63, 0xFF, 0x6C, 0xE1, 0x96, 0x00, 0xDF, 0x0A, 0xEE, 0xD6, 0xD1, 0x8D, 0xB4, 0x96, 0x2E, 0x70, 0x42, 0xD3, 0xB7, 0xB8, 0x6D, + 0x26, 0xC4, 0x1C, 0x5E, 0x48, 0xA6, 0x86, 0xC2, 0x69, 0xC2, 0x75, 0xA9, 0xB8, 0x16, 0xD9, 0x00, 0x16, 0x8D, 0x5E, 0x91, 0x99, 0x6C, 0x28, 0x9E, 0xEB, 0x18, + 0xCC, 0xA5, 0x51, 0xB7, 0x66, 0x28, 0xCF, 0xC1, 0xC9, 0xB6, 0xA3, 0xA4, 0x91, 0xAE, 0xC6, 0x0B, 0x2B, 0x90, 0x20, 0xDC, 0xD3, 0xF7, 0xCA, 0x8C, 0x0A, 0x71, + 0x1F, 0x62, 0x71, 0x88, 0x26, 0xCC, 0x80, 0x28, 0xB1, 0xCE, 0x36, 0x61, 0xDB, 0x2E, 0x5F, 0xC2, 0xA4, 0x18, 0x57, 0xCF, 0x50, 0xC1, 0xA9, 0x65, 0x6B, 0x86, + 0x82, 0xED, 0xB6, 0xA0, 0x28, 0x92, 0xFB, 0x2D, 0xC4, 0x1E, 0x87, 0x64, 0x7E, 0x1D, 0x5F, 0xE6, 0xFF, 0xCD, 0x23, 0x00, 0xE7, 0x63, 0x8D, 0x4F, 0xFB, 0xCB, + 0x57, 0x8A, 0xE2, 0x5E, 0x9B, 0x82, 0x0F, 0xFB, 0x73, 0x62, 0xD2, 0x7A, 0x54, 0xB0, 0xF2, 0x4F, 0x35, 0x5C, 0xAA, 0x4E, 0xEC, 0xAF, 0xB8, 0xFF, 0x2D, 0xB4, + 0x90, 0x70, 0x08, 0x28, 0x9C, 0x02, 0xD0, 0x6D, 0x38, 0xF9, 0xD9, 0x3F, 0x4B, 0x9A, 0x25, 0xE5, 0x1E, 0xFC, 0x31, 0xFF, 0xB6, 0xDB, 0x90, 0x69, 0x40, 0x37, + 0xDF, 0x43, 0x4E, 0x91, 0x32, 0xD3, 0x7D, 0x3E, 0x79, 0x01, 0x0D, 0x98, 0x22, 0x10, 0x31, 0x1D, 0xE1, 0x14, 0x85, 0x89, 0x29, 0x21, 0x61, 0xC6, 0x0C, 0xE7, + 0xA5, 0x78, 0x8F, 0x0A, 0x1F, 0x9B, 0x43, 0x59, 0xFC, 0xEE, 0xC3, 0x94, 0x63, 0xFF, 0x49, 0x28, 0x86, 0x75, 0x1C, 0xD8, 0x41, 0x0C, 0x41, 0x42, 0x44, 0x59, + 0x62, 0xE2, 0x46, 0x93, 0x9C, 0x2D, 0xE5, 0xC8, 0x8C, 0xFD, 0x62, 0x23, 0x19, 0x1D, 0xC6, 0x68, 0xCF, 0xFF, 0xA4, 0x46, 0xF3, 0xAF, 0x03, 0x36, 0xF4, 0xC5, + 0x22, 0xD1, 0x7E, 0x19, 0x82, 0xD6, 0xA6, 0x6E, 0x85, 0xC4, 0x6C, 0x2C, 0x89, 0x15, 0x3F, 0x08, 0x70, 0x14, 0x1F, 0xA4, 0x8A, 0x6B, 0x93, 0xB7, 0x78, 0xA6, + 0x15, 0x32, 0x28, 0x91, 0x4D, 0x6C, 0xE6, 0x25, 0xC4, 0x23, 0xCD, 0xB2, 0x32, 0xC5, 0xC5, 0xEC, 0x8B, 0x39, 0xEC, 0xB5, 0x45, 0x6E, 0x72, 0xAB, 0x99, 0x74, + 0x07, 0x15, 0x95, 0x57, 0x04, 0x70, 0x11, 0xEE, 0x98, 0x2B, 0x84, 0x8C, 0x76, 0xD7, 0xC5, 0x70, 0xD0, 0xAD, 0x73, 0x6A, 0x4B, 0x9E, 0xB4, 0x69, 0x02, 0x14, + 0xB1, 0x16, 0xC3, 0x8A, 0xDD, 0xD4, 0x69, 0xF2, 0xA9, 0xEF, 0x16, 0x83, 0xC7, 0x77, 0xDA, 0xC5, 0x7B, 0x37, 0xAE, 0x15, 0x80, 0xA3, 0xED, 0x81, 0x31, 0x50, + 0x31, 0x22, 0xE5, 0x01, 0x42, 0x1B, 0xB6, 0xFD, 0x73, 0x2F, 0xA6, 0x21, 0x3F, 0x70, 0x97, 0x57, 0x94, 0x90, 0x54, 0x28, 0xB9, 0xA1, 0x45, 0xF7, 0x36, 0xDE, + 0x6F, 0xF2, 0xF4, 0x23, 0x2E, 0x9D, 0xE4, 0x3A, 0xE5, 0x15, 0x56, 0xE4, 0x35, 0x86, 0x67, 0x2F, 0x99, 0x3B, 0xD2, 0x62, 0xBD, 0xB4, 0x07, 0xD4, 0x75, 0xDB, + 0xF7, 0x26, 0x2C, 0xA0, 0x87, 0x9B, 0xE9, 0x30, 0xDE, 0xE0, 0xE1, 0x6F, 0xAC, 0x4F, 0x1C, 0x80, 0x13, 0x56, 0xB1, 0x5F, 0x48, 0x8B, 0xBB, 0x4C, 0x93, 0x12, + 0x95, 0x6A, 0x98, 0x87, 0xFA, 0x18, 0xC9, 0xD9, 0xE0, 0x85, 0x31, 0x2F, 0x66, 0x31, 0x19, 0x81, 0x35, 0x12, 0x13, 0x8F, 0x64, 0x49, 0xE2, 0x63, 0xA3, 0x11, + 0xDB, 0x89, 0xF9, 0xF2, 0xF3, 0x64, 0x0C, 0x03, 0xD0, 0x1B, 0x70, 0x1F, 0xF0, 0xD7, 0x9B, 0xE6, 0xFE, 0x7D, 0x1E, 0x3B, 0x4C, 0x5C, 0x91, 0xED, 0xA8, 0x12, + 0x41, 0x43, 0xBD, 0x1C, 0x5B, 0x42, 0x3E, 0x72, 0x74, 0x71, 0x93, 0xBF, 0x74, 0x44, 0xFA, 0x9F, 0x25, 0xD8, 0xF3, 0x75, 0xD1, 0xB2, 0x0C, 0x30, 0x81, 0x20, + 0x0A, 0xE2, 0x6B, 0xC4, 0xA6, 0x12, 0xC0, 0x98, 0x5D, 0x88, 0x06, 0x21, 0xED, 0xA1, 0x1F, 0xE4, 0xAC, 0x6A, 0x4C, 0x0C, 0xE7, 0xDA, 0x48, 0xAC, 0x6A, 0x4C, + 0x00, 0x57, 0x40, 0xB8, 0xC9, 0x37, 0x1B, 0xAC, 0x41, 0x83, 0xDB, 0x2E, 0x3B, 0x6B, 0xD3, 0xE7, 0x43, 0x30, 0x49, 0x47, 0xF5, 0xD1, 0x93, 0xC4, 0xED, 0x39, + 0xA1, 0xEF, 0xE4, 0xE3, 0xF7, 0xD9, 0x19, 0x6B, 0x10, 0xF6, 0x32, 0x76, 0xCD, 0xBB, 0xB6, 0xB1, 0x5C, 0x12, 0xC7, 0xBC, 0x98, 0x5B, 0xB6, 0xD9, 0x64, 0xA0, + 0xB1, 0xD2, 0x3E, 0xC6, 0x24, 0x42, 0x77, 0x83, 0x71, 0xAC, 0xE0, 0x88, 0x17, 0xEC, 0x5A, 0x73, 0xAF, 0x6B, 0x8A, 0xCD, 0x7C, 0xBC, 0x59, 0xDB, 0xF4, 0x8C, + 0x9B, 0xEF, 0x70, 0xAB, 0x30, 0xD5, 0xE4, 0x41, 0xE7, 0xA0, 0xC3, 0x1B, 0x04, 0x90, 0xEB, 0x08, 0x69, 0x21, 0x5E, 0xDC, 0x52, 0xF9, 0xD3, 0x0F, 0xEF, 0x23, + 0xBC, 0x81, 0xFB, 0x86, 0x5D, 0x6A, 0xEE, 0xD1, 0xBD, 0xC6, 0x87, 0xBF, 0x2F, 0x71, 0x0B, 0x87, 0x88, 0xF1, 0x31, 0x31, 0xE2, 0x36, 0x62, 0x14, 0x15, 0x6B, + 0xFE, 0x22, 0x8E, 0x14, 0x2E, 0x3B, 0x10, 0xA4, 0xD1, 0x52, 0x9B, 0x32, 0x50, 0xB1, 0xC9, 0x18, 0xC1, 0x91, 0x93, 0x6F, 0x61, 0xEE, 0xF6, 0x2B, 0x31, 0x3C, + 0xD0, 0xC7, 0x73, 0xAD, 0xD9, 0xE8, 0x34, 0x9E, 0x37, 0xE9, 0xF5, 0x0F, 0xC0, 0xCE, 0xBC, 0xB9, 0xFF, 0x5C, 0xDF, 0xDF, 0x6F, 0xFB, 0xA0, 0x33, 0xD2, 0x6C, + 0x75, 0x45, 0x13, 0xF8, 0x43, 0xDB, 0xB0, 0x4E, 0xB2, 0xEF, 0xBF, 0x73, 0x57, 0x9E, 0x9F, 0xD7, 0xE0, 0x83, 0xE5, 0xE0, 0x30, 0x98, 0xD7, 0xE4, 0x8A, 0x80, + 0x60, 0xCD, 0xB5, 0x26, 0x0D, 0xBA, 0x37, 0x5A, 0x4C, 0xA3, 0xE8, 0x96, 0x51, 0xC8, 0xB8, 0x63, 0xB9, 0x36, 0x4F, 0xF7, 0x08, 0x16, 0x81, 0x9B, 0x62, 0xA5, + 0xE6, 0x3E, 0x6E, 0x1C, 0x51, 0x42, 0xC5, 0x27, 0xD2, 0x6B, 0xFA, 0x4F, 0xC5, 0x1A, 0x9E, 0xA2, 0xAC, 0x95, 0x87, 0x55, 0xB2, 0x40, 0x69, 0x7A, 0x93, 0x9B, + 0x0E, 0x26, 0x6B, 0xA8, 0xE9, 0x09, 0x64, 0x32, 0xF5, 0xBB, 0x58, 0x81, 0x7B, 0x2E, 0x44, 0x30, 0x64, 0xD7, 0x70, 0x16, 0x16, 0x46, 0x6D, 0x98, 0x95, 0xE5, + 0x0D, 0x25, 0x70, 0x3B, 0x36, 0xF8, 0xF0, 0x29, 0x5C, 0x01, 0x00, 0x9D, 0xB7, 0x85, 0x03, 0x90, 0x86, 0x50, 0xEB, 0x64, 0xC7, 0xCB, 0x07, 0x9C, 0x78, 0x68, + 0xB7, 0x1F, 0x06, 0x1B, 0x04, 0xE2, 0x53, 0x9E, 0x48, 0x77, 0xEB, 0x13, 0xCE, 0x74, 0xAC, 0x59, 0x9B, 0x68, 0xDE, 0xC7, 0xB4, 0x25, 0x9E, 0x57, 0x89, 0xF8, + 0x21, 0xF9, 0xCC, 0x93, 0x38, 0xF3, 0x62, 0xE2, 0x5C, 0x00, 0xF1, 0x99, 0x26, 0xD8, 0x71, 0xF6, 0x89, 0x22, 0xFB, 0x84, 0xB3, 0x8F, 0x00, 0xD1, 0x6C, 0xAF, + 0x78, 0x16, 0x1F, 0x1A, 0xE3, 0xCF, 0xAF, 0x23, 0xCE, 0x6E, 0xC6, 0xB9, 0x74, 0xF2, 0xD9, 0x75, 0x8C, 0xBD, 0x7C, 0x00, 0x68, 0xBF, 0x00, 0x7F, 0x88, 0xB3, + 0x75, 0x33, 0x56, 0x63, 0x4B, 0xCC, 0xCE, 0x11, 0x20, 0x62, 0x4B, 0x3E, 0x87, 0x17, 0xAC, 0xBC, 0x21, 0x01, 0x7F, 0xAA, 0xCD, 0x70, 0x4C, 0x6D, 0xEA, 0x19, + 0x0B, 0x82, 0x1F, 0x31, 0x0F, 0x89, 0x0D, 0xAF, 0xE4, 0xD1, 0x1C, 0x36, 0x62, 0x69, 0x50, 0x78, 0xAA, 0x44, 0x76, 0xD8, 0x3A, 0x32, 0xC9, 0x08, 0x81, 0xA8, + 0x1C, 0x0C, 0xD2, 0x75, 0x1C, 0x96, 0x50, 0x9B, 0x94, 0xFA, 0x54, 0xDA, 0x1C, 0x6F, 0xE0, 0x41, 0xE8, 0x9A, 0x39, 0x80, 0x29, 0xD1, 0x86, 0x99, 0x2A, 0x73, + 0x5D, 0xF6, 0x3B, 0x3B, 0x14, 0x8F, 0x3C, 0xB0, 0x33, 0x1C, 0x92, 0x46, 0x4F, 0xCE, 0x0E, 0xE7, 0xC1, 0xC2, 0x1E, 0x3D, 0xF9, 0x5F, 0x0C, 0x79, 0xF5, 0x60, + 0xD6, 0x04, 0x01, 0x00 }; -//File: index_ov5640.html.gz, Size: 9124 -#define index_ov5640_html_gz_len 9124 -const uint8_t index_ov5640_html_gz[] = { - 0x1F, 0x8B, 0x08, 0x08, 0xD9, 0x6C, 0x6A, 0x5E, 0x00, 0x03, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x6F, 0x76, 0x35, 0x36, 0x34, 0x30, 0x2E, 0x68, 0x74, 0x6D, - 0x6C, 0x00, 0xED, 0x3D, 0x6B, 0x77, 0xDB, 0xB6, 0x92, 0xDF, 0xF3, 0x2B, 0x18, 0xF5, 0x6E, 0x24, 0x9F, 0x58, 0xB6, 0xA8, 0x97, 0x1F, 0xB1, 0x95, 0x4D, 0x1C, - 0x27, 0xE9, 0xB9, 0x4D, 0x6F, 0x1A, 0xA7, 0x69, 0x7B, 0xBA, 0x3D, 0x29, 0x25, 0x41, 0x12, 0x1B, 0x8A, 0xD4, 0x25, 0x29, 0xCB, 0x6E, 0x8E, 0x7F, 0xC7, 0xFE, - 0xA0, 0xFD, 0x63, 0x3B, 0x03, 0x80, 0x24, 0x48, 0x81, 0x24, 0x48, 0x4A, 0xB2, 0xDB, 0x5D, 0xE5, 0x9C, 0x98, 0x0F, 0xCC, 0x60, 0xDE, 0x18, 0x0C, 0x40, 0xF2, - 0xEC, 0xF1, 0xD8, 0x19, 0xF9, 0xB7, 0x0B, 0xA2, 0xCD, 0xFC, 0xB9, 0x35, 0x78, 0x74, 0xC6, 0xFE, 0x68, 0xF0, 0x3B, 0x9B, 0x11, 0x63, 0xCC, 0x0E, 0xE9, 0xE9, - 0x9C, 0xF8, 0x86, 0x36, 0x9A, 0x19, 0xAE, 0x47, 0xFC, 0xF3, 0xDA, 0xD2, 0x9F, 0x34, 0x8F, 0x6B, 0xC9, 0xDB, 0xB6, 0x31, 0x27, 0xE7, 0xB5, 0x6B, 0x93, 0xAC, - 0x16, 0x8E, 0xEB, 0xD7, 0xB4, 0x91, 0x63, 0xFB, 0xC4, 0x86, 0xE6, 0x2B, 0x73, 0xEC, 0xCF, 0xCE, 0xC7, 0xE4, 0xDA, 0x1C, 0x91, 0x26, 0x3D, 0xD9, 0x37, 0x6D, - 0xD3, 0x37, 0x0D, 0xAB, 0xE9, 0x8D, 0x0C, 0x8B, 0x9C, 0xEB, 0x22, 0x2E, 0xDF, 0xF4, 0x2D, 0x32, 0xB8, 0xBC, 0x7A, 0xDF, 0x69, 0x6B, 0xFF, 0xFA, 0xD4, 0xEB, - 0x77, 0x5B, 0x67, 0x87, 0xEC, 0x5A, 0xD4, 0xC6, 0xF3, 0x6F, 0xC5, 0x73, 0xFC, 0x0D, 0x9D, 0xF1, 0xAD, 0xF6, 0x35, 0x76, 0x09, 0x7F, 0x13, 0x20, 0xA2, 0x39, - 0x31, 0xE6, 0xA6, 0x75, 0x7B, 0xAA, 0xBD, 0x70, 0xA1, 0xCF, 0xFD, 0xB7, 0xC4, 0xBA, 0x26, 0xBE, 0x39, 0x32, 0xF6, 0x3D, 0xC3, 0xF6, 0x9A, 0x1E, 0x71, 0xCD, - 0xC9, 0xB3, 0x35, 0xC0, 0xA1, 0x31, 0xFA, 0x32, 0x75, 0x9D, 0xA5, 0x3D, 0x3E, 0xD5, 0xBE, 0xD1, 0x8F, 0xF1, 0xDF, 0x7A, 0xA3, 0x91, 0x63, 0x39, 0x2E, 0xDC, - 0xBF, 0x7C, 0x8D, 0xFF, 0xD6, 0xEF, 0xD3, 0xDE, 0x3D, 0xF3, 0x4F, 0x72, 0xAA, 0xE9, 0xFD, 0xC5, 0x4D, 0xEC, 0xFE, 0xDD, 0xA3, 0xD8, 0xE9, 0xAC, 0x9D, 0x46, - 0x3D, 0x87, 0x3F, 0xCE, 0x86, 0xF7, 0xC8, 0xC8, 0x37, 0x1D, 0xFB, 0x60, 0x6E, 0x98, 0xB6, 0x04, 0xD3, 0xD8, 0xF4, 0x16, 0x96, 0x01, 0x32, 0x98, 0x58, 0x24, - 0x13, 0xCF, 0x37, 0x73, 0x62, 0x2F, 0xF7, 0x73, 0xB0, 0x21, 0x92, 0xE6, 0xD8, 0x74, 0x59, 0xAB, 0x53, 0x94, 0xC3, 0x72, 0x6E, 0xE7, 0xA2, 0xCD, 0xA2, 0xCB, - 0x76, 0x6C, 0x22, 0x11, 0x20, 0x76, 0xB4, 0x72, 0x8D, 0x05, 0x36, 0xC0, 0xBF, 0xEB, 0x4D, 0xE6, 0xA6, 0xCD, 0x8C, 0xEA, 0x54, 0xEB, 0x74, 0x5B, 0x8B, 0x9B, - 0x1C, 0x55, 0x76, 0xFA, 0xF8, 0x6F, 0xBD, 0xD1, 0xC2, 0x18, 0x8F, 0x4D, 0x7B, 0x7A, 0xAA, 0x1D, 0x4B, 0x51, 0x38, 0xEE, 0x98, 0xB8, 0x4D, 0xD7, 0x18, 0x9B, - 0x4B, 0xEF, 0x54, 0xEB, 0xCA, 0xDA, 0xCC, 0x0D, 0x77, 0x0A, 0xB4, 0xF8, 0x0E, 0x10, 0xDB, 0xD4, 0xA5, 0x94, 0xF0, 0x26, 0xAE, 0x39, 0x9D, 0xF9, 0xA0, 0xD2, - 0xB5, 0x36, 0x49, 0xA1, 0x71, 0x17, 0xCA, 0xD3, 0x67, 0xA6, 0xDC, 0xE4, 0x52, 0x33, 0x2C, 0x73, 0x6A, 0x37, 0x4D, 0x9F, 0xCC, 0x81, 0x1D, 0xCF, 0x77, 0x89, - 0x3F, 0x9A, 0x65, 0x91, 0x32, 0x31, 0xA7, 0x4B, 0x97, 0x48, 0x08, 0x09, 0xE5, 0x96, 0xC1, 0x30, 0xDC, 0x5C, 0xBF, 0xD5, 0x5C, 0x91, 0xE1, 0x17, 0xD3, 0x6F, - 0x72, 0x99, 0x0C, 0xC9, 0xC4, 0x71, 0x89, 0xB4, 0x65, 0xD0, 0xC2, 0x72, 0x46, 0x5F, 0x9A, 0x9E, 0x6F, 0xB8, 0xBE, 0x0A, 0x42, 0x63, 0xE2, 0x13, 0x37, 0x1F, - 0x1F, 0x41, 0xAB, 0xC8, 0xC7, 0x96, 0xDE, 0x2D, 0x6F, 0x60, 0xDA, 0x96, 0x69, 0x13, 0x75, 0xF2, 0xD2, 0xFA, 0x8D, 0xA3, 0x63, 0xAD, 0x14, 0x14, 0x63, 0xCE, - 0xA7, 0x59, 0x56, 0x42, 0x79, 0x5D, 0xEF, 0x8C, 0xFB, 0x8D, 0xDE, 0x6A, 0xFD, 0xC7, 0xFA, 0xCD, 0x19, 0x61, 0x66, 0x6A, 0x2C, 0x7D, 0xA7, 0xBA, 0x47, 0xAC, - 0xB9, 0x55, 0x82, 0x8F, 0xFF, 0x9C, 0x93, 0xB1, 0x69, 0x68, 0x0D, 0xC1, 0x9D, 0x8F, 0x5B, 0x60, 0x53, 0x7B, 0x9A, 0x61, 0x8F, 0xB5, 0x86, 0xE3, 0x9A, 0xE0, - 0x08, 0x06, 0x0D, 0x37, 0x16, 0x5C, 0x81, 0x81, 0x63, 0x41, 0xF6, 0x24, 0x2C, 0x67, 0xF8, 0x8C, 0x28, 0x11, 0xB9, 0xDB, 0xE0, 0x4F, 0x21, 0xE4, 0xE0, 0x2F, - 0xD7, 0x81, 0x24, 0x3C, 0x52, 0xF4, 0x59, 0xFA, 0x12, 0x29, 0x4C, 0xD3, 0x19, 0xFE, 0xE6, 0xC6, 0x4D, 0x33, 0x53, 0x77, 0x41, 0xA3, 0x40, 0x87, 0x30, 0xCC, - 0x8E, 0x1A, 0xD0, 0xF4, 0x7A, 0xA6, 0x35, 0x35, 0x8C, 0x92, 0x7B, 0x72, 0x18, 0x8E, 0x54, 0xAE, 0x72, 0xFC, 0x89, 0x46, 0x51, 0x80, 0x5D, 0x39, 0xAB, 0x51, - 0xEC, 0x60, 0xFF, 0x64, 0x36, 0xC4, 0x38, 0x49, 0x8D, 0x22, 0xF8, 0x53, 0x8F, 0x24, 0x11, 0xB2, 0xDC, 0x68, 0x22, 0x41, 0x9C, 0x1E, 0x51, 0xD6, 0xF0, 0xA6, - 0x79, 0xB7, 0x04, 0x6B, 0x36, 0x09, 0xAA, 0xD1, 0x45, 0x82, 0x38, 0x8B, 0x86, 0xDC, 0x28, 0x83, 0xBF, 0x3B, 0x85, 0x7C, 0xE3, 0x9B, 0xE1, 0xD2, 0xF7, 0x1D, - 0xDB, 0xAB, 0x34, 0x44, 0xA5, 0xF9, 0xD9, 0x1F, 0x4B, 0xCF, 0x37, 0x27, 0xB7, 0x4D, 0xEE, 0xD2, 0xE0, 0x67, 0x0B, 0x03, 0x52, 0xC8, 0x21, 0xF1, 0x57, 0x84, - 0x64, 0xA7, 0x1B, 0xB6, 0x71, 0x0D, 0x71, 0x67, 0x3A, 0xB5, 0x64, 0xB6, 0x37, 0x5A, 0xBA, 0x1E, 0xE6, 0x6D, 0x0B, 0xC7, 0x04, 0xC4, 0xEE, 0x7A, 0xC7, 0x71, - 0x1F, 0x54, 0xEC, 0xA8, 0x39, 0x1A, 0x4A, 0xFA, 0x72, 0x96, 0x3E, 0xCA, 0x58, 0xAA, 0x09, 0x07, 0xD8, 0x31, 0xFD, 0x5B, 0xE9, 0x3D, 0xEE, 0x89, 0x92, 0x3B, - 0x81, 0x0B, 0x66, 0x0E, 0x0B, 0x71, 0xBA, 0x4E, 0x47, 0x33, 0x32, 0xFA, 0x42, 0xC6, 0x4F, 0x73, 0xD3, 0xB0, 0xBC, 0xF4, 0xF0, 0xC0, 0xB4, 0x17, 0x4B, 0xBF, - 0x89, 0xE9, 0xD4, 0x62, 0x2B, 0x3A, 0xA7, 0x06, 0x19, 0xB0, 0xD8, 0x6E, 0x67, 0x25, 0x15, 0xBD, 0xC5, 0x4D, 0xB6, 0x10, 0x44, 0x62, 0x07, 0x96, 0x31, 0x24, - 0x56, 0x16, 0xC9, 0xDC, 0x19, 0x52, 0xC2, 0x2E, 0x8F, 0x55, 0xE9, 0xB9, 0x1B, 0xA5, 0x2C, 0x1A, 0xBC, 0xBA, 0x47, 0xFF, 0xA1, 0x2C, 0x47, 0x7A, 0xBC, 0x1F, - 0xBB, 0xE4, 0x11, 0x0B, 0x1C, 0x2C, 0x71, 0x6D, 0x61, 0xA4, 0x26, 0xE3, 0xD0, 0x62, 0x05, 0x54, 0x65, 0x76, 0xE9, 0x1A, 0xF6, 0x94, 0x40, 0x74, 0xB8, 0xD9, - 0x0F, 0x0E, 0xB3, 0xA7, 0x0A, 0x4A, 0x02, 0xC1, 0xE0, 0xDD, 0xCB, 0x9E, 0x9A, 0xB0, 0x10, 0xB1, 0xAF, 0x1D, 0xB0, 0x83, 0x12, 0x79, 0x8A, 0xA0, 0xF1, 0x4C, - 0x42, 0x74, 0xA9, 0xBD, 0xB0, 0x54, 0x45, 0xEA, 0x4B, 0x71, 0x6B, 0x93, 0xA6, 0xFE, 0xB9, 0xC1, 0x22, 0x98, 0x04, 0x4E, 0x26, 0x79, 0xD3, 0xC8, 0xC9, 0xA4, - 0xD3, 0xEA, 0x74, 0x73, 0x73, 0x29, 0x29, 0x97, 0x89, 0xA9, 0xA4, 0x24, 0x98, 0x84, 0x81, 0x26, 0x5F, 0x17, 0xA7, 0x33, 0xE7, 0x9A, 0xB8, 0x12, 0x45, 0x24, - 0xC8, 0xED, 0x9E, 0x74, 0xC7, 0x0A, 0xD8, 0x0C, 0x18, 0x0A, 0xAE, 0x65, 0x81, 0x36, 0x8E, 0xAE, 0xAD, 0x8F, 0xDA, 0x99, 0x16, 0xCA, 0xD0, 0x1D, 0x80, 0x35, - 0x18, 0x43, 0x8B, 0x8C, 0x33, 0x22, 0xF7, 0x98, 0x4C, 0x8C, 0xA5, 0xE5, 0xE7, 0xC8, 0xDB, 0x68, 0xE1, 0xBF, 0xAC, 0x1E, 0xA9, 0x7B, 0xFD, 0x8A, 0x35, 0x90, - 0x73, 0xEA, 0x12, 0xBF, 0x49, 0xFA, 0x0C, 0x86, 0x55, 0x63, 0xB1, 0x20, 0x06, 0xB4, 0x1A, 0x91, 0xB4, 0xD9, 0xAA, 0x52, 0x3A, 0x2D, 0x8F, 0x69, 0x4A, 0x73, - 0xD4, 0x5C, 0x53, 0x0C, 0x13, 0xA5, 0x42, 0x3C, 0x9F, 0x4E, 0x9C, 0xD1, 0x52, 0x36, 0x82, 0xAB, 0x99, 0xD4, 0x3A, 0xBE, 0xD3, 0x40, 0x64, 0x9E, 0x65, 0x52, - 0xC3, 0x5E, 0xDA, 0x36, 0x6A, 0xB4, 0xE9, 0xBB, 0xC0, 0xA6, 0xA4, 0x23, 0x35, 0xC1, 0x95, 0xF2, 0xCE, 0x98, 0x60, 0xD3, 0xEA, 0x34, 0x09, 0x07, 0x94, 0x04, - 0x8A, 0x30, 0x86, 0x68, 0x9E, 0x03, 0x4C, 0x05, 0xA8, 0xAA, 0xC9, 0xC5, 0x9F, 0x2D, 0xE7, 0xB2, 0x9C, 0x21, 0xE8, 0x4C, 0x87, 0x01, 0x8E, 0x75, 0xE7, 0x4E, - 0x87, 0x46, 0xA3, 0xB5, 0xDF, 0xDA, 0xEF, 0xC0, 0x7F, 0x92, 0xDC, 0x3D, 0xDB, 0xB8, 0xB8, 0x78, 0x53, 0x2C, 0x2F, 0x11, 0x7C, 0xF2, 0x4B, 0x28, 0x69, 0x61, - 0x2C, 0x57, 0x17, 0xEA, 0x9E, 0x14, 0xAF, 0xA5, 0xE8, 0x07, 0x39, 0x23, 0x4C, 0x8A, 0x49, 0x17, 0x37, 0x44, 0x89, 0xB5, 0x14, 0x55, 0xF1, 0xDC, 0xF9, 0xB3, - 0xC9, 0x86, 0xD7, 0xFF, 0xF3, 0xD6, 0x2E, 0x88, 0xE2, 0x6F, 0x6D, 0xE9, 0x85, 0xE5, 0xE2, 0xDD, 0xB7, 0x6D, 0xB4, 0xD2, 0xB5, 0xDE, 0xE4, 0xF9, 0x0C, 0x50, - 0x68, 0x43, 0xC6, 0xE9, 0xC2, 0xC4, 0x2B, 0x35, 0xE7, 0x11, 0xDA, 0x94, 0x90, 0xC1, 0xC4, 0xB4, 0xAC, 0xA6, 0xE5, 0xAC, 0xF2, 0x33, 0x91, 0x6C, 0x4B, 0x5E, - 0xB3, 0xD3, 0x7C, 0x93, 0x2F, 0x4B, 0xED, 0x12, 0x22, 0xD7, 0x5F, 0x82, 0xDA, 0xBF, 0xB7, 0xC3, 0x65, 0xBA, 0x46, 0xB9, 0x81, 0xA2, 0x84, 0x3D, 0x56, 0xEB, - 0x48, 0xC9, 0x94, 0x58, 0x26, 0x98, 0x39, 0xAB, 0xF3, 0x56, 0xA6, 0x3F, 0x9A, 0x95, 0x98, 0x54, 0x2D, 0x1C, 0xCF, 0x64, 0xCB, 0x37, 0x2E, 0xB1, 0x0C, 0xCC, - 0xE0, 0x4B, 0xCD, 0xC6, 0x73, 0x27, 0x26, 0x22, 0xB8, 0x0A, 0x27, 0x54, 0x74, 0x0F, 0xA7, 0x92, 0x72, 0xC0, 0x72, 0x87, 0xF4, 0x58, 0x2D, 0x37, 0xEB, 0x9C, - 0x74, 0x3F, 0xEE, 0x19, 0xF2, 0x46, 0x05, 0x22, 0x7A, 0x10, 0xB4, 0xA7, 0x2E, 0xB9, 0x55, 0x60, 0x66, 0x9F, 0xFF, 0x3D, 0x65, 0xB5, 0xD2, 0xF2, 0x45, 0x00, - 0x3A, 0x00, 0x70, 0x2B, 0x3A, 0xE8, 0x7A, 0x0A, 0x5D, 0xA7, 0x77, 0xA9, 0x62, 0x8F, 0x61, 0x25, 0xB0, 0x56, 0x53, 0x08, 0x37, 0x19, 0x43, 0xA8, 0xDC, 0x54, - 0x83, 0xD1, 0x57, 0x7A, 0xD3, 0x22, 0x13, 0x3F, 0x65, 0xA1, 0x83, 0xE6, 0xA9, 0x9D, 0xEC, 0xE8, 0xD6, 0x14, 0xEA, 0x04, 0xB9, 0x91, 0x23, 0x2C, 0xD8, 0xA5, - 0x5B, 0x9F, 0x14, 0x33, 0x46, 0xCF, 0xC2, 0xC8, 0xD3, 0x55, 0x12, 0xA4, 0xCF, 0x54, 0xCD, 0xD0, 0x66, 0xCE, 0x87, 0x7C, 0x50, 0x0F, 0xF9, 0xB9, 0xD1, 0xEE, - 0x4B, 0xD7, 0x11, 0x32, 0x1A, 0x67, 0x91, 0xC6, 0x2A, 0x5E, 0x4A, 0x43, 0x56, 0xEA, 0x04, 0x59, 0x8C, 0x45, 0x52, 0x45, 0x65, 0x7B, 0x65, 0x56, 0x84, 0x59, - 0xAF, 0xD1, 0x64, 0x1A, 0xBB, 0x39, 0x37, 0x20, 0xED, 0x45, 0x73, 0x35, 0x00, 0xA3, 0x4C, 0x7F, 0x2A, 0xE6, 0x2E, 0xD4, 0x13, 0xF5, 0x7E, 0x2B, 0xA7, 0xCB, - 0x91, 0xE5, 0x78, 0xD9, 0x7E, 0x65, 0x0C, 0x41, 0x7E, 0x4B, 0x5F, 0xD2, 0x11, 0xAF, 0x6A, 0x4A, 0x2B, 0x4F, 0xD4, 0xB8, 0xA5, 0x77, 0x94, 0x86, 0xEE, 0x4C, - 0x9F, 0xCA, 0x76, 0xC7, 0x84, 0xCC, 0xF5, 0x96, 0x34, 0xD2, 0x66, 0xD6, 0xDF, 0x7C, 0x72, 0x03, 0xF3, 0x4D, 0x5C, 0xAB, 0x3B, 0xD5, 0x46, 0x44, 0x1E, 0x46, - 0x63, 0x83, 0x9C, 0xAE, 0x52, 0x04, 0xCC, 0xD4, 0xC3, 0xCC, 0x1C, 0x8F, 0x49, 0x66, 0x95, 0x13, 0xE7, 0xBC, 0xD9, 0xA1, 0xD2, 0x90, 0x96, 0xD3, 0x0A, 0x68, - 0xB2, 0x9D, 0xAE, 0xCA, 0xCC, 0xE1, 0x2A, 0x25, 0xF4, 0xC5, 0x24, 0x24, 0x6D, 0x22, 0x54, 0x61, 0xE5, 0x21, 0x12, 0x15, 0x31, 0x26, 0x23, 0xC7, 0x65, 0x8B, - 0xB8, 0x29, 0x13, 0xFF, 0x72, 0x33, 0x2B, 0x44, 0x2E, 0x2B, 0xDD, 0x6D, 0x25, 0x74, 0x64, 0x6E, 0x74, 0xD0, 0xB7, 0x1D, 0x57, 0xF8, 0x70, 0x9C, 0x56, 0x49, - 0x8F, 0x27, 0x6C, 0x99, 0xA4, 0x4A, 0x43, 0x60, 0xA8, 0x46, 0x14, 0x19, 0xC8, 0x01, 0x5B, 0xAD, 0x2B, 0x34, 0x41, 0x15, 0x5D, 0x5A, 0x39, 0xE0, 0xAB, 0x4D, - 0x7C, 0x61, 0xB0, 0x99, 0xB6, 0xDE, 0xB2, 0xC1, 0xC5, 0x37, 0x6A, 0x01, 0xC9, 0x7E, 0x53, 0x45, 0x73, 0x4F, 0xF9, 0x63, 0x06, 0x91, 0xE1, 0x40, 0x1C, 0x6C, - 0xB7, 0x8A, 0xB7, 0x2A, 0x1B, 0x42, 0xCE, 0x0E, 0x85, 0xFD, 0x71, 0x67, 0x87, 0xD1, 0x56, 0xBE, 0x33, 0xDC, 0x24, 0x27, 0x6E, 0xA3, 0xE3, 0xFD, 0x8C, 0x2C, - 0xC3, 0xF3, 0xCE, 0x6B, 0xB8, 0xD9, 0xAB, 0x16, 0xDF, 0x55, 0x77, 0x36, 0x36, 0xAF, 0x35, 0x73, 0x7C, 0x5E, 0xB3, 0x9C, 0xA9, 0x93, 0xB8, 0x47, 0xEF, 0x33, - 0x2D, 0xC3, 0x68, 0x7F, 0x5E, 0x8B, 0xAD, 0x38, 0xD6, 0x28, 0x54, 0x74, 0xA9, 0x36, 0x78, 0xF2, 0xCD, 0xC9, 0xD1, 0x51, 0xFF, 0xD9, 0x13, 0x7B, 0xE8, 0x2D, - 0xF8, 0xFF, 0x1F, 0xD9, 0x02, 0xAD, 0x47, 0x7C, 0x1F, 0x6C, 0xCE, 0x3B, 0x3B, 0xA4, 0xD8, 0x12, 0x14, 0x1C, 0x02, 0x09, 0x29, 0x44, 0xF1, 0x6C, 0x50, 0x46, - 0x57, 0xD0, 0xC4, 0x83, 0x04, 0x67, 0x68, 0xB8, 0x92, 0x26, 0xB4, 0x19, 0x9B, 0x6B, 0xD0, 0x18, 0x52, 0xA3, 0xCA, 0x18, 0x3A, 0x37, 0x49, 0xD2, 0x29, 0x37, - 0x5C, 0x53, 0xBC, 0x15, 0x19, 0xA7, 0x21, 0x04, 0x30, 0x0A, 0x8E, 0xEB, 0xAC, 0xD0, 0x46, 0xDA, 0x28, 0x26, 0x7B, 0x6C, 0x7C, 0x33, 0xB2, 0xBE, 0x04, 0x4A, - 0xAF, 0x05, 0xDA, 0xB0, 0x1D, 0x9F, 0x8D, 0x24, 0x29, 0x5D, 0xC5, 0x58, 0xE5, 0x30, 0xC2, 0x6A, 0x21, 0xE3, 0x02, 0x44, 0xDB, 0xA4, 0xD8, 0xD9, 0xB5, 0x6C, - 0x4C, 0x14, 0x9B, 0xA0, 0xD0, 0x00, 0xB8, 0x36, 0xF8, 0xF9, 0xE2, 0xBB, 0x7F, 0x6A, 0xEF, 0xDE, 0xFE, 0x29, 0xD5, 0x50, 0x1E, 0x51, 0x18, 0x9C, 0x15, 0x7A, - 0xA6, 0x60, 0x4C, 0x1F, 0x81, 0x4C, 0x6A, 0x5C, 0x33, 0x14, 0x03, 0x26, 0x43, 0x16, 0xB1, 0xA7, 0xFE, 0xEC, 0xBC, 0xA6, 0xD7, 0x70, 0x77, 0x4B, 0x70, 0xD6, - 0xAE, 0x69, 0x18, 0xB8, 0xE9, 0xC1, 0xB5, 0x61, 0x2D, 0xF1, 0xA8, 0xA5, 0xC2, 0xEB, 0xBA, 0x69, 0x49, 0x9B, 0xF1, 0x88, 0x12, 0xCA, 0x58, 0x88, 0xC0, 0x71, - 0x29, 0xD7, 0x06, 0x57, 0xC4, 0x3F, 0x3B, 0x64, 0xB7, 0x72, 0xB4, 0x96, 0xDD, 0x37, 0xB8, 0x30, 0x33, 0x87, 0x2C, 0x13, 0xCA, 0x52, 0xFC, 0xC4, 0x35, 0xE6, - 0x04, 0xA5, 0xA2, 0xA4, 0x79, 0x51, 0xEB, 0x21, 0x64, 0x6D, 0xF0, 0x81, 0xD0, 0x2C, 0x03, 0xC8, 0x50, 0x52, 0xFC, 0x19, 0x4F, 0xE1, 0x63, 0xFD, 0x87, 0xF6, - 0xCC, 0x97, 0xEC, 0x9A, 0x06, 0x33, 0x73, 0x05, 0xB9, 0x3F, 0x6E, 0x36, 0xB5, 0xDE, 0xBB, 0xF7, 0x5A, 0xB3, 0xA9, 0xD0, 0xD8, 0x59, 0x50, 0x77, 0x0A, 0xF4, - 0x0F, 0x16, 0xC2, 0xA8, 0x21, 0x54, 0x3F, 0xEC, 0xA8, 0x36, 0xF8, 0xE1, 0xEA, 0xE7, 0x37, 0x2F, 0x1A, 0xED, 0x5E, 0xBF, 0x75, 0xA3, 0x9F, 0xB4, 0x5B, 0x7B, - 0x67, 0x87, 0x0C, 0xAE, 0x78, 0x07, 0x60, 0x60, 0xEF, 0xB5, 0xD7, 0x6F, 0x5F, 0x35, 0xF4, 0xD6, 0x71, 0x55, 0x64, 0xFA, 0x49, 0x6D, 0xF0, 0xD3, 0x0F, 0x11, - 0x65, 0xFD, 0x56, 0x15, 0x64, 0xC7, 0xC0, 0x26, 0xD0, 0xC5, 0x50, 0x75, 0xBB, 0x85, 0x50, 0xA1, 0xC8, 0x3B, 0xE5, 0x44, 0xAE, 0x1F, 0x41, 0xBF, 0x94, 0x87, - 0x56, 0xF7, 0xF8, 0x46, 0xEF, 0xF5, 0xBB, 0x15, 0x78, 0xE8, 0xA3, 0x74, 0x81, 0x90, 0xC6, 0x71, 0xBF, 0x5B, 0x15, 0x57, 0x0F, 0x71, 0x81, 0x40, 0x8E, 0xDA, - 0x20, 0x8F, 0xF6, 0x71, 0x15, 0xD1, 0x76, 0x6B, 0x03, 0xAA, 0xF2, 0x13, 0x44, 0xD5, 0x2A, 0x86, 0x0A, 0x45, 0xDB, 0x2E, 0x29, 0xDA, 0x4E, 0x6D, 0xF0, 0x23, - 0x8A, 0x16, 0x2D, 0x03, 0x78, 0xA8, 0x64, 0x1E, 0x6D, 0x88, 0x52, 0x14, 0x57, 0x1B, 0xED, 0xB6, 0xD5, 0xAE, 0x22, 0x5A, 0xBD, 0x36, 0x40, 0x71, 0x20, 0xA6, - 0xA3, 0x4A, 0x0E, 0x00, 0xDE, 0x44, 0x69, 0x02, 0x72, 0x6E, 0x8E, 0xFA, 0xC7, 0xE5, 0x31, 0x81, 0x27, 0x5D, 0x7D, 0x02, 0x4C, 0xC7, 0x20, 0xA8, 0x4A, 0x6E, - 0x04, 0x5E, 0x84, 0x78, 0xFA, 0xDD, 0xD6, 0x4D, 0xB7, 0x8A, 0xCD, 0x80, 0x57, 0xBC, 0x45, 0x44, 0x80, 0xE4, 0xA6, 0x53, 0x45, 0x46, 0xE0, 0x12, 0x17, 0xDF, - 0xBE, 0x6E, 0x74, 0x81, 0xB1, 0xF6, 0x49, 0xBF, 0x3C, 0x1E, 0x70, 0x87, 0x1F, 0x90, 0x20, 0x20, 0xE6, 0xA6, 0x5D, 0x2C, 0x3A, 0xC4, 0x11, 0x81, 0x33, 0x00, - 0x3C, 0xE2, 0x28, 0x8D, 0x02, 0xEC, 0xFA, 0x2D, 0x25, 0x06, 0x11, 0xE9, 0x47, 0x15, 0xB8, 0x02, 0xAB, 0xFE, 0x01, 0xC5, 0x03, 0x48, 0x30, 0xE8, 0x55, 0x30, - 0x45, 0x40, 0x44, 0x49, 0xD2, 0xFB, 0xD4, 0xD5, 0xCA, 0x63, 0x02, 0x9B, 0x3E, 0xE9, 0xDF, 0x9C, 0xF4, 0xD5, 0x10, 0xE0, 0x88, 0x8F, 0xA3, 0x54, 0x56, 0x4E, - 0x90, 0x9D, 0x32, 0x64, 0xA5, 0x03, 0xFF, 0x5E, 0x1A, 0x16, 0xCC, 0x6F, 0x0A, 0x27, 0x03, 0x1C, 0x0E, 0x64, 0xC2, 0x0E, 0xD4, 0xF2, 0x00, 0x81, 0x92, 0x70, - 0xA3, 0x59, 0x6D, 0xD0, 0x55, 0xC8, 0xB7, 0x62, 0x09, 0x39, 0x85, 0x8D, 0xD1, 0x4F, 0x93, 0x40, 0xB4, 0x3C, 0x4C, 0xFF, 0xC0, 0x25, 0x3A, 0x35, 0x21, 0x82, - 0x94, 0x4A, 0x34, 0x24, 0xB4, 0x1A, 0x37, 0xB5, 0x41, 0xBF, 0x93, 0x9B, 0xA0, 0x95, 0x57, 0xC6, 0x90, 0xD6, 0x68, 0x6C, 0xE2, 0x79, 0x85, 0xF5, 0x11, 0x81, - 0xD6, 0x06, 0x2F, 0xC3, 0xE3, 0x2A, 0x5A, 0x69, 0xE6, 0x71, 0x4A, 0x61, 0x53, 0xD4, 0x22, 0x90, 0xC3, 0x34, 0xD3, 0xEC, 0x70, 0xD5, 0x44, 0x9A, 0xD9, 0xAC, - 0x62, 0xB6, 0xA9, 0x17, 0x9C, 0x4E, 0xBA, 0x86, 0xE7, 0x17, 0xD6, 0x4A, 0x00, 0x08, 0x11, 0x9A, 0x1F, 0xDD, 0x9B, 0x46, 0x42, 0x52, 0xFE, 0x06, 0xFA, 0xF0, - 0x0C, 0x7F, 0xC9, 0xAA, 0x85, 0x85, 0x35, 0x12, 0x81, 0x42, 0x3E, 0x10, 0x1E, 0x57, 0xD2, 0x4A, 0x95, 0xF0, 0x25, 0x90, 0xC3, 0xF5, 0x12, 0x84, 0xB0, 0xEE, - 0x96, 0xF4, 0x92, 0x47, 0x6D, 0x25, 0xBD, 0xCC, 0x0C, 0x77, 0x51, 0x2A, 0x7C, 0x85, 0x90, 0xA0, 0x95, 0xE0, 0xF0, 0xDE, 0x5C, 0x25, 0x22, 0xE6, 0x6F, 0xE0, - 0x2B, 0x63, 0x62, 0x3B, 0xA6, 0x57, 0x7C, 0xB6, 0xCF, 0xE1, 0x6A, 0x83, 0x57, 0xA4, 0xF9, 0x3D, 0x1E, 0x55, 0x51, 0xC7, 0x8B, 0xA5, 0xEF, 0x54, 0x50, 0x48, - 0x40, 0x0B, 0x53, 0x47, 0x8B, 0x6B, 0xE3, 0x78, 0x4B, 0xDA, 0x38, 0xDE, 0xA2, 0x36, 0x0C, 0xF2, 0xD9, 0x22, 0xD7, 0xC4, 0x2A, 0xAC, 0x8E, 0x00, 0xB0, 0x36, - 0xB8, 0xBC, 0x59, 0x38, 0x1E, 0x3E, 0x3A, 0xF5, 0x1D, 0x9E, 0x57, 0x72, 0x92, 0x5E, 0x05, 0x9D, 0x84, 0x04, 0x71, 0x1F, 0xE9, 0x71, 0xAD, 0xF4, 0xB6, 0xA4, - 0x95, 0x3C, 0x5A, 0xAB, 0x68, 0x65, 0x6A, 0x98, 0xF6, 0x88, 0x98, 0x16, 0x3E, 0xC6, 0x51, 0x54, 0x31, 0x02, 0x6C, 0x6D, 0xF0, 0x26, 0x3A, 0xA9, 0xA2, 0x98, - 0x56, 0x05, 0xBD, 0x88, 0xF4, 0xC4, 0xFD, 0xA5, 0x07, 0xB3, 0xF2, 0x2D, 0xE9, 0x46, 0xD7, 0xB7, 0x39, 0xAA, 0x2C, 0xC8, 0xC8, 0x34, 0xAC, 0xCF, 0x64, 0x32, - 0x81, 0x69, 0x50, 0xF1, 0xA1, 0x25, 0x06, 0x0E, 0xE3, 0x0B, 0x3B, 0xD7, 0x2E, 0xE9, 0x79, 0xE1, 0xFA, 0x65, 0x02, 0x5D, 0xF9, 0x22, 0x66, 0x72, 0x4E, 0x28, - 0x2D, 0x4B, 0x7E, 0xEF, 0x84, 0x74, 0x96, 0x9F, 0xB6, 0x7E, 0x4F, 0xA6, 0x74, 0x1B, 0x41, 0x95, 0x39, 0xF4, 0x1B, 0xD7, 0xB8, 0xA5, 0xEF, 0x64, 0xA8, 0x32, - 0xA5, 0xFF, 0x40, 0xC6, 0xDA, 0x47, 0xD3, 0x2E, 0xCF, 0x4C, 0x17, 0x09, 0x21, 0xC4, 0xAE, 0x86, 0xA5, 0x07, 0x53, 0x24, 0x38, 0xA8, 0x86, 0xA4, 0x8F, 0x35, - 0xFD, 0x85, 0x69, 0x3C, 0x84, 0x49, 0xBC, 0xB1, 0x1A, 0x16, 0x1F, 0x50, 0x56, 0x43, 0x18, 0x97, 0x7F, 0x7A, 0xA9, 0x5D, 0xD2, 0x8D, 0xEF, 0x85, 0xC3, 0x15, - 0xDB, 0x93, 0xA7, 0x62, 0xE8, 0xD1, 0xD2, 0x0D, 0xF6, 0xB9, 0xB6, 0xA6, 0x26, 0x77, 0x20, 0xD5, 0x75, 0x35, 0x09, 0x7B, 0x01, 0x81, 0x74, 0x0B, 0x53, 0x4D, - 0xE0, 0x56, 0x8D, 0xC7, 0x2D, 0xA6, 0x62, 0xA3, 0x55, 0xF1, 0x34, 0x6C, 0xB4, 0x02, 0x35, 0x8D, 0xAF, 0xF1, 0x99, 0x88, 0xB1, 0x06, 0xFA, 0xDA, 0x89, 0xA2, - 0xB0, 0xD7, 0xFB, 0x51, 0x14, 0xE5, 0xF7, 0xBE, 0x15, 0x05, 0xD6, 0xF2, 0x19, 0xC7, 0xD1, 0x32, 0x4E, 0x45, 0x01, 0x6B, 0x83, 0x77, 0x86, 0xBD, 0x84, 0x41, - 0x66, 0x57, 0x0A, 0x0B, 0x3B, 0xBE, 0x37, 0xF7, 0xE2, 0x7C, 0xDF, 0xB7, 0xEA, 0x80, 0x90, 0xB9, 0x33, 0x2E, 0x3E, 0xDD, 0xE1, 0x70, 0x2C, 0x24, 0xBE, 0x83, - 0xA3, 0xC2, 0x89, 0x41, 0x80, 0x61, 0xCB, 0x19, 0x01, 0x9B, 0x4A, 0x95, 0x4F, 0x06, 0xAE, 0x96, 0xB6, 0x7D, 0x5B, 0x25, 0x13, 0xB8, 0xB0, 0x9C, 0xE5, 0xB8, - 0x3C, 0x06, 0x48, 0x03, 0xFE, 0x35, 0x99, 0x98, 0xA3, 0xF2, 0x89, 0x04, 0x24, 0x01, 0x6F, 0x9D, 0xB9, 0x22, 0xFC, 0x96, 0x07, 0x5E, 0x32, 0x2A, 0x31, 0x93, - 0x1B, 0x81, 0x16, 0x2F, 0x2F, 0x76, 0x3A, 0xF0, 0x42, 0x9F, 0xF7, 0x14, 0x19, 0x90, 0xDB, 0xFB, 0x0E, 0x0A, 0x40, 0xC4, 0x67, 0x6A, 0x3C, 0x65, 0x94, 0xC5, - 0x20, 0xC3, 0x88, 0x1E, 0x4C, 0xBF, 0xEF, 0x6B, 0x7E, 0x17, 0x51, 0x14, 0x9F, 0xDD, 0xE1, 0xD2, 0x73, 0x38, 0xBD, 0xEB, 0xB4, 0x37, 0x3B, 0xC1, 0x43, 0xE4, - 0xDB, 0xD5, 0x4F, 0xBB, 0x8C, 0x6A, 0x20, 0x1A, 0x7D, 0x8F, 0xEB, 0x0C, 0x05, 0x02, 0x76, 0x75, 0x47, 0x6A, 0xDF, 0x9F, 0x27, 0xB5, 0x1F, 0x80, 0x2B, 0x4D, - 0x4B, 0x44, 0xBC, 0x29, 0x46, 0xBC, 0x37, 0x17, 0xBB, 0xD1, 0xD0, 0xF4, 0xDE, 0x42, 0xDD, 0xF4, 0x5E, 0x43, 0x9D, 0xC6, 0x37, 0x05, 0x06, 0x52, 0x28, 0x99, - 0xC1, 0x72, 0x40, 0x56, 0xCB, 0xAA, 0x12, 0xE4, 0xF4, 0x9B, 0x2A, 0x51, 0x2E, 0x20, 0x23, 0x1E, 0xE4, 0xFA, 0xD1, 0xAA, 0x48, 0x6F, 0xB3, 0xCB, 0xBA, 0xDD, - 0x3C, 0x6A, 0xAB, 0x38, 0x8D, 0x6B, 0xAC, 0x3E, 0x4F, 0xE7, 0x46, 0x61, 0x65, 0x70, 0x38, 0xD0, 0xC5, 0xBB, 0x17, 0xBB, 0x4C, 0x17, 0x82, 0x7E, 0xEF, 0xC7, - 0x8F, 0x42, 0xAE, 0xEF, 0x3B, 0xD6, 0x59, 0xC4, 0x2E, 0x1E, 0xEC, 0x10, 0xA8, 0x36, 0xF8, 0x8E, 0xD8, 0x9E, 0x76, 0xE1, 0xB8, 0xFC, 0x45, 0x98, 0x3B, 0xD1, - 0x1A, 0xED, 0xF9, 0x7E, 0x54, 0xC6, 0x98, 0xBE, 0x6F, 0x7D, 0xCD, 0xE6, 0xA6, 0xEB, 0x3A, 0x6E, 0x61, 0x95, 0x71, 0x38, 0x98, 0x56, 0x34, 0xDF, 0xD1, 0xA3, - 0x9D, 0xA8, 0x2B, 0xE8, 0xF5, 0x7E, 0x34, 0x16, 0xF2, 0x7C, 0xDF, 0x4A, 0xBB, 0x9E, 0x58, 0xE6, 0xA2, 0xB0, 0xCA, 0x28, 0x54, 0x6D, 0xF0, 0xA9, 0xF9, 0x1A, - 0xFE, 0xEE, 0x44, 0x5D, 0xAC, 0xC7, 0xFB, 0x51, 0x16, 0xE7, 0xF6, 0xBE, 0x55, 0x35, 0x5C, 0x14, 0x0F, 0x87, 0x00, 0x53, 0x1B, 0xBC, 0x7C, 0xBF, 0x9B, 0xDC, - 0x0F, 0x3B, 0x53, 0xD4, 0x50, 0x25, 0x7D, 0x50, 0xA6, 0xEE, 0x5B, 0x1B, 0xAB, 0x12, 0xDA, 0x58, 0x21, 0xE1, 0x3F, 0xED, 0x48, 0x1B, 0x2B, 0x75, 0x6D, 0x6C, - 0xD8, 0x5F, 0x56, 0x0F, 0x41, 0x3F, 0xF4, 0xE9, 0xD3, 0xA1, 0x51, 0x7C, 0x38, 0x0A, 0x00, 0x71, 0xD3, 0x18, 0x1C, 0x69, 0x2F, 0x8D, 0xDD, 0x0C, 0x48, 0x61, - 0xBF, 0xBB, 0x70, 0xA1, 0x88, 0xC9, 0xFB, 0xD6, 0xD3, 0xC4, 0x18, 0x91, 0xCF, 0x63, 0xE2, 0x97, 0x59, 0x5B, 0x16, 0x60, 0x6B, 0x83, 0xD7, 0x70, 0xA2, 0xBD, - 0xA2, 0x27, 0xBB, 0x4A, 0xF9, 0xC4, 0xFE, 0x77, 0xA1, 0xB5, 0x18, 0xBF, 0x0F, 0x42, 0x71, 0x90, 0x60, 0x3B, 0x53, 0xBB, 0xD4, 0xE3, 0x4C, 0x31, 0x70, 0xAE, - 0xBE, 0x0F, 0xEC, 0x7C, 0xB7, 0x0A, 0x8C, 0x88, 0xD8, 0x99, 0x0E, 0x05, 0xBE, 0x37, 0xA8, 0x46, 0xC5, 0xA7, 0x1A, 0xF9, 0x9B, 0x81, 0xF3, 0x74, 0xC5, 0x9F, - 0xAE, 0xA3, 0x9B, 0x5A, 0x88, 0xDF, 0xF4, 0x7C, 0xD3, 0xB2, 0x60, 0x2A, 0x4C, 0x7C, 0xED, 0x0A, 0x0F, 0x15, 0x1F, 0xA7, 0x13, 0xB0, 0x04, 0x0F, 0xD1, 0xFA, - 0x2E, 0x31, 0xE6, 0xB5, 0xC1, 0x15, 0xBE, 0x33, 0x19, 0x70, 0xE1, 0x59, 0x71, 0x64, 0x54, 0x8C, 0xC4, 0x76, 0x1D, 0x20, 0x2A, 0x54, 0x13, 0x7F, 0x3F, 0x65, - 0x4D, 0x0B, 0x8E, 0x84, 0x6B, 0x83, 0x4B, 0xDA, 0x58, 0x43, 0x3B, 0xCB, 0xEF, 0x4E, 0xF9, 0x39, 0x3F, 0xFA, 0x44, 0x2F, 0x3E, 0xA2, 0x1B, 0x7F, 0xA3, 0x3A, - 0xE8, 0x95, 0xBD, 0xD5, 0x60, 0x70, 0x46, 0xDF, 0x0E, 0xCB, 0x9B, 0xD1, 0x87, 0xD9, 0x57, 0xFC, 0xE9, 0xE4, 0xA1, 0x63, 0x8D, 0x9F, 0x09, 0xAB, 0xCB, 0x57, - 0xE1, 0xE3, 0xB6, 0x08, 0x02, 0x86, 0x11, 0x60, 0xC8, 0x51, 0xFE, 0xCC, 0x0D, 0xD0, 0xB3, 0x27, 0xA2, 0xF1, 0x1D, 0x65, 0x19, 0xCA, 0x4D, 0x79, 0x34, 0xD8, - 0x25, 0xD3, 0x50, 0x90, 0xB2, 0x27, 0xC6, 0xA5, 0x0F, 0x0A, 0x7F, 0x20, 0x53, 0xD3, 0x03, 0x1A, 0x35, 0x30, 0x8B, 0x43, 0xFA, 0x8C, 0x25, 0x33, 0x66, 0xB5, - 0xE7, 0x77, 0xC5, 0x2E, 0xF9, 0xCB, 0x19, 0xA4, 0x8F, 0x63, 0x17, 0xCA, 0x4F, 0x92, 0x0F, 0x4F, 0xC7, 0x31, 0xE6, 0x19, 0xFD, 0xE3, 0x66, 0x73, 0xD6, 0xC5, - 0xA7, 0x45, 0xB5, 0x80, 0xB5, 0xB3, 0xC3, 0x59, 0x37, 0xEF, 0xD1, 0xB0, 0xDC, 0x47, 0x7D, 0x81, 0xD3, 0xD2, 0x4F, 0xFA, 0xA2, 0x94, 0x06, 0x40, 0xCD, 0xBE, - 0xF6, 0xCE, 0xF0, 0xBE, 0xEC, 0x6B, 0x9F, 0xB0, 0x00, 0xB7, 0xC3, 0x07, 0x7E, 0x91, 0x76, 0x63, 0x3C, 0x76, 0x53, 0x1F, 0xFA, 0xED, 0xC6, 0x1E, 0xFA, 0xED, - 0x07, 0x0F, 0xFD, 0xF6, 0xA3, 0xDD, 0x6E, 0x37, 0x9D, 0x56, 0xEB, 0x58, 0x85, 0x75, 0xC5, 0x07, 0x7F, 0x37, 0xC2, 0xD3, 0x1C, 0xA4, 0xA9, 0xC8, 0x53, 0x37, - 0xE0, 0x49, 0xD8, 0x15, 0x7E, 0x33, 0x99, 0x3C, 0x34, 0x8E, 0xF8, 0xBA, 0x54, 0x79, 0x96, 0x5A, 0xED, 0x5D, 0x3F, 0x9D, 0x4D, 0x8D, 0x7B, 0x53, 0x0F, 0x67, - 0xD3, 0x26, 0xC9, 0x68, 0xD8, 0xCB, 0x0C, 0x86, 0x14, 0x84, 0x39, 0xFD, 0x9B, 0x4D, 0x3A, 0xFD, 0xB4, 0x82, 0xD3, 0x4F, 0xD7, 0x9C, 0x7E, 0x87, 0xDE, 0x1E, - 0x10, 0xFE, 0x77, 0xF3, 0xF8, 0x80, 0xAF, 0x02, 0x5E, 0x2F, 0xE5, 0xAB, 0xD5, 0xDA, 0xA8, 0xDF, 0xE7, 0x3A, 0x49, 0x68, 0x0C, 0x6F, 0x36, 0xE9, 0x24, 0x29, - 0xA6, 0x5B, 0xCA, 0x4E, 0x79, 0xD8, 0x19, 0xEC, 0x66, 0x5C, 0xA2, 0xD9, 0x94, 0xA8, 0x50, 0xDE, 0x3B, 0x3E, 0x13, 0xDA, 0xE9, 0xF2, 0xD4, 0x69, 0x13, 0xEA, - 0x51, 0x7F, 0x11, 0x44, 0x6A, 0x93, 0xCD, 0x24, 0x66, 0x0B, 0x21, 0xC3, 0x55, 0x4E, 0xCC, 0xDE, 0x7F, 0xF7, 0x5D, 0xB1, 0x5C, 0x4C, 0xEC, 0xE5, 0x81, 0xE4, - 0x62, 0x99, 0xB5, 0xD0, 0xDB, 0x05, 0xDC, 0x40, 0xAA, 0x4B, 0x99, 0x6E, 0x04, 0x5E, 0x1B, 0xBC, 0xA4, 0xC7, 0x9A, 0x20, 0xB1, 0x42, 0xC6, 0xAB, 0x3C, 0xED, - 0xA4, 0x80, 0x42, 0xB1, 0x34, 0x22, 0x21, 0xA9, 0x1B, 0x45, 0x5C, 0x19, 0x05, 0x52, 0x81, 0x3D, 0x75, 0xA6, 0x2A, 0xFB, 0x04, 0x6D, 0x92, 0x97, 0x0A, 0x2F, - 0x5C, 0x52, 0x5A, 0x6D, 0x1C, 0xB6, 0x36, 0x78, 0xEF, 0x12, 0xED, 0x95, 0x79, 0xAD, 0xCE, 0x9B, 0xB0, 0x51, 0x30, 0x44, 0xA2, 0x26, 0xE5, 0xE4, 0x0E, 0x3E, - 0xE9, 0xAE, 0x40, 0x5C, 0x6C, 0x57, 0xDD, 0x4E, 0x27, 0xC1, 0x0A, 0x69, 0x57, 0xBB, 0x1A, 0x86, 0x4E, 0x6D, 0xD0, 0xA9, 0x86, 0xA1, 0x5B, 0x1B, 0x74, 0xAB, - 0x61, 0xE8, 0x81, 0x1C, 0x0E, 0x7A, 0xD5, 0x70, 0xF4, 0x6B, 0x83, 0x7E, 0x35, 0x0C, 0x47, 0x20, 0xCB, 0xAA, 0x54, 0x40, 0xE6, 0x72, 0x5C, 0x00, 0x43, 0xFE, - 0x26, 0x47, 0xD6, 0xAA, 0xBA, 0xF3, 0xCC, 0x97, 0x56, 0x69, 0xE7, 0xE1, 0xB0, 0xB5, 0xC1, 0xBB, 0xA5, 0xE5, 0x9B, 0x0B, 0xCB, 0x84, 0x69, 0x7B, 0xA3, 0xAB, - 0x35, 0xB5, 0x76, 0xAF, 0xBD, 0xB7, 0xC3, 0x0C, 0x33, 0xA0, 0x43, 0xED, 0x1D, 0x52, 0x9D, 0x20, 0x09, 0xD3, 0x8F, 0xC5, 0x77, 0x0A, 0x3C, 0x88, 0x70, 0xE6, - 0x3A, 0x8E, 0x5F, 0x5A, 0x1D, 0x01, 0x30, 0xA4, 0xF9, 0x70, 0x54, 0x3A, 0x9A, 0x45, 0x68, 0xCA, 0x18, 0x7A, 0xCA, 0x26, 0xE7, 0x8A, 0xE1, 0x4C, 0x2F, 0x16, - 0xCE, 0x76, 0xE7, 0x3E, 0xDE, 0x6D, 0xF9, 0x94, 0x81, 0xC3, 0xC2, 0x6C, 0xF5, 0x16, 0x66, 0x88, 0x73, 0x54, 0x98, 0xD6, 0x68, 0x81, 0xFB, 0xE8, 0xBD, 0x5D, - 0x7A, 0x4F, 0x40, 0x46, 0xC1, 0x37, 0xB0, 0x89, 0xDE, 0xF3, 0x30, 0x9C, 0x87, 0xEA, 0x83, 0x58, 0xE3, 0x5E, 0x79, 0x8D, 0x04, 0xD0, 0x90, 0x0F, 0xE0, 0x7B, - 0xF0, 0x2A, 0xF9, 0x91, 0x80, 0xAC, 0x9C, 0x23, 0x55, 0x77, 0x1A, 0xA9, 0x2B, 0x56, 0xCC, 0x0B, 0xDA, 0x95, 0x47, 0xF5, 0xCE, 0x43, 0x1C, 0x0B, 0x17, 0xF8, - 0xEA, 0x44, 0xA2, 0xB6, 0xBD, 0x92, 0x22, 0x13, 0x93, 0x48, 0x06, 0xCB, 0x8D, 0x86, 0x6D, 0x2B, 0xDF, 0x69, 0xE6, 0x1F, 0x10, 0xB0, 0xBE, 0xDA, 0x54, 0x7C, - 0x15, 0x5E, 0x60, 0x4E, 0x36, 0x11, 0x08, 0x79, 0x7D, 0x70, 0xB3, 0x00, 0x24, 0xAC, 0xF4, 0x34, 0x80, 0x03, 0x73, 0x15, 0x86, 0x91, 0xB8, 0xA3, 0x17, 0x88, - 0xC4, 0xE2, 0x8C, 0x20, 0xC4, 0x57, 0x72, 0xB4, 0xBB, 0xF7, 0xF4, 0xBF, 0x2B, 0x0F, 0x1E, 0x15, 0x5D, 0xBF, 0x60, 0x1A, 0x2C, 0xC1, 0x80, 0xEF, 0x0B, 0xD4, - 0x8B, 0x24, 0xF4, 0x9B, 0x0B, 0x1F, 0xC2, 0x5A, 0x21, 0x35, 0x38, 0x3A, 0x74, 0x13, 0x9F, 0xCD, 0xF3, 0x0B, 0x2C, 0xFF, 0xA5, 0x36, 0xD9, 0x4C, 0x75, 0x67, - 0x65, 0xDA, 0xC5, 0xAB, 0x3B, 0x3F, 0x99, 0xF6, 0xD8, 0x59, 0x15, 0x2B, 0xF0, 0x88, 0x1D, 0xFD, 0x05, 0x0A, 0x3C, 0x34, 0x3D, 0xC0, 0x15, 0xE2, 0xA6, 0x4B, - 0xD4, 0xDE, 0x67, 0x93, 0x14, 0x32, 0x83, 0xBE, 0xC1, 0x05, 0x56, 0x40, 0xE1, 0x69, 0x74, 0xBD, 0x79, 0xDB, 0x99, 0xDA, 0xCF, 0xA7, 0x62, 0xAE, 0xC6, 0x29, - 0x50, 0xCB, 0xD5, 0xBA, 0x92, 0x72, 0xF3, 0xBD, 0x57, 0xD0, 0x7F, 0x59, 0xE7, 0xE7, 0xF6, 0xDE, 0xF9, 0xD9, 0xC4, 0x00, 0x44, 0xEC, 0x71, 0x69, 0xCB, 0x42, - 0xD8, 0xC8, 0xAE, 0x2E, 0xED, 0xF1, 0x4E, 0xAD, 0x8A, 0xF5, 0x5E, 0x5A, 0x07, 0xED, 0x7E, 0xBB, 0xF3, 0xB0, 0xCC, 0x0A, 0x19, 0xAA, 0x60, 0x54, 0xFA, 0x49, - 0xEF, 0x01, 0x4D, 0x69, 0x9C, 0xC9, 0x84, 0xAD, 0x6B, 0x96, 0x33, 0x2D, 0x0E, 0x7E, 0x43, 0x9F, 0xD2, 0xF5, 0xC8, 0x6E, 0xE3, 0x55, 0xD8, 0x79, 0xC1, 0xD2, - 0x8C, 0xA0, 0x8B, 0xFE, 0xC3, 0x32, 0x2D, 0xCE, 0x91, 0xAA, 0x75, 0x49, 0x38, 0xEA, 0x3E, 0x1C, 0xD3, 0xF2, 0x1D, 0xDF, 0xB0, 0x4A, 0x5B, 0x16, 0x83, 0x06, - 0xC3, 0xFA, 0x88, 0x07, 0xDA, 0x15, 0xF0, 0xB9, 0x53, 0xE3, 0x0A, 0xFA, 0x2F, 0x1F, 0xB8, 0x8E, 0xBB, 0x1B, 0x52, 0x46, 0x05, 0x96, 0x7E, 0x59, 0x67, 0xA9, - 0x52, 0xE8, 0xEA, 0x6F, 0x68, 0x91, 0x7C, 0x23, 0xA1, 0x6B, 0xE9, 0xE3, 0xD5, 0xD2, 0xA1, 0x8B, 0x81, 0x63, 0xE8, 0xA2, 0x47, 0xBB, 0x37, 0xB1, 0x90, 0x82, - 0xF2, 0x36, 0xD6, 0x3B, 0xD9, 0xE4, 0x16, 0x98, 0x4D, 0x44, 0x30, 0xC6, 0x53, 0x25, 0x23, 0xDB, 0x94, 0xDF, 0x54, 0x36, 0xB2, 0x91, 0xA1, 0xFC, 0x8E, 0x37, - 0x8A, 0x4C, 0xCC, 0xE6, 0x19, 0x2C, 0xCC, 0xE1, 0xD8, 0xC1, 0x4E, 0x2B, 0x36, 0x41, 0xE7, 0x1B, 0x5F, 0xA8, 0x0D, 0xB9, 0x7A, 0x48, 0xF5, 0x99, 0xA1, 0x69, - 0xDB, 0x65, 0xD5, 0xC4, 0x61, 0x6B, 0x83, 0x97, 0xEC, 0x60, 0xB7, 0x4B, 0xEA, 0xBC, 0xF3, 0xCD, 0xAF, 0xA7, 0x07, 0x5C, 0xED, 0x5A, 0x4D, 0x89, 0x22, 0x86, - 0x1B, 0x7E, 0xF7, 0xA3, 0xC6, 0xF7, 0xA8, 0x46, 0xDF, 0x01, 0x79, 0x38, 0x25, 0x8D, 0xA9, 0x31, 0xC7, 0x87, 0x97, 0x8B, 0x16, 0x35, 0xDE, 0x20, 0x58, 0xB1, - 0x9A, 0x46, 0xBC, 0xA7, 0x87, 0x5D, 0xD5, 0x18, 0xC4, 0xDF, 0x5A, 0x09, 0x84, 0x37, 0x87, 0xA6, 0xE1, 0xE1, 0x83, 0xFE, 0x70, 0xAC, 0xBD, 0x84, 0x63, 0xED, - 0xBD, 0xB5, 0x0C, 0x5F, 0xBB, 0x2B, 0x73, 0x08, 0x71, 0x3F, 0x5B, 0x84, 0x21, 0xED, 0xA9, 0x05, 0xBA, 0x8D, 0x8F, 0x3F, 0xE0, 0x05, 0xC7, 0xB8, 0x7B, 0xAD, - 0xD7, 0x3D, 0x6E, 0xD5, 0x34, 0x96, 0x15, 0xF3, 0xC7, 0xFA, 0xBD, 0x2F, 0x74, 0x5B, 0x9B, 0x1E, 0x12, 0x28, 0x73, 0x00, 0x91, 0xDE, 0x90, 0x40, 0x6A, 0xBF, - 0x55, 0x76, 0x9B, 0xAD, 0x4B, 0x44, 0x0F, 0xC4, 0xD1, 0x92, 0x1A, 0x42, 0xEC, 0x3D, 0x9B, 0xAC, 0x7D, 0xFC, 0x05, 0x05, 0xED, 0x9E, 0xEC, 0xFD, 0xA7, 0x72, - 0x41, 0xE8, 0x52, 0x41, 0xE0, 0xEE, 0xBE, 0xCD, 0xF2, 0xD4, 0x0E, 0x78, 0xD2, 0xD5, 0x78, 0x6A, 0x57, 0xE0, 0xA9, 0xBD, 0x23, 0x9E, 0x3A, 0x01, 0x4F, 0x6D, - 0x35, 0x9E, 0x3A, 0x15, 0x78, 0xEA, 0xEC, 0x88, 0xA7, 0x6E, 0xC0, 0x53, 0x47, 0x8D, 0xA7, 0x6E, 0x05, 0x9E, 0xBA, 0x3B, 0xE2, 0xA9, 0x17, 0xF0, 0xD4, 0x55, - 0xE3, 0xA9, 0x57, 0x81, 0xA7, 0xDE, 0x8E, 0x78, 0xEA, 0x07, 0x3C, 0xF5, 0xD4, 0x78, 0xEA, 0x57, 0xE0, 0xA9, 0xBF, 0x23, 0x9E, 0x8E, 0x02, 0x9E, 0xFA, 0x6A, - 0x3C, 0x1D, 0x55, 0xE0, 0xE9, 0x68, 0x47, 0x3C, 0x1D, 0x07, 0x3C, 0x1D, 0xA9, 0xF1, 0x74, 0x5C, 0x81, 0xA7, 0xE3, 0x1D, 0xF1, 0x74, 0x12, 0xF0, 0x74, 0xAC, - 0xC6, 0xD3, 0x49, 0x05, 0x9E, 0x4E, 0x76, 0xC4, 0x13, 0xEE, 0xA6, 0x62, 0x4C, 0x9D, 0x28, 0x0E, 0xBA, 0xAD, 0x0A, 0x5C, 0x19, 0xBB, 0xE2, 0x2A, 0x4C, 0x25, - 0x74, 0xD5, 0x5C, 0xA2, 0x4A, 0x32, 0x31, 0xDC, 0x15, 0x5B, 0x51, 0x36, 0xA1, 0x98, 0x4E, 0xE8, 0x55, 0xF2, 0x89, 0xD1, 0xAE, 0xD8, 0x0A, 0x13, 0x0A, 0x5D, - 0x31, 0xA3, 0xD0, 0xAB, 0xA4, 0x14, 0xE3, 0x5D, 0xB1, 0x15, 0xE6, 0x14, 0xBA, 0x62, 0x52, 0xA1, 0x57, 0xC9, 0x2A, 0xC8, 0xAE, 0xD8, 0x0A, 0xD3, 0x0A, 0x5D, - 0x31, 0xAF, 0xD0, 0xAB, 0x24, 0x16, 0x93, 0x5D, 0xB1, 0x15, 0x66, 0x16, 0xBA, 0x62, 0x6A, 0xA1, 0x57, 0xC8, 0x2D, 0x4E, 0xE4, 0x13, 0xB1, 0x8D, 0xB2, 0x45, - 0x7C, 0x3E, 0x45, 0x8E, 0x26, 0x6D, 0x4A, 0x0F, 0x1C, 0x71, 0x20, 0x7C, 0x22, 0x8E, 0x09, 0xE4, 0xC2, 0xB1, 0x27, 0xE6, 0x34, 0x2C, 0x32, 0x3C, 0x98, 0x67, - 0x63, 0x3C, 0xE1, 0x85, 0xBF, 0xCA, 0x85, 0x86, 0xAB, 0x57, 0x97, 0xC5, 0xCA, 0x0C, 0x62, 0x2F, 0x7F, 0xA1, 0x22, 0x03, 0x90, 0xDD, 0x16, 0xBF, 0x3E, 0xA0, - 0x54, 0x57, 0xA0, 0x40, 0x45, 0x2A, 0x0A, 0x3D, 0xB1, 0xA2, 0xD0, 0x57, 0xAE, 0x28, 0x30, 0xE2, 0xB6, 0x53, 0x4B, 0x00, 0xDC, 0x1D, 0xF6, 0xC9, 0x04, 0x75, - 0xA6, 0x3B, 0xE5, 0x99, 0xEE, 0x15, 0x61, 0xBA, 0x53, 0x86, 0xE9, 0x12, 0xCF, 0xB4, 0x2A, 0xCA, 0x09, 0xE8, 0x7D, 0x6D, 0xDE, 0x90, 0xB1, 0xF6, 0x8B, 0xBA, - 0xA8, 0xF4, 0xF2, 0xA2, 0x3A, 0x2A, 0x22, 0x2A, 0x7D, 0x8B, 0xF6, 0xD1, 0x0B, 0xF8, 0xFE, 0x51, 0x9D, 0xEF, 0x5E, 0x79, 0xBE, 0x3B, 0x45, 0xF8, 0xEE, 0x6D, - 0x91, 0xEF, 0x6E, 0xC0, 0xF7, 0x27, 0x75, 0xBE, 0xBB, 0xE5, 0xF9, 0xEE, 0x16, 0xE1, 0xBB, 0xBB, 0x45, 0xBE, 0xDB, 0x10, 0x6C, 0x7E, 0xFC, 0xA4, 0x7D, 0x9C, - 0xB9, 0xC4, 0x9B, 0xE5, 0x57, 0xE2, 0x18, 0x44, 0xD9, 0xB1, 0xBD, 0xB7, 0x83, 0xB9, 0x1B, 0x52, 0xD8, 0x11, 0x79, 0xCA, 0xCD, 0x9B, 0x19, 0x84, 0xCA, 0x37, - 0x89, 0xE4, 0x3C, 0xC9, 0x67, 0x6E, 0xBA, 0x2A, 0x53, 0xDB, 0x8B, 0x61, 0xC7, 0xB5, 0xC1, 0xDB, 0x65, 0x81, 0xF1, 0xED, 0xB8, 0xBC, 0x3D, 0xAB, 0x57, 0xCC, - 0x19, 0x5D, 0x5B, 0xB3, 0xE7, 0x13, 0xCA, 0x33, 0xE4, 0x65, 0x9E, 0x82, 0xDA, 0xCB, 0x57, 0x21, 0x7A, 0x3B, 0xA8, 0x92, 0x63, 0xA4, 0x3F, 0x62, 0xEC, 0xFC, - 0x88, 0x0C, 0x69, 0x90, 0xB1, 0x14, 0x18, 0x8C, 0x8E, 0x0A, 0x6A, 0xF3, 0xB8, 0x64, 0x74, 0x42, 0x1A, 0xB7, 0xA6, 0x4E, 0x9C, 0x7A, 0xA0, 0x00, 0x3E, 0x95, - 0x10, 0x40, 0xBF, 0xBC, 0x00, 0x0A, 0x65, 0x2E, 0x48, 0xE3, 0xF6, 0x04, 0xD0, 0x62, 0x02, 0xB8, 0x8A, 0x5E, 0x7A, 0x9D, 0x61, 0xD0, 0x15, 0x2A, 0x50, 0xBD, - 0x1D, 0xAC, 0x91, 0x60, 0xA4, 0xD5, 0x03, 0x8B, 0x06, 0x8E, 0x8A, 0x29, 0xB4, 0x5D, 0x34, 0xBF, 0x92, 0x17, 0x3F, 0x15, 0xF2, 0xEF, 0x6D, 0x26, 0x58, 0xED, - 0x56, 0x60, 0xD1, 0xC5, 0x05, 0xD0, 0x2A, 0x2F, 0x00, 0xBD, 0x90, 0x00, 0x5A, 0x0F, 0x2B, 0x19, 0xEF, 0xAF, 0x7F, 0xA7, 0x38, 0x5F, 0x5A, 0x45, 0xDD, 0x5F, - 0x18, 0xCD, 0xDA, 0x45, 0x84, 0xB5, 0x55, 0xEF, 0xEF, 0x44, 0x9C, 0x6B, 0xBF, 0x68, 0xF1, 0xAD, 0xAF, 0x59, 0x71, 0xA0, 0x7C, 0x11, 0xB0, 0xB7, 0x83, 0xF5, - 0x2A, 0xA4, 0xF0, 0x44, 0xC2, 0x59, 0xC1, 0x00, 0x7F, 0x52, 0xDE, 0x1D, 0x0A, 0x69, 0x18, 0x69, 0xDD, 0x9E, 0x8A, 0x7B, 0x31, 0x41, 0xB0, 0x6F, 0xA4, 0xAB, - 0xA8, 0xB8, 0x7C, 0xE5, 0xB0, 0xB7, 0x83, 0xA5, 0x2E, 0xA4, 0xF0, 0x58, 0xC2, 0x59, 0x41, 0x15, 0x17, 0x4D, 0x49, 0x8F, 0x4B, 0x4E, 0x2D, 0xF5, 0x6D, 0xE6, - 0xA4, 0x58, 0xED, 0x16, 0x04, 0x21, 0x7E, 0xC0, 0x22, 0x4B, 0xC1, 0xE5, 0x2B, 0xDE, 0xBD, 0x8A, 0xEB, 0xB3, 0xDB, 0x8B, 0xE4, 0x47, 0xB2, 0xAF, 0x9B, 0xE7, - 0xDB, 0x41, 0xD1, 0x5C, 0xB6, 0x55, 0x72, 0xE0, 0xDB, 0x6A, 0x2A, 0x0B, 0xBD, 0x43, 0xD6, 0xB3, 0xCE, 0x7D, 0x86, 0x09, 0x94, 0x5F, 0x79, 0xEB, 0xED, 0x60, - 0x7B, 0x08, 0x52, 0xD8, 0xAE, 0x0D, 0x3E, 0x15, 0x64, 0xAA, 0x4A, 0xFD, 0xA0, 0xF4, 0xFE, 0x90, 0xDD, 0x95, 0xDE, 0x47, 0xF3, 0x9B, 0xE2, 0xA5, 0xF7, 0x8B, - 0x77, 0x3F, 0x17, 0x2B, 0xBD, 0x8B, 0xBD, 0xEC, 0xAE, 0xF4, 0x5E, 0xCE, 0x66, 0x0A, 0x6D, 0x94, 0x05, 0xC6, 0xF0, 0x55, 0x48, 0x23, 0xD3, 0xA3, 0x5D, 0x82, - 0x60, 0xB4, 0xF7, 0xC1, 0x69, 0x28, 0x22, 0xE1, 0x19, 0xE5, 0x78, 0xFB, 0x2C, 0xEB, 0xE9, 0x64, 0x84, 0x85, 0x52, 0xCF, 0xF0, 0xE2, 0x0B, 0x75, 0xFA, 0xFC, - 0x1B, 0x5F, 0x15, 0x9E, 0x05, 0x4E, 0x7B, 0xD7, 0xC8, 0xC1, 0x51, 0x41, 0xDC, 0x5B, 0x7F, 0xC5, 0xC0, 0x20, 0xA1, 0x28, 0x9D, 0xEA, 0x47, 0xC7, 0x73, 0xE5, - 0x3A, 0x39, 0x05, 0x2B, 0x12, 0xCD, 0x3B, 0x62, 0xA9, 0x45, 0x3D, 0x9A, 0x33, 0xF2, 0xB6, 0x13, 0xCD, 0x11, 0x77, 0x8C, 0xF7, 0x02, 0x59, 0x0D, 0x83, 0x2D, - 0x26, 0x00, 0xF9, 0x26, 0x0A, 0x05, 0x01, 0xA4, 0x49, 0x60, 0x23, 0x22, 0x68, 0x53, 0x09, 0xB4, 0x13, 0xDA, 0x4F, 0x09, 0xFC, 0xB4, 0x7D, 0xD9, 0xB8, 0xDF, - 0xD9, 0x41, 0x6D, 0x02, 0xC5, 0x15, 0xE3, 0xA8, 0xA0, 0x4E, 0x8B, 0x2D, 0x0E, 0xC6, 0x74, 0x5A, 0xCC, 0xA8, 0xB7, 0xB6, 0x3A, 0x08, 0xC8, 0x3B, 0x54, 0x00, - 0x1D, 0x65, 0x95, 0x96, 0x9F, 0x66, 0x76, 0x76, 0x90, 0x9F, 0xA0, 0xB4, 0x62, 0x1C, 0x15, 0x54, 0x69, 0xB1, 0xA5, 0xCF, 0x98, 0x4A, 0xD5, 0xE7, 0x97, 0x9C, - 0xC8, 0xAD, 0xA9, 0xB4, 0x4B, 0x05, 0xD0, 0x55, 0x56, 0x69, 0xF9, 0x59, 0x47, 0x67, 0x07, 0xBB, 0x77, 0x51, 0x5A, 0x31, 0x8E, 0x0A, 0xAA, 0xB4, 0xD8, 0x92, - 0x5D, 0x4C, 0xA5, 0xEA, 0xF3, 0x49, 0x4E, 0xE4, 0xD6, 0x54, 0xDA, 0xA3, 0x02, 0xE8, 0x29, 0xAB, 0xB4, 0x7C, 0xA5, 0xA0, 0xB3, 0x83, 0x62, 0x10, 0x4A, 0x2B, - 0xC6, 0x51, 0x41, 0x95, 0x16, 0x5B, 0x7D, 0x8E, 0xA9, 0x54, 0x7D, 0x9D, 0x83, 0x13, 0xB9, 0x35, 0x95, 0xF6, 0xA9, 0x00, 0xFA, 0xCA, 0x2A, 0x2D, 0xBF, 0xBF, - 0xAA, 0xB3, 0x83, 0xBD, 0xDB, 0x28, 0xAD, 0x18, 0x47, 0x05, 0x55, 0x5A, 0xAC, 0x74, 0x1B, 0x53, 0xA9, 0xFA, 0xCA, 0x0D, 0x27, 0x72, 0x6B, 0x2A, 0x3D, 0xA2, - 0x02, 0x38, 0x52, 0x56, 0x69, 0xF9, 0xAD, 0xEB, 0x9D, 0x1D, 0xD4, 0xF3, 0x50, 0x5A, 0x31, 0x8E, 0x0A, 0xAA, 0xB4, 0x58, 0x05, 0x27, 0xA6, 0x52, 0xF5, 0xBD, - 0x53, 0x9C, 0xC8, 0xAD, 0xA9, 0xF4, 0x98, 0x0A, 0xE0, 0x58, 0x59, 0xA5, 0xE5, 0x77, 0xEE, 0x77, 0x76, 0xB0, 0x73, 0x1F, 0xA5, 0x15, 0xE3, 0xA8, 0xA0, 0x4A, - 0x8B, 0xD5, 0x66, 0x63, 0x2A, 0x55, 0xDF, 0xEE, 0xC4, 0x89, 0xDC, 0x9A, 0x4A, 0x4F, 0xA8, 0x00, 0x4E, 0x94, 0x55, 0x5A, 0x7E, 0xCB, 0x40, 0x67, 0x07, 0x9B, - 0x5F, 0x50, 0x5A, 0x2D, 0x91, 0xA3, 0x82, 0x2A, 0x2D, 0xB6, 0xC0, 0xD8, 0x49, 0xD9, 0xFA, 0xA2, 0xA0, 0xD2, 0xB4, 0x05, 0xC6, 0x07, 0x50, 0xBF, 0x33, 0x56, - 0xC3, 0x12, 0x1F, 0xFC, 0x79, 0xF1, 0xD3, 0xCB, 0xF4, 0xC2, 0x7E, 0x6A, 0x15, 0x2F, 0xD6, 0xD7, 0x43, 0x2F, 0xE3, 0x89, 0xF2, 0x42, 0xC2, 0x41, 0xCB, 0xEC, - 0x25, 0x91, 0xDA, 0x1A, 0xF3, 0xD9, 0x96, 0xC6, 0x80, 0x0B, 0x58, 0x5A, 0xA7, 0xDB, 0x92, 0x27, 0x2D, 0x39, 0x96, 0xC6, 0xA9, 0xDC, 0x4E, 0xF0, 0x40, 0xE4, - 0x30, 0x17, 0x47, 0xDE, 0x3F, 0x28, 0xAD, 0xE9, 0x30, 0x80, 0x78, 0xF8, 0xE8, 0xB6, 0x4E, 0x14, 0xE3, 0x07, 0xC8, 0x20, 0x6D, 0x63, 0xFC, 0x06, 0x03, 0x08, - 0xD2, 0xD8, 0x61, 0x4C, 0xBD, 0x51, 0x66, 0x2A, 0x59, 0x05, 0x28, 0xC4, 0x54, 0x5A, 0x65, 0x67, 0xC3, 0x4C, 0x75, 0x19, 0x53, 0x19, 0x4E, 0x9A, 0x60, 0x2A, - 0x39, 0x0F, 0x2E, 0xC4, 0x54, 0xDA, 0x44, 0x38, 0x62, 0xEA, 0x21, 0x04, 0x3A, 0x32, 0x32, 0xA6, 0xA3, 0x12, 0xA1, 0xEE, 0xF2, 0xE2, 0xF0, 0xC5, 0x9B, 0x0B, - 0x8D, 0x2E, 0x69, 0x3A, 0x56, 0xC1, 0x88, 0x17, 0xEF, 0xF4, 0x2F, 0x15, 0xF3, 0x28, 0xE9, 0x42, 0xD4, 0x7B, 0x73, 0xA1, 0x1A, 0xF0, 0x38, 0x64, 0x91, 0x90, - 0xD7, 0x6B, 0x75, 0xCA, 0x54, 0x08, 0x43, 0x22, 0xB7, 0x14, 0xF4, 0x28, 0xFA, 0x76, 0x24, 0x83, 0xCB, 0x62, 0x32, 0x28, 0x54, 0x25, 0x8D, 0xCB, 0xA0, 0x40, - 0xD8, 0x0F, 0x88, 0xDC, 0xA6, 0x0C, 0x30, 0x4A, 0x5E, 0x5E, 0x68, 0xEF, 0xFF, 0xA9, 0x5D, 0xDE, 0x2C, 0x1C, 0x6F, 0xE9, 0x92, 0xDC, 0xA8, 0xC2, 0xE1, 0xE2, - 0x71, 0xA5, 0xDF, 0xEB, 0x75, 0x54, 0x03, 0x4B, 0x2F, 0x7D, 0x08, 0x98, 0xB4, 0x36, 0x18, 0x2F, 0x29, 0xA1, 0xDD, 0x90, 0xC1, 0x0F, 0x04, 0x34, 0xAD, 0x14, - 0x37, 0x39, 0x60, 0x9C, 0x43, 0xBD, 0x85, 0xDB, 0xAB, 0x15, 0x19, 0x94, 0x67, 0x94, 0x9D, 0x8D, 0x0E, 0x07, 0x94, 0xCA, 0x5E, 0xC8, 0xDE, 0xA7, 0x8F, 0x57, - 0x6A, 0x8C, 0x25, 0xEB, 0x68, 0xC5, 0x54, 0x97, 0xF6, 0xC8, 0x68, 0xC1, 0x41, 0x41, 0xDE, 0xE8, 0xEC, 0x10, 0x62, 0xEC, 0xBA, 0x6C, 0x52, 0x44, 0x76, 0x36, - 0x31, 0xA7, 0x60, 0xB0, 0x72, 0x59, 0x52, 0x19, 0xB2, 0xB7, 0x9A, 0xE2, 0x17, 0x48, 0x9B, 0x23, 0x08, 0xF3, 0xA0, 0x7B, 0xF4, 0xAE, 0x40, 0xB2, 0x73, 0x63, - 0x4A, 0xA2, 0xEB, 0x1A, 0x0B, 0xE2, 0x59, 0xC1, 0xD9, 0x60, 0x08, 0x8D, 0x6B, 0xC2, 0x3F, 0x97, 0xAA, 0xCD, 0x5C, 0x32, 0x39, 0xAF, 0x7D, 0x13, 0xE2, 0xE4, - 0x8F, 0xDF, 0x61, 0x93, 0x9A, 0x36, 0x76, 0x56, 0xB6, 0xE5, 0x18, 0x18, 0xF8, 0x8D, 0x85, 0x0F, 0x94, 0x1E, 0xFC, 0xB1, 0xC0, 0x37, 0x5C, 0x19, 0xF8, 0xB4, - 0x96, 0x91, 0xD1, 0x8F, 0xA0, 0xFE, 0x91, 0xE5, 0x78, 0xC1, 0xB4, 0x0D, 0x0F, 0xC3, 0xCF, 0xAB, 0xFE, 0xCF, 0x7F, 0xE7, 0x6D, 0x15, 0x30, 0xE7, 0x53, 0x41, - 0x00, 0x35, 0xCD, 0x73, 0x47, 0xE7, 0x35, 0xA0, 0xD4, 0x75, 0x3C, 0xCF, 0x71, 0xCD, 0xA9, 0x99, 0x32, 0x36, 0xA7, 0x49, 0xFB, 0x50, 0x26, 0xEE, 0x44, 0x63, - 0xC9, 0xB0, 0x7F, 0xE6, 0x8D, 0x5C, 0x73, 0xE1, 0x0F, 0x1E, 0x8D, 0x9D, 0xD1, 0x72, 0x4E, 0x6C, 0xFF, 0xC0, 0x18, 0x8F, 0x2F, 0xAF, 0xE1, 0xE0, 0x3B, 0xFC, - 0x16, 0x1F, 0x48, 0xBE, 0x51, 0x7F, 0xF5, 0xAF, 0x77, 0x38, 0x0C, 0xE3, 0x35, 0x90, 0x17, 0x19, 0xD7, 0xF7, 0xB5, 0xC9, 0xD2, 0x66, 0x23, 0x61, 0x83, 0x60, - 0xDB, 0x3D, 0xED, 0x2B, 0x60, 0xBC, 0x36, 0x5C, 0x6D, 0x68, 0x78, 0xE4, 0xAD, 0xE3, 0xF9, 0xDA, 0xB9, 0x16, 0x62, 0xB4, 0x9C, 0x11, 0xDD, 0xB7, 0x71, 0xC0, - 0xF8, 0xE2, 0x2D, 0x19, 0xE3, 0x3F, 0xBA, 0x16, 0x34, 0x0D, 0xA1, 0x9E, 0x6A, 0xF5, 0xD3, 0x63, 0xBD, 0x8E, 0xF6, 0x17, 0x76, 0x31, 0x21, 0x10, 0xE6, 0xA1, - 0x5D, 0x63, 0xE9, 0x5A, 0xFB, 0xDA, 0x68, 0xB8, 0xF7, 0x95, 0x52, 0x4F, 0x2F, 0xE3, 0xB5, 0x3D, 0xCE, 0xCC, 0x81, 0x3F, 0x23, 0x76, 0x23, 0xA2, 0xCC, 0x25, - 0xDE, 0xC2, 0xB1, 0x3D, 0xC2, 0x88, 0x63, 0x3F, 0x73, 0x12, 0x5D, 0x3F, 0xF0, 0x7C, 0xC3, 0x5F, 0x7A, 0xDA, 0xE3, 0xF3, 0x73, 0xAD, 0xDD, 0x6A, 0x89, 0xCD, - 0x34, 0xE8, 0x26, 0xD9, 0x6E, 0x5F, 0x4B, 0x5C, 0xF8, 0x48, 0x6E, 0xFC, 0xBD, 0x67, 0x21, 0xCC, 0x9D, 0x46, 0x2C, 0x8F, 0xC4, 0x90, 0x84, 0x00, 0xF8, 0xDE, - 0xB8, 0xC6, 0x5E, 0x9C, 0xC0, 0xC6, 0xD8, 0xF0, 0x8D, 0xBD, 0xAF, 0x31, 0x7D, 0x41, 0xAF, 0x40, 0xC9, 0xBE, 0x46, 0x6F, 0x3D, 0x13, 0x6E, 0xDD, 0xED, 0x1D, - 0x80, 0x0C, 0x81, 0xDF, 0x10, 0x9A, 0xB8, 0x6E, 0x9C, 0x62, 0x0A, 0xDD, 0xD4, 0xF7, 0x35, 0xBC, 0x13, 0x87, 0x15, 0x88, 0x7C, 0x14, 0x5C, 0x0B, 0x84, 0x96, - 0x8D, 0x56, 0x82, 0x92, 0xA1, 0xBB, 0x8B, 0xA9, 0x08, 0x02, 0xCE, 0x07, 0x32, 0x05, 0x89, 0x4D, 0xF7, 0x79, 0xFC, 0xD9, 0xA7, 0xC1, 0x67, 0x9F, 0xC5, 0x2D, - 0x41, 0x6B, 0x87, 0x87, 0xE0, 0xD2, 0x9E, 0x63, 0x11, 0xB0, 0x8A, 0x69, 0xA3, 0xCE, 0xBF, 0xF5, 0x0A, 0x16, 0x55, 0x6F, 0xDD, 0xD4, 0x9F, 0x02, 0x82, 0x03, - 0xDF, 0xB9, 0xF2, 0x5D, 0xD3, 0x9E, 0x36, 0xF4, 0xFE, 0x5E, 0x84, 0x8D, 0xDE, 0x46, 0x94, 0x89, 0xFB, 0xF4, 0x3A, 0xED, 0x24, 0x79, 0xA3, 0xC1, 0xAF, 0x3F, - 0xAD, 0xEF, 0xD5, 0x39, 0xF1, 0xF4, 0x1C, 0xCC, 0xAD, 0xC1, 0x0E, 0x9E, 0x50, 0x1A, 0xF7, 0xB4, 0xB3, 0x33, 0xDE, 0x0D, 0x6B, 0x85, 0x17, 0xA1, 0x11, 0xFD, - 0x93, 0xB8, 0x15, 0x9A, 0xE2, 0xEF, 0xFF, 0xF8, 0x1A, 0xD8, 0xEC, 0xDD, 0x21, 0x50, 0xFD, 0x1C, 0x43, 0xF0, 0x3F, 0xBE, 0xC2, 0xFF, 0x77, 0x4F, 0x68, 0xD4, - 0xFD, 0xC7, 0x57, 0xFC, 0x73, 0xF7, 0x04, 0x7A, 0x82, 0x63, 0xDA, 0xDF, 0xDD, 0xEF, 0x54, 0x0E, 0xEB, 0xD2, 0x9B, 0xA6, 0x4A, 0x2F, 0x14, 0x5B, 0x61, 0x9A, - 0xA6, 0x19, 0x44, 0xFD, 0x1E, 0xF9, 0x6F, 0x63, 0xE4, 0x8C, 0x41, 0x3D, 0x3E, 0x58, 0x72, 0xA0, 0x74, 0x0B, 0x54, 0x12, 0x08, 0xAA, 0x15, 0x28, 0xDD, 0x9C, - 0xD0, 0x96, 0x1A, 0x77, 0x95, 0xC8, 0x40, 0x82, 0x96, 0x0B, 0xC3, 0xF5, 0xC8, 0xB7, 0xB6, 0xDF, 0xF0, 0x63, 0x4E, 0x91, 0x22, 0xF1, 0xC1, 0x20, 0xC6, 0x02, - 0xFE, 0x00, 0x0E, 0xDA, 0xD5, 0xB9, 0xD2, 0x42, 0x63, 0xE3, 0x7F, 0x13, 0x66, 0xF3, 0xA6, 0x90, 0xD9, 0x34, 0xA8, 0xD8, 0xC2, 0x3E, 0xF7, 0x8A, 0x98, 0x10, - 0x90, 0x25, 0x18, 0x10, 0x75, 0x88, 0x48, 0x64, 0xEC, 0x62, 0x8A, 0x43, 0xFC, 0x3C, 0xB2, 0xBE, 0x34, 0x6E, 0xE0, 0xBF, 0x64, 0xCC, 0x5A, 0xD3, 0x15, 0x36, - 0x7A, 0x8E, 0xFF, 0x81, 0x82, 0xF0, 0x4F, 0xAA, 0xA1, 0x00, 0xD6, 0xF7, 0x96, 0xD5, 0x60, 0x1F, 0x98, 0x03, 0x1B, 0x59, 0x42, 0x3C, 0xF4, 0x6E, 0x31, 0x32, - 0x39, 0x8E, 0xFF, 0x79, 0x5F, 0x5B, 0xB8, 0x40, 0x18, 0xFD, 0x96, 0x0A, 0x1C, 0x03, 0x22, 0x62, 0xB3, 0xBF, 0xB9, 0x14, 0x2C, 0x2C, 0xEB, 0x39, 0xC3, 0x0A, - 0x24, 0xB0, 0x03, 0x30, 0x99, 0x25, 0x9A, 0x2E, 0xFC, 0x7F, 0xF7, 0x04, 0x3A, 0x81, 0x43, 0xF8, 0xFF, 0xEE, 0x09, 0x76, 0x85, 0x46, 0x85, 0x3D, 0xDE, 0x3D, - 0x81, 0x1E, 0xE1, 0x04, 0xFE, 0x87, 0x36, 0xD8, 0x2F, 0xB6, 0xC2, 0xBF, 0x70, 0x87, 0xF6, 0x8F, 0x37, 0xE9, 0x01, 0xBB, 0xC0, 0x4F, 0xB3, 0x18, 0x64, 0x6F, - 0xD7, 0x6F, 0xD0, 0xB7, 0x9D, 0x7F, 0xBE, 0x01, 0x76, 0xE8, 0xC1, 0x2D, 0xC4, 0x20, 0x7B, 0x8C, 0xE7, 0xF8, 0xE7, 0x36, 0x50, 0x30, 0x5E, 0xE0, 0x47, 0x70, - 0x8D, 0xBE, 0x11, 0x16, 0x2F, 0xB1, 0x03, 0x6C, 0x45, 0xDF, 0xDF, 0x49, 0x5B, 0xB1, 0x23, 0xB8, 0xC6, 0xDF, 0xFA, 0xB8, 0xAF, 0xF1, 0xF7, 0x0A, 0xE6, 0x0A, - 0x27, 0x7A, 0xEF, 0xDF, 0x73, 0xEF, 0x06, 0x19, 0x64, 0xA4, 0xA1, 0x54, 0xC2, 0xB3, 0xDB, 0xBB, 0x27, 0x04, 0xEF, 0x51, 0x22, 0xE1, 0xF8, 0x96, 0x1F, 0xC3, - 0x75, 0xA0, 0x0F, 0xEF, 0x04, 0x04, 0xD3, 0x0B, 0xB7, 0xD1, 0x05, 0x68, 0xE1, 0xE3, 0x7D, 0x4E, 0x3C, 0x9C, 0xDD, 0x86, 0x67, 0x08, 0x4D, 0x61, 0x39, 0x1B, - 0x70, 0x7A, 0x1B, 0x9D, 0xC2, 0x5D, 0xE4, 0x05, 0x15, 0xC0, 0x79, 0xBA, 0x7B, 0xC2, 0x79, 0x42, 0x2D, 0xB2, 0xA3, 0xB8, 0xA8, 0xE1, 0x7F, 0xF4, 0x23, 0x9F, - 0x07, 0xEC, 0x4F, 0x81, 0x77, 0x12, 0x6B, 0x4F, 0x3B, 0x1F, 0xF0, 0xB8, 0x8F, 0x01, 0x00, 0x3C, 0x0A, 0xAE, 0x13, 0xEB, 0xC0, 0xF0, 0xC1, 0x21, 0x20, 0x6F, - 0x22, 0xDE, 0x01, 0x46, 0x94, 0xD0, 0xCD, 0xD7, 0x6E, 0x1D, 0xD8, 0xE0, 0x16, 0x14, 0xE1, 0xDE, 0x29, 0x0F, 0x1B, 0x88, 0x88, 0x71, 0xB9, 0x86, 0x8B, 0x5D, - 0x4E, 0x43, 0xC7, 0xEE, 0xA6, 0x60, 0xE4, 0xA1, 0x30, 0x0E, 0x81, 0x17, 0xD3, 0xB0, 0xD1, 0x51, 0x43, 0xC0, 0xD5, 0xEE, 0xF5, 0x22, 0x6C, 0x89, 0x48, 0xC7, - 0xE6, 0x94, 0x28, 0x90, 0x03, 0xCC, 0xCF, 0xA3, 0xA1, 0x70, 0x04, 0xE6, 0xA0, 0xD5, 0x83, 0x09, 0x65, 0xFD, 0x74, 0x2D, 0xC2, 0x01, 0x04, 0x2F, 0x20, 0x68, - 0xCF, 0x19, 0x8D, 0xA7, 0x51, 0xF8, 0xD4, 0xB4, 0x21, 0x24, 0x3B, 0x5F, 0x9E, 0xC5, 0x90, 0xD1, 0xD4, 0x3F, 0xC4, 0xC4, 0xAE, 0x61, 0xA2, 0x90, 0xB8, 0xC4, - 0xB6, 0xDB, 0x35, 0x1D, 0x9B, 0xC8, 0x7B, 0x8D, 0xC5, 0x4B, 0xDE, 0x11, 0x3F, 0x1B, 0x93, 0x89, 0xB1, 0xB4, 0xFC, 0x08, 0xCC, 0x25, 0x90, 0xE8, 0xDA, 0x3C, - 0x6C, 0xB1, 0x24, 0x3F, 0x77, 0xE8, 0xCE, 0x18, 0x2A, 0x82, 0x51, 0xE1, 0x71, 0x72, 0x54, 0x00, 0xAB, 0x74, 0xFD, 0x46, 0xFD, 0xD2, 0x75, 0x1D, 0xF7, 0xD7, - 0xFA, 0x53, 0x6C, 0xF4, 0xB4, 0xFE, 0xDB, 0xA9, 0x46, 0xE3, 0xE9, 0x5E, 0x3C, 0xB8, 0x0B, 0xE1, 0xF3, 0xF0, 0x50, 0x7B, 0xE1, 0xFB, 0x06, 0x28, 0x00, 0x6B, - 0x2C, 0x33, 0x94, 0x8F, 0x66, 0xF0, 0x24, 0xD0, 0x71, 0xD1, 0x28, 0xD9, 0xF7, 0xEE, 0x41, 0x22, 0x98, 0x58, 0x7A, 0x00, 0x12, 0x24, 0x99, 0x14, 0xD5, 0xC1, - 0xBF, 0x97, 0xC4, 0xBD, 0xBD, 0xA2, 0x02, 0x73, 0xDC, 0x17, 0x10, 0x2A, 0xEB, 0x07, 0xD1, 0x3C, 0xA9, 0xCE, 0x72, 0x9E, 0x03, 0x40, 0x75, 0x09, 0x7D, 0x80, - 0x8E, 0x23, 0x9B, 0x67, 0xDC, 0x84, 0x7A, 0x87, 0x71, 0xEE, 0x9C, 0x2B, 0x23, 0x99, 0x64, 0x41, 0x0B, 0xC7, 0xFE, 0x42, 0x6E, 0x97, 0x0B, 0x10, 0x7F, 0x94, - 0x36, 0x25, 0x12, 0x39, 0x2E, 0x1D, 0x72, 0x00, 0x2D, 0x2F, 0xF8, 0xC0, 0xA9, 0x77, 0x24, 0x8D, 0x22, 0x15, 0x50, 0xEB, 0x44, 0x4F, 0x7C, 0xB6, 0xD6, 0xE8, - 0xEE, 0x91, 0xFC, 0x4C, 0x92, 0x72, 0x72, 0x02, 0xB9, 0xF0, 0xC0, 0xB5, 0xA9, 0x63, 0x27, 0x7A, 0x48, 0xA4, 0x83, 0x90, 0x0C, 0x46, 0x91, 0x61, 0xB9, 0x80, - 0xE4, 0x93, 0xC4, 0x83, 0x43, 0x68, 0x0B, 0xC1, 0xCD, 0xB9, 0xE3, 0x93, 0x44, 0xC4, 0x30, 0x6D, 0xD3, 0x37, 0x0D, 0xEB, 0x53, 0x64, 0x8D, 0x5B, 0x75, 0x7F, - 0x89, 0x8F, 0x17, 0xF0, 0xFF, 0xB5, 0x9C, 0x4F, 0x2D, 0x4F, 0x59, 0xB3, 0x90, 0x30, 0x1E, 0x44, 0x56, 0x22, 0xCA, 0x21, 0x16, 0x16, 0xF8, 0xFD, 0xA0, 0xA7, - 0xC7, 0x8F, 0xE9, 0xD1, 0xA3, 0x50, 0x69, 0x41, 0xF4, 0x38, 0xD7, 0xA2, 0x1B, 0x09, 0x05, 0xAF, 0xE3, 0x4E, 0xE0, 0x08, 0x90, 0x0B, 0x18, 0x12, 0x81, 0x7F, - 0x01, 0xE9, 0x0D, 0xDA, 0xC2, 0xFF, 0x47, 0xFD, 0x07, 0x14, 0xF5, 0xB7, 0x17, 0xE2, 0x33, 0x6C, 0x3B, 0xE1, 0x01, 0x0C, 0x4E, 0x9E, 0x4F, 0x3F, 0x85, 0x44, - 0x5B, 0x9E, 0x24, 0x87, 0xA1, 0x3B, 0x9C, 0xEC, 0xC3, 0x64, 0xE6, 0x92, 0x85, 0xE7, 0x97, 0xB7, 0xDF, 0x8E, 0x1B, 0xF5, 0xF0, 0x8D, 0x46, 0xF5, 0x3D, 0x8C, - 0x4B, 0x96, 0x39, 0xFA, 0x12, 0x86, 0xA5, 0xC8, 0xF2, 0x20, 0xA5, 0xC1, 0xEC, 0x1F, 0x27, 0xD6, 0xE6, 0x88, 0x9B, 0xEA, 0xAB, 0x0F, 0x2F, 0xDE, 0x7D, 0x7E, - 0xF1, 0xF1, 0xE3, 0x07, 0x6D, 0x09, 0x36, 0xAB, 0xF7, 0x3F, 0x63, 0xDA, 0x02, 0x93, 0x00, 0xF7, 0x33, 0xD0, 0xE7, 0x7D, 0xA6, 0x48, 0x5B, 0xBF, 0xFE, 0xF6, - 0x6B, 0xFB, 0x37, 0x00, 0xFD, 0xFA, 0x5F, 0x76, 0x9D, 0x31, 0x82, 0xA8, 0x9E, 0x02, 0x2E, 0x3C, 0xFE, 0x5A, 0x7F, 0x1A, 0x18, 0x7C, 0x23, 0x9D, 0xC2, 0xF0, - 0xF5, 0xBA, 0xF5, 0x3D, 0x60, 0xF5, 0x6E, 0x1F, 0x50, 0xB1, 0x74, 0x10, 0xC6, 0x9C, 0x06, 0x96, 0x2A, 0x4C, 0xE8, 0x40, 0x7F, 0x06, 0x7F, 0xCE, 0x34, 0xFD, - 0x08, 0xFE, 0x3E, 0x7D, 0x1A, 0x99, 0x48, 0xC9, 0xEE, 0xEA, 0x4F, 0x4D, 0xDA, 0x19, 0xCC, 0x4E, 0x1A, 0xE6, 0x19, 0x48, 0xF2, 0x79, 0x7D, 0xBF, 0x7E, 0x5A, - 0xAF, 0xC3, 0xB5, 0xA0, 0xFB, 0xBB, 0x18, 0x3B, 0x77, 0xCF, 0x42, 0x0E, 0xD9, 0xE8, 0x0A, 0x37, 0x22, 0xF1, 0x8B, 0x59, 0xDD, 0x4B, 0x56, 0xE5, 0x3A, 0x4F, - 0xD7, 0x09, 0x7B, 0x9B, 0xF5, 0x94, 0x0E, 0x88, 0x22, 0x4C, 0x86, 0x82, 0x58, 0x68, 0x08, 0x7D, 0x2D, 0x15, 0x35, 0x1D, 0x6E, 0xC7, 0x63, 0x17, 0xB4, 0x4D, - 0xAD, 0x65, 0x6F, 0xCD, 0x85, 0xD5, 0x70, 0x60, 0x63, 0x09, 0x8E, 0xB5, 0xE9, 0x66, 0x26, 0x12, 0xDA, 0x5A, 0xC0, 0xB2, 0x96, 0xF0, 0xB4, 0xEE, 0x2F, 0xD7, - 0x61, 0x1A, 0x9B, 0x2A, 0x6A, 0x6C, 0x2A, 0x68, 0x6C, 0xBA, 0x59, 0x8D, 0x71, 0xD4, 0x95, 0xB5, 0x16, 0xE0, 0xC9, 0xD1, 0x5C, 0x2E, 0x3C, 0x57, 0x1A, 0xD7, - 0xD6, 0x54, 0xA6, 0xAD, 0x32, 0x6A, 0x62, 0xB1, 0x0B, 0x26, 0x45, 0xC4, 0x7D, 0xFB, 0xF1, 0xDD, 0x77, 0x18, 0x6D, 0xE4, 0x2A, 0x0B, 0x35, 0x96, 0x4C, 0xAE, - 0x24, 0x18, 0x30, 0x28, 0xC6, 0x2A, 0x1F, 0x89, 0xB0, 0xA9, 0x45, 0x15, 0x84, 0x1C, 0x43, 0xE0, 0x05, 0x03, 0x35, 0xDF, 0xC5, 0x22, 0x41, 0xE0, 0xBC, 0x11, - 0x54, 0x86, 0x2D, 0x20, 0x80, 0x92, 0x12, 0x19, 0xE6, 0x35, 0x87, 0x11, 0x6A, 0x19, 0x3B, 0x77, 0x11, 0xEA, 0xAF, 0x9E, 0x6A, 0x50, 0x0B, 0xA6, 0xEA, 0x51, - 0x6C, 0xF3, 0x72, 0xA5, 0xC3, 0x27, 0xF4, 0x4A, 0x02, 0xE2, 0x5F, 0x95, 0x93, 0x18, 0x38, 0x2F, 0x04, 0x14, 0xC0, 0x72, 0x2B, 0xC1, 0x42, 0x0B, 0x08, 0x4A, - 0x38, 0xE8, 0x97, 0xC8, 0x52, 0x30, 0xA8, 0x51, 0x41, 0x3F, 0xFD, 0x25, 0xC1, 0x10, 0x94, 0x2A, 0x94, 0x90, 0x04, 0x9F, 0xAD, 0x4A, 0xC7, 0xA3, 0x46, 0x4C, - 0xF0, 0xB1, 0x28, 0x09, 0x1E, 0x5E, 0x1A, 0x51, 0x42, 0xC3, 0x3F, 0x74, 0x94, 0x8A, 0x45, 0x8D, 0x18, 0xFE, 0x6D, 0x21, 0x19, 0x4F, 0xBC, 0x14, 0xA3, 0xC6, - 0x13, 0xFF, 0x24, 0x4E, 0x3A, 0x1E, 0x45, 0xD9, 0xF0, 0xCF, 0xD0, 0xC8, 0xAC, 0x8E, 0x55, 0x7E, 0x32, 0x1D, 0x83, 0x35, 0x01, 0x60, 0x9E, 0xAA, 0x3E, 0xD7, - 0xC5, 0xCC, 0x9A, 0x17, 0x8A, 0xB2, 0x30, 0xF0, 0x26, 0x49, 0x0C, 0x41, 0x74, 0xB8, 0x87, 0x92, 0xDD, 0x7D, 0x44, 0xA1, 0xF7, 0x96, 0xA5, 0x16, 0x85, 0x16, - 0x96, 0x15, 0x84, 0x9F, 0x10, 0x26, 0x25, 0xFC, 0xD0, 0x25, 0x33, 0x5A, 0x6F, 0xCD, 0x94, 0x3F, 0x6D, 0xC1, 0xF0, 0xAE, 0x2B, 0x11, 0x71, 0xCC, 0x97, 0x96, - 0x92, 0x25, 0x41, 0x3B, 0x8E, 0x46, 0x34, 0x24, 0xBA, 0x1C, 0x77, 0xEB, 0xA9, 0x85, 0xAE, 0x5B, 0x2F, 0x05, 0x03, 0x2D, 0x09, 0xAB, 0xE5, 0x66, 0xD0, 0x32, - 0x05, 0xC9, 0xC2, 0x55, 0x4B, 0xEF, 0xA0, 0x5D, 0x1A, 0x23, 0x58, 0x7F, 0x56, 0x63, 0x25, 0xF8, 0xEA, 0xB8, 0x8C, 0x0E, 0x5A, 0xB5, 0xCE, 0x52, 0x0A, 0xFF, - 0xBA, 0x73, 0x9A, 0x46, 0x16, 0xAA, 0x43, 0x6E, 0xF0, 0xFD, 0x63, 0xC9, 0xB0, 0x5B, 0xB2, 0xD8, 0xBF, 0x7B, 0xE7, 0x30, 0xAE, 0x89, 0x82, 0x6B, 0x84, 0x2B, - 0xF3, 0x3C, 0xBB, 0x8B, 0xC0, 0x32, 0xBC, 0x63, 0x64, 0xD8, 0xD7, 0x46, 0xCC, 0x3B, 0x46, 0x30, 0xFD, 0xF5, 0x09, 0x47, 0xDD, 0xA8, 0xB1, 0x06, 0x35, 0x4E, - 0x23, 0x3B, 0x3B, 0xA0, 0x5B, 0xD6, 0xB0, 0x10, 0x62, 0x92, 0x15, 0x3B, 0x89, 0xDD, 0x9E, 0x11, 0xFA, 0x9A, 0x10, 0x7E, 0x9F, 0x9D, 0xB1, 0x06, 0x61, 0x2F, - 0x43, 0x67, 0x7C, 0x7B, 0x60, 0x2C, 0x16, 0x10, 0xBC, 0x2E, 0x66, 0xA6, 0x35, 0x6E, 0x30, 0x50, 0xC1, 0x44, 0x70, 0x6F, 0x02, 0xA1, 0xAB, 0x56, 0x1C, 0x2B, - 0x30, 0x7C, 0xC1, 0xAE, 0x35, 0xEA, 0xED, 0x71, 0xB0, 0x66, 0xC4, 0x9B, 0x1D, 0x8C, 0x5D, 0x63, 0xF5, 0x2D, 0x6E, 0x6A, 0x68, 0x60, 0xA7, 0xFB, 0xAD, 0xFD, - 0x16, 0x6F, 0xE0, 0xBB, 0xB7, 0x61, 0x96, 0x89, 0x78, 0x71, 0xF1, 0xF7, 0xC7, 0x0F, 0xDF, 0x45, 0x78, 0x7D, 0xE7, 0x15, 0xBB, 0xD4, 0xA8, 0xD3, 0x5D, 0x11, - 0x87, 0x7F, 0x2C, 0x70, 0x2A, 0x10, 0x28, 0x45, 0x10, 0x23, 0x6E, 0x78, 0x40, 0x51, 0xB1, 0xE6, 0xCF, 0x44, 0xA4, 0x70, 0xD9, 0x26, 0x2B, 0x0D, 0x30, 0x91, - 0x86, 0x0C, 0x34, 0xD8, 0x0E, 0x81, 0xE0, 0xC8, 0xC9, 0xEB, 0xA5, 0x65, 0xFD, 0x42, 0x0C, 0x17, 0xF4, 0xF1, 0x54, 0x6B, 0xD4, 0x5A, 0xB5, 0xA7, 0x0D, 0x7A, - 0xFD, 0x1D, 0xB0, 0x33, 0x6B, 0xEC, 0x3D, 0xD5, 0xF7, 0xF6, 0x0E, 0x3C, 0xD0, 0x19, 0x69, 0x34, 0xDB, 0x41, 0x13, 0xF8, 0x43, 0xDB, 0xB0, 0x4E, 0xD2, 0xEF, - 0xBF, 0x75, 0x96, 0xAE, 0x97, 0xD5, 0xE0, 0x9D, 0x69, 0x63, 0x11, 0x27, 0xAB, 0xC9, 0x15, 0x01, 0xC1, 0x8E, 0xD7, 0x9A, 0xD4, 0xE8, 0x2E, 0x0E, 0x5E, 0xFE, - 0xD0, 0xE8, 0xE2, 0xB6, 0xD6, 0x10, 0x2B, 0x3A, 0x7C, 0x19, 0x91, 0xA0, 0xA1, 0x37, 0x02, 0x8F, 0xBF, 0x13, 0x8D, 0x03, 0x5C, 0x16, 0x0C, 0xE0, 0x7B, 0xF0, - 0x80, 0x03, 0x97, 0xCC, 0x9D, 0x6B, 0xB2, 0xA6, 0x7F, 0x6C, 0x1E, 0x1A, 0xFF, 0xCC, 0x1C, 0xB3, 0x32, 0x4D, 0x64, 0xB7, 0x58, 0x15, 0xC2, 0x0D, 0x22, 0xB8, - 0x85, 0x02, 0xF7, 0x53, 0x34, 0xEA, 0x6C, 0xF7, 0x0A, 0x1D, 0x15, 0xEE, 0x22, 0xB7, 0x99, 0x39, 0xAB, 0x2C, 0x48, 0xD6, 0x7B, 0x02, 0x38, 0x84, 0x1E, 0x9B, - 0x9E, 0x31, 0xB4, 0xF2, 0xBB, 0xE6, 0xED, 0xC6, 0xBC, 0xFC, 0x0D, 0x0D, 0x82, 0x2B, 0x00, 0xEA, 0xBB, 0xB4, 0x4E, 0x28, 0xA0, 0x25, 0x76, 0x1E, 0xD6, 0x80, - 0xAC, 0x4C, 0xC4, 0x13, 0x03, 0x26, 0x4F, 0x71, 0xCC, 0xAC, 0x78, 0x5C, 0xA0, 0xAC, 0x2C, 0x5E, 0x06, 0x88, 0xF8, 0x29, 0x98, 0x33, 0x58, 0xA8, 0xF6, 0x9C, - 0xB2, 0xA0, 0x9D, 0xC6, 0xEE, 0x86, 0xB9, 0x8D, 0x58, 0x30, 0x7D, 0xC4, 0xE2, 0xDF, 0x5F, 0xB0, 0x82, 0x1B, 0x52, 0x1E, 0x93, 0xC0, 0x93, 0x27, 0x71, 0x6C, - 0xB8, 0x8D, 0x85, 0x0D, 0x20, 0x61, 0x6F, 0xAC, 0x3D, 0x7B, 0x7D, 0x78, 0xB4, 0xB2, 0xC0, 0x49, 0x82, 0xA1, 0xE0, 0x71, 0x4C, 0xF0, 0xC2, 0x18, 0x01, 0x84, - 0x98, 0x63, 0x2A, 0x20, 0xDC, 0x95, 0x56, 0x5B, 0x5B, 0xEF, 0x7F, 0x4E, 0xAD, 0xBE, 0x41, 0xF8, 0xA6, 0xC4, 0x3D, 0x90, 0x3F, 0x1A, 0x73, 0x74, 0x21, 0x3E, - 0x87, 0x4E, 0x60, 0x9C, 0xC6, 0x30, 0x22, 0x63, 0x09, 0xBA, 0xF1, 0x77, 0x78, 0x48, 0x31, 0x4E, 0x0D, 0xD3, 0xBE, 0x20, 0x26, 0xA6, 0x7F, 0x7B, 0xC2, 0x5D, - 0xDA, 0x3D, 0x20, 0xC2, 0x0D, 0x83, 0xC2, 0x72, 0xC6, 0xFA, 0x7A, 0xC8, 0xE1, 0x21, 0x6D, 0x9A, 0x82, 0x86, 0x76, 0xB1, 0x8E, 0x26, 0x93, 0xFA, 0xD5, 0xF0, - 0x33, 0x62, 0x93, 0x09, 0x85, 0xA2, 0x5B, 0x0D, 0x51, 0x1C, 0xB4, 0x57, 0x38, 0xCC, 0x42, 0x35, 0x31, 0x46, 0xE4, 0xB3, 0x0B, 0x71, 0x6C, 0x6A, 0x9B, 0x7F, - 0x12, 0x19, 0x42, 0xE6, 0x8C, 0x0D, 0x62, 0xBB, 0x4E, 0x90, 0x48, 0x22, 0x72, 0xEE, 0x67, 0xF1, 0xEB, 0xF1, 0x21, 0x3A, 0x70, 0xBD, 0x70, 0x69, 0x5D, 0xB4, - 0x05, 0x56, 0xFA, 0x8F, 0x26, 0xC0, 0x91, 0xB1, 0x6D, 0xA8, 0x12, 0xAE, 0x63, 0x19, 0x3C, 0x6C, 0x22, 0xD6, 0xAB, 0x2B, 0x16, 0xC1, 0x33, 0x70, 0xB2, 0xCD, - 0x7D, 0x49, 0xA4, 0xCB, 0xE1, 0xDC, 0xF4, 0x25, 0x08, 0xEB, 0x7A, 0x5D, 0x8A, 0x2B, 0xA5, 0x9E, 0x2E, 0x7A, 0x22, 0x8B, 0x66, 0x74, 0xA9, 0x11, 0x10, 0xC5, - 0xB6, 0x0A, 0x8C, 0xD8, 0x6E, 0xF5, 0xE7, 0x30, 0xE2, 0xE2, 0x06, 0x00, 0x54, 0x75, 0x62, 0x0B, 0x10, 0x43, 0xC1, 0xF6, 0xAE, 0x51, 0x14, 0xF1, 0xDD, 0x6B, - 0xC1, 0x8E, 0xB1, 0xF8, 0xCA, 0xA4, 0xB8, 0xF7, 0xE5, 0x77, 0x97, 0x00, 0x9C, 0x87, 0xF3, 0x59, 0xED, 0x1F, 0x5F, 0x29, 0x8A, 0x3B, 0x6D, 0x02, 0x91, 0xC0, - 0x9B, 0x91, 0x31, 0x9D, 0x7B, 0xF9, 0x4B, 0xEF, 0x54, 0xC3, 0x6D, 0x3F, 0xB1, 0xDD, 0x6A, 0x77, 0xBF, 0x87, 0x16, 0x12, 0x0E, 0x24, 0xD1, 0x7A, 0x2B, 0x67, - 0x7B, 0x6D, 0xDD, 0xF5, 0x91, 0xC2, 0x0A, 0x2B, 0x87, 0x55, 0x5A, 0x65, 0x95, 0x2D, 0x4E, 0x26, 0xA3, 0x14, 0xCF, 0x31, 0x1F, 0xA9, 0xF4, 0x4D, 0x77, 0x5D, - 0xAA, 0x74, 0x29, 0xC9, 0x2E, 0xF1, 0xC7, 0xC2, 0x98, 0x25, 0x8C, 0xF9, 0x09, 0x3F, 0xDA, 0xE3, 0x72, 0x02, 0x13, 0x19, 0x07, 0xF1, 0x96, 0x19, 0x11, 0xAE, - 0x3E, 0x33, 0x3D, 0xC6, 0x4C, 0x80, 0x49, 0x9B, 0x0B, 0x3B, 0x7F, 0x4B, 0x22, 0x5F, 0x76, 0x09, 0x95, 0xF5, 0x87, 0x07, 0x79, 0x7B, 0x28, 0x02, 0x19, 0x0E, - 0xEC, 0x40, 0x40, 0x10, 0x13, 0x51, 0x21, 0x15, 0x65, 0xC8, 0x8C, 0xFD, 0x84, 0x01, 0x9B, 0x8E, 0xD6, 0xB4, 0xE7, 0x5F, 0xA9, 0x55, 0xFF, 0xB6, 0xCF, 0x46, - 0x78, 0x21, 0x68, 0xEE, 0x15, 0x21, 0x68, 0x6D, 0x55, 0x3E, 0x97, 0x98, 0x8D, 0xAD, 0x4F, 0x06, 0x3F, 0x88, 0xC5, 0x14, 0xDF, 0xB9, 0xD6, 0x5A, 0x5B, 0x97, - 0x17, 0x17, 0xD1, 0x42, 0x06, 0x25, 0xB2, 0x11, 0x16, 0xD5, 0x03, 0xF1, 0x48, 0x17, 0xD0, 0x52, 0xC5, 0xC5, 0xEC, 0x8B, 0x45, 0x14, 0x9C, 0x16, 0x64, 0xCE, - 0x9F, 0xE8, 0x86, 0x59, 0x2A, 0xAF, 0x08, 0xE0, 0x22, 0xDC, 0x20, 0x9D, 0x0B, 0x19, 0x6D, 0xA6, 0x16, 0x70, 0xD0, 0xF9, 0x98, 0xDA, 0xFA, 0x03, 0x9F, 0xBA, - 0x09, 0xA0, 0x88, 0x35, 0x1F, 0x36, 0x78, 0x4A, 0x26, 0x49, 0xBE, 0x38, 0x7A, 0x65, 0xC1, 0xD3, 0x61, 0x92, 0x35, 0x16, 0xA0, 0xA9, 0xE7, 0xE7, 0x03, 0x8B, - 0xDB, 0xB2, 0xEB, 0x82, 0xB0, 0x3D, 0xDF, 0x59, 0x5C, 0xD1, 0xAB, 0x89, 0xA8, 0xB0, 0xA2, 0xC5, 0xAC, 0x03, 0xBC, 0x1F, 0xCC, 0x93, 0x44, 0x46, 0xE3, 0xF5, - 0xFF, 0x2B, 0xAC, 0x74, 0x69, 0x0C, 0x4F, 0x3D, 0x9E, 0xED, 0xD2, 0x22, 0x98, 0xB4, 0x07, 0x3A, 0xE7, 0xF4, 0xDC, 0x11, 0x1B, 0x3C, 0xC2, 0x6D, 0xD0, 0x18, - 0x3A, 0xF0, 0xF0, 0x77, 0xD6, 0x27, 0xA6, 0x12, 0x31, 0x05, 0xEF, 0xE5, 0xD2, 0xE2, 0x2C, 0x92, 0xA4, 0x44, 0x01, 0x9E, 0x39, 0x9B, 0x87, 0xA3, 0x06, 0x1B, - 0x28, 0x31, 0x7C, 0x09, 0xCA, 0x4F, 0x89, 0x91, 0x91, 0x98, 0x78, 0x50, 0x8A, 0x13, 0x2F, 0x8C, 0x7C, 0x6C, 0x0F, 0xFD, 0xF3, 0xCF, 0xA3, 0x21, 0x0C, 0x76, - 0x38, 0x01, 0x04, 0xD7, 0x5B, 0x35, 0xF6, 0xEE, 0xB2, 0xD8, 0x61, 0xE2, 0x8A, 0x14, 0xA9, 0x4A, 0x04, 0x8D, 0xDA, 0x72, 0x6C, 0x31, 0xF9, 0xC8, 0xD1, 0x89, - 0xD6, 0x7B, 0x69, 0x07, 0x13, 0x96, 0x34, 0xC1, 0x9E, 0xAF, 0x8B, 0x96, 0xE5, 0xAC, 0x31, 0x04, 0x51, 0x3C, 0x5E, 0x23, 0x36, 0x91, 0x94, 0x0A, 0x76, 0x11, - 0x34, 0x08, 0x68, 0x17, 0x1D, 0x22, 0x85, 0xF6, 0xF8, 0x58, 0x99, 0x48, 0xFF, 0x02, 0x95, 0x5F, 0x2C, 0x81, 0x88, 0x79, 0xA0, 0x72, 0x76, 0x0D, 0x33, 0xDC, - 0xD0, 0x36, 0x21, 0xE3, 0xCD, 0xF2, 0x19, 0xB8, 0x2D, 0x38, 0x1A, 0x4F, 0x8F, 0x73, 0x00, 0x68, 0x4E, 0xCC, 0x1E, 0x84, 0xA1, 0xB0, 0x6C, 0xC3, 0xAE, 0xAF, - 0x09, 0x89, 0x77, 0x66, 0x7C, 0x81, 0x66, 0x23, 0xD6, 0x4C, 0x40, 0x02, 0x78, 0xD7, 0xD3, 0x05, 0x89, 0x20, 0xA0, 0xDD, 0x5E, 0xA8, 0x17, 0x04, 0xE2, 0x99, - 0x68, 0xA4, 0x95, 0xF4, 0xD9, 0xC4, 0xFA, 0x4C, 0x22, 0xA1, 0xB0, 0xF4, 0x19, 0xC4, 0xFA, 0xEC, 0xE1, 0x4E, 0xD0, 0x42, 0xF0, 0xC4, 0x56, 0x24, 0x48, 0x92, - 0x2D, 0x75, 0x22, 0x4A, 0x3D, 0x98, 0x49, 0xE5, 0x40, 0x7C, 0xA6, 0xA9, 0x88, 0x28, 0x32, 0xA2, 0x28, 0x32, 0xC2, 0x45, 0x86, 0x00, 0x51, 0xE2, 0x9E, 0x3F, - 0xAD, 0x0B, 0xE3, 0xCA, 0x4F, 0x2F, 0x23, 0xCE, 0x56, 0xC3, 0x4C, 0x3A, 0xF9, 0x94, 0x49, 0x60, 0x2F, 0x1B, 0x00, 0xDA, 0xCF, 0x61, 0xDC, 0x16, 0xD9, 0x5A, - 0x0D, 0xD5, 0xD8, 0x0A, 0xA6, 0x5C, 0x08, 0x10, 0xB1, 0x25, 0x9F, 0x98, 0x05, 0xAC, 0xBC, 0x22, 0x3E, 0x7F, 0xAE, 0xD3, 0xB0, 0xC7, 0xDA, 0xC4, 0x35, 0xE6, - 0xC4, 0x83, 0x09, 0x59, 0x48, 0xEC, 0x98, 0xDE, 0xCF, 0x1D, 0xA2, 0x58, 0x33, 0x81, 0xC9, 0x70, 0x6A, 0x97, 0x0B, 0x1A, 0xB6, 0x14, 0xA0, 0x43, 0x3A, 0x32, - 0xA1, 0x83, 0x46, 0x6C, 0x6C, 0x0B, 0x4F, 0x95, 0x84, 0x15, 0xB6, 0x8E, 0x9C, 0x27, 0x42, 0xC0, 0x26, 0x4A, 0x03, 0xAD, 0x97, 0x2C, 0x27, 0xB0, 0x84, 0x87, - 0x31, 0x9B, 0x48, 0x6B, 0xC4, 0x06, 0x21, 0x4B, 0xB1, 0x36, 0xA1, 0x83, 0x30, 0xF8, 0x34, 0x32, 0x73, 0x49, 0x61, 0xE5, 0xEA, 0xDA, 0x7B, 0x8B, 0xE0, 0x34, - 0x8F, 0xBF, 0xA9, 0xF3, 0xE2, 0xDB, 0xD7, 0x9A, 0xE3, 0x6A, 0x96, 0xB3, 0x22, 0xB8, 0x59, 0x34, 0x58, 0x0A, 0xD6, 0x86, 0x04, 0x12, 0x4B, 0xC2, 0x26, 0xD3, - 0x18, 0x87, 0xFC, 0x99, 0xE9, 0x41, 0xEA, 0x8E, 0xEF, 0x93, 0x25, 0x8F, 0x6B, 0x61, 0x31, 0x34, 0x97, 0xBD, 0xF5, 0xAD, 0x55, 0x31, 0x71, 0x32, 0x98, 0x48, - 0x96, 0x8F, 0x39, 0x8F, 0x6B, 0xC1, 0x28, 0x6B, 0xFA, 0x5E, 0x40, 0x84, 0xE1, 0xED, 0x07, 0x2B, 0x45, 0x39, 0x03, 0xB9, 0x82, 0x0C, 0xC1, 0x22, 0x59, 0x46, - 0xBC, 0xAE, 0x49, 0x53, 0x56, 0x23, 0xC9, 0xD0, 0x28, 0x96, 0x0B, 0xA5, 0x71, 0x3E, 0x5D, 0x2B, 0x4C, 0xE2, 0x2C, 0x55, 0x67, 0xBF, 0xB3, 0xC3, 0xE0, 0xB1, - 0x39, 0x76, 0x86, 0x8B, 0x05, 0x83, 0x47, 0x67, 0x87, 0x33, 0x7F, 0x6E, 0x0D, 0x1E, 0xFD, 0x2F, 0x5E, 0x72, 0x0B, 0x89, 0x42, 0x10, 0x01, 0x00 +//File: index_ov5640.html.gz, Size: 8880 +#define index_ov5640_html_gz_len 8880 +const unsigned char index_ov5640_html_gz[] = { + 0x1F, 0x8B, 0x08, 0x08, 0x5B, 0xA3, 0x7B, 0x67, 0x00, 0x03, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x6F, 0x76, 0x35, 0x36, 0x34, 0x30, 0x2E, 0x68, 0x74, 0x6D, + 0x6C, 0x00, 0xED, 0x3D, 0xDB, 0x72, 0xDB, 0xC6, 0x92, 0xEF, 0xFE, 0x0A, 0x98, 0xC9, 0x9A, 0x64, 0x59, 0xA4, 0x08, 0xDE, 0x74, 0xB1, 0x44, 0xAF, 0x2D, 0x2B, + 0x76, 0xEA, 0xD8, 0x39, 0x8E, 0xE5, 0x38, 0x49, 0x65, 0x53, 0x0E, 0x48, 0x0C, 0x49, 0xC4, 0x20, 0xC0, 0x03, 0x80, 0xA2, 0x74, 0x5C, 0xFA, 0x8E, 0xFD, 0xA0, + 0xFD, 0xB1, 0xED, 0x9E, 0x19, 0x5C, 0x39, 0x00, 0x06, 0x00, 0x49, 0x29, 0xD9, 0xA5, 0xAB, 0x2C, 0x5C, 0xA6, 0x7B, 0xFA, 0x3E, 0x3D, 0x3D, 0x03, 0xE0, 0xEC, + 0xB1, 0x6E, 0x4F, 0xBC, 0xDB, 0x25, 0x51, 0xE6, 0xDE, 0xC2, 0x1C, 0x3D, 0x3A, 0x63, 0x7F, 0x14, 0xF8, 0x9D, 0xCD, 0x89, 0xA6, 0xB3, 0x43, 0x7A, 0xBA, 0x20, + 0x9E, 0xA6, 0x4C, 0xE6, 0x9A, 0xE3, 0x12, 0xEF, 0xBC, 0xB6, 0xF2, 0xA6, 0xAD, 0xE3, 0x5A, 0xF2, 0xB6, 0xA5, 0x2D, 0xC8, 0x79, 0xED, 0xDA, 0x20, 0xEB, 0xA5, + 0xED, 0x78, 0x35, 0x65, 0x62, 0x5B, 0x1E, 0xB1, 0xA0, 0xF9, 0xDA, 0xD0, 0xBD, 0xF9, 0xB9, 0x4E, 0xAE, 0x8D, 0x09, 0x69, 0xD1, 0x93, 0x03, 0xC3, 0x32, 0x3C, + 0x43, 0x33, 0x5B, 0xEE, 0x44, 0x33, 0xC9, 0xB9, 0x1A, 0xC5, 0xE5, 0x19, 0x9E, 0x49, 0x46, 0x97, 0x57, 0xEF, 0x7B, 0x5D, 0xE5, 0x9F, 0x9F, 0x06, 0xC3, 0x7E, + 0xE7, 0xEC, 0x90, 0x5D, 0x0B, 0xDB, 0xB8, 0xDE, 0x6D, 0xF4, 0x1C, 0x7F, 0x63, 0x5B, 0xBF, 0x55, 0xBE, 0xC6, 0x2E, 0xE1, 0x6F, 0x0A, 0x44, 0xB4, 0xA6, 0xDA, + 0xC2, 0x30, 0x6F, 0x4F, 0x95, 0x17, 0x0E, 0xF4, 0x79, 0xF0, 0x86, 0x98, 0xD7, 0xC4, 0x33, 0x26, 0xDA, 0x81, 0xAB, 0x59, 0x6E, 0xCB, 0x25, 0x8E, 0x31, 0x7D, + 0xB6, 0x01, 0x38, 0xD6, 0x26, 0x5F, 0x66, 0x8E, 0xBD, 0xB2, 0xF4, 0x53, 0xE5, 0x1B, 0xF5, 0x18, 0xFF, 0x6D, 0x36, 0x9A, 0xD8, 0xA6, 0xED, 0xC0, 0xFD, 0xCB, + 0xEF, 0xF0, 0xDF, 0xE6, 0x7D, 0xDA, 0xBB, 0x6B, 0xFC, 0x9B, 0x9C, 0x2A, 0xEA, 0x70, 0x79, 0x13, 0xBB, 0x7F, 0xF7, 0x28, 0x76, 0x3A, 0xEF, 0xA6, 0x51, 0xCF, + 0xE1, 0x8F, 0xB3, 0xE1, 0x5D, 0x32, 0xF1, 0x0C, 0xDB, 0x6A, 0x2F, 0x34, 0xC3, 0x12, 0x60, 0xD2, 0x0D, 0x77, 0x69, 0x6A, 0x20, 0x83, 0xA9, 0x49, 0x32, 0xF1, + 0x7C, 0xB3, 0x20, 0xD6, 0xEA, 0x20, 0x07, 0x1B, 0x22, 0x69, 0xE9, 0x86, 0xC3, 0x5A, 0x9D, 0xA2, 0x1C, 0x56, 0x0B, 0x2B, 0x17, 0x6D, 0x16, 0x5D, 0x96, 0x6D, + 0x11, 0x81, 0x00, 0xB1, 0xA3, 0xB5, 0xA3, 0x2D, 0xB1, 0x01, 0xFE, 0xDD, 0x6C, 0xB2, 0x30, 0x2C, 0x66, 0x54, 0xA7, 0x4A, 0xAF, 0xDF, 0x59, 0xDE, 0xE4, 0xA8, + 0xB2, 0x37, 0xC4, 0x7F, 0x9B, 0x8D, 0x96, 0x9A, 0xAE, 0x1B, 0xD6, 0xEC, 0x54, 0x39, 0x16, 0xA2, 0xB0, 0x1D, 0x9D, 0x38, 0x2D, 0x47, 0xD3, 0x8D, 0x95, 0x7B, + 0xAA, 0xF4, 0x45, 0x6D, 0x16, 0x9A, 0x33, 0x03, 0x5A, 0x3C, 0x1B, 0x88, 0x6D, 0xA9, 0x42, 0x4A, 0x78, 0x13, 0xC7, 0x98, 0xCD, 0x3D, 0x50, 0xE9, 0x46, 0x9B, + 0xA4, 0xD0, 0xB8, 0x0B, 0xE5, 0xE9, 0x33, 0x53, 0x6E, 0x62, 0xA9, 0x69, 0xA6, 0x31, 0xB3, 0x5A, 0x86, 0x47, 0x16, 0xC0, 0x8E, 0xEB, 0x39, 0xC4, 0x9B, 0xCC, + 0xB3, 0x48, 0x99, 0x1A, 0xB3, 0x95, 0x43, 0x04, 0x84, 0x04, 0x72, 0xCB, 0x60, 0x18, 0x6E, 0x6E, 0xDE, 0x6A, 0xAD, 0xC9, 0xF8, 0x8B, 0xE1, 0xB5, 0xB8, 0x4C, + 0xC6, 0x64, 0x6A, 0x3B, 0x44, 0xD8, 0xD2, 0x6F, 0x61, 0xDA, 0x93, 0x2F, 0x2D, 0xD7, 0xD3, 0x1C, 0x4F, 0x06, 0xA1, 0x36, 0xF5, 0x88, 0x93, 0x8F, 0x8F, 0xA0, + 0x55, 0xE4, 0x63, 0x4B, 0xEF, 0x96, 0x37, 0x30, 0x2C, 0xD3, 0xB0, 0x88, 0x3C, 0x79, 0x69, 0xFD, 0xC6, 0xD1, 0xB1, 0x56, 0x12, 0x8A, 0x31, 0x16, 0xB3, 0x2C, + 0x2B, 0xA1, 0xBC, 0x6E, 0x76, 0xC6, 0xFD, 0x46, 0xED, 0x74, 0xFE, 0x63, 0xF3, 0xE6, 0x9C, 0x30, 0x33, 0xD5, 0x56, 0x9E, 0x5D, 0xDD, 0x23, 0x36, 0xDC, 0x2A, + 0xC1, 0xC7, 0x7F, 0x2E, 0x88, 0x6E, 0x68, 0x4A, 0x23, 0xE2, 0xCE, 0xC7, 0x1D, 0xB0, 0xA9, 0xA6, 0xA2, 0x59, 0xBA, 0xD2, 0xB0, 0x1D, 0x03, 0x1C, 0x41, 0xA3, + 0xE1, 0xC6, 0x84, 0x2B, 0x30, 0x70, 0x2C, 0x49, 0x53, 0xC0, 0x72, 0x86, 0xCF, 0x44, 0x25, 0x22, 0x76, 0x1B, 0xFC, 0x49, 0x84, 0x1C, 0xFC, 0xE5, 0x3A, 0x90, + 0x80, 0x47, 0x8A, 0x3E, 0x4B, 0x5F, 0x51, 0x0A, 0xD3, 0x74, 0x86, 0xBF, 0x85, 0x76, 0xD3, 0xCA, 0xD4, 0x9D, 0xDF, 0xC8, 0xD7, 0x21, 0x0C, 0xB3, 0x93, 0x06, + 0x34, 0xBD, 0x9E, 0x2B, 0x2D, 0x05, 0xA3, 0x64, 0x53, 0x0C, 0xC3, 0x91, 0x8A, 0x55, 0x8E, 0xBF, 0xA8, 0x51, 0x14, 0x60, 0x57, 0xCC, 0x6A, 0x18, 0x3B, 0xD8, + 0x3F, 0x91, 0x0D, 0x31, 0x4E, 0x52, 0xA3, 0x08, 0xFE, 0xE4, 0x23, 0x49, 0x88, 0x2C, 0x37, 0x9A, 0x08, 0x10, 0xA7, 0x47, 0x94, 0x0D, 0xBC, 0x69, 0xDE, 0x2D, + 0xC0, 0x9A, 0x4D, 0x82, 0x6C, 0x74, 0x11, 0x20, 0xCE, 0xA2, 0x21, 0x37, 0xCA, 0xE0, 0xEF, 0x4E, 0x22, 0xDF, 0xF8, 0x66, 0xBC, 0xF2, 0x3C, 0xDB, 0x72, 0x2B, + 0x0D, 0x51, 0x69, 0x7E, 0xF6, 0xE7, 0xCA, 0xF5, 0x8C, 0xE9, 0x6D, 0x8B, 0xBB, 0x34, 0xF8, 0xD9, 0x52, 0x83, 0x14, 0x72, 0x4C, 0xBC, 0x35, 0x21, 0xD9, 0xE9, + 0x86, 0xA5, 0x5D, 0x43, 0xDC, 0x99, 0xCD, 0x4C, 0x91, 0xED, 0x4D, 0x56, 0x8E, 0x8B, 0x79, 0xDB, 0xD2, 0x36, 0x00, 0xB1, 0xB3, 0xD9, 0x71, 0xDC, 0x07, 0x25, + 0x3B, 0x6A, 0x4D, 0xC6, 0x82, 0xBE, 0xEC, 0x95, 0x87, 0x32, 0x16, 0x6A, 0xC2, 0x06, 0x76, 0x0C, 0xEF, 0x56, 0x78, 0x8F, 0x7B, 0xA2, 0xE0, 0x8E, 0xEF, 0x82, + 0x99, 0xC3, 0x42, 0x9C, 0xAE, 0xD3, 0xC9, 0x9C, 0x4C, 0xBE, 0x10, 0xFD, 0x69, 0x6E, 0x1A, 0x96, 0x97, 0x1E, 0xB6, 0x0D, 0x6B, 0xB9, 0xF2, 0x5A, 0x98, 0x4E, + 0x2D, 0x77, 0xA2, 0x73, 0x6A, 0x90, 0x3E, 0x8B, 0xDD, 0x6E, 0x56, 0x52, 0x31, 0x58, 0xDE, 0x64, 0x0B, 0x21, 0x4A, 0xEC, 0xC8, 0xD4, 0xC6, 0xC4, 0xCC, 0x22, + 0x99, 0x3B, 0x43, 0x4A, 0xD8, 0xE5, 0xB1, 0x2A, 0x3D, 0x77, 0xA3, 0x94, 0x85, 0x83, 0x57, 0xFF, 0xE8, 0x3F, 0xA4, 0xE5, 0x48, 0x8F, 0x0F, 0x62, 0x97, 0x5C, + 0x62, 0x82, 0x83, 0x25, 0xAE, 0x2D, 0xB5, 0xD4, 0x64, 0x1C, 0x5A, 0xAC, 0x81, 0xAA, 0xCC, 0x2E, 0x1D, 0xCD, 0x9A, 0x11, 0x88, 0x0E, 0x37, 0x07, 0xFE, 0x61, + 0xF6, 0x54, 0x41, 0x4A, 0x20, 0x18, 0xBC, 0x07, 0xD9, 0x53, 0x13, 0x16, 0x22, 0x0E, 0x94, 0x36, 0x3B, 0x28, 0x91, 0xA7, 0x44, 0x34, 0x9E, 0x49, 0x88, 0x2A, + 0xB4, 0x17, 0x96, 0xAA, 0x08, 0x7D, 0x29, 0x6E, 0x6D, 0xC2, 0xD4, 0x3F, 0x37, 0x58, 0xF8, 0x93, 0xC0, 0xE9, 0x34, 0x6F, 0x1A, 0x39, 0x9D, 0xF6, 0x3A, 0xBD, + 0x7E, 0x6E, 0x2E, 0x25, 0xE4, 0x32, 0x31, 0x95, 0x14, 0x04, 0x93, 0x20, 0xD0, 0xE4, 0xEB, 0xE2, 0x74, 0x6E, 0x5F, 0x13, 0x47, 0xA0, 0x88, 0x04, 0xB9, 0xFD, + 0x93, 0xBE, 0x2E, 0x81, 0x4D, 0x83, 0xA1, 0xE0, 0x5A, 0x14, 0x68, 0xE3, 0xE8, 0xBA, 0xEA, 0xA4, 0x9B, 0x69, 0xA1, 0x0C, 0x5D, 0x1B, 0xAC, 0x41, 0x1B, 0x9B, + 0x44, 0xCF, 0x88, 0xDC, 0x3A, 0x99, 0x6A, 0x2B, 0xD3, 0xCB, 0x91, 0xB7, 0xD6, 0xC1, 0x7F, 0x59, 0x3D, 0x52, 0xF7, 0xFA, 0x0D, 0x6B, 0x20, 0xE7, 0xD4, 0x25, + 0x7E, 0x17, 0xF4, 0xE9, 0x0F, 0xAB, 0xDA, 0x72, 0x49, 0x34, 0x68, 0x35, 0x21, 0x69, 0xB3, 0x55, 0xA9, 0x74, 0x5A, 0x1C, 0xD3, 0xA4, 0xE6, 0xA8, 0xB9, 0xA6, + 0x18, 0x24, 0x4A, 0x85, 0x78, 0x3E, 0x9D, 0xDA, 0x93, 0x95, 0x68, 0x04, 0x97, 0x33, 0xA9, 0x4D, 0x7C, 0xA7, 0xBE, 0xC8, 0x5C, 0xD3, 0xA0, 0x86, 0xBD, 0xB2, + 0x2C, 0xD4, 0x68, 0xCB, 0x73, 0x80, 0x4D, 0x41, 0x47, 0x72, 0x82, 0x2B, 0xE5, 0x9D, 0x31, 0xC1, 0xA6, 0xD5, 0x69, 0x12, 0x0E, 0x28, 0x08, 0x14, 0x41, 0x0C, + 0x51, 0x5C, 0x1B, 0x98, 0xF2, 0x51, 0x55, 0x93, 0x8B, 0x37, 0x5F, 0x2D, 0x44, 0x39, 0x83, 0xDF, 0x99, 0x0A, 0x03, 0x1C, 0xEB, 0xCE, 0x99, 0x8D, 0xB5, 0x46, + 0xE7, 0xA0, 0x73, 0xD0, 0x83, 0xFF, 0x04, 0xB9, 0x7B, 0xB6, 0x71, 0x71, 0xF1, 0xA6, 0x58, 0x5E, 0x22, 0xF8, 0xE4, 0x97, 0x50, 0xD2, 0xC2, 0x58, 0xAE, 0x2E, + 0xE4, 0x3D, 0x29, 0x5E, 0x4B, 0x51, 0xDB, 0x39, 0x23, 0x4C, 0x8A, 0x49, 0x17, 0x37, 0x44, 0x81, 0xB5, 0x14, 0x55, 0xF1, 0xC2, 0xFE, 0x77, 0x8B, 0x0D, 0xAF, + 0xFF, 0xE7, 0xAD, 0x3D, 0x22, 0x8A, 0xBF, 0xB5, 0xA5, 0x17, 0x96, 0x8B, 0x7B, 0xDF, 0xB6, 0xD1, 0x49, 0xD7, 0x7A, 0x8B, 0xE7, 0x33, 0x40, 0xA1, 0x05, 0x19, + 0xA7, 0x03, 0x13, 0xAF, 0xD4, 0x9C, 0x27, 0xD2, 0xA6, 0x84, 0x0C, 0xA6, 0x86, 0x69, 0xB6, 0x4C, 0x7B, 0x9D, 0x9F, 0x89, 0x64, 0x5B, 0xF2, 0x86, 0x9D, 0xE6, + 0x9B, 0x7C, 0x59, 0x6A, 0x57, 0x10, 0xB9, 0xFE, 0x12, 0xD4, 0xFE, 0xBD, 0x1D, 0x2E, 0xD3, 0x35, 0xCA, 0x0D, 0x14, 0x25, 0xEC, 0xB1, 0x5A, 0x47, 0x52, 0xA6, + 0xC4, 0x32, 0xC1, 0xCC, 0x59, 0x9D, 0xBB, 0x36, 0xBC, 0xC9, 0xBC, 0xC4, 0xA4, 0x6A, 0x69, 0xBB, 0x06, 0x5B, 0xBE, 0x71, 0x88, 0xA9, 0x61, 0x06, 0x5F, 0x6A, + 0x36, 0x9E, 0x3B, 0x31, 0x89, 0x82, 0xCB, 0x70, 0x42, 0x45, 0xF7, 0x70, 0x2A, 0x29, 0x6D, 0x96, 0x3B, 0xA4, 0xC7, 0x6A, 0xB1, 0x59, 0xE7, 0xA4, 0xFB, 0x71, + 0xCF, 0x10, 0x37, 0x2A, 0x10, 0xD1, 0xFD, 0xA0, 0x3D, 0x73, 0xC8, 0xAD, 0x04, 0x33, 0x07, 0xFC, 0xEF, 0x29, 0xAB, 0x95, 0x96, 0x2F, 0x02, 0xD0, 0x01, 0x80, + 0x5B, 0x51, 0xBB, 0xEF, 0x4A, 0x74, 0x9D, 0xDE, 0xA5, 0x8C, 0x3D, 0x06, 0x95, 0xC0, 0x5A, 0x4D, 0x22, 0xDC, 0x64, 0x0C, 0xA1, 0x62, 0x53, 0xF5, 0x47, 0x5F, + 0xE1, 0x4D, 0x93, 0x4C, 0xBD, 0x94, 0x85, 0x0E, 0x9A, 0xA7, 0xF6, 0xB2, 0xA3, 0x5B, 0x2B, 0x52, 0x27, 0xC8, 0x8D, 0x1C, 0x41, 0xC1, 0x2E, 0xDD, 0xFA, 0x84, + 0x98, 0x31, 0x7A, 0x16, 0x46, 0x9E, 0xAE, 0x12, 0x3F, 0x7D, 0xA6, 0x6A, 0x86, 0x36, 0x0B, 0x3E, 0xE4, 0x83, 0x7A, 0xC8, 0x2F, 0x8D, 0xEE, 0x50, 0xB8, 0x8E, + 0x90, 0xD1, 0x38, 0x8B, 0x34, 0x56, 0xF1, 0x92, 0x1A, 0xB2, 0x52, 0x27, 0xC8, 0xD1, 0x58, 0x24, 0x54, 0x54, 0xB6, 0x57, 0x66, 0x45, 0x98, 0xCD, 0x1A, 0x4D, + 0xA6, 0xB1, 0x1B, 0x0B, 0x0D, 0xD2, 0x5E, 0x34, 0x57, 0x0D, 0x30, 0x8A, 0xF4, 0x27, 0x63, 0xEE, 0x91, 0x7A, 0xA2, 0x3A, 0xEC, 0xE4, 0x74, 0x39, 0x31, 0x6D, + 0x37, 0xDB, 0xAF, 0xB4, 0x31, 0xC8, 0x6F, 0xE5, 0x09, 0x3A, 0xE2, 0x55, 0x4D, 0x61, 0xE5, 0x89, 0x1A, 0xB7, 0xF0, 0x8E, 0xD4, 0xD0, 0x9D, 0xE9, 0x53, 0xD9, + 0xEE, 0x98, 0x90, 0xB9, 0xDA, 0x11, 0x46, 0xDA, 0xCC, 0xFA, 0x9B, 0x47, 0x6E, 0x60, 0xBE, 0x89, 0x6B, 0x75, 0xA7, 0xCA, 0x84, 0x88, 0xC3, 0x68, 0x6C, 0x90, + 0x53, 0x65, 0x8A, 0x80, 0x99, 0x7A, 0x98, 0x1B, 0xBA, 0x4E, 0x32, 0xAB, 0x9C, 0x38, 0xE7, 0xCD, 0x0E, 0x95, 0x9A, 0xB0, 0x9C, 0x56, 0x40, 0x93, 0xDD, 0x74, + 0x55, 0x66, 0x0E, 0x57, 0x29, 0xA1, 0x2F, 0x26, 0x21, 0x61, 0x93, 0x48, 0x15, 0x56, 0x1C, 0x22, 0x51, 0x11, 0x3A, 0x99, 0xD8, 0x0E, 0x5B, 0xC4, 0x4D, 0x99, + 0xF8, 0x97, 0x9B, 0x59, 0x21, 0x72, 0x51, 0xE9, 0x6E, 0x27, 0xA1, 0x23, 0x73, 0xA3, 0x83, 0xBA, 0xEB, 0xB8, 0xC2, 0x87, 0xE3, 0xB4, 0x4A, 0x7A, 0x3C, 0x61, + 0xCB, 0x24, 0x55, 0x18, 0x02, 0x03, 0x35, 0xA2, 0xC8, 0x40, 0x0E, 0xD8, 0x6A, 0x53, 0xA1, 0x09, 0xAA, 0xE8, 0xD2, 0x4A, 0x9B, 0xAF, 0x36, 0xF1, 0x85, 0xC1, + 0x56, 0xDA, 0x7A, 0xCB, 0x16, 0x17, 0xDF, 0xA8, 0x05, 0x24, 0xFB, 0x4D, 0x15, 0xCD, 0x3D, 0xE5, 0x8F, 0x19, 0x44, 0x06, 0x03, 0xB1, 0xBF, 0xDD, 0x2A, 0xDE, + 0xAA, 0x6C, 0x08, 0x39, 0x3B, 0x8C, 0xEC, 0x8F, 0x3B, 0x3B, 0x0C, 0xB7, 0xF2, 0x9D, 0xE1, 0x26, 0xB9, 0xE8, 0x36, 0x3A, 0xDE, 0xCF, 0xC4, 0xD4, 0x5C, 0xF7, + 0xBC, 0x86, 0x9B, 0xBD, 0x6A, 0xF1, 0x5D, 0x75, 0x67, 0xBA, 0x71, 0xAD, 0x18, 0xFA, 0x79, 0xCD, 0xB4, 0x67, 0x76, 0xE2, 0x1E, 0xBD, 0xCF, 0xB4, 0x0C, 0xA3, + 0xFD, 0x79, 0x2D, 0xB6, 0xE2, 0x58, 0xA3, 0x50, 0xE1, 0xA5, 0xDA, 0xE8, 0xC9, 0x37, 0x27, 0x47, 0x47, 0xC3, 0x67, 0x4F, 0xAC, 0xB1, 0xBB, 0xE4, 0xFF, 0x7F, + 0x64, 0x0B, 0xB4, 0x2E, 0xF1, 0x3C, 0xB0, 0x39, 0xF7, 0xEC, 0x90, 0x62, 0x4B, 0x50, 0x70, 0x08, 0x24, 0xA4, 0x10, 0xC5, 0xB3, 0x41, 0x11, 0x5D, 0x7E, 0x13, + 0x17, 0x12, 0x9C, 0xB1, 0xE6, 0x08, 0x9A, 0xD0, 0x66, 0x6C, 0xAE, 0x41, 0x63, 0x48, 0x8D, 0x2A, 0x63, 0x6C, 0xDF, 0x24, 0x49, 0xA7, 0xDC, 0x70, 0x4D, 0xF1, + 0x56, 0x44, 0x4F, 0x43, 0x08, 0x60, 0x14, 0x1C, 0xD7, 0x59, 0xA1, 0x8D, 0xB0, 0x51, 0x4C, 0xF6, 0xD8, 0xF8, 0x66, 0x62, 0x7E, 0xF1, 0x95, 0x5E, 0xF3, 0xB5, + 0x61, 0xD9, 0x1E, 0x1B, 0x49, 0x52, 0xBA, 0x8A, 0xB1, 0xCA, 0x61, 0x22, 0xAB, 0x85, 0x8C, 0x0B, 0x10, 0x6D, 0x8B, 0x62, 0x67, 0xD7, 0xB2, 0x31, 0x51, 0x6C, + 0x11, 0x85, 0xFA, 0xC0, 0xB5, 0xD1, 0x2F, 0x17, 0x6F, 0xFF, 0xA1, 0xBC, 0x7B, 0xF3, 0x6F, 0xA1, 0x86, 0xF2, 0x88, 0xC2, 0xE0, 0x2C, 0xD1, 0x33, 0x05, 0x63, + 0xFA, 0xF0, 0x65, 0x52, 0xE3, 0x9A, 0xA1, 0x18, 0x30, 0x19, 0x32, 0x89, 0x35, 0xF3, 0xE6, 0xE7, 0x35, 0xB5, 0x86, 0xBB, 0x5B, 0xFC, 0xB3, 0x6E, 0x4D, 0xC1, + 0xC0, 0x4D, 0x0F, 0xAE, 0x35, 0x73, 0x85, 0x47, 0x1D, 0x19, 0x5E, 0x37, 0x4D, 0x4B, 0xD8, 0x8C, 0x47, 0x94, 0x40, 0xC6, 0x91, 0x08, 0x1C, 0x97, 0x72, 0x6D, + 0x74, 0x45, 0xBC, 0xB3, 0x43, 0x76, 0x2B, 0x47, 0x6B, 0xD9, 0x7D, 0x83, 0x0B, 0x33, 0x73, 0xC8, 0x32, 0xA1, 0x2C, 0xC5, 0x4F, 0x1D, 0x6D, 0x41, 0x50, 0x2A, + 0x52, 0x9A, 0x8F, 0x6A, 0x3D, 0x80, 0xAC, 0x8D, 0x3E, 0x10, 0x9A, 0x65, 0x00, 0x19, 0x52, 0x8A, 0x3F, 0xE3, 0x29, 0x7C, 0xAC, 0xFF, 0xC0, 0x9E, 0xF9, 0x92, + 0x5D, 0x4B, 0x63, 0x66, 0x2E, 0x21, 0xF7, 0xC7, 0xAD, 0x96, 0x32, 0x78, 0xF7, 0x5E, 0x69, 0xB5, 0x24, 0x1A, 0xDB, 0x4B, 0xEA, 0x4E, 0xBE, 0xFE, 0x7B, 0x35, + 0x3E, 0xA1, 0x20, 0x54, 0x3F, 0xEC, 0xA8, 0x36, 0xFA, 0xF1, 0xEA, 0x97, 0xD7, 0x2F, 0x1A, 0xDD, 0xC1, 0xB0, 0x73, 0xA3, 0x9E, 0x74, 0x3B, 0xCD, 0xB3, 0x43, + 0x06, 0x57, 0xBC, 0x83, 0x6E, 0x6D, 0xF4, 0x5E, 0xF9, 0xEE, 0xCD, 0xAB, 0x86, 0xDA, 0x39, 0xAE, 0x8C, 0x4C, 0xAD, 0x8D, 0x7E, 0xFE, 0x31, 0xA4, 0x6C, 0xD8, + 0xA9, 0x82, 0x0C, 0x4C, 0xFF, 0x47, 0xA0, 0x8B, 0xA1, 0xEA, 0xF7, 0x0B, 0xA1, 0x42, 0x91, 0xF7, 0xCA, 0x89, 0x5C, 0x3D, 0x81, 0x7E, 0x29, 0x0F, 0x9D, 0xFE, + 0xF1, 0x8D, 0x3A, 0x18, 0xF6, 0xCB, 0xF3, 0xA0, 0x1E, 0xA3, 0x74, 0x81, 0x90, 0xC6, 0xF1, 0xB0, 0x5F, 0x15, 0xD7, 0x11, 0xE2, 0x02, 0x81, 0x1C, 0x75, 0x41, + 0x1E, 0xDD, 0xE3, 0x0A, 0xA2, 0x55, 0x87, 0xB5, 0x11, 0x55, 0xF9, 0x09, 0xA2, 0xEA, 0x14, 0x43, 0x85, 0xA2, 0xED, 0x96, 0x14, 0xED, 0xA0, 0x36, 0xFA, 0x09, + 0x45, 0x8B, 0x96, 0x01, 0x3C, 0x54, 0x31, 0x0F, 0xB5, 0x0F, 0x51, 0x8A, 0xE2, 0xEA, 0xA2, 0xDD, 0x76, 0xBA, 0x55, 0x44, 0xDB, 0xAB, 0x8D, 0x50, 0x1C, 0x88, + 0xE9, 0xA8, 0x8A, 0x03, 0xA8, 0xE0, 0x4D, 0x94, 0x26, 0x20, 0xE7, 0xE6, 0x68, 0x78, 0x5C, 0x01, 0x13, 0xB8, 0xD2, 0xD5, 0x27, 0x40, 0x75, 0x0C, 0x92, 0xAA, + 0xE4, 0x47, 0x2A, 0xF8, 0x11, 0x22, 0x1A, 0xF6, 0x3B, 0x37, 0xFD, 0x2A, 0x56, 0x03, 0x7E, 0xF1, 0x06, 0x11, 0x01, 0x92, 0x9B, 0x5E, 0x15, 0x29, 0x81, 0x53, + 0x5C, 0x7C, 0xFF, 0x5D, 0xA3, 0x0F, 0x9C, 0x75, 0x4F, 0x86, 0xE5, 0xF1, 0x80, 0x43, 0x00, 0x1D, 0x48, 0x4B, 0x69, 0x14, 0xE0, 0x08, 0x3F, 0x22, 0x4F, 0x88, + 0xA7, 0x5B, 0x2C, 0xC4, 0xC4, 0x11, 0x81, 0x65, 0x03, 0x3C, 0xE2, 0x28, 0x8D, 0x02, 0x0C, 0xFA, 0x0D, 0x25, 0x06, 0x11, 0xA9, 0x47, 0x15, 0x04, 0x03, 0xE6, + 0xFC, 0x23, 0x4A, 0x18, 0x90, 0x60, 0xE4, 0xAC, 0x10, 0x83, 0x6B, 0x23, 0x70, 0x0A, 0x8C, 0x36, 0xE5, 0xCD, 0x0F, 0x68, 0xA1, 0x5C, 0xA9, 0x43, 0xEA, 0xF2, + 0xE5, 0x89, 0x01, 0x3B, 0x3E, 0x19, 0xDE, 0x9C, 0x0C, 0xE5, 0x10, 0x60, 0xE6, 0x81, 0xA3, 0x65, 0x56, 0x6E, 0x92, 0x9D, 0xBA, 0x64, 0xA5, 0x25, 0xFF, 0x5A, + 0x69, 0x26, 0xCC, 0xB3, 0x0A, 0x27, 0x25, 0x1C, 0x0E, 0x64, 0xC2, 0x0E, 0xE4, 0xF2, 0x91, 0x08, 0x25, 0xC1, 0x86, 0xB7, 0xDA, 0xA8, 0x2F, 0x91, 0xF7, 0xC5, + 0x26, 0x06, 0x14, 0x36, 0x46, 0x3F, 0x4D, 0x46, 0xD1, 0xF2, 0x30, 0x0D, 0x05, 0x6F, 0xE8, 0xD5, 0x22, 0x51, 0xA3, 0x54, 0xC2, 0x23, 0xA0, 0x55, 0xBB, 0xA9, + 0x8D, 0x86, 0xBD, 0xDC, 0x44, 0xB1, 0xBC, 0x32, 0xC6, 0xB4, 0x56, 0x64, 0x11, 0xD7, 0x2D, 0xAC, 0x8F, 0x10, 0xB4, 0x36, 0x7A, 0x19, 0x1C, 0x57, 0xD1, 0x4A, + 0x2B, 0x8F, 0x53, 0x0A, 0x9B, 0xA2, 0x96, 0x08, 0x39, 0x4C, 0x33, 0xAD, 0x1E, 0x57, 0x4D, 0xA8, 0x99, 0xED, 0x2A, 0x66, 0x97, 0x7A, 0xC1, 0x69, 0xAD, 0xA3, + 0xB9, 0x5E, 0x61, 0xAD, 0xF8, 0x80, 0x30, 0x4E, 0xF0, 0xA3, 0x7B, 0xD3, 0x48, 0x40, 0xCA, 0xDF, 0x40, 0x1F, 0xAE, 0xE6, 0xAD, 0x58, 0xD5, 0xB2, 0xB0, 0x46, + 0x42, 0x50, 0x48, 0x4B, 0x82, 0xE3, 0x4A, 0x5A, 0xA9, 0x12, 0xBE, 0x22, 0xE4, 0x70, 0xBD, 0xF8, 0x21, 0xAC, 0xBF, 0x23, 0xBD, 0xE4, 0x51, 0x5B, 0x49, 0x2F, + 0x73, 0xCD, 0x59, 0x96, 0x0A, 0x5F, 0x01, 0x24, 0x68, 0xC5, 0x3F, 0xBC, 0x37, 0x57, 0x09, 0x89, 0xF9, 0x1B, 0xF8, 0x8A, 0x4E, 0x2C, 0xDB, 0x70, 0x8B, 0x57, + 0x1D, 0x38, 0x5C, 0x6D, 0xF4, 0x8A, 0xB4, 0x7E, 0xC0, 0xA3, 0x2A, 0xEA, 0x78, 0xB1, 0xF2, 0xEC, 0x0A, 0x0A, 0xF1, 0x69, 0x61, 0xEA, 0xE8, 0x70, 0x6D, 0x1C, + 0xEF, 0x48, 0x1B, 0xC7, 0x3B, 0xD4, 0x86, 0x46, 0x3E, 0x9B, 0xE4, 0x9A, 0x98, 0x85, 0xD5, 0xE1, 0x03, 0xD6, 0x46, 0x97, 0x37, 0x4B, 0xDB, 0xC5, 0x47, 0xB8, + 0xDE, 0xE2, 0x79, 0x25, 0x27, 0x19, 0x54, 0xD0, 0x49, 0x40, 0x10, 0xF7, 0x91, 0x01, 0xD7, 0xCA, 0x60, 0x47, 0x5A, 0xC9, 0xA3, 0xB5, 0x8A, 0x56, 0x66, 0x9A, + 0x61, 0x4D, 0x88, 0x61, 0xE2, 0xE3, 0x24, 0x45, 0x15, 0x13, 0x81, 0xAD, 0x8D, 0x5E, 0x87, 0x27, 0x55, 0x14, 0xD3, 0xA9, 0xA0, 0x97, 0x28, 0x3D, 0x71, 0x7F, + 0x19, 0xC0, 0x54, 0x7C, 0x47, 0xBA, 0x51, 0xD5, 0x5D, 0x8E, 0x2A, 0x4B, 0x32, 0x31, 0x34, 0xF3, 0x33, 0x99, 0x4E, 0x61, 0x1A, 0x54, 0x7C, 0x68, 0x89, 0x81, + 0xC3, 0xF8, 0xC2, 0xCE, 0x95, 0x4B, 0x7A, 0x5E, 0xB8, 0x8E, 0x9A, 0x40, 0x57, 0xBE, 0x98, 0x9A, 0x9C, 0x13, 0x0A, 0xCB, 0xA3, 0x3F, 0xD8, 0x01, 0x9D, 0xE5, + 0xA7, 0xAD, 0x3F, 0x90, 0x19, 0xDD, 0xCE, 0x50, 0x65, 0xF6, 0xFC, 0xDA, 0xD1, 0x6E, 0xE9, 0xBB, 0x21, 0xAA, 0xCC, 0xE5, 0x3F, 0x10, 0x5D, 0xF9, 0x68, 0x58, + 0xE5, 0x99, 0xE9, 0x23, 0x21, 0x84, 0x58, 0xD5, 0xB0, 0x0C, 0x60, 0x8A, 0x04, 0x07, 0xD5, 0x90, 0x0C, 0x71, 0x6D, 0x61, 0x69, 0x68, 0x0F, 0x61, 0x12, 0xAF, + 0xAD, 0xC7, 0xC5, 0x07, 0x94, 0xF5, 0x18, 0xC6, 0xE5, 0x9F, 0x5F, 0x2A, 0x97, 0x74, 0x03, 0x7E, 0xE1, 0x70, 0xC5, 0xF6, 0x06, 0xCA, 0x18, 0x7A, 0xB8, 0x84, + 0x84, 0x7D, 0x6E, 0xAC, 0xED, 0x89, 0x1D, 0x48, 0x76, 0x7D, 0x4F, 0xC0, 0x9E, 0x4F, 0x20, 0xDD, 0x4A, 0x55, 0x8B, 0x70, 0x2B, 0xC7, 0xE3, 0x0E, 0x53, 0xB1, + 0xC9, 0xBA, 0x78, 0x1A, 0x36, 0x59, 0x83, 0x9A, 0xF4, 0x6B, 0x7C, 0x36, 0x43, 0x57, 0x40, 0x5F, 0x7B, 0x51, 0x14, 0xF6, 0x7A, 0x3F, 0x8A, 0xA2, 0xFC, 0xDE, + 0xB7, 0xA2, 0xC0, 0x5A, 0x3E, 0xE3, 0x38, 0x5A, 0xC6, 0xA9, 0x28, 0x60, 0x6D, 0xF4, 0x4E, 0xB3, 0x56, 0x30, 0xC8, 0xEC, 0x4B, 0x61, 0x41, 0xC7, 0xF7, 0xE6, + 0x5E, 0x9C, 0xEF, 0xFB, 0x56, 0x1D, 0x10, 0xB2, 0xB0, 0xF5, 0xE2, 0xD3, 0x1D, 0x0E, 0xC7, 0x42, 0xE2, 0x3B, 0x38, 0x2A, 0x9C, 0x18, 0xF8, 0x18, 0x76, 0x9C, + 0x11, 0xB0, 0xA9, 0x54, 0xF9, 0x64, 0xE0, 0x6A, 0x65, 0x59, 0xB7, 0x55, 0x32, 0x81, 0x0B, 0xD3, 0x5E, 0xE9, 0xE5, 0x31, 0x40, 0x1A, 0xF0, 0xCF, 0xE9, 0xD4, + 0x98, 0x94, 0x4F, 0x24, 0x70, 0x79, 0xC1, 0x5E, 0x48, 0xC2, 0xEF, 0x78, 0xE0, 0x25, 0x93, 0x12, 0x33, 0xB9, 0x09, 0x68, 0xF1, 0xF2, 0x62, 0xAF, 0x03, 0x2F, + 0xF4, 0x79, 0x4F, 0x91, 0x01, 0xB9, 0xBD, 0xEF, 0xA0, 0x00, 0x44, 0x7C, 0xA6, 0xC6, 0x53, 0x46, 0x59, 0x0C, 0x32, 0x88, 0xE8, 0xFE, 0xF4, 0xFB, 0xBE, 0xE6, + 0x77, 0x21, 0x45, 0xF1, 0xD9, 0x1D, 0x2E, 0x81, 0x07, 0xD3, 0xBB, 0x5E, 0x77, 0xBB, 0x13, 0x3C, 0x44, 0xBE, 0x5B, 0xFD, 0x74, 0xCB, 0xA8, 0x06, 0xA2, 0xD1, + 0x0F, 0xB8, 0xCE, 0x50, 0x20, 0x60, 0x57, 0x77, 0xA4, 0xEE, 0xFD, 0x79, 0x52, 0xF7, 0x01, 0xB8, 0xD2, 0xAC, 0x44, 0xC4, 0x9B, 0x61, 0xC4, 0x7B, 0x7D, 0xB1, + 0x1F, 0x0D, 0xCD, 0xEE, 0x2D, 0xD4, 0xCD, 0xEE, 0x35, 0xD4, 0x29, 0x7C, 0x73, 0xA2, 0x2F, 0x85, 0x92, 0x19, 0x2C, 0x07, 0x64, 0xB5, 0xAC, 0x2A, 0x41, 0x4E, + 0xBD, 0xA9, 0x12, 0xE5, 0x7C, 0x32, 0xE2, 0x41, 0x6E, 0x18, 0xAE, 0x8A, 0x0C, 0xB6, 0xBB, 0xAC, 0xDB, 0xCF, 0xA3, 0xB6, 0x8A, 0xD3, 0x38, 0xDA, 0xFA, 0xF3, + 0x6C, 0xA1, 0x15, 0x56, 0x06, 0x87, 0x03, 0x5D, 0xBC, 0x7B, 0xB1, 0xCF, 0x74, 0xC1, 0xEF, 0xF7, 0x7E, 0xFC, 0x28, 0xE0, 0xFA, 0xBE, 0x63, 0x9D, 0x49, 0xAC, + 0xE2, 0xC1, 0x0E, 0x81, 0x6A, 0xA3, 0xB7, 0xC4, 0x72, 0x95, 0x0B, 0xDB, 0xE1, 0x2F, 0xE4, 0xDC, 0x8B, 0xD6, 0x68, 0xCF, 0xF7, 0xA3, 0x32, 0xC6, 0xF4, 0x7D, + 0xEB, 0x6B, 0xBE, 0x30, 0x1C, 0xC7, 0x76, 0x0A, 0xAB, 0x8C, 0xC3, 0xC1, 0xB4, 0xA2, 0xF5, 0x8E, 0x1E, 0xED, 0x45, 0x5D, 0x7E, 0xAF, 0xF7, 0xA3, 0xB1, 0x80, + 0xE7, 0xFB, 0x56, 0xDA, 0xF5, 0xD4, 0x34, 0x96, 0x85, 0x55, 0x46, 0xA1, 0x6A, 0xA3, 0x4F, 0xAD, 0xEF, 0xE0, 0xEF, 0x5E, 0xD4, 0xC5, 0x7A, 0xBC, 0x1F, 0x65, + 0x71, 0x6E, 0xEF, 0x5B, 0x55, 0xE3, 0x65, 0xF1, 0x70, 0x08, 0x30, 0xB5, 0xD1, 0xCB, 0xF7, 0xFB, 0xC9, 0xFD, 0xB0, 0x33, 0x49, 0x0D, 0x55, 0xD2, 0x07, 0x65, + 0xEA, 0xBE, 0xB5, 0xB1, 0x2E, 0xA1, 0x8D, 0x35, 0x12, 0xFE, 0xF3, 0x9E, 0xB4, 0xB1, 0x96, 0xD7, 0xC6, 0x96, 0xFD, 0x65, 0xFD, 0x10, 0xF4, 0x43, 0x9F, 0x82, + 0x1D, 0x6B, 0xC5, 0x87, 0x23, 0x1F, 0x10, 0x37, 0x8D, 0xC1, 0x91, 0xF2, 0x52, 0xDB, 0xCF, 0x80, 0x14, 0xF4, 0xBB, 0x0F, 0x17, 0x0A, 0x99, 0xDC, 0x87, 0x9E, + 0xA2, 0xCF, 0x76, 0xF1, 0xF7, 0xA3, 0xE6, 0x29, 0x84, 0x3F, 0x63, 0x44, 0x97, 0xD4, 0x89, 0xD7, 0x72, 0x3D, 0xC3, 0x34, 0x21, 0x11, 0x27, 0x9E, 0x72, 0x85, + 0x87, 0x92, 0x0F, 0x15, 0x45, 0xB0, 0xF8, 0x8F, 0x12, 0x7A, 0x0E, 0xD1, 0x16, 0xB5, 0xD1, 0x15, 0xBE, 0x39, 0x16, 0x70, 0xE1, 0x59, 0x3E, 0x32, 0xE9, 0xC7, + 0x8F, 0xE8, 0x83, 0x86, 0xF8, 0xE4, 0x60, 0xFC, 0x45, 0xCF, 0x20, 0x66, 0xF6, 0xB0, 0xF5, 0xE8, 0x8C, 0xBE, 0xB4, 0x92, 0x37, 0xA3, 0xCF, 0xD8, 0xAE, 0xF9, + 0x43, 0x93, 0x63, 0xDB, 0xD4, 0x9F, 0x45, 0x16, 0x9B, 0xAE, 0x82, 0xA7, 0x00, 0x11, 0x04, 0xF4, 0xE4, 0x63, 0xC8, 0x11, 0xF6, 0xDC, 0xF1, 0xD1, 0xB3, 0x07, + 0x35, 0xF1, 0xD5, 0x49, 0x19, 0xD2, 0x4E, 0x79, 0x62, 0xD1, 0x21, 0xB3, 0xC0, 0xF0, 0x44, 0x0F, 0xB2, 0x0A, 0x9F, 0x5F, 0xFC, 0x40, 0x66, 0x86, 0x0B, 0x34, + 0x2A, 0xA0, 0xA7, 0x43, 0xFA, 0xE8, 0x17, 0xB3, 0x2D, 0xB9, 0xC7, 0x0A, 0xA3, 0x5D, 0xF2, 0x67, 0xC6, 0x85, 0x4F, 0x89, 0x16, 0x0A, 0x57, 0xC9, 0x67, 0x3A, + 0xE3, 0x18, 0xF3, 0xAC, 0xF0, 0x71, 0xAB, 0x35, 0xEF, 0xE3, 0x43, 0x6C, 0x8A, 0xCF, 0xDA, 0xD9, 0xE1, 0xBC, 0x9F, 0xF7, 0xC4, 0x4A, 0xEE, 0x13, 0x88, 0xC0, + 0x69, 0xE9, 0x07, 0x10, 0x51, 0x4A, 0x23, 0xA0, 0xE6, 0x40, 0x79, 0xA7, 0xB9, 0x5F, 0x0E, 0x94, 0x4F, 0x38, 0x1F, 0xDF, 0xE3, 0x73, 0x88, 0x48, 0xBB, 0xA6, + 0xEB, 0x4E, 0xEA, 0xB3, 0x88, 0xFD, 0xD8, 0xB3, 0x88, 0x43, 0xFF, 0x59, 0xC4, 0x61, 0xB8, 0xF9, 0xE5, 0xA6, 0xD7, 0xE9, 0x1C, 0xCB, 0xB0, 0x2E, 0xF9, 0x3C, + 0xE2, 0x56, 0x78, 0x5A, 0x80, 0x34, 0x25, 0x79, 0xEA, 0xFB, 0x3C, 0x45, 0x36, 0x89, 0xDE, 0x4C, 0xA7, 0x0F, 0x8D, 0x23, 0x5E, 0xA6, 0x2E, 0xCF, 0x52, 0xA7, + 0xBB, 0xEF, 0x87, 0x46, 0xA9, 0x71, 0x6F, 0xEB, 0x99, 0x51, 0xDA, 0x24, 0x19, 0x0D, 0x07, 0x99, 0xC1, 0x90, 0x82, 0x30, 0xA7, 0x7F, 0xBD, 0x4D, 0xA7, 0x9F, + 0x55, 0x70, 0xFA, 0xD9, 0x86, 0xD3, 0xEF, 0xD1, 0xDB, 0x7D, 0xC2, 0xFF, 0x6E, 0x1E, 0xEF, 0xF3, 0x55, 0xC0, 0xEB, 0x85, 0x7C, 0x75, 0x3A, 0x5B, 0xF5, 0xFB, + 0x5C, 0x27, 0x09, 0x8C, 0xE1, 0xF5, 0x36, 0x9D, 0x24, 0xC5, 0x74, 0x4B, 0xD9, 0x29, 0x0F, 0x3B, 0xA3, 0xFD, 0x8C, 0x4B, 0x34, 0x9B, 0x8A, 0x2A, 0x94, 0xF7, + 0x8E, 0x8F, 0x88, 0xF5, 0xFA, 0x3C, 0x75, 0xDA, 0x86, 0x7A, 0xE4, 0x9F, 0x4F, 0x4F, 0x6D, 0xB2, 0x9D, 0xC4, 0x6C, 0x09, 0x79, 0x70, 0xE1, 0xC4, 0xEC, 0xFD, + 0xDB, 0xB7, 0xC5, 0x72, 0xB1, 0x68, 0x2F, 0x0F, 0x24, 0x17, 0xCB, 0x2C, 0x8D, 0xDC, 0x2E, 0xE1, 0x06, 0x52, 0x5D, 0xCA, 0x74, 0x43, 0xF0, 0xDA, 0xE8, 0x25, + 0x3D, 0x56, 0x22, 0x12, 0x2B, 0x64, 0xBC, 0xD2, 0x33, 0x3F, 0x0A, 0x18, 0xA9, 0x9D, 0x84, 0x24, 0x24, 0x75, 0x23, 0x89, 0x2B, 0xA3, 0x5E, 0x12, 0x61, 0x4F, + 0x9E, 0xA9, 0xCA, 0x3E, 0x41, 0x9B, 0xE4, 0xA5, 0xC2, 0x4B, 0x87, 0x94, 0x56, 0x1B, 0x87, 0xAD, 0x8D, 0xDE, 0x3B, 0x44, 0x79, 0x65, 0x5C, 0xCB, 0xF3, 0x16, + 0xD9, 0x37, 0x14, 0x20, 0x91, 0x93, 0x72, 0x72, 0x43, 0x8F, 0x70, 0x93, 0x10, 0xAE, 0xBD, 0xC9, 0xEE, 0xAE, 0x11, 0x60, 0x85, 0xB4, 0xAB, 0x5B, 0x0D, 0x43, + 0xAF, 0x36, 0xEA, 0x55, 0xC3, 0xD0, 0xAF, 0x8D, 0xFA, 0xD5, 0x30, 0x0C, 0x40, 0x0E, 0xED, 0x41, 0x35, 0x1C, 0xC3, 0xDA, 0x68, 0x58, 0x0D, 0xC3, 0x11, 0xC8, + 0xB2, 0x2A, 0x15, 0x90, 0xB9, 0x1C, 0x17, 0xC0, 0x90, 0xBF, 0xE7, 0x89, 0xB5, 0xAA, 0xEE, 0x3C, 0x8B, 0x95, 0x59, 0xDA, 0x79, 0x38, 0x6C, 0x6D, 0xF4, 0x6E, + 0x65, 0x7A, 0xC6, 0xD2, 0x34, 0x60, 0xDA, 0xDE, 0xE8, 0x2B, 0x2D, 0xA5, 0x3B, 0xE8, 0x36, 0xF7, 0x98, 0x61, 0xFA, 0x74, 0xC8, 0xBD, 0xDA, 0xA6, 0xE7, 0x27, + 0x61, 0xEA, 0x71, 0xF4, 0x11, 0xE3, 0x07, 0x11, 0xCE, 0x1C, 0xDB, 0xF6, 0x4A, 0xAB, 0xC3, 0x07, 0x86, 0x34, 0x1F, 0x8E, 0x4A, 0x47, 0xB3, 0x10, 0x4D, 0x19, + 0x43, 0x4F, 0xD9, 0xF3, 0x58, 0x31, 0x9C, 0xA9, 0xC5, 0xC2, 0xD9, 0xFE, 0xDC, 0xC7, 0xBD, 0x2D, 0x9F, 0x32, 0x70, 0x58, 0x98, 0xAD, 0xDE, 0xC2, 0x0C, 0x71, + 0x81, 0x0A, 0x53, 0x1A, 0x1D, 0x70, 0x1F, 0x75, 0xB0, 0x4F, 0xEF, 0xF1, 0xC9, 0x28, 0xF8, 0x62, 0xA8, 0xA8, 0xF7, 0x3C, 0x0C, 0xE7, 0xA1, 0xFA, 0x20, 0xA6, + 0x3E, 0x28, 0xAF, 0x11, 0x1F, 0x1A, 0xF2, 0x01, 0x7C, 0x3D, 0x57, 0x25, 0x3F, 0x8A, 0x20, 0x2B, 0xE7, 0x48, 0xD5, 0x9D, 0x46, 0xE8, 0x8A, 0x15, 0xF3, 0x82, + 0x6E, 0xE5, 0x51, 0xBD, 0xF7, 0x10, 0xC7, 0xC2, 0x25, 0xBE, 0xD1, 0x8D, 0xC8, 0xED, 0xB6, 0xA2, 0xC8, 0xA2, 0x49, 0x24, 0x83, 0xE5, 0x46, 0xC3, 0x76, 0x99, + 0xEE, 0x35, 0xF3, 0xF7, 0x09, 0xD8, 0x5C, 0xF6, 0x29, 0xBE, 0x28, 0x17, 0x61, 0x4E, 0x34, 0x11, 0x08, 0x78, 0x7D, 0x70, 0xB3, 0x00, 0x24, 0xAC, 0xF4, 0x34, + 0x80, 0x03, 0x73, 0x15, 0x06, 0x91, 0xB8, 0xA7, 0x16, 0x88, 0xC4, 0xD1, 0x19, 0x41, 0x80, 0xAF, 0xE4, 0x68, 0x77, 0xEF, 0xE9, 0x7F, 0x5F, 0x1C, 0x3C, 0x2A, + 0xBA, 0x7E, 0xC1, 0x34, 0x58, 0x80, 0x01, 0xDF, 0x17, 0xA6, 0x16, 0x49, 0xE8, 0xB7, 0x17, 0x3E, 0x22, 0x2B, 0x81, 0xD4, 0xE0, 0xE8, 0xD0, 0x4D, 0x3C, 0x36, + 0xCF, 0x2F, 0xB0, 0xFC, 0x97, 0xDA, 0x64, 0x3B, 0xD5, 0x9D, 0xB5, 0x61, 0x15, 0xAF, 0xEE, 0xFC, 0x6C, 0x58, 0xBA, 0xBD, 0x2E, 0x56, 0xE0, 0x89, 0x76, 0xF4, + 0x17, 0x28, 0xF0, 0xD0, 0xF4, 0x00, 0x97, 0x6C, 0x5B, 0x0E, 0x91, 0x7B, 0xBD, 0x45, 0x52, 0xC8, 0x0C, 0xFA, 0x06, 0x17, 0x58, 0x01, 0x85, 0xAB, 0xD0, 0x05, + 0xE0, 0x5D, 0x67, 0x6A, 0xBF, 0x9C, 0x46, 0x73, 0x35, 0x4E, 0x81, 0x5C, 0xAE, 0xD6, 0x17, 0x94, 0x9B, 0xEF, 0xBD, 0x82, 0xFE, 0xEB, 0x26, 0x3F, 0xB7, 0xF7, + 0xCE, 0xCF, 0x36, 0x06, 0x20, 0x62, 0xE9, 0xA5, 0x2D, 0x0B, 0x61, 0x43, 0xBB, 0xBA, 0xB4, 0xF4, 0xBD, 0x5A, 0x15, 0xEB, 0xBD, 0xB4, 0x0E, 0xBA, 0xC3, 0x6E, + 0xEF, 0x61, 0x99, 0x15, 0x32, 0x54, 0xC1, 0xA8, 0xD4, 0x93, 0xC1, 0x03, 0x9A, 0xD2, 0xD8, 0xD3, 0x29, 0x5B, 0xD7, 0x2C, 0x67, 0x5A, 0x1C, 0xFC, 0x86, 0x3E, + 0xB4, 0xE7, 0x92, 0xFD, 0xC6, 0xAB, 0xA0, 0xF3, 0x82, 0xA5, 0x99, 0x88, 0x2E, 0x86, 0x0F, 0xCB, 0xB4, 0x38, 0x47, 0xB2, 0xD6, 0x25, 0xE0, 0xA8, 0xFF, 0x70, + 0x4C, 0xCB, 0xB3, 0x3D, 0xCD, 0x2C, 0x6D, 0x59, 0x0C, 0x1A, 0x0C, 0xEB, 0x23, 0x1E, 0x28, 0x57, 0xC0, 0xE7, 0x5E, 0x8D, 0xCB, 0xEF, 0xBF, 0x7C, 0xE0, 0x3A, + 0xEE, 0x6F, 0x49, 0x19, 0x15, 0x58, 0xFA, 0x75, 0x93, 0xA5, 0x4A, 0xA1, 0x6B, 0xB8, 0xA5, 0x45, 0xF2, 0xAD, 0x84, 0xAE, 0x95, 0x87, 0x57, 0x4B, 0x87, 0x2E, + 0x06, 0x8E, 0xA1, 0x8B, 0x1E, 0xED, 0xDF, 0xC4, 0x02, 0x0A, 0xCA, 0xDB, 0xD8, 0xE0, 0x64, 0x9B, 0x5B, 0x60, 0xB6, 0x11, 0xC1, 0x18, 0x4F, 0x95, 0x8C, 0x6C, + 0x5B, 0x7E, 0x53, 0xD9, 0xC8, 0x26, 0x9A, 0xF4, 0x2B, 0x9F, 0x28, 0xB2, 0x68, 0x36, 0xCF, 0x60, 0x61, 0x0E, 0xC7, 0x0E, 0xF6, 0x5A, 0xB1, 0xF1, 0x3B, 0xDF, + 0xFA, 0x42, 0x6D, 0xC0, 0xD5, 0x43, 0xAA, 0xCF, 0x8C, 0x0D, 0xCB, 0x2A, 0xAB, 0x26, 0x0E, 0x5B, 0x1B, 0xBD, 0x64, 0x07, 0xFB, 0x5D, 0x52, 0xE7, 0x9D, 0x6F, + 0x7F, 0x3D, 0xDD, 0xE7, 0x6A, 0xDF, 0x6A, 0x4A, 0x14, 0x31, 0x9C, 0xE0, 0x73, 0x04, 0x35, 0xBE, 0x47, 0x35, 0xFC, 0x3C, 0xC1, 0xC3, 0x29, 0x69, 0xCC, 0xB4, + 0x05, 0x3E, 0xCB, 0x58, 0xB4, 0xA8, 0xF1, 0x1A, 0xC1, 0x8A, 0xD5, 0x34, 0xE2, 0x3D, 0x3D, 0xEC, 0xAA, 0xC6, 0x28, 0xFE, 0x12, 0x3B, 0x20, 0xBC, 0x35, 0x36, + 0x34, 0x17, 0x9F, 0xFB, 0x85, 0x63, 0xE5, 0x25, 0x1C, 0x2B, 0xEF, 0xCD, 0x55, 0xF0, 0x16, 0x4E, 0x91, 0x43, 0x44, 0xF7, 0xB3, 0x85, 0x18, 0xD2, 0x1E, 0x1F, + 0xA0, 0xDB, 0xF8, 0xF8, 0xF3, 0x1E, 0x70, 0x8C, 0xBB, 0xD7, 0x06, 0xFD, 0xE3, 0x4E, 0x4D, 0x61, 0x59, 0x31, 0x7F, 0xCA, 0xD7, 0xFD, 0x42, 0xB7, 0xB5, 0xA9, + 0x01, 0x81, 0x22, 0x07, 0x88, 0xD2, 0x1B, 0x10, 0x48, 0xED, 0xB7, 0xCA, 0x6E, 0xB3, 0x4D, 0x89, 0xA8, 0xBE, 0x38, 0x3A, 0x42, 0x43, 0x88, 0xBD, 0x76, 0x8F, + 0xB5, 0x8F, 0x3F, 0xAF, 0xDC, 0x1D, 0x88, 0x5E, 0x87, 0x28, 0x16, 0x84, 0x2A, 0x14, 0x04, 0xEE, 0xEE, 0xDB, 0x2E, 0x4F, 0x5D, 0x9F, 0x27, 0x55, 0x8E, 0xA7, + 0x6E, 0x05, 0x9E, 0xBA, 0x7B, 0xE2, 0xA9, 0xE7, 0xF3, 0xD4, 0x95, 0xE3, 0xA9, 0x57, 0x81, 0xA7, 0xDE, 0x9E, 0x78, 0xEA, 0xFB, 0x3C, 0xF5, 0xE4, 0x78, 0xEA, + 0x57, 0xE0, 0xA9, 0xBF, 0x27, 0x9E, 0x06, 0x3E, 0x4F, 0x7D, 0x39, 0x9E, 0x06, 0x15, 0x78, 0x1A, 0xEC, 0x89, 0xA7, 0xA1, 0xCF, 0xD3, 0x40, 0x8E, 0xA7, 0x61, + 0x05, 0x9E, 0x86, 0x7B, 0xE2, 0xE9, 0xC8, 0xE7, 0x69, 0x28, 0xC7, 0xD3, 0x51, 0x05, 0x9E, 0x8E, 0xF6, 0xC4, 0xD3, 0xB1, 0xCF, 0xD3, 0x91, 0x1C, 0x4F, 0xC7, + 0x15, 0x78, 0x3A, 0xDE, 0x13, 0x4F, 0x27, 0x3E, 0x4F, 0xC7, 0x72, 0x3C, 0x9D, 0x54, 0xE0, 0xE9, 0x64, 0x4F, 0x3C, 0xE1, 0x6E, 0x2A, 0xC6, 0xD4, 0x89, 0xE4, + 0xA0, 0xDB, 0xA9, 0xC0, 0x95, 0xB6, 0x2F, 0xAE, 0x82, 0x54, 0x42, 0x95, 0xCD, 0x25, 0xAA, 0x24, 0x13, 0xE3, 0x7D, 0xB1, 0x15, 0x66, 0x13, 0x92, 0xE9, 0x84, + 0x5A, 0x25, 0x9F, 0x98, 0xEC, 0x8B, 0xAD, 0x20, 0xA1, 0x50, 0x25, 0x33, 0x0A, 0xB5, 0x4A, 0x4A, 0xA1, 0xEF, 0x8B, 0xAD, 0x20, 0xA7, 0x50, 0x25, 0x93, 0x0A, + 0xB5, 0x4A, 0x56, 0x41, 0xF6, 0xC5, 0x56, 0x90, 0x56, 0xA8, 0x92, 0x79, 0x85, 0x5A, 0x25, 0xB1, 0x98, 0xEE, 0x8B, 0xAD, 0x20, 0xB3, 0x50, 0x25, 0x53, 0x0B, + 0xB5, 0x42, 0x6E, 0x71, 0x22, 0x9E, 0x88, 0x6D, 0x95, 0x2D, 0xE2, 0xF1, 0x29, 0x72, 0x38, 0x69, 0x93, 0x7A, 0xE0, 0x88, 0x03, 0xE1, 0x13, 0x71, 0x4C, 0x20, + 0x17, 0xB6, 0x35, 0x35, 0x66, 0x41, 0x91, 0xE1, 0xC1, 0x3C, 0x1B, 0xE3, 0x46, 0xDE, 0xFF, 0x29, 0x5D, 0x68, 0xB8, 0x7A, 0x75, 0x59, 0xAC, 0xCC, 0x10, 0xED, + 0xE5, 0x2F, 0x54, 0x64, 0x00, 0xB2, 0xBB, 0xD1, 0x97, 0x91, 0x4B, 0xD5, 0x15, 0x28, 0x50, 0x91, 0x8A, 0xC2, 0x20, 0x5A, 0x51, 0x18, 0x4A, 0x57, 0x14, 0x18, + 0x71, 0xBB, 0xA9, 0x25, 0x00, 0xEE, 0x1E, 0x7B, 0x83, 0xBA, 0x3C, 0xD3, 0xBD, 0xF2, 0x4C, 0x0F, 0x8A, 0x30, 0xDD, 0x2B, 0xC3, 0x74, 0x89, 0x67, 0x5A, 0x25, + 0xE5, 0x04, 0xF4, 0x7E, 0x67, 0xDC, 0x10, 0x5D, 0xF9, 0x55, 0x5E, 0x54, 0x6A, 0x79, 0x51, 0x1D, 0x15, 0x11, 0x95, 0xBA, 0x43, 0xFB, 0x18, 0xF8, 0x7C, 0xFF, + 0x24, 0xCF, 0xF7, 0xA0, 0x3C, 0xDF, 0xBD, 0x22, 0x7C, 0x0F, 0x76, 0xC8, 0x77, 0xDF, 0xE7, 0xFB, 0x93, 0x3C, 0xDF, 0xFD, 0xF2, 0x7C, 0xF7, 0x8B, 0xF0, 0xDD, + 0xDF, 0x21, 0xDF, 0xF8, 0xB5, 0xDA, 0x9F, 0x3E, 0x29, 0x1F, 0xE7, 0x0E, 0x71, 0xE7, 0xF9, 0x95, 0x38, 0x06, 0x51, 0x76, 0x6C, 0x1F, 0xEC, 0x61, 0xEE, 0x86, + 0x14, 0xF6, 0xA2, 0x3C, 0xE5, 0xE6, 0xCD, 0x0C, 0x42, 0xE6, 0x13, 0x25, 0x62, 0x9E, 0xC4, 0x33, 0x37, 0x55, 0x96, 0xA9, 0xDD, 0xC5, 0xB0, 0xE3, 0xDA, 0xE8, + 0xCD, 0xAA, 0xC0, 0xF8, 0x76, 0x5C, 0xDE, 0x9E, 0xE5, 0x2B, 0xE6, 0x8C, 0xAE, 0x9D, 0xD9, 0xF3, 0x09, 0xE5, 0x19, 0xF2, 0x32, 0x57, 0x42, 0xED, 0xE5, 0xAB, + 0x10, 0x83, 0x3D, 0x54, 0xC9, 0x31, 0xD2, 0x1F, 0x31, 0x76, 0x7E, 0x42, 0x86, 0x14, 0xC8, 0x58, 0x0A, 0x0C, 0x46, 0x47, 0x05, 0xB5, 0x79, 0x5C, 0x32, 0x3A, + 0x21, 0x8D, 0x3B, 0x53, 0x27, 0x4E, 0x3D, 0x50, 0x00, 0x9F, 0x4A, 0x08, 0x60, 0x58, 0x5E, 0x00, 0x85, 0x32, 0x17, 0xA4, 0x71, 0x77, 0x02, 0xE8, 0x30, 0x01, + 0x5C, 0x85, 0xEF, 0xC0, 0xCD, 0x30, 0xE8, 0x0A, 0x15, 0xA8, 0xC1, 0x1E, 0xD6, 0x48, 0x30, 0xD2, 0xAA, 0xBE, 0x45, 0x03, 0x47, 0xC5, 0x14, 0xDA, 0x2D, 0x9A, + 0x5F, 0x89, 0x8B, 0x9F, 0x12, 0xF9, 0xF7, 0x2E, 0x13, 0xAC, 0x6E, 0xC7, 0xB7, 0xE8, 0xE2, 0x02, 0xE8, 0x94, 0x17, 0x80, 0x5A, 0x48, 0x00, 0x9D, 0x87, 0x95, + 0x8C, 0x0F, 0x37, 0x3F, 0x5B, 0x9A, 0x2F, 0xAD, 0xA2, 0xEE, 0x1F, 0x19, 0xCD, 0xBA, 0x45, 0x84, 0xB5, 0x53, 0xEF, 0xEF, 0x85, 0x9C, 0x2B, 0xBF, 0x2A, 0xF1, + 0xAD, 0xAF, 0x59, 0x71, 0xA0, 0x7C, 0x11, 0x70, 0xB0, 0x87, 0xF5, 0x2A, 0xA4, 0xF0, 0x44, 0xC0, 0x59, 0xC1, 0x00, 0x7F, 0x52, 0xDE, 0x1D, 0x0A, 0x69, 0x18, + 0x69, 0xDD, 0x9D, 0x8A, 0x07, 0x31, 0x41, 0xB0, 0x4F, 0x26, 0xCB, 0xA8, 0xB8, 0x7C, 0xE5, 0x70, 0xB0, 0x87, 0xA5, 0x2E, 0xA4, 0xF0, 0x58, 0xC0, 0x59, 0x41, + 0x15, 0x17, 0x4D, 0x49, 0x8F, 0x4B, 0x4E, 0x2D, 0xD5, 0x5D, 0xE6, 0xA4, 0x58, 0xED, 0x8E, 0x08, 0x22, 0xFA, 0x3E, 0xFB, 0x2C, 0x05, 0x97, 0xAF, 0x78, 0x0F, + 0x2A, 0xAE, 0xCF, 0xEE, 0x2E, 0x92, 0x1F, 0x89, 0x3E, 0x76, 0x9C, 0x6F, 0x07, 0x45, 0x73, 0xD9, 0x4E, 0xC9, 0x81, 0x6F, 0xA7, 0xA9, 0x2C, 0xF4, 0x0E, 0x59, + 0xCF, 0x26, 0xF7, 0x19, 0x26, 0x50, 0x7E, 0xE5, 0x6D, 0xB0, 0x87, 0xED, 0x21, 0x48, 0x61, 0xB7, 0x36, 0xFA, 0x54, 0x90, 0xA9, 0x2A, 0xF5, 0x83, 0xD2, 0xFB, + 0x43, 0xF6, 0x57, 0x7A, 0x9F, 0x2C, 0x6E, 0x8A, 0x97, 0xDE, 0x2F, 0xDE, 0xFD, 0x52, 0xAC, 0xF4, 0x1E, 0xED, 0x65, 0x7F, 0xA5, 0xF7, 0x72, 0x36, 0x53, 0x68, + 0xA3, 0x2C, 0x30, 0x86, 0xAF, 0x42, 0x9A, 0x18, 0x2E, 0xED, 0x12, 0x04, 0xA3, 0xBC, 0xF7, 0x4F, 0x03, 0x11, 0x45, 0x9E, 0x51, 0x8E, 0xB7, 0xCF, 0xB2, 0x9E, + 0x5E, 0x46, 0x58, 0x28, 0xF5, 0x0C, 0x2F, 0xBE, 0x50, 0x67, 0xC8, 0x3F, 0xF9, 0x53, 0xE1, 0x59, 0xE0, 0xB4, 0x77, 0x8D, 0xB4, 0x8F, 0x0A, 0xE2, 0xDE, 0xF9, + 0x2B, 0x06, 0x46, 0x09, 0x45, 0xA9, 0x54, 0x3F, 0x2A, 0x9E, 0x4B, 0xD7, 0xC9, 0x29, 0x58, 0x91, 0x68, 0xDE, 0x8B, 0x96, 0x5A, 0xE4, 0xA3, 0x39, 0x23, 0x6F, + 0x37, 0xD1, 0x1C, 0x71, 0xC7, 0x78, 0x2F, 0x90, 0xD5, 0x30, 0xD8, 0x62, 0x02, 0x10, 0x6F, 0xA2, 0x90, 0x10, 0x40, 0x9A, 0x04, 0xB6, 0x22, 0x82, 0x2E, 0x95, + 0x40, 0x37, 0xA1, 0xFD, 0x94, 0xC0, 0x4F, 0xDB, 0x97, 0x8D, 0xFB, 0xBD, 0x3D, 0xD4, 0x26, 0x50, 0x5C, 0x31, 0x8E, 0x0A, 0xEA, 0xB4, 0xD8, 0xE2, 0x60, 0x4C, + 0xA7, 0xC5, 0x8C, 0x7A, 0x67, 0xAB, 0x83, 0x80, 0xBC, 0x47, 0x05, 0xD0, 0x93, 0x56, 0x69, 0xF9, 0x69, 0x66, 0x6F, 0x0F, 0xF9, 0x09, 0x4A, 0x2B, 0xC6, 0x51, + 0x41, 0x95, 0x16, 0x5B, 0xFA, 0x8C, 0xA9, 0x54, 0x7E, 0x7E, 0xC9, 0x89, 0xDC, 0x99, 0x4A, 0xFB, 0x54, 0x00, 0x7D, 0x69, 0x95, 0x96, 0x9F, 0x75, 0xF4, 0xF6, + 0xB0, 0x7B, 0x17, 0xA5, 0x15, 0xE3, 0xA8, 0xA0, 0x4A, 0x8B, 0x2D, 0xD9, 0xC5, 0x54, 0x2A, 0x3F, 0x9F, 0xE4, 0x44, 0xEE, 0x4C, 0xA5, 0x03, 0x2A, 0x80, 0x81, + 0xB4, 0x4A, 0xCB, 0x57, 0x0A, 0x7A, 0x7B, 0x28, 0x06, 0xA1, 0xB4, 0x62, 0x1C, 0x15, 0x54, 0x69, 0xB1, 0xD5, 0xE7, 0x98, 0x4A, 0xE5, 0xD7, 0x39, 0x38, 0x91, + 0x3B, 0x53, 0xE9, 0x90, 0x0A, 0x60, 0x28, 0xAD, 0xD2, 0xF2, 0xFB, 0xAB, 0x7A, 0x7B, 0xD8, 0xBB, 0x8D, 0xD2, 0x8A, 0x71, 0x54, 0x50, 0xA5, 0xC5, 0x4A, 0xB7, + 0x31, 0x95, 0xCA, 0xAF, 0xDC, 0x70, 0x22, 0x77, 0xA6, 0xD2, 0x23, 0x2A, 0x80, 0x23, 0x69, 0x95, 0x96, 0xDF, 0xBA, 0xDE, 0xDB, 0x43, 0x3D, 0x0F, 0xA5, 0x15, + 0xE3, 0xA8, 0xA0, 0x4A, 0x8B, 0x55, 0x70, 0x62, 0x2A, 0x95, 0xDF, 0x3B, 0xC5, 0x89, 0xDC, 0x99, 0x4A, 0x8F, 0xA9, 0x00, 0x8E, 0xA5, 0x55, 0x5A, 0x7E, 0xE7, + 0x7E, 0x6F, 0x0F, 0x3B, 0xF7, 0x51, 0x5A, 0x31, 0x8E, 0x0A, 0xAA, 0xB4, 0x58, 0x6D, 0x36, 0xA6, 0x52, 0xF9, 0xED, 0x4E, 0x9C, 0xC8, 0x9D, 0xA9, 0xF4, 0x84, + 0x0A, 0xE0, 0x44, 0x5A, 0xA5, 0xE5, 0xB7, 0x0C, 0xF4, 0xF6, 0xB0, 0xF9, 0x05, 0xA5, 0xD5, 0x89, 0x72, 0x54, 0x50, 0xA5, 0xC5, 0x16, 0x18, 0x7B, 0x29, 0x5B, + 0x5F, 0x24, 0x54, 0x9A, 0xB6, 0xC0, 0xF8, 0x00, 0xEA, 0x77, 0xDA, 0x7A, 0x5C, 0xE2, 0x83, 0x3F, 0x2F, 0x7E, 0x7E, 0x99, 0x5E, 0xD8, 0x4F, 0xAD, 0xE2, 0xC5, + 0xFA, 0x7A, 0xE8, 0x65, 0xBC, 0xA8, 0xBC, 0x90, 0x70, 0x35, 0xF8, 0x14, 0xF9, 0x06, 0xF3, 0xD9, 0x96, 0xC6, 0x80, 0x0B, 0x58, 0x5A, 0xAF, 0xDF, 0x11, 0x27, + 0x2D, 0x39, 0x96, 0xC6, 0xA9, 0xDC, 0x4D, 0xF0, 0x40, 0xE4, 0x30, 0x17, 0x47, 0xDE, 0x3F, 0x48, 0xAD, 0xE9, 0x30, 0x80, 0x78, 0xF8, 0xE8, 0x77, 0x4E, 0x24, + 0xE3, 0x07, 0xC8, 0x20, 0x6D, 0x63, 0xFC, 0x16, 0x03, 0x08, 0xD2, 0xD8, 0x63, 0x4C, 0xBD, 0x96, 0x66, 0x2A, 0x59, 0x05, 0x28, 0xC4, 0x54, 0x5A, 0x65, 0x67, + 0xCB, 0x4C, 0xF5, 0x19, 0x53, 0x19, 0x4E, 0x9A, 0x60, 0x2A, 0x39, 0x0F, 0x2E, 0xC4, 0x54, 0xDA, 0x44, 0x38, 0x64, 0xEA, 0x21, 0x04, 0x3A, 0x32, 0xA1, 0xDF, + 0x28, 0x2F, 0x1C, 0xEA, 0x2E, 0x2F, 0x0E, 0x5F, 0xBC, 0xBE, 0x50, 0xE8, 0x92, 0xA6, 0x6D, 0x16, 0x8C, 0x78, 0xF1, 0x4E, 0xFF, 0x52, 0x31, 0x8F, 0x92, 0x1E, + 0x89, 0x7A, 0xE1, 0x87, 0xE4, 0xF3, 0x02, 0x1E, 0x87, 0x2C, 0x12, 0xF2, 0x06, 0x9D, 0x5E, 0x99, 0x0A, 0x61, 0x40, 0xE4, 0x8E, 0x82, 0x1E, 0x45, 0xDF, 0x0D, + 0x65, 0x70, 0x59, 0x4C, 0x06, 0x85, 0xAA, 0xA4, 0x71, 0x19, 0x14, 0x08, 0xFB, 0x3E, 0x91, 0xBB, 0x94, 0x01, 0x46, 0xC9, 0xCB, 0x0B, 0xE5, 0xFD, 0x3F, 0x94, + 0xCB, 0x9B, 0xA5, 0xED, 0xAE, 0x1C, 0x92, 0x1B, 0x55, 0x38, 0x5C, 0xE2, 0x4B, 0xF2, 0x83, 0x41, 0x4F, 0x36, 0xB0, 0x0C, 0xD2, 0x87, 0x80, 0x69, 0x67, 0x8B, + 0xF1, 0x92, 0x12, 0xDA, 0x0F, 0x18, 0xFC, 0x40, 0x40, 0xD3, 0x52, 0x71, 0x93, 0x03, 0xC6, 0x39, 0x54, 0x3B, 0xB8, 0xBD, 0x5A, 0x92, 0x41, 0x71, 0x46, 0xD9, + 0xDB, 0xEA, 0x70, 0x40, 0xA9, 0x1C, 0x04, 0xEC, 0x7D, 0xFA, 0x78, 0x25, 0xC7, 0x58, 0xB2, 0x8E, 0x56, 0x4C, 0x75, 0x69, 0x8F, 0x8C, 0x16, 0x1C, 0x14, 0xC4, + 0x8D, 0xCE, 0x0E, 0x21, 0xC6, 0x6E, 0xCA, 0x26, 0x45, 0x64, 0x67, 0x53, 0x63, 0x06, 0x06, 0x2B, 0x96, 0x25, 0x95, 0x21, 0x7B, 0xAB, 0x29, 0x7E, 0x12, 0xB4, + 0x35, 0x81, 0x30, 0x0F, 0xBA, 0x47, 0xEF, 0xF2, 0x25, 0xBB, 0xD0, 0x66, 0x24, 0xBC, 0xAE, 0xB0, 0x20, 0x9E, 0x15, 0x9C, 0x35, 0x86, 0x50, 0xBB, 0x26, 0xFC, + 0xFB, 0xA5, 0xCA, 0xDC, 0x21, 0xD3, 0xF3, 0xDA, 0x37, 0x01, 0x4E, 0xFE, 0xF8, 0x1D, 0x36, 0xA9, 0x29, 0xBA, 0xBD, 0xB6, 0x4C, 0x5B, 0xC3, 0xC0, 0xAF, 0x2D, + 0x3D, 0xA0, 0xB4, 0xFD, 0xE7, 0x12, 0xDF, 0x70, 0xA5, 0xE1, 0xD3, 0x5A, 0x5A, 0x46, 0x3F, 0x11, 0xF5, 0x4F, 0x4C, 0xDB, 0xF5, 0xA7, 0x6D, 0x78, 0x18, 0x7C, + 0xEF, 0xF4, 0x7F, 0xFE, 0x3B, 0x6F, 0xAB, 0x80, 0xB1, 0x98, 0x45, 0x04, 0x50, 0x53, 0x5C, 0x67, 0x72, 0x5E, 0x03, 0x4A, 0x1D, 0xDB, 0x75, 0x6D, 0xC7, 0x98, + 0x19, 0x29, 0x63, 0x73, 0x9A, 0xB4, 0x0F, 0x45, 0xE2, 0x4E, 0x34, 0x16, 0x0C, 0xFB, 0x67, 0xEE, 0xC4, 0x31, 0x96, 0xDE, 0xE8, 0x91, 0x6E, 0x4F, 0x56, 0x0B, + 0x62, 0x79, 0x6D, 0x4D, 0xD7, 0x2F, 0xAF, 0xE1, 0xE0, 0x2D, 0x7E, 0x8B, 0x0F, 0x24, 0xDF, 0xA8, 0xBF, 0xFA, 0xE7, 0x3B, 0x1C, 0x86, 0xF1, 0x1A, 0xC8, 0x8B, + 0xE8, 0xF5, 0x03, 0x65, 0xBA, 0xB2, 0xD8, 0x48, 0xD8, 0x20, 0xD8, 0xB6, 0xA9, 0x7C, 0x05, 0x8C, 0xD7, 0x9A, 0xA3, 0x8C, 0x35, 0x97, 0xBC, 0xB1, 0x5D, 0x4F, + 0x39, 0x57, 0x02, 0x8C, 0xA6, 0x3D, 0xA1, 0xFB, 0x36, 0xDA, 0x8C, 0x2F, 0xDE, 0x92, 0x31, 0xFE, 0x93, 0x63, 0x42, 0xD3, 0x00, 0xEA, 0xA9, 0x52, 0x3F, 0x3D, + 0x56, 0xEB, 0x68, 0x7F, 0x41, 0x17, 0x53, 0x02, 0x61, 0x1E, 0xDA, 0x35, 0x56, 0x8E, 0x79, 0xA0, 0x4C, 0xC6, 0xCD, 0xAF, 0x94, 0x7A, 0x7A, 0x19, 0xAF, 0x35, + 0x39, 0x33, 0x6D, 0x6F, 0x4E, 0xAC, 0x46, 0x48, 0x99, 0x43, 0xDC, 0xA5, 0x6D, 0xB9, 0x84, 0x11, 0xC7, 0x7E, 0xC6, 0x34, 0xBC, 0xDE, 0x76, 0x3D, 0xCD, 0x5B, + 0xB9, 0xCA, 0xE3, 0xF3, 0x73, 0xA5, 0xDB, 0xE9, 0x44, 0x9B, 0x29, 0xD0, 0x4D, 0xB2, 0xDD, 0x81, 0x92, 0xB8, 0xF0, 0x91, 0xDC, 0x78, 0xCD, 0x67, 0x01, 0xCC, + 0x9D, 0x42, 0x4C, 0x97, 0xC4, 0x90, 0x04, 0x00, 0xF8, 0xDE, 0xB8, 0x46, 0x33, 0x4E, 0x60, 0x43, 0xD7, 0x3C, 0xAD, 0xF9, 0x35, 0xA6, 0x2F, 0xE8, 0x15, 0x28, + 0x39, 0x50, 0xE8, 0xAD, 0x67, 0x91, 0x5B, 0x77, 0xCD, 0x36, 0xC8, 0x10, 0xF8, 0x0D, 0xA0, 0x89, 0xE3, 0xC4, 0x29, 0xA6, 0xD0, 0x2D, 0xF5, 0x40, 0xC1, 0x3B, + 0x71, 0xD8, 0x08, 0x91, 0x8F, 0xFC, 0x6B, 0xBE, 0xD0, 0xB2, 0xD1, 0x0A, 0x50, 0x32, 0x74, 0x77, 0x31, 0x15, 0x41, 0xC0, 0xF9, 0x40, 0x66, 0x20, 0xB1, 0xD9, + 0x01, 0x8F, 0x3F, 0x07, 0x34, 0xF8, 0x1C, 0xB0, 0xB8, 0x15, 0xD1, 0xDA, 0xE1, 0x21, 0xB8, 0xB4, 0x6B, 0x9B, 0x04, 0xAC, 0x62, 0xD6, 0xA8, 0xF3, 0x6F, 0xBD, + 0x82, 0x45, 0xD5, 0x3B, 0x37, 0xF5, 0xA7, 0x80, 0xA0, 0xED, 0xD9, 0x57, 0x9E, 0x63, 0x58, 0xB3, 0x86, 0x3A, 0x6C, 0x86, 0xD8, 0xE8, 0x6D, 0x44, 0x99, 0xB8, + 0x4F, 0xAF, 0xD3, 0x4E, 0x92, 0x37, 0x1A, 0xFC, 0xFA, 0xD3, 0x7A, 0xB3, 0xCE, 0x89, 0xA7, 0xE7, 0x60, 0x6E, 0x0D, 0x76, 0xF0, 0x84, 0xD2, 0xD8, 0x54, 0xCE, + 0xCE, 0x78, 0x37, 0xAC, 0x15, 0x5E, 0x84, 0x46, 0xF4, 0x4F, 0xE2, 0x56, 0x60, 0x8A, 0x7F, 0x7C, 0xFB, 0xD5, 0xB7, 0xD9, 0xBB, 0x43, 0xA0, 0xFA, 0x39, 0x86, + 0xE0, 0x6F, 0xBF, 0xC2, 0xFF, 0x77, 0x4F, 0x68, 0xD4, 0xFD, 0xF6, 0x2B, 0xFE, 0xB9, 0x7B, 0x02, 0x3D, 0xC1, 0x31, 0xED, 0xEF, 0xEE, 0x0F, 0x2A, 0x87, 0x4D, + 0xE9, 0xCD, 0x52, 0xA5, 0x17, 0x88, 0xAD, 0x30, 0x4D, 0xB3, 0x0C, 0xA2, 0xFE, 0x08, 0xFD, 0xB7, 0x31, 0xB1, 0x75, 0x50, 0x8F, 0x07, 0x96, 0xEC, 0x2B, 0xDD, + 0x04, 0x95, 0xF8, 0x82, 0xEA, 0xF8, 0x4A, 0x37, 0xA6, 0xB4, 0xA5, 0xC2, 0x5D, 0x25, 0x34, 0x10, 0xBF, 0xE5, 0x52, 0x73, 0x5C, 0xF2, 0xBD, 0xE5, 0x35, 0xBC, + 0x98, 0x53, 0xA4, 0x48, 0x7C, 0x34, 0x8A, 0xB1, 0x80, 0x3F, 0x80, 0x83, 0x76, 0x75, 0xAE, 0xB4, 0xC0, 0xD8, 0xF8, 0xDF, 0x84, 0xD9, 0xBC, 0x2E, 0x64, 0x36, + 0x0D, 0x2A, 0xB6, 0xA0, 0xCF, 0x66, 0x11, 0x13, 0x02, 0xB2, 0x22, 0x06, 0x44, 0x1D, 0x22, 0x14, 0x19, 0xBB, 0x98, 0xE2, 0x10, 0xBF, 0x4C, 0xCC, 0x2F, 0x8D, + 0x1B, 0xF8, 0x2F, 0x19, 0xB3, 0x36, 0x74, 0x85, 0x8D, 0x9E, 0xE3, 0x7F, 0xA0, 0x20, 0xFC, 0x93, 0x6A, 0x28, 0x80, 0xF5, 0xBD, 0x69, 0x36, 0xD8, 0x07, 0xE6, + 0xC0, 0x46, 0x56, 0x10, 0x0F, 0xDD, 0x5B, 0x8C, 0x4C, 0xB6, 0xED, 0x7D, 0x3E, 0x50, 0x96, 0x0E, 0x10, 0x46, 0xBF, 0xA5, 0x02, 0xC7, 0x80, 0x88, 0x58, 0xEC, + 0x6F, 0x2E, 0x05, 0x4B, 0xD3, 0x7C, 0xCE, 0xB0, 0x02, 0x09, 0xEC, 0x00, 0x4C, 0x66, 0x85, 0xA6, 0x0B, 0xFF, 0xDF, 0x3D, 0x81, 0x4E, 0xE0, 0x10, 0xFE, 0xBF, + 0x7B, 0x82, 0x5D, 0xA1, 0x51, 0x61, 0x8F, 0x77, 0x4F, 0xA0, 0x47, 0x38, 0x81, 0xFF, 0xA1, 0x0D, 0xF6, 0x8B, 0xAD, 0xF0, 0x2F, 0xDC, 0xA1, 0xFD, 0xE3, 0x4D, + 0x7A, 0xC0, 0x2E, 0xF0, 0xD3, 0x2C, 0x06, 0xD9, 0xDB, 0xF5, 0x1B, 0xF4, 0x6D, 0xE7, 0x9F, 0x6F, 0x80, 0x1D, 0x7A, 0x70, 0x0B, 0x31, 0xC8, 0xD2, 0xF1, 0x1C, + 0xFF, 0xDC, 0xFA, 0x0A, 0xC6, 0x0B, 0xFC, 0x08, 0xAE, 0xD1, 0x37, 0xC2, 0xE2, 0x25, 0x76, 0x80, 0xAD, 0xE8, 0xFB, 0x3B, 0x69, 0x2B, 0x76, 0x04, 0xD7, 0xF8, + 0x5B, 0x1F, 0x0F, 0x14, 0xFE, 0x5E, 0xC1, 0x5C, 0xE1, 0x84, 0xEF, 0xFD, 0x7B, 0xEE, 0xDE, 0x20, 0x83, 0x8C, 0x34, 0x94, 0x4A, 0x70, 0x76, 0x7B, 0xF7, 0x84, + 0xE0, 0x3D, 0x4A, 0x24, 0x1C, 0xDF, 0xF2, 0x63, 0xB8, 0x0E, 0xF4, 0xE1, 0x1D, 0x9F, 0x60, 0x7A, 0xE1, 0x36, 0xBC, 0x00, 0x2D, 0x3C, 0xBC, 0xCF, 0x89, 0x87, + 0xB3, 0xDB, 0xE0, 0x0C, 0xA1, 0x29, 0x2C, 0x67, 0x03, 0x4E, 0x6F, 0xC3, 0x53, 0xB8, 0x8B, 0xBC, 0xA0, 0x02, 0x38, 0x4F, 0x77, 0x4F, 0x38, 0x4F, 0xA8, 0x45, + 0x76, 0x14, 0x17, 0x35, 0xFC, 0x8F, 0x7E, 0xE4, 0xF1, 0x80, 0xFD, 0xC9, 0xF7, 0x4E, 0x62, 0x36, 0x95, 0xF3, 0x11, 0x8F, 0xFB, 0x18, 0x00, 0xC0, 0xA3, 0xE0, + 0x3A, 0x31, 0xDB, 0x9A, 0x07, 0x0E, 0x01, 0x79, 0x13, 0x71, 0xDB, 0x18, 0x51, 0x02, 0x37, 0xDF, 0xB8, 0xD5, 0xB6, 0xC0, 0x2D, 0x28, 0xC2, 0xE6, 0x29, 0x0F, + 0x1B, 0x88, 0x88, 0x71, 0xB9, 0x81, 0x8B, 0x5D, 0x4E, 0x43, 0xC7, 0xEE, 0xA6, 0x60, 0xE4, 0xA1, 0x30, 0x0E, 0x81, 0x17, 0xD3, 0xB0, 0xD1, 0x51, 0x23, 0x82, + 0xAB, 0x3B, 0x18, 0x84, 0xD8, 0x12, 0x91, 0x8E, 0xCD, 0x29, 0x51, 0x20, 0x6D, 0xCC, 0xCF, 0xC3, 0xA1, 0x70, 0x02, 0xE6, 0xA0, 0xD4, 0xFD, 0x09, 0x65, 0xFD, + 0x74, 0x23, 0xC2, 0x01, 0x04, 0x2F, 0x20, 0x28, 0xCF, 0x19, 0x8D, 0xA7, 0x61, 0xF8, 0x54, 0x94, 0x31, 0x24, 0x3B, 0x5F, 0x9E, 0xC5, 0x90, 0xD1, 0xD4, 0x3F, + 0xC0, 0xC4, 0xAE, 0x61, 0xA2, 0x90, 0xB8, 0xC4, 0xB6, 0xDB, 0xB5, 0x6C, 0x8B, 0x88, 0x7B, 0x8D, 0xC5, 0x4B, 0xDE, 0x11, 0x3F, 0xD3, 0xC9, 0x54, 0x5B, 0x99, + 0x5E, 0x08, 0xE6, 0x10, 0x48, 0x74, 0x2D, 0x1E, 0xB6, 0x58, 0x92, 0x9F, 0x3B, 0x74, 0x67, 0x0C, 0x15, 0xFE, 0xA8, 0xF0, 0x38, 0x39, 0x2A, 0x80, 0x55, 0x3A, + 0x5E, 0xA3, 0x7E, 0xE9, 0x38, 0xB6, 0xF3, 0x5B, 0xFD, 0x29, 0x36, 0x7A, 0x5A, 0xFF, 0xFD, 0x54, 0xA1, 0xF1, 0xB4, 0x19, 0x0F, 0xEE, 0x91, 0xF0, 0x79, 0x78, + 0xA8, 0xBC, 0xF0, 0x3C, 0x0D, 0x14, 0x80, 0x35, 0x96, 0x39, 0xCA, 0x47, 0xD1, 0x78, 0x12, 0x68, 0x3B, 0x68, 0x94, 0xEC, 0x7B, 0xF7, 0x20, 0x11, 0x4C, 0x2C, + 0x5D, 0x00, 0xF1, 0x93, 0x4C, 0x8A, 0xAA, 0xFD, 0xAF, 0x15, 0x71, 0x6E, 0xAF, 0xA8, 0xC0, 0x6C, 0xE7, 0x05, 0x84, 0xCA, 0x7A, 0x3B, 0x9C, 0x27, 0xD5, 0x59, + 0xCE, 0xD3, 0x06, 0x54, 0x97, 0xD0, 0x07, 0xE8, 0x38, 0xB4, 0x79, 0xC6, 0x4D, 0xA0, 0x77, 0x18, 0xE7, 0xCE, 0xB9, 0x32, 0x92, 0x49, 0x16, 0xB4, 0xB0, 0xAD, + 0x2F, 0xE4, 0x76, 0xB5, 0x04, 0xF1, 0x87, 0x69, 0x53, 0x22, 0x91, 0xE3, 0xD2, 0x21, 0x6D, 0x68, 0x79, 0xC1, 0x07, 0x4E, 0xB5, 0x27, 0x68, 0x14, 0xAA, 0x80, + 0x5A, 0x27, 0x7A, 0xE2, 0xB3, 0x8D, 0x46, 0x77, 0x8F, 0xC4, 0x67, 0x82, 0x94, 0x93, 0x13, 0xC8, 0x85, 0x07, 0xAE, 0x4D, 0x1D, 0x3B, 0xD1, 0x43, 0x22, 0x1D, + 0x84, 0x64, 0x30, 0x8C, 0x0C, 0xAB, 0x25, 0x24, 0x9F, 0x24, 0x1E, 0x1C, 0x02, 0x5B, 0xF0, 0x6F, 0x2E, 0x6C, 0x8F, 0x24, 0x22, 0x86, 0x61, 0x19, 0x9E, 0xA1, + 0x99, 0x9F, 0x42, 0x6B, 0xDC, 0xA9, 0xFB, 0x0B, 0x7C, 0xBC, 0x80, 0xFF, 0x6F, 0xE4, 0x7C, 0x72, 0x79, 0xCA, 0x86, 0x85, 0x04, 0xF1, 0x20, 0xB4, 0x92, 0xA8, + 0x1C, 0x62, 0x61, 0x81, 0xDF, 0xF7, 0x7B, 0x7A, 0xFC, 0x98, 0x1E, 0x3D, 0x0A, 0x94, 0xE6, 0x47, 0x8F, 0x73, 0x25, 0xBC, 0x91, 0x50, 0xF0, 0x26, 0xEE, 0x04, + 0x0E, 0x1F, 0x79, 0x04, 0x43, 0x22, 0xF0, 0x2F, 0x21, 0xBD, 0x41, 0x5B, 0xF8, 0xFF, 0xA8, 0xFF, 0x80, 0xA2, 0xFE, 0xEE, 0x42, 0x7C, 0x86, 0x6D, 0x27, 0x3C, + 0x80, 0xC1, 0x89, 0xF3, 0xE9, 0xA7, 0x90, 0x68, 0x8B, 0x93, 0xE4, 0x20, 0x74, 0x07, 0x93, 0x7D, 0x98, 0xCC, 0x5C, 0xB2, 0xF0, 0xFC, 0xF2, 0xF6, 0x7B, 0xBD, + 0x51, 0x0F, 0xDE, 0x68, 0x54, 0x6F, 0x62, 0x5C, 0x32, 0x8D, 0xC9, 0x97, 0x20, 0x2C, 0x85, 0x96, 0x07, 0x29, 0x0D, 0x66, 0xFF, 0x38, 0xB1, 0x36, 0x26, 0xDC, + 0x54, 0x5F, 0x7D, 0x78, 0xF1, 0xEE, 0xF3, 0x8B, 0x8F, 0x1F, 0x3F, 0x28, 0x2B, 0xB0, 0x59, 0x75, 0xF8, 0x19, 0xD3, 0x16, 0x98, 0x04, 0x38, 0x9F, 0x81, 0x3E, + 0xF7, 0x33, 0x45, 0xDA, 0xF9, 0xED, 0xF7, 0xDF, 0xBA, 0xBF, 0x03, 0xE8, 0xD7, 0xFF, 0xB2, 0xEA, 0x8C, 0x11, 0x44, 0xF5, 0x14, 0x70, 0xE1, 0xF1, 0xD7, 0xFA, + 0x53, 0xDF, 0xE0, 0x1B, 0xE9, 0x14, 0x06, 0xAF, 0xD7, 0xAD, 0x37, 0x81, 0xD5, 0xBB, 0x03, 0x40, 0xC5, 0xD2, 0x41, 0x18, 0x73, 0x1A, 0x58, 0xAA, 0x30, 0xA0, + 0x03, 0xF5, 0x19, 0xFC, 0x39, 0x53, 0xD4, 0x23, 0xF8, 0xFB, 0xF4, 0x69, 0x68, 0x22, 0x25, 0xBB, 0xAB, 0x3F, 0x35, 0x68, 0x67, 0x30, 0x3B, 0x69, 0x18, 0x67, + 0x20, 0xC9, 0xE7, 0xF5, 0x83, 0xFA, 0x69, 0xBD, 0x0E, 0xD7, 0xFC, 0xEE, 0xEF, 0x62, 0xEC, 0xDC, 0x3D, 0x0B, 0x38, 0x64, 0xA3, 0x2B, 0xDC, 0x08, 0xC5, 0x1F, + 0xCD, 0xEA, 0x5E, 0xB2, 0x2A, 0xD7, 0x79, 0xBA, 0x4E, 0xD8, 0xDB, 0xAC, 0x67, 0x74, 0x40, 0x8C, 0xC2, 0x64, 0x28, 0x88, 0x85, 0x86, 0xC0, 0xD7, 0x52, 0x51, + 0xD3, 0xE1, 0x56, 0xD7, 0x1D, 0xD0, 0x36, 0xB5, 0x96, 0xE6, 0x86, 0x0B, 0xCB, 0xE1, 0xC0, 0xC6, 0x02, 0x1C, 0x1B, 0xD3, 0xCD, 0x4C, 0x24, 0xB4, 0x75, 0x04, + 0xCB, 0x46, 0xC2, 0xD3, 0xB9, 0xBF, 0x5C, 0x87, 0x69, 0x6C, 0x26, 0xA9, 0xB1, 0x59, 0x44, 0x63, 0xB3, 0xED, 0x6A, 0x8C, 0xA3, 0xAE, 0xAC, 0x35, 0x1F, 0x4F, + 0x8E, 0xE6, 0x72, 0xE1, 0xB9, 0xD2, 0xB8, 0xB6, 0x66, 0x22, 0x6D, 0x95, 0x51, 0x13, 0x8B, 0x5D, 0x30, 0x29, 0x22, 0xCE, 0x9B, 0x8F, 0xEF, 0xDE, 0x62, 0xB4, + 0x11, 0xAB, 0x2C, 0xD0, 0x58, 0x32, 0xB9, 0x12, 0x60, 0xC0, 0xA0, 0x18, 0xAB, 0x7C, 0x24, 0xC2, 0xA6, 0x12, 0x56, 0x10, 0x72, 0x0C, 0x81, 0x17, 0x0C, 0xE4, + 0x7C, 0x17, 0x8B, 0x04, 0xBE, 0xF3, 0x86, 0x50, 0x19, 0xB6, 0x80, 0x00, 0x52, 0x4A, 0x64, 0x98, 0x37, 0x1C, 0x26, 0x52, 0xCB, 0xD8, 0xBB, 0x8B, 0x50, 0x7F, + 0x75, 0x65, 0x83, 0x9A, 0x3F, 0x55, 0x0F, 0x63, 0x9B, 0x9B, 0x2B, 0x1D, 0x3E, 0xA1, 0x97, 0x12, 0x10, 0xFF, 0xAA, 0x9C, 0xC0, 0xC0, 0x79, 0x21, 0xA0, 0x00, + 0x96, 0x5B, 0x01, 0x16, 0x5A, 0x40, 0x90, 0xC2, 0x41, 0xBF, 0x44, 0x96, 0x82, 0x41, 0x8E, 0x0A, 0xFA, 0xE9, 0x2F, 0x01, 0x06, 0xBF, 0x54, 0x21, 0x85, 0xC4, + 0xFF, 0x6C, 0x55, 0x3A, 0x1E, 0x39, 0x62, 0xFC, 0x8F, 0x45, 0x09, 0xF0, 0xF0, 0xD2, 0x88, 0x14, 0x1A, 0xFE, 0xA1, 0xA3, 0x54, 0x2C, 0x72, 0xC4, 0xF0, 0x6F, + 0x0B, 0x89, 0x78, 0xE2, 0xA5, 0x18, 0x39, 0x9E, 0xF8, 0x27, 0x71, 0xD2, 0xF1, 0x48, 0xCA, 0x86, 0x7F, 0x86, 0x46, 0x64, 0x75, 0xAC, 0xF2, 0x93, 0xE9, 0x18, + 0xAC, 0x09, 0x00, 0xF3, 0x54, 0xF5, 0xB9, 0x1A, 0xCD, 0xAC, 0x79, 0xA1, 0x28, 0x0B, 0x03, 0x6F, 0x92, 0xC4, 0xE0, 0x47, 0x87, 0x7B, 0x28, 0xD9, 0xDD, 0x47, + 0x14, 0x7A, 0x6F, 0x9A, 0x72, 0x51, 0x68, 0x69, 0x9A, 0x7E, 0xF8, 0x09, 0x60, 0x52, 0xC2, 0x0F, 0x5D, 0x32, 0xA3, 0xF5, 0xD6, 0x4C, 0xF9, 0xD3, 0x16, 0x0C, + 0xEF, 0xA6, 0x12, 0x11, 0xC7, 0x62, 0x65, 0x4A, 0x59, 0x12, 0xB4, 0xE3, 0x68, 0xA2, 0x86, 0x44, 0x97, 0xE3, 0x6E, 0x5D, 0xB9, 0xD0, 0x75, 0xEB, 0xA6, 0x60, + 0xA0, 0x25, 0x61, 0xB9, 0xDC, 0x0C, 0x5A, 0xA6, 0x20, 0x59, 0x3A, 0x72, 0xE9, 0x1D, 0xB4, 0x4B, 0x63, 0x04, 0xEB, 0xCF, 0x72, 0xAC, 0xF8, 0x5F, 0x1D, 0x17, + 0xD1, 0x41, 0xAB, 0xD6, 0x59, 0x4A, 0xE1, 0x5F, 0x77, 0x4E, 0xD3, 0xC8, 0x52, 0x76, 0xC8, 0xF5, 0xBF, 0x7F, 0x2C, 0x18, 0x76, 0x4B, 0x16, 0xFB, 0xF7, 0xEF, + 0x1C, 0xDA, 0x35, 0x91, 0x70, 0x8D, 0x60, 0x65, 0x9E, 0x67, 0x77, 0x21, 0x58, 0x86, 0x77, 0x4C, 0x34, 0xEB, 0x5A, 0x8B, 0x79, 0xC7, 0x04, 0xA6, 0xBF, 0x1E, + 0xE1, 0xA8, 0x1B, 0x35, 0xD6, 0xA0, 0xC6, 0x69, 0x64, 0x67, 0x6D, 0xBA, 0x65, 0x0D, 0x0B, 0x21, 0x06, 0x59, 0xB3, 0x93, 0xD8, 0xED, 0x39, 0xA1, 0xAF, 0x09, + 0xE1, 0xF7, 0xD9, 0x19, 0x6B, 0x10, 0xF4, 0x32, 0xB6, 0xF5, 0xDB, 0xB6, 0xB6, 0x5C, 0x42, 0xF0, 0xBA, 0x98, 0x1B, 0xA6, 0xDE, 0x60, 0xA0, 0x11, 0x13, 0xC1, + 0xBD, 0x09, 0x84, 0xAE, 0x5A, 0x71, 0xAC, 0xC0, 0xF0, 0x05, 0xBB, 0xD6, 0xA8, 0x77, 0x75, 0x7F, 0xCD, 0x88, 0x37, 0x6B, 0xEB, 0x8E, 0xB6, 0xFE, 0x1E, 0x37, + 0x35, 0x34, 0xB0, 0xD3, 0x83, 0xCE, 0x41, 0x87, 0x37, 0xF0, 0x9C, 0xDB, 0x20, 0xCB, 0x44, 0xBC, 0xB8, 0xF8, 0xFB, 0xD3, 0x87, 0xB7, 0x21, 0x5E, 0xCF, 0x7E, + 0xC5, 0x2E, 0x35, 0xEA, 0x74, 0x57, 0xC4, 0xE1, 0x9F, 0x4B, 0x9C, 0x0A, 0xF8, 0x4A, 0x89, 0x88, 0x11, 0x37, 0x3C, 0xA0, 0xA8, 0x58, 0xF3, 0x67, 0x51, 0xA4, + 0x70, 0xD9, 0x22, 0x6B, 0x05, 0x30, 0x91, 0x86, 0x08, 0xD4, 0xDF, 0x0E, 0x81, 0xE0, 0xC8, 0xC9, 0x77, 0x2B, 0xD3, 0xFC, 0x95, 0x68, 0x0E, 0xE8, 0xE3, 0xA9, + 0xD2, 0xA8, 0x75, 0x6A, 0x4F, 0x1B, 0xF4, 0xFA, 0x3B, 0x60, 0x67, 0xDE, 0x68, 0x3E, 0x55, 0x9B, 0xCD, 0xB6, 0x0B, 0x3A, 0x23, 0x8D, 0x56, 0xD7, 0x6F, 0x02, + 0x7F, 0x68, 0x1B, 0xD6, 0x49, 0xFA, 0xFD, 0x37, 0xF6, 0xCA, 0x71, 0xB3, 0x1A, 0xBC, 0x33, 0x2C, 0x2C, 0xE2, 0x64, 0x35, 0xB9, 0x22, 0x20, 0x58, 0x7D, 0xA3, + 0x49, 0x8D, 0xEE, 0xE2, 0xE0, 0xE5, 0x0F, 0x85, 0x2E, 0x6E, 0x2B, 0x8D, 0x68, 0x45, 0x87, 0x2F, 0x23, 0x12, 0x34, 0xF4, 0x86, 0xEF, 0xF1, 0x77, 0x51, 0xE3, + 0x00, 0x97, 0x05, 0x03, 0xF8, 0x01, 0x3C, 0xA0, 0xED, 0x90, 0x85, 0x7D, 0x4D, 0x36, 0xF4, 0x8F, 0xCD, 0x03, 0xE3, 0x9F, 0x1B, 0x3A, 0x2B, 0xD3, 0x84, 0x76, + 0x8B, 0x55, 0x21, 0xDC, 0x20, 0x82, 0x5B, 0x28, 0x70, 0x3F, 0x45, 0xA3, 0xCE, 0x76, 0xAF, 0xD0, 0x51, 0xE1, 0x2E, 0x74, 0x9B, 0xB9, 0xBD, 0xCE, 0x82, 0x64, + 0xBD, 0x27, 0x80, 0x03, 0x68, 0xDD, 0x70, 0xB5, 0xB1, 0x99, 0xDF, 0x35, 0x6F, 0xA7, 0xF3, 0xF2, 0x37, 0x34, 0xF0, 0xAF, 0x00, 0xA8, 0xE7, 0xD0, 0x3A, 0x61, + 0x04, 0x2D, 0xB1, 0xF2, 0xB0, 0xFA, 0x64, 0x65, 0x22, 0x9E, 0x6A, 0x30, 0x79, 0x8A, 0x63, 0x66, 0xC5, 0xE3, 0x02, 0x65, 0xE5, 0xE8, 0x65, 0x80, 0x88, 0x9F, + 0x82, 0x39, 0x83, 0x85, 0x2A, 0xCF, 0x29, 0x0B, 0xCA, 0x69, 0xEC, 0x6E, 0x90, 0xDB, 0x44, 0x0B, 0xA6, 0x8F, 0x58, 0xFC, 0xFB, 0x0B, 0x56, 0x70, 0x03, 0xCA, + 0x63, 0x12, 0x78, 0xF2, 0x24, 0x8E, 0x0D, 0xB7, 0xB1, 0xB0, 0x01, 0x24, 0xE8, 0x8D, 0xB5, 0x67, 0xAF, 0x0F, 0x0F, 0x57, 0x16, 0x38, 0x49, 0x30, 0x14, 0x3C, + 0x8E, 0x09, 0x3E, 0x32, 0x46, 0x00, 0x21, 0x86, 0x4E, 0x05, 0x84, 0xBB, 0xD2, 0x6A, 0x1B, 0xEB, 0xFD, 0xCF, 0xA9, 0xD5, 0x37, 0x08, 0xDF, 0x94, 0xD8, 0x04, + 0xF9, 0xA3, 0x31, 0x87, 0x17, 0xE2, 0x73, 0xE8, 0x04, 0xC6, 0x59, 0x0C, 0x23, 0x32, 0x96, 0xA0, 0x1B, 0x7F, 0x87, 0x87, 0x14, 0xE3, 0x4C, 0x33, 0xAC, 0x0B, + 0x62, 0x60, 0xFA, 0xD7, 0x8C, 0xDC, 0xA5, 0xDD, 0x03, 0x22, 0xDC, 0x30, 0x18, 0x59, 0xCE, 0xD8, 0x5C, 0x0F, 0x39, 0x3C, 0xA4, 0x4D, 0x53, 0xD0, 0xD0, 0x2E, + 0x36, 0xD1, 0x64, 0x52, 0xBF, 0x1E, 0x7F, 0x46, 0x6C, 0x22, 0xA1, 0x50, 0x74, 0xEB, 0x31, 0x8A, 0x83, 0xF6, 0x0A, 0x87, 0xF1, 0x81, 0xD3, 0x77, 0x88, 0x60, + 0xC1, 0x3B, 0xAA, 0x21, 0x56, 0x90, 0x0F, 0xA7, 0xA5, 0xA1, 0x09, 0x6C, 0xA9, 0x3E, 0xAD, 0x62, 0x71, 0x3A, 0x68, 0x12, 0xAD, 0x22, 0x57, 0x2C, 0x4D, 0x67, + 0xE0, 0x64, 0x5B, 0xEE, 0x92, 0x48, 0x57, 0xE3, 0x85, 0xE1, 0x09, 0x10, 0xD6, 0xD5, 0xBA, 0x10, 0x57, 0x4A, 0x95, 0x3B, 0xEA, 0x1F, 0x2C, 0xC6, 0xD0, 0x05, + 0x40, 0x40, 0x14, 0x5B, 0xC0, 0x9F, 0xB0, 0x3D, 0xE4, 0xCF, 0x61, 0x1C, 0xC4, 0x65, 0x79, 0xD4, 0x65, 0x62, 0x63, 0x0E, 0x43, 0xC1, 0x76, 0x94, 0x51, 0x14, + 0xF1, 0x3D, 0x65, 0xFE, 0x3E, 0xAE, 0xF8, 0x7A, 0x61, 0x74, 0x47, 0xCA, 0x1F, 0x0E, 0x01, 0x38, 0x17, 0x67, 0x99, 0xCA, 0xB7, 0x5F, 0x29, 0x8A, 0x3B, 0x65, + 0x0A, 0xFE, 0xE9, 0xCE, 0x89, 0x4E, 0x67, 0x44, 0xDE, 0xCA, 0x3D, 0x55, 0x70, 0x33, 0x4E, 0x6C, 0x0F, 0xD9, 0xDD, 0x1F, 0x81, 0x85, 0x04, 0xE1, 0x3D, 0x5C, + 0x05, 0xE5, 0x6C, 0x6F, 0xAC, 0x86, 0x3E, 0x92, 0x58, 0xF7, 0xE4, 0xB0, 0x52, 0x6B, 0x9F, 0xA2, 0x25, 0xC3, 0x64, 0xEC, 0xE0, 0x99, 0xDF, 0x23, 0x99, 0xBE, + 0xE9, 0x5E, 0x48, 0x99, 0x2E, 0x05, 0x39, 0x1F, 0xFE, 0x58, 0x70, 0x31, 0x23, 0x23, 0x71, 0xC2, 0x8F, 0x9A, 0x5C, 0x4E, 0x60, 0x22, 0xBA, 0x1F, 0x05, 0x99, + 0x11, 0xE1, 0x9A, 0x30, 0xD3, 0x63, 0xCC, 0x04, 0x98, 0xB4, 0xB9, 0xB0, 0xF3, 0x37, 0x0A, 0xF2, 0xC5, 0x90, 0x40, 0x59, 0x7F, 0xBA, 0x90, 0x4D, 0x07, 0x22, + 0x10, 0xE1, 0xC0, 0x0E, 0x22, 0x08, 0x62, 0x22, 0x2A, 0xA4, 0xA2, 0x0C, 0x99, 0xB1, 0x5F, 0x64, 0x18, 0xA5, 0x63, 0x28, 0xED, 0xF9, 0x37, 0x6A, 0xD5, 0xBF, + 0x1F, 0xB0, 0x71, 0x37, 0x12, 0xCA, 0x9A, 0x45, 0x08, 0xDA, 0x58, 0x2B, 0xCF, 0x25, 0x66, 0x6B, 0xAB, 0x86, 0xFE, 0x0F, 0x82, 0x2D, 0xC5, 0x77, 0xAE, 0x74, + 0x36, 0x56, 0xCB, 0xA3, 0x4B, 0x5B, 0x01, 0x83, 0x02, 0xD9, 0x44, 0x96, 0xBA, 0x7D, 0xF1, 0x08, 0x97, 0xB5, 0x52, 0xC5, 0xC5, 0xEC, 0x8B, 0x45, 0x14, 0x4C, + 0xD6, 0x33, 0x67, 0x35, 0x74, 0x1B, 0x2B, 0x95, 0x57, 0x08, 0x70, 0x11, 0x6C, 0x5B, 0xCE, 0x85, 0x0C, 0xB7, 0x38, 0x47, 0x70, 0xD0, 0x59, 0x92, 0xDC, 0xAA, + 0x00, 0x9F, 0x50, 0x45, 0x40, 0x11, 0x6B, 0x3E, 0xAC, 0xFF, 0xEC, 0x4A, 0x92, 0x7C, 0xEA, 0xBB, 0xF9, 0xE0, 0xD1, 0xED, 0xCE, 0xF5, 0x88, 0xB8, 0x5C, 0xCF, + 0x5E, 0x5E, 0xD1, 0xAB, 0x09, 0xBF, 0x5E, 0xD3, 0x22, 0x51, 0x1B, 0xEF, 0xFB, 0xF3, 0x8F, 0x28, 0xA9, 0xF1, 0xBA, 0xFA, 0x15, 0x56, 0x90, 0x14, 0x86, 0xA7, + 0x9E, 0x98, 0x6B, 0xE2, 0x2D, 0x61, 0x0F, 0x74, 0x2E, 0xE7, 0x3A, 0x13, 0x16, 0xFE, 0x83, 0xED, 0xC5, 0xE8, 0xFC, 0x78, 0xF8, 0x07, 0xEB, 0x13, 0x87, 0xE8, + 0x98, 0x8A, 0x9A, 0xB9, 0xB4, 0xD8, 0xCB, 0x24, 0x29, 0x61, 0x88, 0x66, 0xEE, 0xE2, 0x62, 0xDC, 0x67, 0x43, 0x1D, 0x06, 0xA0, 0x88, 0xFA, 0x52, 0xA2, 0x5C, + 0x28, 0x26, 0x1E, 0x56, 0xE2, 0xC4, 0x47, 0xC6, 0x2E, 0xB6, 0x37, 0xFD, 0xF9, 0xE7, 0xC9, 0x18, 0x86, 0x2B, 0x9C, 0x58, 0x81, 0xF3, 0xAC, 0x1B, 0xCD, 0xBB, + 0x2C, 0x76, 0x98, 0xB8, 0x42, 0x45, 0xCA, 0x12, 0x41, 0xE3, 0xAE, 0x18, 0x5B, 0x4C, 0x3E, 0x62, 0x74, 0x51, 0xFB, 0xBB, 0xB4, 0xFC, 0x89, 0x40, 0x9A, 0x60, + 0xCF, 0x37, 0x45, 0xCB, 0x72, 0xC1, 0x18, 0x82, 0x30, 0xA2, 0x6E, 0x10, 0x9B, 0x48, 0xF6, 0x22, 0x76, 0xE1, 0x37, 0x88, 0x68, 0xEB, 0x62, 0x05, 0xF0, 0x0B, + 0x5F, 0x5B, 0xEC, 0x1A, 0x26, 0x7D, 0x81, 0x59, 0x41, 0x12, 0x98, 0x65, 0xEE, 0x70, 0x3B, 0xE2, 0x23, 0x3C, 0x63, 0xCC, 0x01, 0xA0, 0x69, 0x22, 0x7B, 0x36, + 0x84, 0xC2, 0xB2, 0x3D, 0xAC, 0x9E, 0x12, 0xC9, 0x45, 0x33, 0x9D, 0x1B, 0x9A, 0x4D, 0x58, 0xB3, 0x08, 0x12, 0xC0, 0xBB, 0x39, 0x56, 0x47, 0xA7, 0x4B, 0x7C, + 0xC4, 0x86, 0x76, 0xCD, 0x40, 0xA4, 0x08, 0xC4, 0xD3, 0xC0, 0x50, 0xA0, 0xE9, 0x09, 0xF6, 0x66, 0x72, 0x9D, 0x90, 0x75, 0x7A, 0x52, 0xBD, 0x99, 0x50, 0x47, + 0xB5, 0xE0, 0x3F, 0xC4, 0x14, 0x0A, 0x92, 0x64, 0x4B, 0x9D, 0x44, 0xA5, 0xEE, 0x4F, 0x2E, 0x72, 0x20, 0x3E, 0xD3, 0x3C, 0x20, 0x2A, 0x32, 0x22, 0x29, 0x32, + 0xC2, 0x45, 0x86, 0x00, 0x61, 0xD6, 0x9C, 0x3F, 0xD3, 0x09, 0x42, 0xC2, 0xCF, 0x2F, 0x43, 0xCE, 0xD6, 0xE3, 0x4C, 0x3A, 0xF9, 0x2C, 0x22, 0xC2, 0x5E, 0x36, + 0x00, 0xB4, 0x5F, 0xC0, 0xA0, 0x19, 0x65, 0x6B, 0x3D, 0x96, 0x63, 0xCB, 0x9F, 0x85, 0x20, 0x40, 0xC8, 0x96, 0x78, 0xAE, 0xE2, 0xB3, 0xF2, 0x8A, 0x78, 0xFC, + 0x51, 0x47, 0xCD, 0xD2, 0x95, 0xA9, 0xA3, 0x2D, 0x08, 0x7E, 0xD9, 0x3E, 0x20, 0x36, 0xB8, 0x92, 0x45, 0x73, 0xD0, 0x88, 0x0D, 0x10, 0xC1, 0xA9, 0x14, 0xD9, + 0x41, 0xEB, 0xD0, 0x8C, 0x43, 0x04, 0x6C, 0xBE, 0x30, 0x52, 0x06, 0xC9, 0xB9, 0x2E, 0x1B, 0xF7, 0x75, 0x4A, 0x7D, 0x62, 0x74, 0x8F, 0x36, 0x70, 0xC8, 0xC4, + 0x9E, 0x59, 0x80, 0x29, 0xD6, 0x86, 0x99, 0x2A, 0x1B, 0xFC, 0xD9, 0xEF, 0xEC, 0xD0, 0x7F, 0x3C, 0x86, 0x9D, 0x61, 0x51, 0x70, 0xF4, 0xE8, 0xEC, 0x70, 0xEE, + 0x2D, 0xCC, 0xD1, 0xA3, 0xFF, 0x05, 0xDF, 0x19, 0xEB, 0xA3, 0xC1, 0x08, 0x01, 0x00 + }; diff --git a/libraries/ESP32/examples/Camera/CameraWebServer/ci.json b/libraries/ESP32/examples/Camera/CameraWebServer/ci.json index 25c42144223..35c3056dda8 100644 --- a/libraries/ESP32/examples/Camera/CameraWebServer/ci.json +++ b/libraries/ESP32/examples/Camera/CameraWebServer/ci.json @@ -1,7 +1,20 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "fqbn": { + "esp32": [ + "espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=custom,FlashMode=dio", + "espressif:esp32:esp32:PSRAM=disabled,PartitionScheme=custom,FlashMode=dio" + ], + "esp32s2": [ + "espressif:esp32:esp32s2:PSRAM=enabled,PartitionScheme=custom,FlashMode=dio", + "espressif:esp32:esp32s2:PSRAM=disabled,PartitionScheme=custom,FlashMode=dio" + ], + "esp32s3": [ + "espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=custom,FlashMode=qio", + "espressif:esp32:esp32s3:PSRAM=enabled,USBMode=default,PartitionScheme=custom,FlashMode=qio", + "espressif:esp32:esp32s3:PSRAM=disabled,USBMode=default,PartitionScheme=custom,FlashMode=qio" + ] + }, + "requires": [ + "CONFIG_CAMERA_TASK_STACK_SIZE=[0-9]+" + ] } diff --git a/libraries/ESP32/examples/Camera/CameraWebServer/partitions.csv b/libraries/ESP32/examples/Camera/CameraWebServer/partitions.csv index 4f76ca6d746..b9f18c465a7 100644 --- a/libraries/ESP32/examples/Camera/CameraWebServer/partitions.csv +++ b/libraries/ESP32/examples/Camera/CameraWebServer/partitions.csv @@ -1,5 +1,6 @@ # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x5000, otadata, data, ota, 0xe000, 0x2000, -app0, app, ota_0, 0x10000, 0x3d0000, -fr, data, , 0x3e0000, 0x20000, +app0, app, ota_0, 0x10000, 0x3c0000, +fr, data, , 0x3d0000, 0x20000, +coredump, data, coredump,0x3f0000, 0x10000, diff --git a/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ExternalWakeUp.ino b/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ExternalWakeUp.ino index fb4228031f6..aed57c49047 100644 --- a/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ExternalWakeUp.ino +++ b/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ExternalWakeUp.ino @@ -1,33 +1,35 @@ /* -Deep Sleep with External Wake Up -===================================== -This code displays how to use deep sleep with -an external trigger as a wake up source and how -to store data in RTC memory to use it over reboots - -This code is under Public Domain License. - -Hardware Connections -====================== -Push Button to GPIO 33 pulled down with a 10K Ohm -resistor - -NOTE: -====== -Only RTC IO can be used as a source for external wake -source. They are pins: 0,2,4,12-15,25-27,32-39. - -Author: -Pranav Cherukupalli + Deep Sleep with External Wake Up + ===================================== + This code displays how to use deep sleep with + an external trigger as a wake up source and how + to store data in RTC memory to use it over reboots + + This code is under Public Domain License. + + Hardware Connections + ====================== + Push Button to GPIO 33 pulled down with a 10K Ohm + resistor + + NOTE: + ====== + Only RTC IO can be used as a source for external wake + source. They are pins: 0,2,4,12-15,25-27,32-39. + + Author: + Pranav Cherukupalli */ +#include "driver/rtc_io.h" -#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex - +#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO) // 2 ^ GPIO_NUMBER in hex +#define USE_EXT0_WAKEUP 1 // 1 = EXT0 wakeup, 0 = EXT1 wakeup +#define WAKEUP_GPIO GPIO_NUM_33 // Only RTC IO are allowed - ESP32 Pin example RTC_DATA_ATTR int bootCount = 0; /* -Method to print the reason by which ESP32 -has been awaken from sleep + Method to print the reason by which ESP32 + has been awaken from sleep */ void print_wakeup_reason() { esp_sleep_wakeup_cause_t wakeup_reason; @@ -56,20 +58,35 @@ void setup() { print_wakeup_reason(); /* - First we configure the wake up source - We set our ESP32 to wake up for an external trigger. - There are two types for ESP32, ext0 and ext1 . - ext0 uses RTC_IO to wakeup thus requires RTC peripherals - to be on while ext1 uses RTC Controller so does not need - peripherals to be powered on. - Note that using internal pullups/pulldowns also requires - RTC peripherals to be turned on. + First we configure the wake up source + We set our ESP32 to wake up for an external trigger. + There are two types for ESP32, ext0 and ext1 . + ext0 uses RTC_IO to wakeup thus requires RTC peripherals + to be on while ext1 uses RTC Controller so does not need + peripherals to be powered on. + Note that using internal pullups/pulldowns also requires + RTC peripherals to be turned on. */ - esp_sleep_enable_ext0_wakeup(GPIO_NUM_33, 1); //1 = High, 0 = Low - +#if USE_EXT0_WAKEUP + esp_sleep_enable_ext0_wakeup(WAKEUP_GPIO, 1); //1 = High, 0 = Low + // Configure pullup/downs via RTCIO to tie wakeup pins to inactive level during deepsleep. + // EXT0 resides in the same power domain (RTC_PERIPH) as the RTC IO pullup/downs. + // No need to keep that power domain explicitly, unlike EXT1. + rtc_gpio_pullup_dis(WAKEUP_GPIO); + rtc_gpio_pulldown_en(WAKEUP_GPIO); + +#else // EXT1 WAKEUP //If you were to use ext1, you would use it like - //esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH); - + esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH); + /* + If there are no external pull-up/downs, tie wakeup pins to inactive level with internal pull-up/downs via RTC IO + during deepsleep. However, RTC IO relies on the RTC_PERIPH power domain. Keeping this power domain on will + increase some power consumption. However, if we turn off the RTC_PERIPH domain or if certain chips lack the RTC_PERIPH + domain, we will use the HOLD feature to maintain the pull-up and pull-down on the pins during sleep. + */ + rtc_gpio_pulldown_en(WAKEUP_GPIO); // GPIO33 is tie to GND in order to wake up in HIGH + rtc_gpio_pullup_dis(WAKEUP_GPIO); // Disable PULL_UP in order to allow it to wakeup on HIGH +#endif //Go to sleep now Serial.println("Going to sleep now"); esp_deep_sleep_start(); diff --git a/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ci.json b/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ci.json index 25c42144223..cd679adefad 100644 --- a/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ci.json +++ b/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ci.json @@ -2,6 +2,7 @@ "targets": { "esp32c3": false, "esp32c6": false, - "esp32h2": false + "esp32h2": false, + "esp32p4": false } } diff --git a/libraries/ESP32/examples/DeepSleep/SmoothBlink_ULP_Code/SmoothBlink_ULP_Code.ino b/libraries/ESP32/examples/DeepSleep/SmoothBlink_ULP_Code/SmoothBlink_ULP_Code.ino index 5b21a211557..789d9fa3dc9 100644 --- a/libraries/ESP32/examples/DeepSleep/SmoothBlink_ULP_Code/SmoothBlink_ULP_Code.ino +++ b/libraries/ESP32/examples/DeepSleep/SmoothBlink_ULP_Code/SmoothBlink_ULP_Code.ino @@ -139,7 +139,6 @@ void ulp_setup() { void setup() { Serial.begin(115200); - while (!Serial) {} // wait for Serial to start ulp_setup(); // it really only runs on the first ESP32 boot Serial.printf("\nStarted smooth blink with delay %ld\n", *fadeCycleDelay); diff --git a/libraries/ESP32/examples/DeepSleep/SmoothBlink_ULP_Code/ci.json b/libraries/ESP32/examples/DeepSleep/SmoothBlink_ULP_Code/ci.json index 1af543242e3..6afa60f44c4 100644 --- a/libraries/ESP32/examples/DeepSleep/SmoothBlink_ULP_Code/ci.json +++ b/libraries/ESP32/examples/DeepSleep/SmoothBlink_ULP_Code/ci.json @@ -3,6 +3,7 @@ "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false, "esp32s3": false } diff --git a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino index 5aacf1baaf0..9d2b248ba44 100644 --- a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino +++ b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino @@ -15,9 +15,11 @@ Pranav Cherukupalli */ #if CONFIG_IDF_TARGET_ESP32 -#define THRESHOLD 40 /* Greater the value, more the sensitivity */ -#else //ESP32-S2 and ESP32-S3 + default for other chips (to be adjusted) */ +#define THRESHOLD 40 /* Greater the value, more the sensitivity */ +#elif (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3) #define THRESHOLD 5000 /* Lower the value, more the sensitivity */ +#else // ESP32-P4 + default for other chips (to be adjusted) */ +#define THRESHOLD 500 /* Lower the value, more the sensitivity */ #endif RTC_DATA_ATTR int bootCount = 0; @@ -88,7 +90,7 @@ void setup() { touchSleepWakeUpEnable(T3, THRESHOLD); touchSleepWakeUpEnable(T7, THRESHOLD); -#else //ESP32-S2 + ESP32-S3 +#else //ESP32-S2 + ESP32-S3 + ESP32-P4 //Setup sleep wakeup on Touch Pad 3 (GPIO3) touchSleepWakeUpEnable(T3, THRESHOLD); diff --git a/libraries/ESP32/examples/FreeRTOS/BasicMultiThreading/BasicMultiThreading.ino b/libraries/ESP32/examples/FreeRTOS/BasicMultiThreading/BasicMultiThreading.ino index 9e26ca69416..8704568dbeb 100644 --- a/libraries/ESP32/examples/FreeRTOS/BasicMultiThreading/BasicMultiThreading.ino +++ b/libraries/ESP32/examples/FreeRTOS/BasicMultiThreading/BasicMultiThreading.ino @@ -7,9 +7,9 @@ // Please read file README.md in the folder containing this example. #if CONFIG_FREERTOS_UNICORE -#define ARDUINO_RUNNING_CORE 0 +#define TASK_RUNNING_CORE 0 #else -#define ARDUINO_RUNNING_CORE 1 +#define TASK_RUNNING_CORE 1 #endif #define ANALOG_INPUT_PIN A0 @@ -51,7 +51,7 @@ void setup() { , &analog_read_task_handle // With task handle we will be able to manipulate with this task. , - ARDUINO_RUNNING_CORE // Core on which the task will run + TASK_RUNNING_CORE // Core on which the task will run ); Serial.printf("Basic Multi Threading Arduino Example\n"); diff --git a/libraries/ESP32/examples/FreeRTOS/BasicMultiThreading/README.md b/libraries/ESP32/examples/FreeRTOS/BasicMultiThreading/README.md index c7112e8b4f9..f48e352dd45 100644 --- a/libraries/ESP32/examples/FreeRTOS/BasicMultiThreading/README.md +++ b/libraries/ESP32/examples/FreeRTOS/BasicMultiThreading/README.md @@ -32,7 +32,7 @@ It is also worth mentioning that two or more tasks running the same function wil ``` - **pxTaskCode** is the name of your function which will run as a task - **pcName** is a string of human-readable descriptions for your task - - **usStackDepth** is the number of words (word = 4B) available to the task. If you see an error similar to this "Debug exception reason: Stack canary watchpoint triggered (Task Blink)" you should increase it + - **usStackDepth** is the number of words (word = 4 B) available to the task. If you see an error similar to this "Debug exception reason: Stack canary watchpoint triggered (Task Blink)" you should increase it - **pvParameters** is a parameter that will be passed to the task function - it must be explicitly converted to (void*) and in your function explicitly converted back to the intended data type. - **uxPriority** is a number from 0 to configMAX_PRIORITIES which determines how the FreeRTOS will allow the tasks to run. 0 is the lowest priority. - **pxCreatedTask** task handle is a pointer to the task which allows you to manipulate the task - delete it, suspend and resume. @@ -62,10 +62,6 @@ To get more information about the Espressif boards see [Espressif Development Ki * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file. - ## Troubleshooting ***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** diff --git a/libraries/ESP32/examples/FreeRTOS/Mutex/Mutex.ino b/libraries/ESP32/examples/FreeRTOS/Mutex/Mutex.ino index 9ace13a1983..f368e0e864c 100644 --- a/libraries/ESP32/examples/FreeRTOS/Mutex/Mutex.ino +++ b/libraries/ESP32/examples/FreeRTOS/Mutex/Mutex.ino @@ -17,9 +17,7 @@ void Task(void *pvParameters); void setup() { // Initialize serial communication at 115200 bits per second: Serial.begin(115200); - while (!Serial) { - delay(100); - } + Serial.printf(" Task 0 | Task 1\n"); #ifdef USE_MUTEX diff --git a/libraries/ESP32/examples/FreeRTOS/Mutex/README.md b/libraries/ESP32/examples/FreeRTOS/Mutex/README.md index d1c8c19e3be..435528bd771 100644 --- a/libraries/ESP32/examples/FreeRTOS/Mutex/README.md +++ b/libraries/ESP32/examples/FreeRTOS/Mutex/README.md @@ -51,10 +51,6 @@ To get more information about the Espressif boards see [Espressif Development Ki * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file. - ## Example Log Output The expected output of shared variables protected by mutex demonstrates mutually exclusive access from tasks - they do not interrupt each other and do not rewrite the value before the other task has read it back. diff --git a/libraries/ESP32/examples/FreeRTOS/Queue/Queue.ino b/libraries/ESP32/examples/FreeRTOS/Queue/Queue.ino index b617bdd74ac..1ddecea30dc 100644 --- a/libraries/ESP32/examples/FreeRTOS/Queue/Queue.ino +++ b/libraries/ESP32/examples/FreeRTOS/Queue/Queue.ino @@ -24,9 +24,6 @@ typedef struct { void setup() { // Initialize serial communication at 115200 bits per second: Serial.begin(115200); - while (!Serial) { - delay(10); - } // Create the queue which will have number of elements, each of size `message_t` and pass the address to . QueueHandle = xQueueCreate(QueueElementSize, sizeof(message_t)); diff --git a/libraries/ESP32/examples/FreeRTOS/Queue/README.md b/libraries/ESP32/examples/FreeRTOS/Queue/README.md index 745ce9e8db6..e81d6741e2a 100644 --- a/libraries/ESP32/examples/FreeRTOS/Queue/README.md +++ b/libraries/ESP32/examples/FreeRTOS/Queue/README.md @@ -29,10 +29,6 @@ To get more information about the Espressif boards see [Espressif Development Ki * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file. - ## Example Log Output ``` diff --git a/libraries/ESP32/examples/FreeRTOS/Semaphore/README.md b/libraries/ESP32/examples/FreeRTOS/Semaphore/README.md index 8f860a52db5..fcb38eed1d6 100644 --- a/libraries/ESP32/examples/FreeRTOS/Semaphore/README.md +++ b/libraries/ESP32/examples/FreeRTOS/Semaphore/README.md @@ -35,10 +35,6 @@ To get more information about the Espressif boards see [Espressif Development Ki * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file. - ## Example Log Output ``` diff --git a/libraries/ESP32/examples/FreeRTOS/Semaphore/Semaphore.ino b/libraries/ESP32/examples/FreeRTOS/Semaphore/Semaphore.ino index 66f43f9421c..077d20329e3 100644 --- a/libraries/ESP32/examples/FreeRTOS/Semaphore/Semaphore.ino +++ b/libraries/ESP32/examples/FreeRTOS/Semaphore/Semaphore.ino @@ -36,9 +36,7 @@ void warehouse_worker_task(void *pvParameters) { void setup() { Serial.begin(115200); - while (!Serial) { - delay(100); - } + // Create the semaphore package_delivered_semaphore = xSemaphoreCreateCounting(10, 0); diff --git a/libraries/ESP32/examples/GPIO/BlinkRGB/BlinkRGB.ino b/libraries/ESP32/examples/GPIO/BlinkRGB/BlinkRGB.ino index fa4e7596099..9544ce7cc25 100644 --- a/libraries/ESP32/examples/GPIO/BlinkRGB/BlinkRGB.ino +++ b/libraries/ESP32/examples/GPIO/BlinkRGB/BlinkRGB.ino @@ -6,7 +6,7 @@ Calling digitalWrite(RGB_BUILTIN, HIGH) will use hidden RGB driver. RGBLedWrite demonstrates control of each channel: - void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val) + void rgbLedWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val) WARNING: After using digitalWrite to drive RGB LED it will be impossible to drive the same pin with normal HIGH/LOW level @@ -27,13 +27,13 @@ void loop() { digitalWrite(RGB_BUILTIN, LOW); // Turn the RGB LED off delay(1000); - neopixelWrite(RGB_BUILTIN, RGB_BRIGHTNESS, 0, 0); // Red + rgbLedWrite(RGB_BUILTIN, RGB_BRIGHTNESS, 0, 0); // Red delay(1000); - neopixelWrite(RGB_BUILTIN, 0, RGB_BRIGHTNESS, 0); // Green + rgbLedWrite(RGB_BUILTIN, 0, RGB_BRIGHTNESS, 0); // Green delay(1000); - neopixelWrite(RGB_BUILTIN, 0, 0, RGB_BRIGHTNESS); // Blue + rgbLedWrite(RGB_BUILTIN, 0, 0, RGB_BRIGHTNESS); // Blue delay(1000); - neopixelWrite(RGB_BUILTIN, 0, 0, 0); // Off / black + rgbLedWrite(RGB_BUILTIN, 0, 0, 0); // Off / black delay(1000); #endif } diff --git a/libraries/ESP32/examples/GPIO/FunctionalInterrupt/FunctionalInterrupt.ino b/libraries/ESP32/examples/GPIO/FunctionalInterrupt/FunctionalInterrupt.ino index 2ea0ed2a4b3..a38c6e6b5bc 100644 --- a/libraries/ESP32/examples/GPIO/FunctionalInterrupt/FunctionalInterrupt.ino +++ b/libraries/ESP32/examples/GPIO/FunctionalInterrupt/FunctionalInterrupt.ino @@ -56,9 +56,7 @@ Button button2(BUTTON2); void setup() { Serial.begin(115200); - while (!Serial) { - delay(10); - } + Serial.println("Starting Functional Interrupt example."); button1.begin(); button2.begin(); diff --git a/libraries/ESP32/examples/HWCDC_Events/ci.json b/libraries/ESP32/examples/HWCDC_Events/ci.json index edef5051e09..56e38bbcdf2 100644 --- a/libraries/ESP32/examples/HWCDC_Events/ci.json +++ b/libraries/ESP32/examples/HWCDC_Events/ci.json @@ -1,6 +1,10 @@ { - "targets": { - "esp32": false, - "esp32s2": false - } + "fqbn": { + "esp32s3": [ + "espressif:esp32:esp32s3:USBMode=hwcdc,PartitionScheme=huge_app,FlashMode=dio" + ] + }, + "requires": [ + "CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED=y" + ] } diff --git a/libraries/ESP32/examples/MacAddress/GetMacAddress/GetMacAddress.ino b/libraries/ESP32/examples/MacAddress/GetMacAddress/GetMacAddress.ino index 4ed2df35d41..effcd0e5642 100644 --- a/libraries/ESP32/examples/MacAddress/GetMacAddress/GetMacAddress.ino +++ b/libraries/ESP32/examples/MacAddress/GetMacAddress/GetMacAddress.ino @@ -34,9 +34,6 @@ esp_mac_type_t values: void setup() { Serial.begin(115200); - while (!Serial) { - delay(100); - } Serial.println("Interface\t\t\t\t\t\tMAC address (6 bytes, 4 universally administered, default)"); diff --git a/libraries/ESP32/examples/RMT/Legacy_RMT_Driver_Compatible/Legacy_RMT_Driver_Compatible.ino b/libraries/ESP32/examples/RMT/Legacy_RMT_Driver_Compatible/Legacy_RMT_Driver_Compatible.ino new file mode 100644 index 00000000000..b42fe15f0cd --- /dev/null +++ b/libraries/ESP32/examples/RMT/Legacy_RMT_Driver_Compatible/Legacy_RMT_Driver_Compatible.ino @@ -0,0 +1,37 @@ +/* + * This example demonstrates how to use the file build_opt.h to disable the new RMT Driver + * Note that this file shall be added the Arduino project + * + * If the content of this file changes, it is necessary to delete the compiled Arduino IDE cache + * It can be done by changing, for instance, the "Core Debug Level" option, forcing the system to rebuild the Arduino Core + * + */ + +#ifndef ESP32_ARDUINO_NO_RGB_BUILTIN + +// add the file "build_opt.h" to your Arduino project folder with "-DESP32_ARDUINO_NO_RGB_BUILTIN" to use the RMT Legacy driver +#error "ESP32_ARDUINO_NO_RGB_BUILTIN is not defined, this example is intended to demonstrate the RMT Legacy driver." +#error "Please add the file 'build_opt.h' with '-DESP32_ARDUINO_NO_RGB_BUILTIN' to your Arduino project folder." + +#else + +// add the file "build_opt.h" to your Arduino project folder with "-DESP32_ARDUINO_NO_RGB_BUILTIN" to use the RMT Legacy driver +// rgbLedWrite() is a function that writes to the RGB LED and it won't be available here +#include "driver/rmt.h" + +bool installed = false; + +void setup() { + Serial.begin(115200); + Serial.println("This sketch is using the RMT Legacy driver."); + installed = rmt_driver_install(RMT_CHANNEL_0, 0, 0) == ESP_OK; +} + +void loop() { + String msg = "RMT Legacy driver is installed: "; + msg += (char *)(installed ? "Yes." : "No."); + Serial.println(msg); + delay(5000); +} + +#endif // ESP32_ARDUINO_NO_RGB_BUILTIN diff --git a/libraries/ESP32/examples/RMT/Legacy_RMT_Driver_Compatible/build_opt.h b/libraries/ESP32/examples/RMT/Legacy_RMT_Driver_Compatible/build_opt.h new file mode 100644 index 00000000000..583b42d9880 --- /dev/null +++ b/libraries/ESP32/examples/RMT/Legacy_RMT_Driver_Compatible/build_opt.h @@ -0,0 +1 @@ +-DESP32_ARDUINO_NO_RGB_BUILTIN diff --git a/libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopback.ino b/libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopback.ino index eada1c7ea6b..5d0406aee0e 100644 --- a/libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopback.ino +++ b/libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopback.ino @@ -1,4 +1,4 @@ -// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// Copyright 2025 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. @@ -21,7 +21,7 @@ * */ -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 // ESP32 C3 has only 2 channels for RX and 2 for TX, thus MAX RMT_MEM is 128 #define RMT_TX_PIN 4 #define RMT_RX_PIN 5 @@ -35,14 +35,11 @@ rmt_data_t my_data[256]; rmt_data_t data[256]; -static EventGroupHandle_t events; - #define RMT_FREQ 10000000 // tick time is 100ns -#define RMT_NUM_EXCHANGED_DATA 30 +#define RMT_NUM_EXCHANGED_DATA 32 void setup() { Serial.begin(115200); - events = xEventGroupCreate(); if (!rmtInit(RMT_TX_PIN, RMT_TX_MODE, RMT_MEM_NUM_BLOCKS_1, RMT_FREQ)) { Serial.println("init sender failed\n"); @@ -50,25 +47,41 @@ void setup() { if (!rmtInit(RMT_RX_PIN, RMT_RX_MODE, RMT_MEM_RX, RMT_FREQ)) { Serial.println("init receiver failed\n"); } + Serial.println(); + Serial.println("RMT tick set to: 100ns"); // End of transmission shall be detected when line is idle for 2us = 20*100ns rmtSetRxMaxThreshold(RMT_RX_PIN, 20); // Disable Glitch filter rmtSetRxMinThreshold(RMT_RX_PIN, 0); - Serial.println("real tick set to: 100ns"); - Serial.printf("\nPlease connect GPIO %d to GPIO %d, now.\n", RMT_TX_PIN, RMT_RX_PIN); -} - -void loop() { - // Init data - int i; - for (i = 0; i < 255; i++) { - data[i].val = 0x80010001 + ((i % 13) << 16) + 13 - (i % 13); + // create multiple pulses with different width to be sent + for (int i = 0; i < 255; i++) { + data[i].level0 = 1; // HIGH + data[i].duration0 = 1 + 13 - (i % 13); // number of Tick on High + data[i].level1 = 0; // LOW + data[i].duration1 = 1 + (i % 13); // number of Ticks on Low my_data[i].val = 0; } data[255].val = 0; + Serial.println(); + Serial.println("===================================================================================================="); + Serial.println("Preloaded Data that will sent (time in 0.1us):"); + // Printout the received data plus the original values + for (int i = 0; i < RMT_NUM_EXCHANGED_DATA; i++) { + Serial.printf("%08lx=[%c 0x%02x|%c 0x%02x] ", data[i].val, data[i].level0 ? 'H' : 'L', data[i].duration0, data[i].level1 ? 'H' : 'L', data[i].duration1); + if (!((i + 1) % 4)) { + Serial.println(); + } + } + Serial.println("===================================================================================================="); + Serial.printf("Please connect GPIO %d to GPIO %d, now.", RMT_TX_PIN, RMT_RX_PIN); + Serial.println(); + Serial.println(); +} + +void loop() { // Start an async data read size_t rx_num_symbols = RMT_NUM_EXCHANGED_DATA; rmtReadAsync(RMT_RX_PIN, my_data, &rx_num_symbols); @@ -84,13 +97,13 @@ void loop() { Serial.printf("Got %d RMT symbols\n", rx_num_symbols); // Printout the received data plus the original values - for (i = 0; i < 60; i++) { + for (int i = 0; i < RMT_NUM_EXCHANGED_DATA; i++) { Serial.printf("%08lx=%08lx ", my_data[i].val, data[i].val); if (!((i + 1) % 4)) { - Serial.println(""); + Serial.println(); } } - Serial.println("\n"); + Serial.println(); - delay(500); + delay(2000); } diff --git a/libraries/ESP32/examples/RMT/RMTReadXJT/RMTReadXJT.ino b/libraries/ESP32/examples/RMT/RMTReadXJT/RMTReadXJT.ino index d9e86ce8399..762225bcdf5 100644 --- a/libraries/ESP32/examples/RMT/RMTReadXJT/RMTReadXJT.ino +++ b/libraries/ESP32/examples/RMT/RMTReadXJT/RMTReadXJT.ino @@ -13,7 +13,7 @@ // limitations under the License. /** - * @brief This example demonstrates usage of RMT for receiving XJT D12 data + * @brief This example demonstrates usage of RMT for receiving XJT D16 data * * The output is the RMT data read and processed * @@ -21,7 +21,7 @@ // // Note: This example uses a FrSKY device communication -// using XJT D12 protocol +// using XJT D16 protocol // // ; 0 bit = 6us low/10us high // ; 1 bit = 14us low/10us high diff --git a/libraries/ESP32/examples/RMT/RMTWriteNeoPixel/RMTWriteNeoPixel.ino b/libraries/ESP32/examples/RMT/RMTWrite_RGB_LED/RMTWrite_RGB_LED.ino similarity index 93% rename from libraries/ESP32/examples/RMT/RMTWriteNeoPixel/RMTWriteNeoPixel.ino rename to libraries/ESP32/examples/RMT/RMTWrite_RGB_LED/RMTWrite_RGB_LED.ino index 0a8b8b8269f..74f0ac4f6b1 100644 --- a/libraries/ESP32/examples/RMT/RMTWriteNeoPixel/RMTWriteNeoPixel.ino +++ b/libraries/ESP32/examples/RMT/RMTWrite_RGB_LED/RMTWrite_RGB_LED.ino @@ -1,4 +1,4 @@ -// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -20,17 +20,17 @@ */ // The effect seen in (Espressif devkits) ESP32C6, ESP32H2, ESP32C3, ESP32S2 and ESP32S3 is like a Blink of RGB LED -#ifdef PIN_NEOPIXEL -#define BUILTIN_RGBLED_PIN PIN_NEOPIXEL +#ifdef PIN_LED_RGB +#define BUILTIN_RGBLED_PIN PIN_LED_RGB #else -#define BUILTIN_RGBLED_PIN 21 // ESP32 has no builtin RGB LED (PIN_NEOPIXEL) +#define BUILTIN_RGBLED_PIN 21 // ESP32 has no builtin RGB LED (PIN_LED_RGB) #endif #define NR_OF_LEDS 8 * 4 #define NR_OF_ALL_BITS 24 * NR_OF_LEDS // -// Note: This example uses Neopixel LED board, 32 LEDs chained one +// Note: This example uses a board with 32 WS2812b LEDs chained one // after another, each RGB LED has its 24 bit value // for color configuration (8b for each color) // diff --git a/libraries/ESP32/examples/RMT/RMT_CPUFreq_Test/RMT_CPUFreq_Test.ino b/libraries/ESP32/examples/RMT/RMT_CPUFreq_Test/RMT_CPUFreq_Test.ino index 93ab0182802..900f0f064f3 100644 --- a/libraries/ESP32/examples/RMT/RMT_CPUFreq_Test/RMT_CPUFreq_Test.ino +++ b/libraries/ESP32/examples/RMT/RMT_CPUFreq_Test/RMT_CPUFreq_Test.ino @@ -17,7 +17,7 @@ * that RMT works on any CPU/APB Frequency. * * It uses an ESP32 Arduino builtin RGB NeoLED function based on RMT: - * void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val) + * void rgbLedWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val) * * The output is a visual WS2812 RGB LED color change routine using each time a * different CPU Frequency, just to illustrate how it works. Serial output indicates @@ -26,10 +26,10 @@ // Default DevKit RGB LED GPIOs: // The effect seen in (Espressif devkits) ESP32C6, ESP32H2, ESP32C3, ESP32S2 and ESP32S3 is like a Blink of RGB LED -#ifdef PIN_NEOPIXEL -#define MY_LED_GPIO PIN_NEOPIXEL +#ifdef PIN_RGB_LED +#define MY_LED_GPIO PIN_RGB_LED #else -#define MY_LED_GPIO 21 // ESP32 has no builtin RGB LED (PIN_NEOPIXEL) +#define MY_LED_GPIO 21 // ESP32 has no builtin RGB LED (PIN_RGB_LED) #endif // Set the correct GPIO to any necessary by changing RGB_LED_GPIO value @@ -65,22 +65,22 @@ void loop() { Serial.updateBaudRate(115200); Serial.printf("\n--changed CPU Frequency to %lu MHz\n", getCpuFrequencyMhz()); - neopixelWrite(RGB_LED_GPIO, BRIGHTNESS, BRIGHTNESS, BRIGHTNESS); // White + rgbLedWrite(RGB_LED_GPIO, BRIGHTNESS, BRIGHTNESS, BRIGHTNESS); // White Serial.println("White"); delay(1000); - neopixelWrite(RGB_LED_GPIO, 0, 0, 0); // Off + rgbLedWrite(RGB_LED_GPIO, 0, 0, 0); // Off Serial.println("Off"); delay(1000); - neopixelWrite(RGB_LED_GPIO, BRIGHTNESS, 0, 0); // Red + rgbLedWrite(RGB_LED_GPIO, BRIGHTNESS, 0, 0); // Red Serial.println("Red"); delay(1000); - neopixelWrite(RGB_LED_GPIO, 0, BRIGHTNESS, 0); // Green + rgbLedWrite(RGB_LED_GPIO, 0, BRIGHTNESS, 0); // Green Serial.println("Green"); delay(1000); - neopixelWrite(RGB_LED_GPIO, 0, 0, BRIGHTNESS); // Blue + rgbLedWrite(RGB_LED_GPIO, 0, 0, BRIGHTNESS); // Blue Serial.println("Blue"); delay(1000); - neopixelWrite(RGB_LED_GPIO, 0, 0, 0); // Off + rgbLedWrite(RGB_LED_GPIO, 0, 0, 0); // Off Serial.println("Off"); delay(1000); } diff --git a/libraries/ESP32/examples/RMT/RMT_LED_Blink/RMT_LED_Blink.ino b/libraries/ESP32/examples/RMT/RMT_LED_Blink/RMT_LED_Blink.ino index 8c2b8db3cd1..1cdd2224ea5 100644 --- a/libraries/ESP32/examples/RMT/RMT_LED_Blink/RMT_LED_Blink.ino +++ b/libraries/ESP32/examples/RMT/RMT_LED_Blink/RMT_LED_Blink.ino @@ -1,4 +1,4 @@ -// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// Copyright 2025 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. @@ -13,16 +13,16 @@ // limitations under the License. /** - * @brief This example demonstrate how to use RMT to just blink a regular LED (GPIO) - * It uses all the different RMT Writing APIs to blink the LED by hardware, not being - * necessary the regular Blink code in Arduino. - * - * The output is the Blinking LED in the GPIO and a serial output describing what is - * going on, along the execution. - * - * The circuit is just a LED and a resistor of 270 ohms connected to the GPIO - * GPIO ---> resistor 270 ohms ---> + LED - ---> GND - */ + @brief This example demonstrate how to use RMT to just blink a regular LED (GPIO) + It uses all the different RMT Writing APIs to blink the LED by hardware, not being + necessary the regular Blink code in Arduino. + + The output is the Blinking LED in the GPIO and a serial output describing what is + going on, along the execution. + + The circuit is just a LED and a resistor of 270 ohms connected to the GPIO + GPIO ---> resistor 270 ohms ---> + LED - ---> GND +*/ #define BLINK_GPIO 2 @@ -232,7 +232,7 @@ void RMT_Mixed_Write_Blink() { Serial.println("===> rmtWrite() (Blocking Mode) to Blink the LED."); Serial.println("Blinking at 500ms on + 500ms off :: 4 blinks"); for (uint8_t i = 0; i < 4; i++) { - if (!rmtWrite(BLINK_GPIO, blink_500ms_rmt_data, RMT_SYMBOLS_OF(blink_500ms_rmt_data) - 2, RMT_WAIT_FOR_EVER)) { + if (!rmtWrite(BLINK_GPIO, blink_500ms_rmt_data, RMT_SYMBOLS_OF(blink_500ms_rmt_data) - 1, RMT_WAIT_FOR_EVER)) { Serial.println("===> rmtWrite Blink 0.5s Error!"); } } @@ -240,7 +240,7 @@ void RMT_Mixed_Write_Blink() { Serial.println("===> rmtWriteAsync() (Non-Blocking Mode) to Blink the LED."); Serial.println("Blinking at 250ms on + 250ms off :: 5 blinks"); for (uint8_t i = 0; i < 5; i++) { - if (!rmtWriteAsync(BLINK_GPIO, blink_250ms_rmt_data, RMT_SYMBOLS_OF(blink_250ms_rmt_data) - 2)) { + if (!rmtWriteAsync(BLINK_GPIO, blink_250ms_rmt_data, RMT_SYMBOLS_OF(blink_250ms_rmt_data) - 1)) { Serial.println("===> rmtWrite Blink 0.25s Error!"); } // wait (blocks) until all the data is sent out @@ -267,9 +267,11 @@ void RMT_Loop_Write_Blink() { Serial.println("===> rmtWriteLooping Blink 0.25s Error!"); } delay(5000); + Serial.println("Blinking OFF for 2 seconds"); - if (!rmtWriteLooping(BLINK_GPIO, NULL, 0)) { - Serial.println("===> rmtWriteLooping Blink OFF Error!"); + rmt_data_t blink_STOP_rmt_data[] = {{0, 0, 0, 0}}; + if (!rmtWrite(BLINK_GPIO, blink_STOP_rmt_data, RMT_SYMBOLS_OF(blink_STOP_rmt_data), RMT_WAIT_FOR_EVER)) { + Serial.println("===> rmtWrite Blink STOP Error!"); } delay(2000); } @@ -278,19 +280,19 @@ void RMT_Single_Write_Blocking_Blink() { Serial.println("Using RMT Writing and its Completion to blink an LED."); Serial.println("Blinking at 1s on + 1s off :: 2 blinks"); for (uint8_t i = 0; i < 2; i++) { - if (!rmtWrite(BLINK_GPIO, blink_1s_rmt_data, RMT_SYMBOLS_OF(blink_1s_rmt_data) - 2, RMT_WAIT_FOR_EVER)) { + if (!rmtWrite(BLINK_GPIO, blink_1s_rmt_data, RMT_SYMBOLS_OF(blink_1s_rmt_data) - 1, RMT_WAIT_FOR_EVER)) { Serial.println("===> rmtWrite Blink 1s Error!"); } } Serial.println("Blinking at 500ms on + 500ms off :: 4 blinks"); for (uint8_t i = 0; i < 4; i++) { - if (!rmtWrite(BLINK_GPIO, blink_500ms_rmt_data, RMT_SYMBOLS_OF(blink_500ms_rmt_data) - 2, RMT_WAIT_FOR_EVER)) { + if (!rmtWrite(BLINK_GPIO, blink_500ms_rmt_data, RMT_SYMBOLS_OF(blink_500ms_rmt_data) - 1, RMT_WAIT_FOR_EVER)) { Serial.println("===> rmtWrite Blink 0.5s Error!"); } } Serial.println("Blinking at 250ms on + 250ms off :: 8 blinks"); for (uint8_t i = 0; i < 8; i++) { - if (!rmtWrite(BLINK_GPIO, blink_250ms_rmt_data, RMT_SYMBOLS_OF(blink_250ms_rmt_data) - 2, RMT_WAIT_FOR_EVER)) { + if (!rmtWrite(BLINK_GPIO, blink_250ms_rmt_data, RMT_SYMBOLS_OF(blink_250ms_rmt_data) - 1, RMT_WAIT_FOR_EVER)) { Serial.println("===> rmtWrite Blink 0.25s Error!"); } } @@ -302,7 +304,7 @@ void RMT_Write_Aync_Non_Blocking_Blink() { Serial.println("Using RMT Async Writing and its Completion to blink an LED."); Serial.println("Blinking at 1s on + 1s off :: 5 blinks"); for (uint8_t i = 0; i < 5; i++) { - if (!rmtWriteAsync(BLINK_GPIO, blink_1s_rmt_data, RMT_SYMBOLS_OF(blink_1s_rmt_data) - 2)) { + if (!rmtWriteAsync(BLINK_GPIO, blink_1s_rmt_data, RMT_SYMBOLS_OF(blink_1s_rmt_data) - 1)) { Serial.println("===> rmtWrite Blink 1s Error!"); } // wait (blocks) until all the data is sent out @@ -310,7 +312,7 @@ void RMT_Write_Aync_Non_Blocking_Blink() { } Serial.println("Blinking at 500ms on + 500ms off :: 5 blinks"); for (uint8_t i = 0; i < 5; i++) { - if (!rmtWriteAsync(BLINK_GPIO, blink_500ms_rmt_data, RMT_SYMBOLS_OF(blink_500ms_rmt_data) - 2)) { + if (!rmtWriteAsync(BLINK_GPIO, blink_500ms_rmt_data, RMT_SYMBOLS_OF(blink_500ms_rmt_data) - 1)) { Serial.println("===> rmtWrite Blink 0.5s Error!"); } // wait (blocks) until all the data is sent out @@ -318,7 +320,7 @@ void RMT_Write_Aync_Non_Blocking_Blink() { } Serial.println("Blinking at 250ms on + 250ms off :: 5 blinks"); for (uint8_t i = 0; i < 5; i++) { - if (!rmtWriteAsync(BLINK_GPIO, blink_250ms_rmt_data, RMT_SYMBOLS_OF(blink_250ms_rmt_data) - 2)) { + if (!rmtWriteAsync(BLINK_GPIO, blink_250ms_rmt_data, RMT_SYMBOLS_OF(blink_250ms_rmt_data) - 1)) { Serial.println("===> rmtWrite Blink 0.25s Error!"); } // wait (blocks) until all the data is sent out @@ -345,7 +347,6 @@ void setup() { RMT_Mixed_Write_Blink(); Serial.println("End of Mixed Calls testing"); - delay(1000); Serial.println("\n==============================="); Serial.println("Starting a Blinking sequence..."); diff --git a/libraries/ESP32/examples/ResetReason/ResetReason/ResetReason.ino b/libraries/ESP32/examples/ResetReason/ResetReason/ResetReason.ino index 3c9dbb9b12f..0104c6422f2 100644 --- a/libraries/ESP32/examples/ResetReason/ResetReason/ResetReason.ino +++ b/libraries/ESP32/examples/ResetReason/ResetReason/ResetReason.ino @@ -26,6 +26,8 @@ #include "esp32c6/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/rtc.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif diff --git a/libraries/ESP32/examples/Serial/OnReceiveError_BREAK_Demo/OnReceiveError_BREAK_Demo.ino b/libraries/ESP32/examples/Serial/OnReceiveError_BREAK_Demo/OnReceiveError_BREAK_Demo.ino index caf0cde501a..209cf8922be 100644 --- a/libraries/ESP32/examples/Serial/OnReceiveError_BREAK_Demo/OnReceiveError_BREAK_Demo.ino +++ b/libraries/ESP32/examples/Serial/OnReceiveError_BREAK_Demo/OnReceiveError_BREAK_Demo.ino @@ -35,7 +35,7 @@ before reading data, if necessary. In long UART transmissions, some data will be received based on FIFO Full parameter, and whenever - an error ocurs, it will raise the UART error interrupt. + an error occurs, it will raise the UART error interrupt. This sketch produces BREAK UART error in the beginning of a transmission and also at the end of a transmission. It will be possible to understand the order of the events in the logs. @@ -80,7 +80,11 @@ void onReceiveFunction() { received_bytes = received_bytes + available; Serial.printf("onReceive Callback:: There are %d bytes available: {", available); while (available--) { - Serial.print((char)Serial1.read()); + char c = Serial1.read(); + Serial.printf("0x%x='%c'", c, c); + if (available) { + Serial.print(" "); + } } Serial.println("}"); } diff --git a/libraries/ESP32/examples/Serial/RS485_Echo_Demo/RS485_Echo_Demo.ino b/libraries/ESP32/examples/Serial/RS485_Echo_Demo/RS485_Echo_Demo.ino index dfd4d452690..50ee6f53fe2 100644 --- a/libraries/ESP32/examples/Serial/RS485_Echo_Demo/RS485_Echo_Demo.ino +++ b/libraries/ESP32/examples/Serial/RS485_Echo_Demo/RS485_Echo_Demo.ino @@ -21,9 +21,6 @@ void setup() { Serial.begin(115200); - while (!Serial) { - delay(10); - } RS485.begin(9600, SERIAL_8N1, RS485_RX_PIN, RS485_TX_PIN); while (!RS485) { diff --git a/libraries/ESP32/examples/Serial/RxFIFOFull_Demo/RxFIFOFull_Demo.ino b/libraries/ESP32/examples/Serial/RxFIFOFull_Demo/RxFIFOFull_Demo.ino index e18dbbe5a5b..7722ef6f47a 100644 --- a/libraries/ESP32/examples/Serial/RxFIFOFull_Demo/RxFIFOFull_Demo.ino +++ b/libraries/ESP32/examples/Serial/RxFIFOFull_Demo/RxFIFOFull_Demo.ino @@ -91,9 +91,9 @@ void testAndReport(uint8_t fifoFull) { } } - uint32_t pastTime = millis() - now; + uint32_t pastTime = millis() - now; // codespell:ignore pasttime Serial.printf("\nIt has sent %d bytes from Serial1 TX to Serial1 RX\n", sentBytes); - Serial.printf("It took %lu milliseconds to read %d bytes\n", pastTime, bytesReceived); + Serial.printf("It took %lu milliseconds to read %d bytes\n", pastTime, bytesReceived); // codespell:ignore pasttime Serial.printf("Per execution Serial.read() number of bytes data and time information:\n"); for (i = 0; i < DATA_SIZE; i++) { Serial.printf("#%03d - Received %03lu bytes after %lu ms.\n", i, bytesJustReceived[i], i > 0 ? timeStamp[i] - timeStamp[i - 1] : timeStamp[i] - now); diff --git a/libraries/ESP32/examples/Serial/RxTimeout_Demo/RxTimeout_Demo.ino b/libraries/ESP32/examples/Serial/RxTimeout_Demo/RxTimeout_Demo.ino index acddd73a44c..35d2da5c199 100644 --- a/libraries/ESP32/examples/Serial/RxTimeout_Demo/RxTimeout_Demo.ino +++ b/libraries/ESP32/examples/Serial/RxTimeout_Demo/RxTimeout_Demo.ino @@ -21,6 +21,15 @@ If UART receives less than 120 bytes, it will wait RX Timeout to understand that the bus is IDLE and then copy the data from the FIFO to the Arduino internal buffer, making it available to the Arduino API. + There is an important detail about how HardwareSerial works using ESP32 and ESP32-S2: + If the baud rate is lower than 250,000, it will select REF_TICK as clock source in order to avoid that + the baud rate may change when the CPU Frequency is changed. Default UART clock source is APB, which changes + when CPU clock source is also changed. But when it selects REF_TICK as UART clock source, RX Timeout is limited to 1. + Therefore, in order to change the ESP32/ESP32-S2 RX Timeout it is necessary to fix the UART Clock Source to APB. + + In the case of the other SoC, such as ESP32-S3, C3, C6, H2 and P4, there is no such RX Timeout limitation. + Those will set the UART Source Clock as XTAL, which allows the baud rate to be high and it is steady, not + changing with the CPU Frequency. */ #include @@ -45,6 +54,12 @@ void setup() { // UART1 will have its RX<->TX cross connected // GPIO4 <--> GPIO5 using external wire +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 + // UART_CLK_SRC_APB will allow higher values of RX Timeout + // default for ESP32 and ESP32-S2 is REF_TICK which limits the RX Timeout to 1 + // setClockSource() must be called before begin() + Serial1.setClockSource(UART_CLK_SRC_APB); +#endif Serial1.begin(BAUD, SERIAL_8N1, RXPIN, TXPIN); // Rx = 4, Tx = 5 will work for ESP32, S2, S3 and C3 #if USE_INTERNAL_PIN_LOOPBACK uart_internal_loopback(TEST_UART, RXPIN); @@ -85,9 +100,9 @@ void testAndReport(uint8_t rxTimeout) { } } - uint32_t pastTime = millis() - now; + uint32_t pastTime = millis() - now; // codespell:ignore pasttime Serial.printf("\nIt has sent %d bytes from Serial1 TX to Serial1 RX\n", sentBytes); - Serial.printf("It took %lu milliseconds to read %d bytes\n", pastTime, bytesReceived); + Serial.printf("It took %lu milliseconds to read %d bytes\n", pastTime, bytesReceived); // codespell:ignore pasttime Serial.print("Received data: ["); Serial.write(dataReceived, DATA_SIZE); Serial.println("]"); diff --git a/libraries/ESP32/examples/Serial/Serial_STD_Func_OnReceive/Serial_STD_Func_OnReceive.ino b/libraries/ESP32/examples/Serial/Serial_STD_Func_OnReceive/Serial_STD_Func_OnReceive.ino index eff21a1939e..3c5ff0ba6fc 100644 --- a/libraries/ESP32/examples/Serial/Serial_STD_Func_OnReceive/Serial_STD_Func_OnReceive.ino +++ b/libraries/ESP32/examples/Serial/Serial_STD_Func_OnReceive/Serial_STD_Func_OnReceive.ino @@ -11,7 +11,7 @@ */ // soc/soc_caps.h has information about each SoC target -// in this example, we use SOC_UART_NUM that goes from 1 to 3, +// in this example, we use SOC_UART_HP_NUM that goes from 1 to 3, // depending on the number of available UARTs in the ESP32xx // This makes the code transparent to what SoC is used. #include "soc/soc_caps.h" @@ -24,9 +24,9 @@ #define TXPIN 5 // GPIO 5 => TX for Serial1 or Serial2 // declare testingSerial (as reference) related to TEST_UART number defined above (only for Serial1 and Serial2) -#if SOC_UART_NUM > 1 && TEST_UART == 1 +#if SOC_UART_HP_NUM > 1 && TEST_UART == 1 HardwareSerial &testingSerial = Serial1; -#elif SOC_UART_NUM > 2 && TEST_UART == 2 +#elif SOC_UART_HP_NUM > 2 && TEST_UART == 2 HardwareSerial &testingSerial = Serial2; #endif @@ -36,11 +36,11 @@ void processOnReceiving(HardwareSerial &mySerial) { int8_t uart_num = -1; if (&mySerial == &Serial0) { uart_num = 0; -#if SOC_UART_NUM > 1 +#if SOC_UART_HP_NUM > 1 } else if (&mySerial == &Serial1) { uart_num = 1; #endif -#if SOC_UART_NUM > 2 +#if SOC_UART_HP_NUM > 2 } else if (&mySerial == &Serial2) { uart_num = 2; #endif diff --git a/libraries/ESP32/examples/Serial/onReceiveExample/onReceiveExample.ino b/libraries/ESP32/examples/Serial/onReceiveExample/onReceiveExample.ino index fe66b07b875..17d800b3b39 100644 --- a/libraries/ESP32/examples/Serial/onReceiveExample/onReceiveExample.ino +++ b/libraries/ESP32/examples/Serial/onReceiveExample/onReceiveExample.ino @@ -5,20 +5,20 @@ void HardwareSerial::onReceive(OnReceiveCb function, bool onlyOnTimeout = false) It is possible to register an UART callback function that will be called - every time that UART receives data and an associated interrupt is generated. + every time that UART receives data and an associated UART interrupt is generated. - In summary, HardwareSerial::onReceive() works like an RX Interrupt callback, that can be adjusted - using HardwareSerial::setRxFIFOFull() and HardwareSerial::setRxTimeout(). + In summary, HardwareSerial::onReceive() works like an RX Interrupt callback, that + can be adjusted using HardwareSerial::setRxFIFOFull() and HardwareSerial::setRxTimeout(). - OnReceive will be called, while receiving a stream of data, when every 120 bytes are received (default FIFO Full), - which may not help in case that the application needs to get all data at once before processing it. - Therefore, a way to make it work is by detecting the end of a stream transmission. This can be based on a protocol - or based on timeout with the UART line in idle (no data received - this is the case of this example). + In case that is not changed or it is set to , the callback function is + executed whenever any event happens first (FIFO Full or RX Timeout). + OnReceive will be called when every 120 bytes are received(default FIFO Full), + or when RX Timeout occurs after 1 UART symbol by default. - In some cases, it is necessary to wait for receiving all the data before processing it and parsing the - UART input. This example demonstrates a way to create a String with all data received from UART0 and - signaling it using a Mutex for another task to process it. This example uses a timeout of 500ms as a way to - know when the reception of data has finished. + This example demonstrates a way to create a String with all data received from UART0 only + after RX Timeout. This example uses an RX timeout of about 3.5 Symbols as a way to know + when the reception of data has finished. + In order to achieve it, the sketch sets to . The onReceive() callback is called whenever the RX ISR is triggered. It can occur because of two possible events: @@ -34,90 +34,73 @@ 2- UART RX Timeout: it happens, based on a timeout equivalent to a number of symbols at the current baud rate. If the UART line is idle for this timeout, it will raise an interrupt. - This time can be changed by HardwareSerial::setRxTimeout(uint8_t rxTimeout) + This time can be changed by HardwareSerial::setRxTimeout(uint8_t rxTimeout). + is bound to the clock source. + In order to use it properly, ESP32 and ESP32-S2 shall set the UART Clock Source to APB. When any of those two interrupts occur, IDF UART driver will copy FIFO data to its internal RingBuffer and then Arduino can read such data. At the same time, Arduino Layer will execute the callback function defined with HardwareSerial::onReceive(). - parameter (default false) can be used by the application to tell Arduino to - only execute the callback when the second event above happens (Rx Timeout). At this time all - received data will be available to be read by the Arduino application. But if the number of - received bytes is higher than the FIFO space, it will generate an error of FIFO overflow. - In order to avoid such problem, the application shall set an appropriate RX buffer size using + parameter can be used by the application to tell Arduino to only execute + the callback when Rx Timeout happens, by setting it to . + At this time all received data will be available to be read by the Arduino application. + The application shall set an appropriate RX buffer size using HardwareSerial::setRxBufferSize(size_t new_size) before executing begin() for the Serial port. -*/ -// this will make UART0 work in any case (using or not USB) -#if ARDUINO_USB_CDC_ON_BOOT -#define UART0 Serial0 -#else -#define UART0 Serial -#endif + MODBUS timeout of 3.5 symbol is based on these documents: + https://www.automation.com/en-us/articles/2012-1/introduction-to-modbus + https://minimalmodbus.readthedocs.io/en/stable/serialcommunication.html +*/ // global variable to keep the results from onReceive() String uart_buffer = ""; -// a pause of a half second in the UART transmission is considered the end of transmission. -const uint32_t communicationTimeout_ms = 500; - -// Create a mutex for the access to uart_buffer -// only one task can read/write it at a certain time -SemaphoreHandle_t uart_buffer_Mutex = NULL; - -// UART_RX_IRQ will be executed as soon as data is received by the UART -// This is a callback function executed from a high priority -// task created when onReceive() is used +// The Modbus RTU standard prescribes a silent period corresponding to 3.5 characters between each +// message, to be able to figure out where one message ends and the next one starts. +const uint32_t modbusRxTimeoutLimit = 4; +const uint32_t baudrate = 19200; + +// UART_RX_IRQ will be executed as soon as data is received by the UART and an RX Timeout occurs +// This is a callback function executed from a high priority monitor task +// All data will be buffered into RX Buffer, which may have its size set to whatever necessary void UART0_RX_CB() { - // take the mutex, waits forever until loop() finishes its processing - if (xSemaphoreTake(uart_buffer_Mutex, portMAX_DELAY)) { - uint32_t now = millis(); // tracks timeout - while ((millis() - now) < communicationTimeout_ms) { - if (UART0.available()) { - uart_buffer += (char)UART0.read(); - now = millis(); // reset the timer - } - } - // releases the mutex for data processing - xSemaphoreGive(uart_buffer_Mutex); + while (Serial0.available()) { + uart_buffer += (char)Serial0.read(); } } // setup() and loop() are functions executed by a low priority task // Therefore, there are 2 tasks running when using onReceive() void setup() { - UART0.begin(115200); - - // creates a mutex object to control access to uart_buffer - uart_buffer_Mutex = xSemaphoreCreateMutex(); - if (uart_buffer_Mutex == NULL) { - log_e("Error creating Mutex. Sketch will fail."); - while (true) { - UART0.println("Mutex error (NULL). Program halted."); - delay(2000); - } - } - - UART0.onReceive(UART0_RX_CB); // sets the callback function - UART0.println("Send data to UART0 in order to activate the RX callback"); + // Using Serial0 will work in any case (using or not USB CDC on Boot) +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 + // UART_CLK_SRC_APB will allow higher values of RX Timeout + // default for ESP32 and ESP32-S2 is REF_TICK which limits the RX Timeout to 1 + // setClockSource() must be called before begin() + Serial0.setClockSource(UART_CLK_SRC_APB); +#endif + // the amount of data received or waiting to be proessed shall not exceed this limit of 1024 bytes + Serial0.setRxBufferSize(1024); // default is 256 bytes + Serial0.begin(baudrate); // default pins and default mode 8N1 (8 bits data, no parity bit, 1 stopbit) + // set RX Timeout based on UART symbols ~ 3.5 symbols of 11 bits (MODBUS standard) ~= 2 ms at 19200 + Serial0.setRxTimeout(modbusRxTimeoutLimit); // 4 symbols at 19200 8N1 is about 2.08 ms (40 bits) + // sets the callback function that will be executed only after RX Timeout + Serial0.onReceive(UART0_RX_CB, true); + Serial0.println("Send data using Serial Monitor in order to activate the RX callback"); } uint32_t counter = 0; void loop() { + // String is filled by the UART Callback whenever data is received and RX Timeout occurs if (uart_buffer.length() > 0) { - // signals that the onReceive function shall not change uart_buffer while processing - if (xSemaphoreTake(uart_buffer_Mutex, portMAX_DELAY)) { - // process the received data from UART0 - example, just print it beside a counter - UART0.print("["); - UART0.print(counter++); - UART0.print("] ["); - UART0.print(uart_buffer.length()); - UART0.print(" bytes] "); - UART0.println(uart_buffer); - uart_buffer = ""; // reset uart_buffer for the next UART reading - // releases the mutex for more data to be received - xSemaphoreGive(uart_buffer_Mutex); - } + // process the received data from Serial - example, just print it beside a counter + Serial0.print("["); + Serial0.print(counter++); + Serial0.print("] ["); + Serial0.print(uart_buffer.length()); + Serial0.print(" bytes] "); + Serial0.println(uart_buffer); + uart_buffer = ""; // reset uart_buffer for the next UART reading } - UART0.println("Sleeping for 1 second..."); - delay(1000); + delay(1); } diff --git a/libraries/ESP32/examples/Template/ExampleTemplate/README.md b/libraries/ESP32/examples/Template/ExampleTemplate/README.md index f5aa7b35e86..91b50967e9e 100644 --- a/libraries/ESP32/examples/Template/ExampleTemplate/README.md +++ b/libraries/ESP32/examples/Template/ExampleTemplate/README.md @@ -64,10 +64,6 @@ To get more information about the Espressif boards see [Espressif Development Ki * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file. - ## Example/Log Output ==(OPTIONAL)== ==*Add the log/serial output here!*== diff --git a/libraries/ESP32/examples/Time/SimpleTime/SimpleTime.ino b/libraries/ESP32/examples/Time/SimpleTime/SimpleTime.ino index 8c76f15d483..d82e5f2977d 100644 --- a/libraries/ESP32/examples/Time/SimpleTime/SimpleTime.ino +++ b/libraries/ESP32/examples/Time/SimpleTime/SimpleTime.ino @@ -33,14 +33,6 @@ void setup() { // First step is to configure WiFi STA and connect in order to get the current time and date. Serial.printf("Connecting to %s ", ssid); WiFi.begin(ssid, password); - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - } - Serial.println(" CONNECTED"); - - // set notification call-back function - sntp_set_time_sync_notification_cb(timeavailable); /** * NTP server address could be acquired via DHCP, @@ -52,6 +44,15 @@ void setup() { */ esp_sntp_servermode_dhcp(1); // (optional) + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(" CONNECTED"); + + // set notification call-back function + sntp_set_time_sync_notification_cb(timeavailable); + /** * This will set configured ntp servers and constant TimeZone/daylightOffset * should be OK if your time zone does not need to adjust daylightOffset twice a year, diff --git a/libraries/ESP32/examples/Time/SimpleTime/ci.json b/libraries/ESP32/examples/Time/SimpleTime/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/ESP32/examples/Time/SimpleTime/ci.json +++ b/libraries/ESP32/examples/Time/SimpleTime/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/ESP32/examples/Timer/RepeatTimer/RepeatTimer.ino b/libraries/ESP32/examples/Timer/RepeatTimer/RepeatTimer.ino index 18fdc8035a5..e4ef7bc865b 100644 --- a/libraries/ESP32/examples/Timer/RepeatTimer/RepeatTimer.ino +++ b/libraries/ESP32/examples/Timer/RepeatTimer/RepeatTimer.ino @@ -33,7 +33,7 @@ void setup() { Serial.begin(115200); // Set BTN_STOP_ALARM to input mode - pinMode(BTN_STOP_ALARM, INPUT); + pinMode(BTN_STOP_ALARM, INPUT_PULLUP); // Create semaphore to inform us when the timer has fired timerSemaphore = xSemaphoreCreateBinary(); diff --git a/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino b/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino index 9acfdddb3a1..43f3bc36592 100644 --- a/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino +++ b/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino @@ -1,7 +1,7 @@ /* This is an example how to use Touch Intrrerupts -The sketh will tell when it is touched and then relesased as like a push-button +The sketch will tell when it is touched and then released as like a push-button This method based on touchInterruptSetThresholdDirection() is only available for ESP32 */ diff --git a/libraries/ESP32/examples/Touch/TouchButton/ci.json b/libraries/ESP32/examples/Touch/TouchButton/ci.json index 1af543242e3..cec76a84f9d 100644 --- a/libraries/ESP32/examples/Touch/TouchButton/ci.json +++ b/libraries/ESP32/examples/Touch/TouchButton/ci.json @@ -1,9 +1,5 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } + "requires": [ + "CONFIG_SOC_TOUCH_VERSION_1=y" + ] } diff --git a/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino b/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino index 5dc9bfeed3f..df9b3f41149 100644 --- a/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino +++ b/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino @@ -1,7 +1,7 @@ /* This is an example how to use Touch Intrrerupts -The sketh will tell when it is touched and then relesased as like a push-button +The sketch will tell when it is touched and then released as like a push-button This method based on touchInterruptGetLastStatus() is only available for ESP32 S2 and S3 */ diff --git a/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json b/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json index e7d65393dd6..2710fa7940e 100644 --- a/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json +++ b/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_TOUCH_VERSION_2=y" + ] } diff --git a/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino b/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino index 0f0880902fb..3b4e5f0b9e9 100644 --- a/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino +++ b/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino @@ -3,7 +3,12 @@ This is an example how to use Touch Intrrerupts The bigger the threshold, the more sensible is the touch */ +#if CONFIG_IDF_TARGET_ESP32P4 +int threshold = 0; // when 0 is used, the benchmarked value will be used +#else int threshold = 40; +#endif + bool touch1detected = false; bool touch2detected = false; diff --git a/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json b/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json index 25c42144223..c0ecf9fc0a5 100644 --- a/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json +++ b/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json @@ -1,7 +1,5 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" + ] } diff --git a/libraries/ESP32/examples/Touch/TouchRead/ci.json b/libraries/ESP32/examples/Touch/TouchRead/ci.json index 25c42144223..c0ecf9fc0a5 100644 --- a/libraries/ESP32/examples/Touch/TouchRead/ci.json +++ b/libraries/ESP32/examples/Touch/TouchRead/ci.json @@ -1,7 +1,5 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" + ] } diff --git a/libraries/ESP32/examples/Utilities/HEXBuilder/HEXBuilder.ino b/libraries/ESP32/examples/Utilities/HEXBuilder/HEXBuilder.ino index 069368da89f..f580a763b54 100644 --- a/libraries/ESP32/examples/Utilities/HEXBuilder/HEXBuilder.ino +++ b/libraries/ESP32/examples/Utilities/HEXBuilder/HEXBuilder.ino @@ -2,9 +2,7 @@ void setup() { Serial.begin(115200); - while (!Serial) { - delay(10); - } + Serial.println("\n\n\nStart."); // Convert a HEX string like 6c6c6f20576f726c64 to a binary buffer diff --git a/libraries/ESP32/examples/Utilities/MD5Builder/MD5Builder.ino b/libraries/ESP32/examples/Utilities/MD5Builder/MD5Builder.ino index da692bbfcde..cb1b350d834 100644 --- a/libraries/ESP32/examples/Utilities/MD5Builder/MD5Builder.ino +++ b/libraries/ESP32/examples/Utilities/MD5Builder/MD5Builder.ino @@ -12,9 +12,7 @@ void setup() { Serial.begin(115200); - while (!Serial) { - delay(10); - } + Serial.println("\n\n\nStart."); // Check if a password obfuscated in an MD5 actually diff --git a/libraries/ESP32/examples/Utilities/SHA1Builder/SHA1Builder.ino b/libraries/ESP32/examples/Utilities/SHA1Builder/SHA1Builder.ino index 09cae874592..251307c4016 100644 --- a/libraries/ESP32/examples/Utilities/SHA1Builder/SHA1Builder.ino +++ b/libraries/ESP32/examples/Utilities/SHA1Builder/SHA1Builder.ino @@ -13,9 +13,7 @@ void setup() { Serial.begin(115200); - while (!Serial) { - delay(10); - } + Serial.println("\n\n\nStart."); // Check if a password obfuscated in an SHA1 actually diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino deleted file mode 100644 index 67b9123c937..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2023 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 ESP Zigbee stack 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. - */ - -#ifndef ZIGBEE_MODE_ED -#error "Zigbee end device mode is not selected in Tools->Zigbee mode" -#endif - -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - -#define LED_PIN RGB_BUILTIN - -/* Default End Device config */ -#define ESP_ZB_ZED_CONFIG() \ - { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ - .nwk_cfg = { \ - .zed_cfg = \ - { \ - .ed_timeout = ED_AGING_TIMEOUT, \ - .keep_alive = ED_KEEP_ALIVE, \ - }, \ - }, \ - } - -#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ - { .radio_mode = ZB_RADIO_MODE_NATIVE, } - -#define ESP_ZB_DEFAULT_HOST_CONFIG() \ - { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, } - -/* Zigbee configuration */ -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN -#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ -#define HA_ESP_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ -#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ - -/********************* Zigbee functions **************************/ -static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { - ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); -} - -void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { - uint32_t *p_sg_p = signal_struct->p_app_signal; - esp_err_t err_status = signal_struct->esp_err_status; - esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; - switch (sig_type) { - case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: - log_i("Zigbee stack initialized"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); - break; - case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: - case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: - if (err_status == ESP_OK) { - log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); - if (esp_zb_bdb_is_factory_new()) { - log_i("Start network formation"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); - } else { - log_i("Device rebooted"); - } - } else { - /* commissioning failed */ - log_w("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); - } - break; - case ESP_ZB_BDB_SIGNAL_STEERING: - if (err_status == ESP_OK) { - esp_zb_ieee_addr_t extended_pan_id; - esp_zb_get_extended_pan_id(extended_pan_id); - log_i( - "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", - extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], - extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address() - ); - } else { - log_i("Network steering was not successful (status: %s)", esp_err_to_name(err_status)); - esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); - } - break; - default: log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; - } -} - -static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { - esp_err_t ret = ESP_OK; - switch (callback_id) { - case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; - default: log_w("Receive Zigbee action(0x%x) callback", callback_id); break; - } - return ret; -} - -static void esp_zb_task(void *pvParameters) { - esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZED_CONFIG(); - esp_zb_init(&zb_nwk_cfg); - esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); - esp_zb_ep_list_t *esp_zb_on_off_light_ep = esp_zb_on_off_light_ep_create(HA_ESP_LIGHT_ENDPOINT, &light_cfg); - esp_zb_device_register(esp_zb_on_off_light_ep); - esp_zb_core_action_handler_register(zb_action_handler); - esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); - - //Erase NVRAM before creating connection to new Coordinator - esp_zb_nvram_erase_at_start(true); //Comment out this line to erase NVRAM data if you are conneting to new Coordinator - - ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_main_loop_iteration(); -} - -/* Handle the light attribute */ - -static esp_err_t zb_attribute_handler(const esp_zb_zcl_set_attr_value_message_t *message) { - esp_err_t ret = ESP_OK; - bool light_state = 0; - - if (!message) { - log_e("Empty message"); - } - if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { - log_e("Received message: error status(%d)", message->info.status); - } - - log_i( - "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, - message->attribute.data.size - ); - if (message->info.dst_endpoint == HA_ESP_LIGHT_ENDPOINT) { - if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { - if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; - log_i("Light sets to %s", light_state ? "On" : "Off"); - neopixelWrite(LED_PIN, 255 * light_state, 255 * light_state, 255 * light_state); // Toggle light - } - } - } - return ret; -} - -/********************* Arduino functions **************************/ -void setup() { - // Init Zigbee - esp_zb_platform_config_t config = { - .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), - }; - ESP_ERROR_CHECK(esp_zb_platform_config(&config)); - - // Init RMT and leave light OFF - neopixelWrite(LED_PIN, 0, 0, 0); - - // Start Zigbee task - xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); -} - -void loop() { - //empty, zigbee running in task -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/ci.json b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/ci.json deleted file mode 100644 index 7cfaa76784d..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/ci.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/Zigbee_Light_Switch.ino b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/Zigbee_Light_Switch.ino deleted file mode 100644 index 6c19b145f35..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/Zigbee_Light_Switch.ino +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright 2023 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 ESP Zigbee stack to control a light bulb. - * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. - * 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. - */ - -#ifndef ZIGBEE_MODE_ZCZR -#error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" -#endif - -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - -/* Switch configuration */ -#define GPIO_INPUT_IO_TOGGLE_SWITCH GPIO_NUM_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, -} switch_func_t; - -typedef struct { - uint8_t pin; - switch_func_t func; -} switch_func_pair_t; - -typedef enum { - SWITCH_IDLE, - SWITCH_PRESS_ARMED, - SWITCH_PRESS_DETECTED, - SWITCH_PRESSED, - SWITCH_RELEASE_DETECTED, -} switch_state_t; - -static switch_func_pair_t button_func_pair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; - -/* Default Coordinator config */ -#define ESP_ZB_ZC_CONFIG() \ - { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, .install_code_policy = INSTALLCODE_POLICY_ENABLE, .nwk_cfg = { \ - .zczr_cfg = \ - { \ - .max_children = MAX_CHILDREN, \ - }, \ - } \ - } - -#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ - { .radio_mode = ZB_RADIO_MODE_NATIVE, } - -#define ESP_ZB_DEFAULT_HOST_CONFIG() \ - { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, } - -typedef struct light_bulb_device_params_s { - esp_zb_ieee_addr_t ieee_addr; - uint8_t endpoint; - uint16_t short_addr; -} light_bulb_device_params_t; - -/* Zigbee configuration */ -#define MAX_CHILDREN 10 /* the max amount of connected devices */ -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define HA_ONOFF_SWITCH_ENDPOINT 1 /* esp light switch device endpoint */ -#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ - -/********************* Zigbee functions **************************/ -static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) { - if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { - /* implemented light switch toggle functionality */ - esp_zb_zcl_on_off_cmd_t cmd_req; - cmd_req.zcl_basic_cmd.src_endpoint = HA_ONOFF_SWITCH_ENDPOINT; - cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; - log_i("Send 'on_off toggle' command"); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - } -} - -static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { - ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); -} - -static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - log_i("Bound successfully!"); - if (user_ctx) { - light_bulb_device_params_t *light = (light_bulb_device_params_t *)user_ctx; - log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); - free(light); - } - } -} - -static void user_find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - log_i("Found light"); - esp_zb_zdo_bind_req_param_t bind_req; - light_bulb_device_params_t *light = (light_bulb_device_params_t *)malloc(sizeof(light_bulb_device_params_t)); - light->endpoint = endpoint; - light->short_addr = addr; - esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); - esp_zb_get_long_address(bind_req.src_address); - bind_req.src_endp = HA_ONOFF_SWITCH_ENDPOINT; - bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; - bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; - memcpy(bind_req.dst_address_u.addr_long, light->ieee_addr, sizeof(esp_zb_ieee_addr_t)); - bind_req.dst_endp = endpoint; - bind_req.req_dst_addr = esp_zb_get_short_address(); - log_i("Try to bind On/Off"); - esp_zb_zdo_device_bind_req(&bind_req, bind_cb, (void *)light); - } -} - -void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { - uint32_t *p_sg_p = signal_struct->p_app_signal; - esp_err_t err_status = signal_struct->esp_err_status; - esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; - esp_zb_zdo_signal_device_annce_params_t *dev_annce_params = NULL; - switch (sig_type) { - case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: - log_i("Zigbee stack initialized"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); - break; - case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: - case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: - if (err_status == ESP_OK) { - log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); - if (esp_zb_bdb_is_factory_new()) { - log_i("Start network formation"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION); - } else { - log_i("Device rebooted"); - log_i("Openning network for joining for %d seconds", 180); - esp_zb_bdb_open_network(180); - } - } else { - log_e("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); - } - break; - case ESP_ZB_BDB_SIGNAL_FORMATION: - if (err_status == ESP_OK) { - esp_zb_ieee_addr_t extended_pan_id; - esp_zb_get_extended_pan_id(extended_pan_id); - log_i( - "Formed network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", - extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], - extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address() - ); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); - } else { - log_i("Restart network formation (status: %s)", esp_err_to_name(err_status)); - esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_FORMATION, 1000); - } - break; - case ESP_ZB_BDB_SIGNAL_STEERING: - if (err_status == ESP_OK) { - log_i("Network steering started"); - } - break; - case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE: - dev_annce_params = (esp_zb_zdo_signal_device_annce_params_t *)esp_zb_app_signal_get_params(p_sg_p); - log_i("New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr); - esp_zb_zdo_match_desc_req_param_t cmd_req; - cmd_req.dst_nwk_addr = dev_annce_params->device_short_addr; - cmd_req.addr_of_interest = dev_annce_params->device_short_addr; - esp_zb_zdo_find_on_off_light(&cmd_req, user_find_cb, NULL); - break; - case ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: - if (err_status == ESP_OK) { - if (*(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)) { - log_i("Network(0x%04hx) is open for %d seconds", esp_zb_get_pan_id(), *(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)); - } else { - log_w("Network(0x%04hx) closed, devices joining not allowed.", esp_zb_get_pan_id()); - } - } - break; - default: log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; - } -} - -static void esp_zb_task(void *pvParameters) { - esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZC_CONFIG(); - esp_zb_init(&zb_nwk_cfg); - esp_zb_on_off_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_ON_OFF_SWITCH_CONFIG(); - esp_zb_ep_list_t *esp_zb_on_off_switch_ep = esp_zb_on_off_switch_ep_create(HA_ONOFF_SWITCH_ENDPOINT, &switch_cfg); - esp_zb_device_register(esp_zb_on_off_switch_ep); - esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); - ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_main_loop_iteration(); -} - -/********************* GPIO functions **************************/ -static QueueHandle_t gpio_evt_queue = NULL; - -static void IRAM_ATTR gpio_isr_handler(void *arg) { - xQueueSendFromISR(gpio_evt_queue, (switch_func_pair_t *)arg, NULL); -} - -static void switch_gpios_intr_enabled(bool enabled) { - for (int i = 0; i < PAIR_SIZE(button_func_pair); ++i) { - if (enabled) { - enableInterrupt((button_func_pair[i]).pin); - } else { - disableInterrupt((button_func_pair[i]).pin); - } - } -} - -/********************* Arduino functions **************************/ -void setup() { - // Init Zigbee - esp_zb_platform_config_t config = { - .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), - }; - - ESP_ERROR_CHECK(esp_zb_platform_config(&config)); - - // Init button switch - for (int i = 0; i < PAIR_SIZE(button_func_pair); i++) { - pinMode(button_func_pair[i].pin, INPUT_PULLUP); - /* create a queue to handle gpio event from isr */ - gpio_evt_queue = xQueueCreate(10, sizeof(switch_func_pair_t)); - if (gpio_evt_queue == 0) { - log_e("Queue was not created and must not be used"); - while (1); - } - attachInterruptArg(button_func_pair[i].pin, gpio_isr_handler, (void *)(button_func_pair + i), FALLING); - } - - // Start Zigbee task - xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); -} - -void loop() { - // Handle button switch in loop() - uint8_t pin = 0; - switch_func_pair_t button_func_pair; - static switch_state_t switch_state = SWITCH_IDLE; - bool evt_flag = false; - - /* check if there is any queue received, if yes read out the button_func_pair */ - if (xQueueReceive(gpio_evt_queue, &button_func_pair, portMAX_DELAY)) { - pin = button_func_pair.pin; - switch_gpios_intr_enabled(false); - evt_flag = true; - } - while (evt_flag) { - bool value = digitalRead(pin); - switch (switch_state) { - case SWITCH_IDLE: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break; - case SWITCH_PRESS_DETECTED: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break; - case SWITCH_RELEASE_DETECTED: - switch_state = SWITCH_IDLE; - /* callback to button_handler */ - (*esp_zb_buttons_handler)(&button_func_pair); - break; - default: break; - } - if (switch_state == SWITCH_IDLE) { - switch_gpios_intr_enabled(true); - evt_flag = false; - break; - } - vTaskDelay(10 / portTICK_PERIOD_MS); - } -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/ci.json b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/ci.json deleted file mode 100644 index 7cfaa76784d..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/ci.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino b/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino deleted file mode 100644 index ed966fa86b5..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino +++ /dev/null @@ -1,349 +0,0 @@ -// 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 temperature sensor. - * - * The example demonstrates how to use ESP Zigbee stack to create a end device temperatu sensor. - * The temperature sensor 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. - */ - -#ifndef ZIGBEE_MODE_ED -#error "Zigbee end device mode is not selected in Tools->Zigbee mode" -#endif - -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - -/* Switch configuration */ -#define GPIO_INPUT_IO_TOGGLE_SWITCH GPIO_NUM_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, -} switch_func_t; - -typedef struct { - uint8_t pin; - switch_func_t func; -} switch_func_pair_t; - -typedef enum { - SWITCH_IDLE, - SWITCH_PRESS_ARMED, - SWITCH_PRESS_DETECTED, - SWITCH_PRESSED, - SWITCH_RELEASE_DETECTED, -} switch_state_t; - -static switch_func_pair_t button_func_pair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; - -/* Default End Device config */ -#define ESP_ZB_ZED_CONFIG() \ - { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ - .nwk_cfg = { \ - .zed_cfg = \ - { \ - .ed_timeout = ED_AGING_TIMEOUT, \ - .keep_alive = ED_KEEP_ALIVE, \ - }, \ - }, \ - } - -#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ - { .radio_mode = ZB_RADIO_MODE_NATIVE, } - -#define ESP_ZB_DEFAULT_HOST_CONFIG() \ - { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, } - -/* Zigbee configuration */ -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN -#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ -#define HA_ESP_SENSOR_ENDPOINT 10 /* esp temperature sensor device endpoint, used for temperature measurement */ -#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ - -/* Temperature sensor configuration */ -#define ESP_TEMP_SENSOR_UPDATE_INTERVAL (1) /* Local sensor update interval (second) */ -#define ESP_TEMP_SENSOR_MIN_VALUE (10) /* Local sensor min measured value (degree Celsius) */ -#define ESP_TEMP_SENSOR_MAX_VALUE (50) /* Local sensor max measured value (degree Celsius) */ - -/* Attribute values in ZCL string format - * The string should be started with the length of its own. - */ -#define MANUFACTURER_NAME \ - "\x0B" \ - "ESPRESSIF" -#define MODEL_IDENTIFIER "\x09" CONFIG_IDF_TARGET - -/********************* Zigbee functions **************************/ -static int16_t zb_temperature_to_s16(float temp) { - return (int16_t)(temp * 100); -} - -static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) { - if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { - /* Send report attributes command */ - esp_zb_zcl_report_attr_cmd_t report_attr_cmd; - report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; - report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID; - report_attr_cmd.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; - report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; - report_attr_cmd.zcl_basic_cmd.src_endpoint = HA_ESP_SENSOR_ENDPOINT; - - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); - esp_zb_lock_release(); - log_i("Send 'report attributes' command"); - } -} - -static void esp_app_temp_sensor_handler(float temperature) { - int16_t measured_value = zb_temperature_to_s16(temperature); - Serial.println("Updating temperature sensor value..."); - Serial.println(measured_value); - /* Update temperature sensor measured value */ - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_set_attribute_val( - HA_ESP_SENSOR_ENDPOINT, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &measured_value, - false - ); - esp_zb_lock_release(); -} - -static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { - ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); -} - -void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { - uint32_t *p_sg_p = signal_struct->p_app_signal; - esp_err_t err_status = signal_struct->esp_err_status; - esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; - switch (sig_type) { - case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: - log_i("Zigbee stack initialized"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); - break; - case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: - case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: - if (err_status == ESP_OK) { - log_i("Start network steering"); - log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); - // Start Temperature sensor reading task - xTaskCreate(temp_sensor_value_update, "temp_sensor_update", 2048, NULL, 10, NULL); - if (esp_zb_bdb_is_factory_new()) { - log_i("Start network steering"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); - } else { - log_i("Device rebooted"); - } - } else { - /* commissioning failed */ - log_w("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); - } - break; - case ESP_ZB_BDB_SIGNAL_STEERING: - if (err_status == ESP_OK) { - esp_zb_ieee_addr_t extended_pan_id; - esp_zb_get_extended_pan_id(extended_pan_id); - log_i( - "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", - extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], - extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address() - ); - } else { - log_i("Network steering was not successful (status: %s)", esp_err_to_name(err_status)); - esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); - } - break; - default: log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; - } -} - -static esp_zb_cluster_list_t *custom_temperature_sensor_clusters_create(esp_zb_temperature_sensor_cfg_t *temperature_sensor) { - esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); - esp_zb_attribute_list_t *basic_cluster = esp_zb_basic_cluster_create(&(temperature_sensor->basic_cfg)); - ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)MANUFACTURER_NAME)); - ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)MODEL_IDENTIFIER)); - ESP_ERROR_CHECK(esp_zb_cluster_list_add_basic_cluster(cluster_list, basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); - ESP_ERROR_CHECK( - esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(&(temperature_sensor->identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE) - ); - ESP_ERROR_CHECK( - esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE) - ); - ESP_ERROR_CHECK(esp_zb_cluster_list_add_temperature_meas_cluster( - cluster_list, esp_zb_temperature_meas_cluster_create(&(temperature_sensor->temp_meas_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE - )); - return cluster_list; -} - -static esp_zb_ep_list_t *custom_temperature_sensor_ep_create(uint8_t endpoint_id, esp_zb_temperature_sensor_cfg_t *temperature_sensor) { - esp_zb_ep_list_t *ep_list = esp_zb_ep_list_create(); - esp_zb_endpoint_config_t endpoint_config = { - .endpoint = endpoint_id, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID, .app_device_version = 0 - }; - esp_zb_ep_list_add_ep(ep_list, custom_temperature_sensor_clusters_create(temperature_sensor), endpoint_config); - return ep_list; -} - -static void esp_zb_task(void *pvParameters) { - esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZED_CONFIG(); - esp_zb_init(&zb_nwk_cfg); - /* Create customized temperature sensor endpoint */ - esp_zb_temperature_sensor_cfg_t sensor_cfg = ESP_ZB_DEFAULT_TEMPERATURE_SENSOR_CONFIG(); - /* Set (Min|Max)MeasuredValure */ - sensor_cfg.temp_meas_cfg.min_value = zb_temperature_to_s16(ESP_TEMP_SENSOR_MIN_VALUE); - sensor_cfg.temp_meas_cfg.max_value = zb_temperature_to_s16(ESP_TEMP_SENSOR_MAX_VALUE); - esp_zb_ep_list_t *esp_zb_sensor_ep = custom_temperature_sensor_ep_create(HA_ESP_SENSOR_ENDPOINT, &sensor_cfg); - /* Register the device */ - esp_zb_device_register(esp_zb_sensor_ep); - - /* Config the reporting info */ - esp_zb_zcl_reporting_info_t reporting_info = { - .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, - .ep = HA_ESP_SENSOR_ENDPOINT, - .cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, - .cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, - .attr_id = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, - .u = - { - .send_info = - { - .min_interval = 1, - .max_interval = 0, - .delta = - { - .u16 = 100, - }, - .def_min_interval = 1, - .def_max_interval = 0, - }, - }, - .dst = - { - .profile_id = ESP_ZB_AF_HA_PROFILE_ID, - }, - .manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC, - }; - esp_zb_zcl_update_reporting_info(&reporting_info); - esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); - - //Erase NVRAM before creating connection to new Coordinator - //esp_zb_nvram_erase_at_start(true); //Comment out this line to erase NVRAM data if you are conneting to new Coordinator - - ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_main_loop_iteration(); -} - -/********************* GPIO functions **************************/ -static QueueHandle_t gpio_evt_queue = NULL; - -static void IRAM_ATTR gpio_isr_handler(void *arg) { - xQueueSendFromISR(gpio_evt_queue, (switch_func_pair_t *)arg, NULL); -} - -static void switch_gpios_intr_enabled(bool enabled) { - for (int i = 0; i < PAIR_SIZE(button_func_pair); ++i) { - if (enabled) { - enableInterrupt((button_func_pair[i]).pin); - } else { - disableInterrupt((button_func_pair[i]).pin); - } - } -} - -/************************ Temp sensor *****************************/ -static void temp_sensor_value_update(void *arg) { - for (;;) { - float tsens_value = temperatureRead(); - esp_app_temp_sensor_handler(tsens_value); - delay(1000); - } -} - -/********************* Arduino functions **************************/ -void setup() { - Serial.begin(115200); - // Init Zigbee - esp_zb_platform_config_t config = { - .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), - }; - ESP_ERROR_CHECK(esp_zb_platform_config(&config)); - - // Init button switch - for (int i = 0; i < PAIR_SIZE(button_func_pair); i++) { - pinMode(button_func_pair[i].pin, INPUT_PULLUP); - /* create a queue to handle gpio event from isr */ - gpio_evt_queue = xQueueCreate(10, sizeof(switch_func_pair_t)); - if (gpio_evt_queue == 0) { - log_e("Queue was not created and must not be used"); - while (1); - } - attachInterruptArg(button_func_pair[i].pin, gpio_isr_handler, (void *)(button_func_pair + i), FALLING); - } - - // Start Zigbee task - xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); -} - -void loop() { - // Handle button switch in loop() - uint8_t pin = 0; - switch_func_pair_t button_func_pair; - static switch_state_t switch_state = SWITCH_IDLE; - bool evt_flag = false; - float temperature; - - /* check if there is any queue received, if yes read out the button_func_pair */ - if (xQueueReceive(gpio_evt_queue, &button_func_pair, portMAX_DELAY)) { - pin = button_func_pair.pin; - switch_gpios_intr_enabled(false); - evt_flag = true; - } - while (evt_flag) { - bool value = digitalRead(pin); - switch (switch_state) { - case SWITCH_IDLE: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break; - case SWITCH_PRESS_DETECTED: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break; - case SWITCH_RELEASE_DETECTED: - switch_state = SWITCH_IDLE; - /* callback to button_handler */ - (*esp_zb_buttons_handler)(&button_func_pair); - break; - default: break; - } - if (switch_state == SWITCH_IDLE) { - switch_gpios_intr_enabled(true); - evt_flag = false; - break; - } - delay(10); - } -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/ci.json b/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/ci.json deleted file mode 100644 index 7cfaa76784d..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/ci.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/Zigbee_Thermostat.ino deleted file mode 100644 index 1ace7d866e1..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/Zigbee_Thermostat.ino +++ /dev/null @@ -1,565 +0,0 @@ -// 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 thermostat. - * - * The example demonstrates how to use ESP Zigbee stack to get data from temperature - * sensor end device and act as an thermostat. - * The temperature sensor is a Zigbee end device, which is controlled by a Zigbee coordinator (thermostat). - * 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. - */ - -#ifndef ZIGBEE_MODE_ZCZR -#error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" -#endif - -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - -#define ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0])) - -/* Switch configuration */ -#define GPIO_INPUT_IO_TOGGLE_SWITCH GPIO_NUM_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, -} switch_func_t; - -typedef struct { - uint8_t pin; - switch_func_t func; -} switch_func_pair_t; - -typedef enum { - SWITCH_IDLE, - SWITCH_PRESS_ARMED, - SWITCH_PRESS_DETECTED, - SWITCH_PRESSED, - SWITCH_RELEASE_DETECTED, -} switch_state_t; - -static switch_func_pair_t button_func_pair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; - -/* Default Coordinator config */ -#define ESP_ZB_ZC_CONFIG() \ - { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, .install_code_policy = INSTALLCODE_POLICY_ENABLE, .nwk_cfg = { \ - .zczr_cfg = \ - { \ - .max_children = MAX_CHILDREN, \ - }, \ - } \ - } - -#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ - { .radio_mode = ZB_RADIO_MODE_NATIVE, } - -#define ESP_ZB_DEFAULT_HOST_CONFIG() \ - { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, } - -/* Temperature sensor device parameters */ -typedef struct temp_sensor_device_params_s { - esp_zb_ieee_addr_t ieee_addr; - uint8_t endpoint; - uint16_t short_addr; -} temp_sensor_device_params_t; - -typedef struct zbstring_s { - uint8_t len; - char data[]; -} ESP_ZB_PACKED_STRUCT zbstring_t; - -static temp_sensor_device_params_t temp_sensor; - -/* Zigbee configuration */ -#define MAX_CHILDREN 10 /* the max amount of connected devices */ -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define HA_THERMOSTAT_ENDPOINT 1 /* esp light switch device endpoint */ -#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ - -/* Attribute values in ZCL string format - * The string should be started with the length of its own. - */ -#define MANUFACTURER_NAME \ - "\x0B" \ - "ESPRESSIF" -#define MODEL_IDENTIFIER "\x09" CONFIG_IDF_TARGET - -/********************* Zigbee functions **************************/ -static float zb_s16_to_temperature(int16_t value) { - return 1.0 * value / 100; -} - -static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) { - if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { - /* Send "read attributes" command to the bound sensor */ - esp_zb_zcl_read_attr_cmd_t read_req; - read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; - read_req.zcl_basic_cmd.src_endpoint = HA_THERMOSTAT_ENDPOINT; - read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; - - uint16_t attributes[] = { - ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, - ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID - }; - read_req.attr_number = ARRAY_LENTH(attributes); - read_req.attr_field = attributes; - - /* Send "configure report attribute" command to the bound sensor */ - esp_zb_zcl_config_report_cmd_t report_cmd; - report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; - report_cmd.zcl_basic_cmd.src_endpoint = HA_THERMOSTAT_ENDPOINT; - report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; - - int16_t report_change = 200; /* report on each 2 degree changes */ - esp_zb_zcl_config_report_record_t records[] = { - { - .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, - .attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, - .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16, - .min_interval = 0, - .max_interval = 10, - .reportable_change = &report_change, - }, - }; - report_cmd.record_number = ARRAY_LENTH(records); - report_cmd.record_field = records; - - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_config_report_cmd_req(&report_cmd); - esp_zb_lock_release(); - log_i("Send 'configure reporting' command"); - - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_read_attr_cmd_req(&read_req); - esp_zb_lock_release(); - log_i("Send 'read attributes' command"); - } -} - -static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { - ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); -} - -static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { - esp_zb_zdo_bind_req_param_t *bind_req = (esp_zb_zdo_bind_req_param_t *)user_ctx; - - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - /* Local binding succeeds */ - if (bind_req->req_dst_addr == esp_zb_get_short_address()) { - log_i("Successfully bind the temperature sensor from address(0x%x) on endpoint(%d)", temp_sensor.short_addr, temp_sensor.endpoint); - - /* Read peer Manufacture Name & Model Identifier */ - esp_zb_zcl_read_attr_cmd_t read_req; - read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; - read_req.zcl_basic_cmd.src_endpoint = HA_THERMOSTAT_ENDPOINT; - read_req.zcl_basic_cmd.dst_endpoint = temp_sensor.endpoint; - read_req.zcl_basic_cmd.dst_addr_u.addr_short = temp_sensor.short_addr; - read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_BASIC; - - uint16_t attributes[] = { - ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, - ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, - }; - read_req.attr_number = ARRAY_LENTH(attributes); - read_req.attr_field = attributes; - - esp_zb_zcl_read_attr_cmd_req(&read_req); - } - if (bind_req->req_dst_addr == temp_sensor.short_addr) { - log_i("The temperature sensor from address(0x%x) on endpoint(%d) successfully binds us", temp_sensor.short_addr, temp_sensor.endpoint); - } - free(bind_req); - } else { - /* Bind failed, maybe retry the binding ? */ - - // esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); - } -} - -static void user_find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - log_i("Found temperature sensor"); - /* Store the information of the remote device */ - temp_sensor_device_params_t *sensor = (temp_sensor_device_params_t *)user_ctx; - sensor->endpoint = endpoint; - sensor->short_addr = addr; - esp_zb_ieee_address_by_short(sensor->short_addr, sensor->ieee_addr); - log_d("Temperature sensor found: short address(0x%x), endpoint(%d)", sensor->short_addr, sensor->endpoint); - - /* 1. Send binding request to the sensor */ - esp_zb_zdo_bind_req_param_t *bind_req = (esp_zb_zdo_bind_req_param_t *)calloc(sizeof(esp_zb_zdo_bind_req_param_t), 1); - bind_req->req_dst_addr = addr; - log_d("Request temperature sensor to bind us"); - - /* populate the src information of the binding */ - memcpy(bind_req->src_address, sensor->ieee_addr, sizeof(esp_zb_ieee_addr_t)); - bind_req->src_endp = endpoint; - bind_req->cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; - log_d("Bind temperature sensor"); - - /* populate the dst information of the binding */ - bind_req->dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; - esp_zb_get_long_address(bind_req->dst_address_u.addr_long); - bind_req->dst_endp = HA_THERMOSTAT_ENDPOINT; - - log_i("Request temperature sensor to bind us"); - esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); - - /* 2. Send binding request to self */ - bind_req = (esp_zb_zdo_bind_req_param_t *)calloc(sizeof(esp_zb_zdo_bind_req_param_t), 1); - bind_req->req_dst_addr = esp_zb_get_short_address(); - - /* populate the src information of the binding */ - esp_zb_get_long_address(bind_req->src_address); - bind_req->src_endp = HA_THERMOSTAT_ENDPOINT; - bind_req->cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; - - /* populate the dst information of the binding */ - bind_req->dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; - memcpy(bind_req->dst_address_u.addr_long, sensor->ieee_addr, sizeof(esp_zb_ieee_addr_t)); - bind_req->dst_endp = endpoint; - - log_i("Bind temperature sensor"); - esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); - } -} - -static void find_temperature_sensor(esp_zb_zdo_match_desc_req_param_t *param, esp_zb_zdo_match_desc_callback_t user_cb, void *user_ctx) { - uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT}; - param->profile_id = ESP_ZB_AF_HA_PROFILE_ID; - param->num_in_clusters = 1; - param->num_out_clusters = 0; - param->cluster_list = cluster_list; - esp_zb_zdo_match_cluster(param, user_cb, (void *)&temp_sensor); -} - -void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { - uint32_t *p_sg_p = signal_struct->p_app_signal; - esp_err_t err_status = signal_struct->esp_err_status; - esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; - esp_zb_zdo_signal_device_annce_params_t *dev_annce_params = NULL; - switch (sig_type) { - case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: - log_i("Zigbee stack initialized"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); - break; - case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: - case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: - if (err_status == ESP_OK) { - log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); - if (esp_zb_bdb_is_factory_new()) { - log_i("Start network formation"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION); - } else { - log_i("Device rebooted"); - log_i("Openning network for joining for %d seconds", 180); - esp_zb_bdb_open_network(180); - } - } else { - log_e("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); - } - break; - case ESP_ZB_BDB_SIGNAL_FORMATION: - if (err_status == ESP_OK) { - esp_zb_ieee_addr_t extended_pan_id; - esp_zb_get_extended_pan_id(extended_pan_id); - log_i( - "Formed network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", - extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], - extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address() - ); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); - } else { - log_i("Restart network formation (status: %s)", esp_err_to_name(err_status)); - esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_FORMATION, 1000); - } - break; - case ESP_ZB_BDB_SIGNAL_STEERING: - if (err_status == ESP_OK) { - log_i("Network steering started"); - } - break; - case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE: - dev_annce_params = (esp_zb_zdo_signal_device_annce_params_t *)esp_zb_app_signal_get_params(p_sg_p); - log_i("New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr); - esp_zb_zdo_match_desc_req_param_t cmd_req; - cmd_req.dst_nwk_addr = dev_annce_params->device_short_addr; - cmd_req.addr_of_interest = dev_annce_params->device_short_addr; - find_temperature_sensor(&cmd_req, user_find_cb, NULL); - break; - case ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: - if (err_status == ESP_OK) { - if (*(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)) { - log_i("Network(0x%04hx) is open for %d seconds", esp_zb_get_pan_id(), *(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)); - } else { - log_w("Network(0x%04hx) closed, devices joining not allowed.", esp_zb_get_pan_id()); - } - } - break; - default: log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; - } -} - -static void esp_app_zb_attribute_handler(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { - /* Basic cluster attributes */ - if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_BASIC) { - if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { - zbstring_t *zbstr = (zbstring_t *)attribute->data.value; - char *string = (char *)malloc(zbstr->len + 1); - memcpy(string, zbstr->data, zbstr->len); - string[zbstr->len] = '\0'; - log_i("Peer Manufacturer is \"%s\"", string); - free(string); - } - if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { - zbstring_t *zbstr = (zbstring_t *)attribute->data.value; - char *string = (char *)malloc(zbstr->len + 1); - memcpy(string, zbstr->data, zbstr->len); - string[zbstr->len] = '\0'; - log_i("Peer Model is \"%s\"", string); - free(string); - } - } - - /* Temperature Measurement cluster attributes */ - if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT) { - if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) { - int16_t value = attribute->data.value ? *(int16_t *)attribute->data.value : 0; - log_i("Measured Value is %.2f degrees Celsius", zb_s16_to_temperature(value)); - } - if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) { - int16_t min_value = attribute->data.value ? *(int16_t *)attribute->data.value : 0; - log_i("Min Measured Value is %.2f degrees Celsius", zb_s16_to_temperature(min_value)); - } - if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) { - int16_t max_value = attribute->data.value ? *(int16_t *)attribute->data.value : 0; - log_i("Max Measured Value is %.2f degrees Celsius", zb_s16_to_temperature(max_value)); - } - if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { - uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0; - log_i("Tolerance is %.2f degrees Celsius", 1.0 * tolerance / 100); - } - } -} - -static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message) { - if (!message) { - log_e("Empty message"); - } - if (message->status != ESP_ZB_ZCL_STATUS_SUCCESS) { - log_e("Received message: error status(%d)", message->status); - } - log_i( - "Received report from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->src_address.u.short_addr, message->src_endpoint, - message->dst_endpoint, message->cluster - ); - esp_app_zb_attribute_handler(message->cluster, &message->attribute); - return ESP_OK; -} - -static esp_err_t zb_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_resp_message_t *message) { - if (!message) { - log_e("Empty message"); - } - if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { - log_e("Received message: error status(%d)", message->info.status); - } - log_i( - "Read attribute response: from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->info.src_address.u.short_addr, - message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster - ); - - esp_zb_zcl_read_attr_resp_variable_t *variable = message->variables; - while (variable) { - log_i( - "Read attribute response: status(%d), cluster(0x%x), attribute(0x%x), type(0x%x), value(%d)", variable->status, message->info.cluster, - variable->attribute.id, variable->attribute.data.type, variable->attribute.data.value ? *(uint8_t *)variable->attribute.data.value : 0 - ); - if (variable->status == ESP_ZB_ZCL_STATUS_SUCCESS) { - esp_app_zb_attribute_handler(message->info.cluster, &variable->attribute); - } - - variable = variable->next; - } - - return ESP_OK; -} - -static esp_err_t zb_configure_report_resp_handler(const esp_zb_zcl_cmd_config_report_resp_message_t *message) { - if (!message) { - log_e("Empty message"); - } - if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { - log_e("Received message: error status(%d)", message->info.status); - } - esp_zb_zcl_config_report_resp_variable_t *variable = message->variables; - while (variable) { - log_i( - "Configure report response: status(%d), cluster(0x%x), direction(0x%x), attribute(0x%x)", variable->status, message->info.cluster, variable->direction, - variable->attribute_id - ); - variable = variable->next; - } - - return ESP_OK; -} - -static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { - esp_err_t ret = ESP_OK; - switch (callback_id) { - case ESP_ZB_CORE_REPORT_ATTR_CB_ID: ret = zb_attribute_reporting_handler((esp_zb_zcl_report_attr_message_t *)message); break; - case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: ret = zb_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); break; - case ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID: ret = zb_configure_report_resp_handler((esp_zb_zcl_cmd_config_report_resp_message_t *)message); break; - default: log_w("Receive Zigbee action(0x%x) callback", callback_id); break; - } - return ret; -} - -static esp_zb_cluster_list_t *custom_thermostat_clusters_create(esp_zb_thermostat_cfg_t *thermostat) { - esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); - esp_zb_attribute_list_t *basic_cluster = esp_zb_basic_cluster_create(&(thermostat->basic_cfg)); - ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)MANUFACTURER_NAME)); - ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)MODEL_IDENTIFIER)); - ESP_ERROR_CHECK(esp_zb_cluster_list_add_basic_cluster(cluster_list, basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); - ESP_ERROR_CHECK( - esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(&(thermostat->identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE) - ); - ESP_ERROR_CHECK( - esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE) - ); - ESP_ERROR_CHECK( - esp_zb_cluster_list_add_thermostat_cluster(cluster_list, esp_zb_thermostat_cluster_create(&(thermostat->thermostat_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE) - ); - /* Add temperature measurement cluster for attribute reporting */ - ESP_ERROR_CHECK(esp_zb_cluster_list_add_temperature_meas_cluster(cluster_list, esp_zb_temperature_meas_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE)); - return cluster_list; -} - -static esp_zb_ep_list_t *custom_thermostat_ep_create(uint8_t endpoint_id, esp_zb_thermostat_cfg_t *thermostat) { - esp_zb_ep_list_t *ep_list = esp_zb_ep_list_create(); - esp_zb_endpoint_config_t endpoint_config = { - .endpoint = endpoint_id, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID, .app_device_version = 0 - }; - esp_zb_ep_list_add_ep(ep_list, custom_thermostat_clusters_create(thermostat), endpoint_config); - return ep_list; -} - -static void esp_zb_task(void *pvParameters) { - /* Initialize Zigbee stack */ - esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZC_CONFIG(); - esp_zb_init(&zb_nwk_cfg); - /* Create customized thermostat endpoint */ - esp_zb_thermostat_cfg_t thermostat_cfg = ESP_ZB_DEFAULT_THERMOSTAT_CONFIG(); - esp_zb_ep_list_t *esp_zb_thermostat_ep = custom_thermostat_ep_create(HA_THERMOSTAT_ENDPOINT, &thermostat_cfg); - /* Register the device */ - esp_zb_device_register(esp_zb_thermostat_ep); - - esp_zb_core_action_handler_register(zb_action_handler); - esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); - ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_main_loop_iteration(); -} - -/********************* GPIO functions **************************/ -static QueueHandle_t gpio_evt_queue = NULL; - -static void IRAM_ATTR gpio_isr_handler(void *arg) { - xQueueSendFromISR(gpio_evt_queue, (switch_func_pair_t *)arg, NULL); -} - -static void switch_gpios_intr_enabled(bool enabled) { - for (int i = 0; i < PAIR_SIZE(button_func_pair); ++i) { - if (enabled) { - enableInterrupt((button_func_pair[i]).pin); - } else { - disableInterrupt((button_func_pair[i]).pin); - } - } -} - -/********************* Arduino functions **************************/ -void setup() { - // Init Zigbee - esp_zb_platform_config_t config = { - .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), - }; - - ESP_ERROR_CHECK(esp_zb_platform_config(&config)); - - // Init button switch - for (int i = 0; i < PAIR_SIZE(button_func_pair); i++) { - pinMode(button_func_pair[i].pin, INPUT_PULLUP); - /* create a queue to handle gpio event from isr */ - gpio_evt_queue = xQueueCreate(10, sizeof(switch_func_pair_t)); - if (gpio_evt_queue == 0) { - log_e("Queue was not created and must not be used"); - while (1); - } - attachInterruptArg(button_func_pair[i].pin, gpio_isr_handler, (void *)(button_func_pair + i), FALLING); - } - - // Start Zigbee task - xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); -} - -void loop() { - // Handle button switch in loop() - uint8_t pin = 0; - switch_func_pair_t button_func_pair; - static switch_state_t switch_state = SWITCH_IDLE; - bool evt_flag = false; - - /* check if there is any queue received, if yes read out the button_func_pair */ - if (xQueueReceive(gpio_evt_queue, &button_func_pair, portMAX_DELAY)) { - pin = button_func_pair.pin; - switch_gpios_intr_enabled(false); - evt_flag = true; - } - while (evt_flag) { - bool value = digitalRead(pin); - switch (switch_state) { - case SWITCH_IDLE: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break; - case SWITCH_PRESS_DETECTED: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break; - case SWITCH_RELEASE_DETECTED: - switch_state = SWITCH_IDLE; - /* callback to button_handler */ - (*esp_zb_buttons_handler)(&button_func_pair); - break; - default: break; - } - if (switch_state == SWITCH_IDLE) { - switch_gpios_intr_enabled(true); - evt_flag = false; - break; - } - delay(10); - } -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/ci.json b/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/ci.json deleted file mode 100644 index 7cfaa76784d..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/ci.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } -} diff --git a/libraries/ESP32/keywords.txt b/libraries/ESP32/keywords.txt index 6cfd3fcab4c..866e76babd8 100644 --- a/libraries/ESP32/keywords.txt +++ b/libraries/ESP32/keywords.txt @@ -6,12 +6,50 @@ # Datatypes (KEYWORD1) ####################################### +Serial4 KEYWORD1 +espCtColor_t KEYWORD1 +espXyColor_t KEYWORD1 +espHsvColor_t KEYWORD1 +espRgbColor_t KEYWORD1 + ####################################### # Methods and Functions (KEYWORD2) ####################################### +espXYToRgbColor KEYWORD2 +espXYColorToRgb KEYWORD2 +espRgbColorToXYColor KEYWORD2 +espRgbToXYColor KEYWORD2 +espHsvColorToRgbColor KEYWORD2 +espHsvToRgbColor KEYWORD2 +espCTColorToRgbColor KEYWORD2 +espCTToRgbColor KEYWORD2 +espRgbColorToHsvColor KEYWORD2 +espRgbToHsvColor KEYWORD2 + ####################################### # Constants (LITERAL1) ####################################### RGB_BUILTIN LITERAL1 +HSV_BLACK LITERAL1 +HSV_WHITE LITERAL1 +HSV_RED LITERAL1 +HSV_YELLOW LITERAL1 +HSV_GREEN LITERAL1 +HSV_CYAN LITERAL1 +HSV_BLUE LITERAL1 +HSV_MAGENTA LITERAL1 +COOL_WHITE_COLOR_TEMPERATURE LITERAL1 +DAYLIGHT_WHITE_COLOR_TEMPERATURE LITERAL1 +WHITE_COLOR_TEMPERATURE LITERAL1 +SOFT_WHITE_COLOR_TEMPERATURE LITERAL1 +WARM_WHITE_COLOR_TEMPERATURE LITERAL1 +RGB_BLACK LITERAL1 +RGB_WHITE LITERAL1 +RGB_RED LITERAL1 +RGB_YELLOW LITERAL1 +RGB_GREEN LITERAL1 +RGB_CYAN LITERAL1 +RGB_BLUE LITERAL1 +RGB_MAGENTA LITERAL1 diff --git a/libraries/ESP32/library.properties b/libraries/ESP32/library.properties index c928bcf844e..7ebc69be71f 100644 --- a/libraries/ESP32/library.properties +++ b/libraries/ESP32/library.properties @@ -1,5 +1,5 @@ name=ESP32 -version=2.0.0 +version=3.2.0 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 sketches examples diff --git a/libraries/ESP_I2S/examples/ES8388_loopback/ES8388_loopback.ino b/libraries/ESP_I2S/examples/ES8388_loopback/ES8388_loopback.ino index edec1f9c4ea..43232be8354 100644 --- a/libraries/ESP_I2S/examples/ES8388_loopback/ES8388_loopback.ino +++ b/libraries/ESP_I2S/examples/ES8388_loopback/ES8388_loopback.ino @@ -40,9 +40,6 @@ void setup() { // Initialize the serial port Serial.begin(115200); - while (!Serial) { - delay(10); - } pinMode(PA_ENABLE, OUTPUT); digitalWrite(PA_ENABLE, HIGH); diff --git a/libraries/ESP_I2S/examples/ES8388_loopback/ci.json b/libraries/ESP_I2S/examples/ES8388_loopback/ci.json new file mode 100644 index 00000000000..e0f64e28943 --- /dev/null +++ b/libraries/ESP_I2S/examples/ES8388_loopback/ci.json @@ -0,0 +1,6 @@ +{ + "requires": [ + "CONFIG_SOC_I2S_SUPPORTED=y", + "CONFIG_SOC_I2C_SUPPORTED=y" + ] +} diff --git a/libraries/ESP_I2S/examples/Record_to_WAV/Record_to_WAV.ino b/libraries/ESP_I2S/examples/Record_to_WAV/Record_to_WAV.ino index c3ae734faf6..e8f09554cb8 100644 --- a/libraries/ESP_I2S/examples/Record_to_WAV/Record_to_WAV.ino +++ b/libraries/ESP_I2S/examples/Record_to_WAV/Record_to_WAV.ino @@ -32,9 +32,6 @@ void setup() { // Initialize the serial port Serial.begin(115200); - while (!Serial) { - delay(10); - } Serial.println("Initializing I2S bus..."); diff --git a/libraries/ESP_I2S/examples/Record_to_WAV/ci.json b/libraries/ESP_I2S/examples/Record_to_WAV/ci.json index 35b6e255471..a45dc2f0120 100644 --- a/libraries/ESP_I2S/examples/Record_to_WAV/ci.json +++ b/libraries/ESP_I2S/examples/Record_to_WAV/ci.json @@ -1,8 +1,6 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false - } + "requires": [ + "CONFIG_SOC_SDMMC_HOST_SUPPORTED=y", + "CONFIG_SOC_I2S_SUPPORTED=y" + ] } diff --git a/libraries/ESP_I2S/examples/Simple_tone/ci.json b/libraries/ESP_I2S/examples/Simple_tone/ci.json new file mode 100644 index 00000000000..9842f2f9b2a --- /dev/null +++ b/libraries/ESP_I2S/examples/Simple_tone/ci.json @@ -0,0 +1,5 @@ +{ + "requires": [ + "CONFIG_SOC_I2S_SUPPORTED=y" + ] +} diff --git a/libraries/ESP_I2S/library.properties b/libraries/ESP_I2S/library.properties old mode 100755 new mode 100644 index a2e7b021fad..263e9823275 --- a/libraries/ESP_I2S/library.properties +++ b/libraries/ESP_I2S/library.properties @@ -1,5 +1,5 @@ name=ESP_I2S -version=1.0.0 +version=3.2.0 author=me-no-dev maintainer=me-no-dev sentence=Library for ESP I2S communication diff --git a/libraries/ESP_I2S/src/ESP_I2S.cpp b/libraries/ESP_I2S/src/ESP_I2S.cpp index 84050dfa6f8..6bf8089e48a 100644 --- a/libraries/ESP_I2S/src/ESP_I2S.cpp +++ b/libraries/ESP_I2S/src/ESP_I2S.cpp @@ -7,12 +7,23 @@ #include "esp32-hal-periman.h" #include "wav_header.h" +#if ARDUINO_HAS_MP3_DECODER #include "mp3dec.h" +#endif + +#if SOC_I2S_HW_VERSION_2 +#undef I2S_STD_CLK_DEFAULT_CONFIG +#define I2S_STD_CLK_DEFAULT_CONFIG(rate) \ + { .sample_rate_hz = rate, .clk_src = I2S_CLK_SRC_DEFAULT, .ext_clk_freq_hz = 0, .mclk_multiple = I2S_MCLK_MULTIPLE_256, } +#endif #define I2S_READ_CHUNK_SIZE 1920 -#define I2S_DEFAULT_CFG() \ - { .id = I2S_NUM_AUTO, .role = I2S_ROLE_MASTER, .dma_desc_num = 6, .dma_frame_num = 240, .auto_clear = true, } +#define I2S_DEFAULT_CFG() \ + { \ + .id = I2S_NUM_AUTO, .role = I2S_ROLE_MASTER, .dma_desc_num = 6, .dma_frame_num = 240, .auto_clear = true, .auto_clear_before_cb = false, \ + .intr_priority = 0 \ + } #define I2S_STD_CHAN_CFG(_sample_rate, _data_bit_width, _slot_mode) \ { \ @@ -714,9 +725,15 @@ bool I2SClass::end() { #if SOC_I2S_SUPPORTS_TDM case I2S_MODE_TDM: #endif - perimanClearPinBus(_mclk); - perimanClearPinBus(_bclk); - perimanClearPinBus(_ws); + if (_mclk >= 0) { + perimanClearPinBus(_mclk); + } + if (_bclk >= 0) { + perimanClearPinBus(_bclk); + } + if (_ws >= 0) { + perimanClearPinBus(_ws); + } if (_dout >= 0) { perimanClearPinBus(_dout); } @@ -803,32 +820,36 @@ bool I2SClass::configureRX(uint32_t rate, i2s_data_bit_width_t bits_cfg, i2s_slo size_t I2SClass::readBytes(char *buffer, size_t size) { size_t bytes_read = 0; + size_t bytes_to_read = 0; size_t total_size = 0; last_error = ESP_FAIL; if (rx_chan == NULL) { return total_size; } while (total_size < size) { - bytes_read = size - total_size; - if (rx_transform_buf != NULL && bytes_read > I2S_READ_CHUNK_SIZE) { - bytes_read = I2S_READ_CHUNK_SIZE; + bytes_read = 0; + bytes_to_read = size - total_size; + if (rx_transform_buf != NULL && bytes_to_read > I2S_READ_CHUNK_SIZE) { + bytes_to_read = I2S_READ_CHUNK_SIZE; } - I2S_ERROR_CHECK_RETURN(rx_fn(rx_chan, rx_transform_buf, (char *)(buffer + total_size), bytes_read, &bytes_read, _timeout), 0); + I2S_ERROR_CHECK_RETURN(rx_fn(rx_chan, rx_transform_buf, (char *)(buffer + total_size), bytes_to_read, &bytes_read, _timeout), 0); total_size += bytes_read; } return total_size; } -size_t I2SClass::write(uint8_t *buffer, size_t size) { +size_t I2SClass::write(const uint8_t *buffer, size_t size) { size_t written = 0; size_t bytes_sent = 0; + size_t bytes_to_send = 0; last_error = ESP_FAIL; if (tx_chan == NULL) { return written; } while (written < size) { - bytes_sent = size - written; - esp_err_t err = i2s_channel_write(tx_chan, (char *)(buffer + written), bytes_sent, &bytes_sent, _timeout); + bytes_sent = 0; + bytes_to_send = size - written; + esp_err_t err = i2s_channel_write(tx_chan, (char *)(buffer + written), bytes_to_send, &bytes_sent, _timeout); setWriteError(err); I2S_ERROR_CHECK_RETURN(err, written); written += bytes_sent; @@ -1007,6 +1028,7 @@ void I2SClass::playWAV(uint8_t *data, size_t len) { write(data + WAVE_HEADER_SIZE + data_offset, data_chunk->subchunk_size); } +#if ARDUINO_HAS_MP3_DECODER bool I2SClass::playMP3(uint8_t *src, size_t src_len) { int16_t outBuf[MAX_NCHAN * MAX_NGRAN * MAX_NSAMP]; uint8_t *readPtr = NULL; @@ -1044,5 +1066,6 @@ bool I2SClass::playMP3(uint8_t *src, size_t src_len) { MP3FreeDecoder(decoder); return true; } +#endif #endif /* SOC_I2S_SUPPORTED */ diff --git a/libraries/ESP_I2S/src/ESP_I2S.h b/libraries/ESP_I2S/src/ESP_I2S.h index c83e3815ddb..b5c076bed04 100644 --- a/libraries/ESP_I2S/src/ESP_I2S.h +++ b/libraries/ESP_I2S/src/ESP_I2S.h @@ -1,5 +1,9 @@ #pragma once +#if defined __has_include && __has_include("mp3dec.h") +#define ARDUINO_HAS_MP3_DECODER 1 +#endif + #include "soc/soc_caps.h" #if SOC_I2S_SUPPORTED @@ -62,7 +66,7 @@ class I2SClass : public Stream { bool end(); size_t readBytes(char *buffer, size_t size); - size_t write(uint8_t *buffer, size_t size); + size_t write(const uint8_t *buffer, size_t size); i2s_chan_handle_t txChan(); uint32_t txSampleRate(); @@ -85,8 +89,10 @@ class I2SClass : public Stream { uint8_t *recordWAV(size_t rec_seconds, size_t *out_size); // Play short PCM WAV from memory void playWAV(uint8_t *data, size_t len); +#if ARDUINO_HAS_MP3_DECODER // Play short MP3 from memory bool playMP3(uint8_t *src, size_t src_len); +#endif private: esp_err_t last_error; diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ESP_NOW_Broadcast_Master.ino b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ESP_NOW_Broadcast_Master.ino index bab8da6f66a..6ee7dc6f846 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ESP_NOW_Broadcast_Master.ino +++ b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ESP_NOW_Broadcast_Master.ino @@ -64,9 +64,6 @@ ESP_NOW_Broadcast_Peer broadcast_peer(ESPNOW_WIFI_CHANNEL, WIFI_IF_STA, NULL); void setup() { Serial.begin(115200); - while (!Serial) { - delay(10); - } // Initialize the Wi-Fi module WiFi.mode(WIFI_STA); diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ci.json b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ci.json index d8b3664bc65..36babb82730 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ci.json +++ b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ci.json @@ -1,5 +1,5 @@ { - "targets": { - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] } diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ESP_NOW_Broadcast_Slave.ino b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ESP_NOW_Broadcast_Slave.ino index 54978916afc..5f1a8bd8807 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ESP_NOW_Broadcast_Slave.ino +++ b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ESP_NOW_Broadcast_Slave.ino @@ -80,9 +80,6 @@ void register_new_master(const esp_now_recv_info_t *info, const uint8_t *data, i void setup() { Serial.begin(115200); - while (!Serial) { - delay(10); - } // Initialize the Wi-Fi module WiFi.mode(WIFI_STA); diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ci.json b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ci.json index d8b3664bc65..36babb82730 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ci.json +++ b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ci.json @@ -1,5 +1,5 @@ { - "targets": { - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] } diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Network/ESP_NOW_Network.ino b/libraries/ESP_NOW/examples/ESP_NOW_Network/ESP_NOW_Network.ino index bed4392d7b9..48ea6b731ce 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Network/ESP_NOW_Network.ino +++ b/libraries/ESP_NOW/examples/ESP_NOW_Network/ESP_NOW_Network.ino @@ -248,9 +248,6 @@ void setup() { uint8_t self_mac[6]; Serial.begin(115200); - while (!Serial) { - delay(10); - } // Initialize the Wi-Fi module WiFi.mode(WIFI_STA); diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Network/ci.json b/libraries/ESP_NOW/examples/ESP_NOW_Network/ci.json index d8b3664bc65..36babb82730 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Network/ci.json +++ b/libraries/ESP_NOW/examples/ESP_NOW_Network/ci.json @@ -1,5 +1,5 @@ { - "targets": { - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] } diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Serial/ci.json b/libraries/ESP_NOW/examples/ESP_NOW_Serial/ci.json index d8b3664bc65..36babb82730 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Serial/ci.json +++ b/libraries/ESP_NOW/examples/ESP_NOW_Serial/ci.json @@ -1,5 +1,5 @@ { - "targets": { - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] } diff --git a/libraries/ESP_NOW/library.properties b/libraries/ESP_NOW/library.properties old mode 100755 new mode 100644 index d0f2b2c7783..f3e5c109a9b --- a/libraries/ESP_NOW/library.properties +++ b/libraries/ESP_NOW/library.properties @@ -1,5 +1,5 @@ name=ESP_NOW -version=1.0.0 +version=3.2.0 author=me-no-dev maintainer=P-R-O-C-H-Y sentence=Library for ESP_NOW diff --git a/libraries/ESP_NOW/src/ESP32_NOW.cpp b/libraries/ESP_NOW/src/ESP32_NOW.cpp index a27fafac15e..6fd3ff0a0b1 100644 --- a/libraries/ESP_NOW/src/ESP32_NOW.cpp +++ b/libraries/ESP_NOW/src/ESP32_NOW.cpp @@ -1,3 +1,8 @@ +#include "sdkconfig.h" +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +#warning "ESP-NOW is only supported in SoCs with native Wi-Fi support" +#else + #include "ESP32_NOW.h" #include #include "esp_system.h" @@ -190,13 +195,19 @@ bool ESP_NOW_Class::end() { if (!_esp_now_has_begun) { return true; } - //remove all peers? + //remove all peers + for (uint8_t i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) { + if (_esp_now_peers[i] != NULL) { + removePeer(*_esp_now_peers[i]); + } + } esp_err_t err = esp_now_deinit(); if (err != ESP_OK) { log_e("esp_now_deinit failed! 0x%x", err); return false; } _esp_now_has_begun = false; + //clear the peer list memset(_esp_now_peers, 0, sizeof(ESP_NOW_Peer *) * ESP_NOW_MAX_TOTAL_PEER_NUM); return true; } @@ -262,6 +273,10 @@ void ESP_NOW_Class::onNewPeer(void (*cb)(const esp_now_recv_info_t *info, const new_arg = arg; } +bool ESP_NOW_Class::removePeer(ESP_NOW_Peer &peer) { + return peer.remove(); +} + ESP_NOW_Class ESP_NOW; /* @@ -396,3 +411,5 @@ size_t ESP_NOW_Peer::send(const uint8_t *data, int len) { ESP_NOW_Peer::operator bool() const { return added; } + +#endif diff --git a/libraries/ESP_NOW/src/ESP32_NOW.h b/libraries/ESP_NOW/src/ESP32_NOW.h index 03a34330700..efba9243aee 100644 --- a/libraries/ESP_NOW/src/ESP32_NOW.h +++ b/libraries/ESP_NOW/src/ESP32_NOW.h @@ -1,11 +1,41 @@ #pragma once +#include "sdkconfig.h" +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +#warning "ESP-NOW is only supported in SoCs with native Wi-Fi support" +#else + #include "esp_wifi_types.h" #include "Print.h" #include "esp_now.h" #include "esp32-hal-log.h" #include "esp_mac.h" +class ESP_NOW_Peer; //forward declaration for friend function + +class ESP_NOW_Class : public Print { +public: + const uint8_t BROADCAST_ADDR[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + ESP_NOW_Class(); + ~ESP_NOW_Class(); + + bool begin(const uint8_t *pmk = NULL /* 16 bytes */); + bool end(); + + int getTotalPeerCount(); + int getEncryptedPeerCount(); + + int availableForWrite(); + size_t write(const uint8_t *data, size_t len); + size_t write(uint8_t data) { + return write(&data, 1); + } + + void onNewPeer(void (*cb)(const esp_now_recv_info_t *info, const uint8_t *data, int len, void *arg), void *arg); + bool removePeer(ESP_NOW_Peer &peer); +}; + class ESP_NOW_Peer { private: uint8_t mac[6]; @@ -47,28 +77,10 @@ class ESP_NOW_Peer { virtual void onSent(bool success) { log_i("Message transmission to peer " MACSTR " %s", MAC2STR(mac), success ? "successful" : "failed"); } -}; - -class ESP_NOW_Class : public Print { -public: - const uint8_t BROADCAST_ADDR[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - - ESP_NOW_Class(); - ~ESP_NOW_Class(); - - bool begin(const uint8_t *pmk = NULL /* 16 bytes */); - bool end(); - int getTotalPeerCount(); - int getEncryptedPeerCount(); - - int availableForWrite(); - size_t write(const uint8_t *data, size_t len); - size_t write(uint8_t data) { - return write(&data, 1); - } - - void onNewPeer(void (*cb)(const esp_now_recv_info_t *info, const uint8_t *data, int len, void *arg), void *arg); + friend bool ESP_NOW_Class::removePeer(ESP_NOW_Peer &); }; extern ESP_NOW_Class ESP_NOW; + +#endif diff --git a/libraries/ESP_NOW/src/ESP32_NOW_Serial.cpp b/libraries/ESP_NOW/src/ESP32_NOW_Serial.cpp index e4220d45675..5603da2ba13 100644 --- a/libraries/ESP_NOW/src/ESP32_NOW_Serial.cpp +++ b/libraries/ESP_NOW/src/ESP32_NOW_Serial.cpp @@ -1,3 +1,8 @@ +#include "sdkconfig.h" +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +#warning "ESP-NOW is only supported in SoCs with native Wi-Fi support" +#else + #include "ESP32_NOW_Serial.h" #include #include "esp_now.h" @@ -11,7 +16,7 @@ * */ -ESP_NOW_Serial_Class::ESP_NOW_Serial_Class(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk) +ESP_NOW_Serial_Class::ESP_NOW_Serial_Class(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk, bool remove_on_fail) : ESP_NOW_Peer(mac_addr, channel, iface, lmk) { tx_ring_buf = NULL; rx_queue = NULL; @@ -19,6 +24,7 @@ ESP_NOW_Serial_Class::ESP_NOW_Serial_Class(const uint8_t *mac_addr, uint8_t chan queued_size = 0; queued_buff = NULL; resend_count = 0; + _remove_on_fail = remove_on_fail; } ESP_NOW_Serial_Class::~ESP_NOW_Serial_Class() { @@ -264,9 +270,17 @@ void ESP_NOW_Serial_Class::onSent(bool success) { //the data is lost in this case vRingbufferReturnItem(tx_ring_buf, queued_buff); queued_buff = NULL; - xSemaphoreGive(tx_sem); - end(); log_e(MACSTR " : RE-SEND_MAX[%u]", MAC2STR(addr()), resend_count); + //if we are not able to send the data and remove_on_fail is set, remove the peer + if (_remove_on_fail) { + xSemaphoreGive(tx_sem); + end(); + return; + } + //log_d(MACSTR ": NEXT", MAC2STR(addr())); + checkForTxData(); } } } + +#endif diff --git a/libraries/ESP_NOW/src/ESP32_NOW_Serial.h b/libraries/ESP_NOW/src/ESP32_NOW_Serial.h index 42349f6c20b..7cc43d85ef8 100644 --- a/libraries/ESP_NOW/src/ESP32_NOW_Serial.h +++ b/libraries/ESP_NOW/src/ESP32_NOW_Serial.h @@ -1,5 +1,10 @@ #pragma once +#include "sdkconfig.h" +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +#warning "ESP-NOW is only supported in SoCs with native Wi-Fi support" +#else + #include "esp_wifi_types.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -17,12 +22,13 @@ class ESP_NOW_Serial_Class : public Stream, public ESP_NOW_Peer { size_t queued_size; uint8_t *queued_buff; size_t resend_count; + bool _remove_on_fail; bool checkForTxData(); size_t tryToSend(); public: - ESP_NOW_Serial_Class(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface = WIFI_IF_AP, const uint8_t *lmk = NULL); + ESP_NOW_Serial_Class(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface = WIFI_IF_AP, const uint8_t *lmk = NULL, bool remove_on_fail = false); ~ESP_NOW_Serial_Class(); size_t setRxBufferSize(size_t); size_t setTxBufferSize(size_t); @@ -47,3 +53,5 @@ class ESP_NOW_Serial_Class : public Stream, public ESP_NOW_Peer { void onReceive(const uint8_t *data, size_t len, bool broadcast); void onSent(bool success); }; + +#endif diff --git a/libraries/ESP_SR/examples/Basic/ci.json b/libraries/ESP_SR/examples/Basic/ci.json index 97ae5ee5616..c395378f45e 100644 --- a/libraries/ESP_SR/examples/Basic/ci.json +++ b/libraries/ESP_SR/examples/Basic/ci.json @@ -1,9 +1,18 @@ { + "fqbn": { + "esp32s3": [ + "espressif:esp32:esp32s3:USBMode=default,PartitionScheme=esp_sr_16,FlashSize=16M,FlashMode=dio" + ] + }, + "requires": [ + "CONFIG_SOC_I2S_SUPPORTED=y" + ], "targets": { "esp32": false, "esp32c3": false, "esp32c6": false, "esp32h2": false, + "esp32p4": false, "esp32s2": false } } diff --git a/libraries/ESP_SR/library.properties b/libraries/ESP_SR/library.properties old mode 100755 new mode 100644 index bf029b5e0dc..295761bd9fb --- a/libraries/ESP_SR/library.properties +++ b/libraries/ESP_SR/library.properties @@ -1,5 +1,5 @@ name=ESP_SR -version=1.0.0 +version=3.2.0 author=me-no-dev maintainer=me-no-dev sentence=Library for ESP Sound Recognition diff --git a/libraries/ESPmDNS/examples/mDNS-SD_Extended/ci.json b/libraries/ESPmDNS/examples/mDNS-SD_Extended/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/ESPmDNS/examples/mDNS-SD_Extended/ci.json +++ b/libraries/ESPmDNS/examples/mDNS-SD_Extended/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/ESPmDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino b/libraries/ESPmDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino index d2e48c0580c..e630d668cea 100644 --- a/libraries/ESPmDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino +++ b/libraries/ESPmDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino @@ -68,6 +68,8 @@ void browseService(const char *service, const char *proto) { Serial.print(" "); Serial.print(i + 1); Serial.print(": "); + Serial.print(MDNS.instanceName(i)); + Serial.print(" - "); Serial.print(MDNS.hostname(i)); Serial.print(" ("); Serial.print(MDNS.address(i)); diff --git a/libraries/ESPmDNS/examples/mDNS_Web_Server/ci.json b/libraries/ESPmDNS/examples/mDNS_Web_Server/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/ESPmDNS/examples/mDNS_Web_Server/ci.json +++ b/libraries/ESPmDNS/examples/mDNS_Web_Server/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/ESPmDNS/library.properties b/libraries/ESPmDNS/library.properties index 6f1281a47c3..6d36d61b783 100644 --- a/libraries/ESPmDNS/library.properties +++ b/libraries/ESPmDNS/library.properties @@ -1,5 +1,5 @@ name=ESPmDNS -version=2.0.0 +version=3.2.0 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 mDNS Library diff --git a/libraries/ESPmDNS/src/ESPmDNS.cpp b/libraries/ESPmDNS/src/ESPmDNS.cpp index 546de43c20a..5d422513bbd 100644 --- a/libraries/ESPmDNS/src/ESPmDNS.cpp +++ b/libraries/ESPmDNS/src/ESPmDNS.cpp @@ -39,6 +39,7 @@ License (MIT license): #endif #include "ESPmDNS.h" +#ifdef CONFIG_MDNS_MAX_INTERFACES #include #include "esp_mac.h" #include "soc/soc_caps.h" @@ -298,6 +299,15 @@ String MDNSResponder::hostname(int idx) { return String(result->hostname); } +String MDNSResponder::instanceName(int idx) { + mdns_result_t *result = _getResult(idx); + if (!result) { + log_e("Result %d not found", idx); + return String(); + } + return String(result->instance_name); +} + IPAddress MDNSResponder::address(int idx) { mdns_result_t *result = _getResult(idx); if (!result) { @@ -391,3 +401,5 @@ String MDNSResponder::txtKey(int idx, int txtIdx) { } MDNSResponder MDNS; + +#endif /* CONFIG_MDNS_MAX_INTERFACES */ diff --git a/libraries/ESPmDNS/src/ESPmDNS.h b/libraries/ESPmDNS/src/ESPmDNS.h index 04ac382cfdc..1fb90bbf454 100644 --- a/libraries/ESPmDNS/src/ESPmDNS.h +++ b/libraries/ESPmDNS/src/ESPmDNS.h @@ -41,6 +41,9 @@ License (MIT license): #ifndef ESP32MDNS_H #define ESP32MDNS_H +#include "sdkconfig.h" +#ifdef CONFIG_MDNS_MAX_INTERFACES + #include "Arduino.h" #include "mdns.h" #include "esp_interface.h" @@ -107,6 +110,7 @@ class MDNSResponder { } String hostname(int idx); + String instanceName(int idx); IPAddress address(int idx); IPAddress addressV6(int idx); uint16_t port(int idx); @@ -125,4 +129,5 @@ class MDNSResponder { extern MDNSResponder MDNS; +#endif /* CONFIG_MDNS_MAX_INTERFACES */ #endif //ESP32MDNS_H diff --git a/libraries/Ethernet/examples/ETH_LAN8720/ETH_LAN8720.ino b/libraries/Ethernet/examples/ETH_LAN8720/ETH_LAN8720.ino index 1453df63434..59a32750bf6 100644 --- a/libraries/Ethernet/examples/ETH_LAN8720/ETH_LAN8720.ino +++ b/libraries/Ethernet/examples/ETH_LAN8720/ETH_LAN8720.ino @@ -5,13 +5,21 @@ // Important to be defined BEFORE including ETH.h for ETH.begin() to work. // Example RMII LAN8720 (Olimex, etc.) -#ifndef ETH_PHY_TYPE -#define ETH_PHY_TYPE ETH_PHY_LAN8720 +#ifndef ETH_PHY_MDC +#define ETH_PHY_TYPE ETH_PHY_LAN8720 +#if CONFIG_IDF_TARGET_ESP32 #define ETH_PHY_ADDR 0 #define ETH_PHY_MDC 23 #define ETH_PHY_MDIO 18 #define ETH_PHY_POWER -1 #define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN +#elif CONFIG_IDF_TARGET_ESP32P4 +#define ETH_PHY_ADDR 0 +#define ETH_PHY_MDC 31 +#define ETH_PHY_MDIO 52 +#define ETH_PHY_POWER 51 +#define ETH_CLK_MODE EMAC_CLK_EXT_IN +#endif #endif #include diff --git a/libraries/Ethernet/examples/ETH_LAN8720/ci.json b/libraries/Ethernet/examples/ETH_LAN8720/ci.json index 1af543242e3..0eab13b8841 100644 --- a/libraries/Ethernet/examples/ETH_LAN8720/ci.json +++ b/libraries/Ethernet/examples/ETH_LAN8720/ci.json @@ -1,9 +1,8 @@ { + "requires": [ + "CONFIG_ETH_USE_ESP32_EMAC=y" + ], "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false + "esp32p4": false } } diff --git a/libraries/Ethernet/examples/ETH_TLK110/ETH_TLK110.ino b/libraries/Ethernet/examples/ETH_TLK110/ETH_TLK110.ino index 3252cd120f4..242281c3997 100644 --- a/libraries/Ethernet/examples/ETH_TLK110/ETH_TLK110.ino +++ b/libraries/Ethernet/examples/ETH_TLK110/ETH_TLK110.ino @@ -5,13 +5,21 @@ #include -#ifndef ETH_PHY_TYPE -#define ETH_PHY_TYPE ETH_PHY_TLK110 +#ifndef ETH_PHY_MDC +#define ETH_PHY_TYPE ETH_PHY_TLK110 +#if CONFIG_IDF_TARGET_ESP32 #define ETH_PHY_ADDR 31 #define ETH_PHY_MDC 23 #define ETH_PHY_MDIO 18 #define ETH_PHY_POWER 17 #define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN +#elif CONFIG_IDF_TARGET_ESP32P4 +#define ETH_PHY_ADDR 1 +#define ETH_PHY_MDC 31 +#define ETH_PHY_MDIO 52 +#define ETH_PHY_POWER 51 +#define ETH_CLK_MODE EMAC_CLK_EXT_IN +#endif #endif static bool eth_connected = false; diff --git a/libraries/Ethernet/examples/ETH_TLK110/ci.json b/libraries/Ethernet/examples/ETH_TLK110/ci.json index 1af543242e3..dcdfd06db51 100644 --- a/libraries/Ethernet/examples/ETH_TLK110/ci.json +++ b/libraries/Ethernet/examples/ETH_TLK110/ci.json @@ -1,9 +1,5 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } + "requires": [ + "CONFIG_ETH_USE_ESP32_EMAC=y" + ] } diff --git a/libraries/Ethernet/examples/ETH_W5500_Arduino_SPI/ETH_W5500_Arduino_SPI.ino b/libraries/Ethernet/examples/ETH_W5500_Arduino_SPI/ETH_W5500_Arduino_SPI.ino index d4bc78a1c07..d5d57333a55 100644 --- a/libraries/Ethernet/examples/ETH_W5500_Arduino_SPI/ETH_W5500_Arduino_SPI.ino +++ b/libraries/Ethernet/examples/ETH_W5500_Arduino_SPI/ETH_W5500_Arduino_SPI.ino @@ -9,7 +9,7 @@ // Set this to 1 to enable dual Ethernet support #define USE_TWO_ETH_PORTS 0 -#ifndef ETH_PHY_TYPE +#ifndef ETH_PHY_CS #define ETH_PHY_TYPE ETH_PHY_W5500 #define ETH_PHY_ADDR 1 #define ETH_PHY_CS 15 @@ -24,7 +24,7 @@ #if USE_TWO_ETH_PORTS // Second port on shared SPI bus -#ifndef ETH1_PHY_TYPE +#ifndef ETH1_PHY_CS #define ETH1_PHY_TYPE ETH_PHY_W5500 #define ETH1_PHY_ADDR 1 #define ETH1_PHY_CS 32 diff --git a/libraries/Ethernet/examples/ETH_W5500_IDF_SPI/ETH_W5500_IDF_SPI.ino b/libraries/Ethernet/examples/ETH_W5500_IDF_SPI/ETH_W5500_IDF_SPI.ino index 512bb78ff5e..dad54a745b7 100644 --- a/libraries/Ethernet/examples/ETH_W5500_IDF_SPI/ETH_W5500_IDF_SPI.ino +++ b/libraries/Ethernet/examples/ETH_W5500_IDF_SPI/ETH_W5500_IDF_SPI.ino @@ -8,7 +8,7 @@ // Set this to 1 to enable dual Ethernet support #define USE_TWO_ETH_PORTS 0 -#ifndef ETH_PHY_TYPE +#ifndef ETH_PHY_CS #define ETH_PHY_TYPE ETH_PHY_W5500 #define ETH_PHY_ADDR 1 #define ETH_PHY_CS 15 @@ -22,7 +22,7 @@ #if USE_TWO_ETH_PORTS // Second port on shared SPI bus -#ifndef ETH1_PHY_TYPE +#ifndef ETH1_PHY_CS #define ETH1_PHY_TYPE ETH_PHY_W5500 #define ETH1_PHY_ADDR 1 #define ETH1_PHY_CS 32 diff --git a/libraries/Ethernet/examples/ETH_WIFI_BRIDGE/ETH_WIFI_BRIDGE.ino b/libraries/Ethernet/examples/ETH_WIFI_BRIDGE/ETH_WIFI_BRIDGE.ino new file mode 100644 index 00000000000..ba89d5de607 --- /dev/null +++ b/libraries/Ethernet/examples/ETH_WIFI_BRIDGE/ETH_WIFI_BRIDGE.ino @@ -0,0 +1,78 @@ +#include +#include +#include + +#define ETH_TYPE ETH_PHY_W5500 +#define ETH_ADDR 1 +#define ETH_CS 15 +#define ETH_IRQ 4 +#define ETH_RST 5 +#define ETH_SPI_SCK 14 +#define ETH_SPI_MISO 12 +#define ETH_SPI_MOSI 13 + +#define AP_SSID "ESP32-ETH-WIFI-BRIDGE" +#define AP_PASS "password" + +IPAddress ap_ip(192, 168, 4, 1); +IPAddress ap_mask(255, 255, 255, 0); +IPAddress ap_leaseStart(192, 168, 4, 2); +IPAddress ap_dns(8, 8, 4, 4); + +void setup() { + Serial.begin(115200); + Serial.setDebugOutput(true); + Network.onEvent(onEvent); + + WiFi.AP.begin(); + WiFi.AP.config(ap_ip, ap_ip, ap_mask, ap_leaseStart, ap_dns); + WiFi.AP.create(AP_SSID, AP_PASS); + if (!WiFi.AP.waitStatusBits(ESP_NETIF_STARTED_BIT, 1000)) { + Serial.println("Failed to start AP!"); + return; + } + delay(100); + + SPI.begin(ETH_SPI_SCK, ETH_SPI_MISO, ETH_SPI_MOSI); + ETH.begin(ETH_TYPE, ETH_ADDR, ETH_CS, ETH_IRQ, ETH_RST, SPI); +} + +void loop() { + delay(20000); +} + +void onEvent(arduino_event_id_t event, arduino_event_info_t info) { + switch (event) { + case ARDUINO_EVENT_ETH_START: Serial.println("ETH Started"); break; + case ARDUINO_EVENT_ETH_CONNECTED: Serial.println("ETH Connected"); break; + case ARDUINO_EVENT_ETH_GOT_IP: + Serial.println("ETH Got IP"); + Serial.println(ETH); + WiFi.AP.enableNAPT(true); + break; + case ARDUINO_EVENT_ETH_LOST_IP: + Serial.println("ETH Lost IP"); + WiFi.AP.enableNAPT(false); + break; + case ARDUINO_EVENT_ETH_DISCONNECTED: + Serial.println("ETH Disconnected"); + WiFi.AP.enableNAPT(false); + break; + case ARDUINO_EVENT_ETH_STOP: Serial.println("ETH Stopped"); break; + + case ARDUINO_EVENT_WIFI_AP_START: + Serial.println("AP Started"); + Serial.println(WiFi.AP); + break; + case ARDUINO_EVENT_WIFI_AP_STACONNECTED: Serial.println("AP STA Connected"); break; + case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: Serial.println("AP STA Disconnected"); break; + case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED: + Serial.print("AP STA IP Assigned: "); + Serial.println(IPAddress(info.wifi_ap_staipassigned.ip.addr)); + break; + case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED: Serial.println("AP Probe Request Received"); break; + case ARDUINO_EVENT_WIFI_AP_STOP: Serial.println("AP Stopped"); break; + + default: break; + } +} diff --git a/libraries/Ethernet/examples/ETH_WIFI_BRIDGE/ci.json b/libraries/Ethernet/examples/ETH_WIFI_BRIDGE/ci.json new file mode 100644 index 00000000000..618e46bd244 --- /dev/null +++ b/libraries/Ethernet/examples/ETH_WIFI_BRIDGE/ci.json @@ -0,0 +1,6 @@ +{ + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] +} diff --git a/libraries/Ethernet/library.properties b/libraries/Ethernet/library.properties index c32adf1a7ea..d34ae036417 100644 --- a/libraries/Ethernet/library.properties +++ b/libraries/Ethernet/library.properties @@ -1,5 +1,5 @@ name=Ethernet -version=2.0.0 +version=3.2.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables network connection (local and Internet) using the ESP32 Ethernet. diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 2480dd982ec..3dfba37c684 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -22,6 +22,7 @@ #define ARDUINO_CORE_BUILD #include "ETH.h" +#if CONFIG_ETH_ENABLED #include "esp_system.h" #include "esp_event.h" #include "esp_eth.h" @@ -30,7 +31,9 @@ #include "driver/gpio.h" #include "driver/spi_master.h" #if CONFIG_ETH_USE_ESP32_EMAC +#if defined __has_include && __has_include("soc/emac_ext_struct.h") #include "soc/emac_ext_struct.h" +#endif /* __has_include("soc/emac_ext_struct.h" */ #include "soc/rtc.h" #endif /* CONFIG_ETH_USE_ESP32_EMAC */ #include "esp32-hal-periman.h" @@ -72,6 +75,7 @@ static void onEthConnected(arduino_event_id_t event, arduino_event_info_t info) log_e("Could not find ETH interface with that handle!"); return; } +#if CONFIG_LWIP_IPV6 if (_ethernets[index]->getStatusBits() & ESP_NETIF_WANT_IP6_BIT) { esp_err_t err = esp_netif_create_ip6_linklocal(_ethernets[index]->netif()); if (err != ESP_OK) { @@ -80,6 +84,7 @@ static void onEthConnected(arduino_event_id_t event, arduino_event_info_t info) log_v("Enabled IPv6 Link Local on %s", _ethernets[index]->desc()); } } +#endif } } @@ -119,7 +124,8 @@ void ETHClass::_onEthEvent(int32_t event_id, void *event_data) { } ETHClass::ETHClass(uint8_t eth_index) - : _eth_handle(NULL), _eth_index(eth_index), _phy_type(ETH_PHY_MAX), _glue_handle(NULL), _mac(NULL), _phy(NULL) + : _eth_handle(NULL), _eth_index(eth_index), _phy_type(ETH_PHY_MAX), _glue_handle(NULL), _mac(NULL), _phy(NULL), _eth_started(false), _link_speed(100), + _full_duplex(true), _auto_negotiation(true) #if ETH_SPI_SUPPORTS_CUSTOM , _spi(NULL) @@ -130,7 +136,8 @@ ETHClass::ETHClass(uint8_t eth_index) , _pin_mcd(-1), _pin_mdio(-1), _pin_power(-1), _pin_rmii_clock(-1) #endif /* CONFIG_ETH_USE_ESP32_EMAC */ -{ + , + _task_stack_size(4096), _eth_connected_event_handle(0) { } ETHClass::~ETHClass() {} @@ -141,7 +148,47 @@ bool ETHClass::ethDetachBus(void *bus_pointer) { return true; } +void ETHClass::setTaskStackSize(size_t size) { + _task_stack_size = size; +} + #if CONFIG_ETH_USE_ESP32_EMAC +#if CONFIG_IDF_TARGET_ESP32 +#define ETH_EMAC_DEFAULT_CONFIG() ETH_ESP32_EMAC_DEFAULT_CONFIG() +#elif CONFIG_IDF_TARGET_ESP32P4 +// clang-format off +#define ETH_EMAC_DEFAULT_CONFIG() \ + { \ + .smi_gpio = {.mdc_num = 31, .mdio_num = 52}, \ + .interface = EMAC_DATA_INTERFACE_RMII, \ + .clock_config = { \ + .rmii = { \ + .clock_mode = EMAC_CLK_EXT_IN, \ + .clock_gpio = (emac_rmii_clock_gpio_t)ETH_RMII_CLK \ + } \ + }, \ + .dma_burst_len = ETH_DMA_BURST_LEN_32, \ + .intr_priority = 0, \ + .emac_dataif_gpio = { \ + .rmii = { \ + .tx_en_num = ETH_RMII_TX_EN, \ + .txd0_num = ETH_RMII_TX0, \ + .txd1_num = ETH_RMII_TX1, \ + .crs_dv_num = ETH_RMII_CRS_DV, \ + .rxd0_num = ETH_RMII_RX0, \ + .rxd1_num = ETH_RMII_RX1_EN \ + } \ + }, \ + .clock_config_out_in = { \ + .rmii = { \ + .clock_mode = EMAC_CLK_EXT_IN, \ + .clock_gpio = (emac_rmii_clock_gpio_t) - 1 \ + } \ + }, \ + } +#endif +// clang-format on + bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, int power, eth_clock_mode_t clock_mode) { esp_err_t ret = ESP_OK; if (_eth_index > 2) { @@ -165,14 +212,23 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i Network.begin(); _ethernets[_eth_index] = this; - eth_esp32_emac_config_t mac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); +#if CONFIG_IDF_TARGET_ESP32 +#undef DEFAULT_RMII_CLK_GPIO +#define DEFAULT_RMII_CLK_GPIO (emac_rmii_clock_gpio_t)(0) +#endif + + eth_esp32_emac_config_t mac_config = ETH_EMAC_DEFAULT_CONFIG(); +#if CONFIG_IDF_TARGET_ESP32 mac_config.clock_config.rmii.clock_mode = (clock_mode) ? EMAC_CLK_OUT : EMAC_CLK_EXT_IN; mac_config.clock_config.rmii.clock_gpio = (1 == clock_mode) ? EMAC_APPL_CLK_OUT_GPIO : (2 == clock_mode) ? EMAC_CLK_OUT_GPIO : (3 == clock_mode) ? EMAC_CLK_OUT_180_GPIO : EMAC_CLK_IN_GPIO; - mac_config.smi_mdc_gpio_num = digitalPinToGPIONumber(mdc); - mac_config.smi_mdio_gpio_num = digitalPinToGPIONumber(mdio); +#elif CONFIG_IDF_TARGET_ESP32P4 + mac_config.clock_config.rmii.clock_mode = (emac_rmii_clock_mode_t)clock_mode; +#endif + mac_config.smi_gpio.mdc_num = digitalPinToGPIONumber(mdc); + mac_config.smi_gpio.mdio_num = digitalPinToGPIONumber(mdio); _pin_mcd = digitalPinToGPIONumber(mdc); _pin_mdio = digitalPinToGPIONumber(mdio); @@ -214,9 +270,10 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i eth_mac_config_t eth_mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_mac_config.sw_reset_timeout_ms = 1000; + eth_mac_config.rx_task_stack_size = _task_stack_size; - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config, ð_mac_config); - if (mac == NULL) { + _mac = esp_eth_mac_new_esp32(&mac_config, ð_mac_config); + if (_mac == NULL) { log_e("esp_eth_mac_new_esp32 failed"); return false; } @@ -225,23 +282,25 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i phy_config.phy_addr = phy_addr; phy_config.reset_gpio_num = _pin_power; - esp_eth_phy_t *phy = NULL; switch (type) { - case ETH_PHY_LAN8720: phy = esp_eth_phy_new_lan87xx(&phy_config); break; - case ETH_PHY_TLK110: phy = esp_eth_phy_new_ip101(&phy_config); break; - case ETH_PHY_RTL8201: phy = esp_eth_phy_new_rtl8201(&phy_config); break; - case ETH_PHY_DP83848: phy = esp_eth_phy_new_dp83848(&phy_config); break; - case ETH_PHY_KSZ8041: phy = esp_eth_phy_new_ksz80xx(&phy_config); break; - case ETH_PHY_KSZ8081: phy = esp_eth_phy_new_ksz80xx(&phy_config); break; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0) + case ETH_PHY_GENERIC: _phy = esp_eth_phy_new_generic(&phy_config); break; +#endif + case ETH_PHY_LAN8720: _phy = esp_eth_phy_new_lan87xx(&phy_config); break; + case ETH_PHY_TLK110: _phy = esp_eth_phy_new_ip101(&phy_config); break; + case ETH_PHY_RTL8201: _phy = esp_eth_phy_new_rtl8201(&phy_config); break; + case ETH_PHY_DP83848: _phy = esp_eth_phy_new_dp83848(&phy_config); break; + case ETH_PHY_KSZ8041: _phy = esp_eth_phy_new_ksz80xx(&phy_config); break; + case ETH_PHY_KSZ8081: _phy = esp_eth_phy_new_ksz80xx(&phy_config); break; default: log_e("Unsupported PHY %d", type); break; } - if (phy == NULL) { + if (_phy == NULL) { log_e("esp_eth_phy_new failed"); return false; } _eth_handle = NULL; - esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); + esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(_mac, _phy); ret = esp_eth_driver_install(ð_config, &_eth_handle); if (ret != ESP_OK) { log_e("Ethernet driver install failed: %d", ret); @@ -293,6 +352,19 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i return false; } + // auto negotiation needs to be disabled to change duplex mode and link speed + if (!_auto_negotiation) { + if (!_setAutoNegotiation(_auto_negotiation)) { + return false; + } + if (!_setFullDuplex(_full_duplex)) { + return false; + } + if (!_setLinkSpeed(_link_speed)) { + return false; + } + } + if (_eth_ev_instance == NULL && esp_event_handler_instance_register(ETH_EVENT, ESP_EVENT_ANY_ID, &_eth_event_cb, NULL, &_eth_ev_instance)) { log_e("event_handler_instance_register for ETH_EVENT Failed!"); return false; @@ -301,7 +373,7 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i /* attach to receive events */ initNetif((Network_Interface_ID)(ESP_NETIF_ID_ETH + _eth_index)); - Network.onSysEvent(onEthConnected, ARDUINO_EVENT_ETH_CONNECTED); + _eth_connected_event_handle = Network.onSysEvent(onEthConnected, ARDUINO_EVENT_ETH_CONNECTED); ret = esp_eth_start(_eth_handle); if (ret != ESP_OK) { @@ -309,6 +381,8 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i return false; } + _eth_started = true; + if (!perimanSetPinBus(_pin_rmii_clock, ESP32_BUS_TYPE_ETHERNET_CLK, (void *)(this), -1, -1)) { goto err; } @@ -578,6 +652,9 @@ bool ETHClass::beginSPI( __unused eth_mac_config_t eth_mac_config = ETH_MAC_DEFAULT_CONFIG(); __unused eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); + // Set RX Task Stack Size + eth_mac_config.rx_task_stack_size = _task_stack_size; + // Update PHY config based on board specific configuration phy_config.phy_addr = phy_addr; phy_config.reset_gpio_num = _pin_rst; @@ -727,6 +804,19 @@ bool ETHClass::beginSPI( return false; } + // auto negotiation needs to be disabled to change duplex mode and link speed + if (!_auto_negotiation) { + if (!_setAutoNegotiation(_auto_negotiation)) { + return false; + } + if (!_setFullDuplex(_full_duplex)) { + return false; + } + if (!_setLinkSpeed(_link_speed)) { + return false; + } + } + if (_eth_ev_instance == NULL && esp_event_handler_instance_register(ETH_EVENT, ESP_EVENT_ANY_ID, &_eth_event_cb, NULL, &_eth_ev_instance)) { log_e("event_handler_instance_register for ETH_EVENT Failed!"); return false; @@ -742,6 +832,8 @@ bool ETHClass::beginSPI( return false; } + _eth_started = true; + // If Arduino's SPI is used, cs pin is in GPIO mode #if ETH_SPI_SUPPORTS_CUSTOM if (_spi == NULL) { @@ -788,7 +880,7 @@ bool ETHClass::beginSPI( perimanSetPinBusExtraType(_pin_rst, "ETH_RST"); } - Network.onSysEvent(onEthConnected, ARDUINO_EVENT_ETH_CONNECTED); + _eth_connected_event_handle = Network.onSysEvent(onEthConnected, ARDUINO_EVENT_ETH_CONNECTED); return true; @@ -824,7 +916,8 @@ static bool empty_ethDetachBus(void *bus_pointer) { void ETHClass::end(void) { - Network.removeEvent(onEthConnected, ARDUINO_EVENT_ETH_CONNECTED); + Network.removeEvent(_eth_connected_event_handle); + _eth_connected_event_handle = 0; if (_eth_handle != NULL) { if (esp_eth_stop(_eth_handle) != ESP_OK) { @@ -835,6 +928,9 @@ void ETHClass::end(void) { while (getStatusBits() & ESP_NETIF_STARTED_BIT) { delay(10); } + + _eth_started = false; + //delete glue first if (_glue_handle != NULL) { if (esp_eth_del_netif_glue(_glue_handle) != ESP_OK) { @@ -884,7 +980,7 @@ void ETHClass::end(void) { #if ETH_SPI_SUPPORTS_CUSTOM _spi = NULL; #endif -#if CONFIG_ETH_USE_ESP32_EMAC +#if (CONFIG_ETH_USE_ESP32_EMAC && !defined(CONFIG_IDF_TARGET_ESP32P4)) perimanSetBusDeinit(ESP32_BUS_TYPE_ETHERNET_RMII, empty_ethDetachBus); perimanSetBusDeinit(ESP32_BUS_TYPE_ETHERNET_CLK, empty_ethDetachBus); perimanSetBusDeinit(ESP32_BUS_TYPE_ETHERNET_MCD, empty_ethDetachBus); @@ -948,6 +1044,30 @@ bool ETHClass::fullDuplex() const { return (link_duplex == ETH_DUPLEX_FULL); } +bool ETHClass::_setFullDuplex(bool on) { + if (_eth_handle == NULL) { + return false; + } + eth_duplex_t link_duplex = on ? ETH_DUPLEX_FULL : ETH_DUPLEX_HALF; + esp_err_t err = esp_eth_ioctl(_eth_handle, ETH_CMD_S_DUPLEX_MODE, &link_duplex); + if (err != ESP_OK) { + log_e("Failed to set duplex mode: 0x%x: %s", err, esp_err_to_name(err)); + } + return err == ESP_OK; +} + +bool ETHClass::setFullDuplex(bool on) { + if (_eth_started) { + log_e("This method must be called before ETH.begin()"); + return false; + } + if (_auto_negotiation) { + log_w("Auto Negotiation MUST be OFF for this setting to be applied"); + } + _full_duplex = on; + return true; +} + bool ETHClass::autoNegotiation() const { if (_eth_handle == NULL) { return false; @@ -957,6 +1077,26 @@ bool ETHClass::autoNegotiation() const { return auto_nego; } +bool ETHClass::_setAutoNegotiation(bool on) { + if (_eth_handle == NULL) { + return false; + } + esp_err_t err = esp_eth_ioctl(_eth_handle, ETH_CMD_S_AUTONEGO, &on); + if (err != ESP_OK) { + log_e("Failed to set auto negotiation: 0x%x: %s", err, esp_err_to_name(err)); + } + return err == ESP_OK; +} + +bool ETHClass::setAutoNegotiation(bool on) { + if (_eth_started) { + log_e("This method must be called before ETH.begin()"); + return false; + } + _auto_negotiation = on; + return true; +} + uint32_t ETHClass::phyAddr() const { if (_eth_handle == NULL) { return 0; @@ -966,7 +1106,7 @@ uint32_t ETHClass::phyAddr() const { return phy_addr; } -uint8_t ETHClass::linkSpeed() const { +uint16_t ETHClass::linkSpeed() const { if (_eth_handle == NULL) { return 0; } @@ -975,6 +1115,34 @@ uint8_t ETHClass::linkSpeed() const { return (link_speed == ETH_SPEED_10M) ? 10 : 100; } +bool ETHClass::_setLinkSpeed(uint16_t speed) { + if (_eth_handle == NULL) { + return false; + } + eth_speed_t link_speed = (speed == 10) ? ETH_SPEED_10M : ETH_SPEED_100M; + esp_err_t err = esp_eth_ioctl(_eth_handle, ETH_CMD_S_SPEED, &link_speed); + if (err != ESP_OK) { + log_e("Failed to set link speed: 0x%x: %s", err, esp_err_to_name(err)); + } + return err == ESP_OK; +} + +bool ETHClass::setLinkSpeed(uint16_t speed) { + if (speed != 10 && speed != 100) { + log_e("Ethernet currently supports only 10 or 100 Mbps link speed"); + return false; + } + if (_eth_started) { + log_e("This method must be called before ETH.begin()"); + return false; + } + if (_auto_negotiation) { + log_w("Auto Negotiation MUST be OFF for this setting to be applied"); + } + _link_speed = speed; + return true; +} + // void ETHClass::getMac(uint8_t* mac) // { // if(_eth_handle != NULL && mac != NULL){ @@ -998,3 +1166,5 @@ size_t ETHClass::printDriverInfo(Print &out) const { } ETHClass ETH; + +#endif /* CONFIG_ETH_ENABLED */ diff --git a/libraries/Ethernet/src/ETH.h b/libraries/Ethernet/src/ETH.h index b481b9e36c3..c52aac6ec6f 100644 --- a/libraries/Ethernet/src/ETH.h +++ b/libraries/Ethernet/src/ETH.h @@ -18,8 +18,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "sdkconfig.h" +#if CONFIG_ETH_ENABLED + #ifndef _ETH_H_ #define _ETH_H_ +#include "esp_idf_version.h" // // Example configurations for pins_arduino.h to allow starting with ETH.begin(); @@ -75,6 +79,7 @@ #if CONFIG_ETH_USE_ESP32_EMAC #define ETH_PHY_IP101 ETH_PHY_TLK110 +#if CONFIG_IDF_TARGET_ESP32 typedef enum { ETH_CLOCK_GPIO0_IN, ETH_CLOCK_GPIO0_OUT, @@ -88,6 +93,31 @@ typedef enum { #define ETH_RMII_RX0 25 #define ETH_RMII_RX1_EN 26 #define ETH_RMII_CRS_DV 27 +#elif CONFIG_IDF_TARGET_ESP32P4 +typedef emac_rmii_clock_mode_t eth_clock_mode_t; +#include "pins_arduino.h" +#ifndef ETH_RMII_TX_EN +#define ETH_RMII_TX_EN 49 +#endif +#ifndef ETH_RMII_TX0 +#define ETH_RMII_TX0 34 +#endif +#ifndef ETH_RMII_TX1 +#define ETH_RMII_TX1 35 +#endif +#ifndef ETH_RMII_RX0 +#define ETH_RMII_RX0 29 +#endif +#ifndef ETH_RMII_RX1_EN +#define ETH_RMII_RX1_EN 30 +#endif +#ifndef ETH_RMII_CRS_DV +#define ETH_RMII_CRS_DV 28 +#endif +#ifndef ETH_RMII_CLK +#define ETH_RMII_CLK 50 +#endif +#endif #endif /* CONFIG_ETH_USE_ESP32_EMAC */ #ifndef ETH_PHY_SPI_FREQ_MHZ @@ -98,6 +128,10 @@ typedef enum { typedef enum { #if CONFIG_ETH_USE_ESP32_EMAC +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0) + ETH_PHY_GENERIC, +#define ETH_PHY_JL1101 ETH_PHY_GENERIC +#endif ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_RTL8201, @@ -153,10 +187,19 @@ class ETHClass : public NetworkInterface { void end(); + // This function must be called before `begin()` + void setTaskStackSize(size_t size); + // ETH Handle APIs bool fullDuplex() const; - uint8_t linkSpeed() const; + bool setFullDuplex(bool on); + + uint16_t linkSpeed() const; + bool setLinkSpeed(uint16_t speed); //10 or 100 + bool autoNegotiation() const; + bool setAutoNegotiation(bool on); + uint32_t phyAddr() const; esp_eth_handle_t handle() const; @@ -186,6 +229,10 @@ class ETHClass : public NetworkInterface { esp_eth_netif_glue_handle_t _glue_handle; esp_eth_mac_t *_mac; esp_eth_phy_t *_phy; + bool _eth_started; + uint16_t _link_speed; + bool _full_duplex; + bool _auto_negotiation; #if ETH_SPI_SUPPORTS_CUSTOM SPIClass *_spi; char _cs_str[10]; @@ -203,6 +250,8 @@ class ETHClass : public NetworkInterface { int8_t _pin_power; int8_t _pin_rmii_clock; #endif /* CONFIG_ETH_USE_ESP32_EMAC */ + size_t _task_stack_size; + network_event_handle_t _eth_connected_event_handle; static bool ethDetachBus(void *bus_pointer); bool beginSPI( @@ -212,6 +261,9 @@ class ETHClass : public NetworkInterface { #endif int sck, int miso, int mosi, spi_host_device_t spi_host, uint8_t spi_freq_mhz ); + bool _setFullDuplex(bool on); + bool _setLinkSpeed(uint16_t speed); + bool _setAutoNegotiation(bool on); friend class EthernetClass; // to access beginSPI }; @@ -219,3 +271,4 @@ class ETHClass : public NetworkInterface { extern ETHClass ETH; #endif /* _ETH_H_ */ +#endif /* CONFIG_ETH_ENABLED */ diff --git a/libraries/FFat/examples/FFat_time/ci.json b/libraries/FFat/examples/FFat_time/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/FFat/examples/FFat_time/ci.json +++ b/libraries/FFat/examples/FFat_time/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/FFat/library.properties b/libraries/FFat/library.properties index ec5e030ad1e..35940fd5472 100644 --- a/libraries/FFat/library.properties +++ b/libraries/FFat/library.properties @@ -1,5 +1,5 @@ name=FFat -version=2.0.0 +version=3.2.0 author=Hristo Gochkov, Ivan Grokhtkov, Larry Bernstone maintainer=Hristo Gochkov sentence=ESP32 FAT on Flash File System diff --git a/libraries/FFat/src/FFat.cpp b/libraries/FFat/src/FFat.cpp index 1227e172602..4a2274b2fdb 100644 --- a/libraries/FFat/src/FFat.cpp +++ b/libraries/FFat/src/FFat.cpp @@ -46,7 +46,11 @@ bool F_Fat::begin(bool formatOnFail, const char *basePath, uint8_t maxOpenFiles, } esp_vfs_fat_mount_config_t conf = { - .format_if_mount_failed = formatOnFail, .max_files = maxOpenFiles, .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, .disk_status_check_enable = false + .format_if_mount_failed = formatOnFail, + .max_files = maxOpenFiles, + .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, + .disk_status_check_enable = false, + .use_one_fat = false }; esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(basePath, partitionLabel, &conf, &_wl_handle); if (err) { @@ -98,7 +102,7 @@ bool F_Fat::format(bool full_wipe, char *partitionLabel) { } // Now do a mount with format_if_fail (which it will) esp_vfs_fat_mount_config_t conf = { - .format_if_mount_failed = true, .max_files = 1, .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, .disk_status_check_enable = false + .format_if_mount_failed = true, .max_files = 1, .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, .disk_status_check_enable = false, .use_one_fat = false }; result = esp_vfs_fat_spiflash_mount_rw_wl("/format_ffat", partitionLabel, &conf, &temp_handle); esp_vfs_fat_spiflash_unmount_rw_wl("/format_ffat", temp_handle); @@ -152,13 +156,4 @@ size_t F_Fat::freeBytes() { return free_sect * sect_size; } -bool F_Fat::exists(const char *path) { - File f = open(path, "r", false); - return (f == true) && !f.isDirectory(); -} - -bool F_Fat::exists(const String &path) { - return exists(path.c_str()); -} - F_Fat FFat = F_Fat(FSImplPtr(new VFSImpl())); diff --git a/libraries/FFat/src/FFat.h b/libraries/FFat/src/FFat.h index 70cff69dc35..3f700396777 100644 --- a/libraries/FFat/src/FFat.h +++ b/libraries/FFat/src/FFat.h @@ -32,8 +32,6 @@ class F_Fat : public FS { size_t usedBytes(); size_t freeBytes(); void end(); - bool exists(const char *path); - bool exists(const String &path); private: wl_handle_t _wl_handle = WL_INVALID_HANDLE; diff --git a/libraries/FS/library.properties b/libraries/FS/library.properties index 2018a1a7885..07bd296bb83 100644 --- a/libraries/FS/library.properties +++ b/libraries/FS/library.properties @@ -1,5 +1,5 @@ name=FS -version=2.0.0 +version=3.2.0 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 File System diff --git a/libraries/FS/src/FS.cpp b/libraries/FS/src/FS.cpp index 8470ce1fe55..252fc3e3944 100644 --- a/libraries/FS/src/FS.cpp +++ b/libraries/FS/src/FS.cpp @@ -105,7 +105,7 @@ bool File::seek(uint32_t pos, SeekMode mode) { size_t File::position() const { if (!*this) { - return 0; + return (size_t)-1; } return _p->position(); diff --git a/libraries/FS/src/FS.h b/libraries/FS/src/FS.h index 5f2a91761d2..6572ad987b3 100644 --- a/libraries/FS/src/FS.h +++ b/libraries/FS/src/FS.h @@ -64,7 +64,7 @@ class File : public Stream { bool seek(uint32_t pos) { return seek(pos, SeekSet); } - size_t position() const; + size_t position() const; // returns (size_t)-1 on error size_t size() const; bool setBufferSize(size_t size); void close(); diff --git a/libraries/HTTPClient/examples/Authorization/ci.json b/libraries/HTTPClient/examples/Authorization/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/HTTPClient/examples/Authorization/ci.json +++ b/libraries/HTTPClient/examples/Authorization/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/HTTPClient/examples/BasicHttpClient/ci.json b/libraries/HTTPClient/examples/BasicHttpClient/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/HTTPClient/examples/BasicHttpClient/ci.json +++ b/libraries/HTTPClient/examples/BasicHttpClient/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino b/libraries/HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino index 138e68d7b99..73e127d1261 100644 --- a/libraries/HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino +++ b/libraries/HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino @@ -14,43 +14,32 @@ #include -// This is GandiStandardSSLCA2.pem, the root Certificate Authority that signed -// the server certificate for the demo server https://jigsaw.w3.org in this -// example. This certificate is valid until Sep 11 23:59:59 2024 GMT -const char *rootCACertificate = "-----BEGIN CERTIFICATE-----\n" - "MIIF6TCCA9GgAwIBAgIQBeTcO5Q4qzuFl8umoZhQ4zANBgkqhkiG9w0BAQwFADCB\n" - "iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl\n" - "cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV\n" - "BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQw\n" - "OTEyMDAwMDAwWhcNMjQwOTExMjM1OTU5WjBfMQswCQYDVQQGEwJGUjEOMAwGA1UE\n" - "CBMFUGFyaXMxDjAMBgNVBAcTBVBhcmlzMQ4wDAYDVQQKEwVHYW5kaTEgMB4GA1UE\n" - "AxMXR2FuZGkgU3RhbmRhcmQgU1NMIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IB\n" - "DwAwggEKAoIBAQCUBC2meZV0/9UAPPWu2JSxKXzAjwsLibmCg5duNyj1ohrP0pIL\n" - "m6jTh5RzhBCf3DXLwi2SrCG5yzv8QMHBgyHwv/j2nPqcghDA0I5O5Q1MsJFckLSk\n" - "QFEW2uSEEi0FXKEfFxkkUap66uEHG4aNAXLy59SDIzme4OFMH2sio7QQZrDtgpbX\n" - "bmq08j+1QvzdirWrui0dOnWbMdw+naxb00ENbLAb9Tr1eeohovj0M1JLJC0epJmx\n" - "bUi8uBL+cnB89/sCdfSN3tbawKAyGlLfOGsuRTg/PwSWAP2h9KK71RfWJ3wbWFmV\n" - "XooS/ZyrgT5SKEhRhWvzkbKGPym1bgNi7tYFAgMBAAGjggF1MIIBcTAfBgNVHSME\n" - "GDAWgBRTeb9aqitKz1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQUs5Cn2MmvTs1hPJ98\n" - "rV1/Qf1pMOowDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYD\n" - "VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMCIGA1UdIAQbMBkwDQYLKwYBBAGy\n" - "MQECAhowCAYGZ4EMAQIBMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNl\n" - "cnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNy\n" - "bDB2BggrBgEFBQcBAQRqMGgwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRy\n" - "dXN0LmNvbS9VU0VSVHJ1c3RSU0FBZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZ\n" - "aHR0cDovL29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAWGf9\n" - "crJq13xhlhl+2UNG0SZ9yFP6ZrBrLafTqlb3OojQO3LJUP33WbKqaPWMcwO7lWUX\n" - "zi8c3ZgTopHJ7qFAbjyY1lzzsiI8Le4bpOHeICQW8owRc5E69vrOJAKHypPstLbI\n" - "FhfFcvwnQPYT/pOmnVHvPCvYd1ebjGU6NSU2t7WKY28HJ5OxYI2A25bUeo8tqxyI\n" - "yW5+1mUfr13KFj8oRtygNeX56eXVlogMT8a3d2dIhCe2H7Bo26y/d7CQuKLJHDJd\n" - "ArolQ4FCR7vY4Y8MDEZf7kYzawMUgtN+zY+vkNaOJH1AQrRqahfGlZfh8jjNp+20\n" - "J0CT33KpuMZmYzc4ZCIwojvxuch7yPspOqsactIGEk72gtQjbz7Dk+XYtsDe3CMW\n" - "1hMwt6CaDixVBgBwAc/qOR2A24j3pSC4W/0xJmmPLQphgzpHphNULB7j7UTKvGof\n" - "KA5R2d4On3XNDgOVyvnFqSot/kGkoUeuDcL5OWYzSlvhhChZbH2UF3bkRYKtcCD9\n" - "0m9jqNf6oDP6N8v3smWe2lBvP+Sn845dWDKXcCMu5/3EFZucJ48y7RetWIExKREa\n" - "m9T8bJUox04FB6b9HbwZ4ui3uRGKLXASUoWNjDNKD/yZkuBjcNqllEdjB+dYxzFf\n" - "BT02Vf6Dsuimrdfp5gJ0iHRc2jTbkNJtUQoj1iM=\n" - "-----END CERTIFICATE-----\n"; +// This is a Google Trust Services cert, the root Certificate Authority that +// signed the server certificate for the demo server https://jigsaw.w3.org in this +// example. This certificate is valid until Jan 28 00:00:42 2028 GMT +const char *rootCACertificate = R"string_literal( +-----BEGIN CERTIFICATE----- +MIIDejCCAmKgAwIBAgIQf+UwvzMTQ77dghYQST2KGzANBgkqhkiG9w0BAQsFADBX +MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UE +CxMHUm9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTIzMTEx +NTAzNDMyMVoXDTI4MDEyODAwMDA0MlowRzELMAkGA1UEBhMCVVMxIjAgBgNVBAoT +GUdvb2dsZSBUcnVzdCBTZXJ2aWNlcyBMTEMxFDASBgNVBAMTC0dUUyBSb290IFI0 +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE83Rzp2iLYK5DuDXFgTB7S0md+8Fhzube +Rr1r1WEYNa5A3XP3iZEwWus87oV8okB2O6nGuEfYKueSkWpz6bFyOZ8pn6KY019e +WIZlD6GEZQbR3IvJx3PIjGov5cSr0R2Ko4H/MIH8MA4GA1UdDwEB/wQEAwIBhjAd +BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUgEzW63T/STaj1dj8tT7FavCUHYwwHwYDVR0jBBgwFoAUYHtmGkUN +l8qJUC99BM00qP/8/UswNgYIKwYBBQUHAQEEKjAoMCYGCCsGAQUFBzAChhpodHRw +Oi8vaS5wa2kuZ29vZy9nc3IxLmNydDAtBgNVHR8EJjAkMCKgIKAehhxodHRwOi8v +Yy5wa2kuZ29vZy9yL2dzcjEuY3JsMBMGA1UdIAQMMAowCAYGZ4EMAQIBMA0GCSqG +SIb3DQEBCwUAA4IBAQAYQrsPBtYDh5bjP2OBDwmkoWhIDDkic574y04tfzHpn+cJ +odI2D4SseesQ6bDrarZ7C30ddLibZatoKiws3UL9xnELz4ct92vID24FfVbiI1hY ++SW6FoVHkNeWIP0GCbaM4C6uVdF5dTUsMVs/ZbzNnIdCp5Gxmx5ejvEau8otR/Cs +kGN+hr/W5GvT1tMBjgWKZ1i4//emhA1JG1BbPzoLJQvyEotc03lXjTaCzv8mEbep +8RqZ7a2CPsgRbuvTPBwcOMBBmuFeU88+FSBX6+7iP0il8b4Z0QFqIwwMHfs/L6K1 +vepuoxtGzi4CZ68zJpiq1UvSqTbFJjtbD4seiMHl +-----END CERTIFICATE----- +)string_literal"; // Not sure if NetworkClientSecure checks the validity date of the certificate. // Setting clock just to be sure... diff --git a/libraries/HTTPClient/examples/BasicHttpsClient/ci.json b/libraries/HTTPClient/examples/BasicHttpsClient/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/HTTPClient/examples/BasicHttpsClient/ci.json +++ b/libraries/HTTPClient/examples/BasicHttpsClient/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/HTTPClient/examples/HTTPClientEnterprise/HTTPClientEnterprise.ino b/libraries/HTTPClient/examples/HTTPClientEnterprise/HTTPClientEnterprise.ino index 7f1d1dd3575..d8b66ac19d9 100644 --- a/libraries/HTTPClient/examples/HTTPClientEnterprise/HTTPClientEnterprise.ino +++ b/libraries/HTTPClient/examples/HTTPClientEnterprise/HTTPClientEnterprise.ino @@ -3,6 +3,12 @@ /*|TESTED BOARDS: Devkit v1 DOIT, Devkitc v4 |*/ /*|CORE: June 2018 |*/ /*|----------------------------------------------------------|*/ + +#include "sdkconfig.h" +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +#error "WPA-Enterprise is only supported in SoCs with native Wi-Fi support" +#endif + #include #include #if __has_include("esp_eap_client.h") diff --git a/libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json b/libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json index d8b3664bc65..04eb62b977a 100644 --- a/libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json +++ b/libraries/HTTPClient/examples/HTTPClientEnterprise/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] } diff --git a/libraries/HTTPClient/examples/ReuseConnection/ci.json b/libraries/HTTPClient/examples/ReuseConnection/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/HTTPClient/examples/ReuseConnection/ci.json +++ b/libraries/HTTPClient/examples/ReuseConnection/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/HTTPClient/examples/StreamHttpClient/ci.json b/libraries/HTTPClient/examples/StreamHttpClient/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/HTTPClient/examples/StreamHttpClient/ci.json +++ b/libraries/HTTPClient/examples/StreamHttpClient/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/HTTPClient/library.properties b/libraries/HTTPClient/library.properties index 56af94c740f..f2dafc36d1b 100644 --- a/libraries/HTTPClient/library.properties +++ b/libraries/HTTPClient/library.properties @@ -1,5 +1,5 @@ name=HTTPClient -version=2.0.0 +version=3.2.0 author=Markus Sattler maintainer=Markus Sattler sentence=HTTP Client for ESP32 diff --git a/libraries/HTTPClient/src/HTTPClient.cpp b/libraries/HTTPClient/src/HTTPClient.cpp index 54eedf0ac2e..ec812f07201 100644 --- a/libraries/HTTPClient/src/HTTPClient.cpp +++ b/libraries/HTTPClient/src/HTTPClient.cpp @@ -28,15 +28,8 @@ #include #include - -#ifdef HTTPCLIENT_1_1_COMPATIBLE -#include -#include -#endif - #include #include - #include "HTTPClient.h" /// Cookie jar support @@ -56,6 +49,7 @@ class TransportTraits { } }; +#ifndef HTTPCLIENT_NOSECURE class TLSTraits : public TransportTraits { public: TLSTraits(const char *CAcert, const char *clicert = nullptr, const char *clikey = nullptr) : _cacert(CAcert), _clicert(clicert), _clikey(clikey) {} @@ -81,6 +75,7 @@ class TLSTraits : public TransportTraits { const char *_clicert; const char *_clikey; }; +#endif // HTTPCLIENT_NOSECURE #endif // HTTPCLIENT_1_1_COMPATIBLE /** @@ -145,6 +140,12 @@ bool HTTPClient::begin(NetworkClient &client, String url) { _port = (protocol == "https" ? 443 : 80); _secure = (protocol == "https"); + +#ifdef HTTPCLIENT_NOSECURE + if (_secure) { + return false; + } +#endif // HTTPCLIENT_NOSECURE return beginInternal(url, protocol.c_str()); } @@ -174,10 +175,16 @@ bool HTTPClient::begin(NetworkClient &client, String host, uint16_t port, String _uri = uri; _protocol = (https ? "https" : "http"); _secure = https; + +#ifdef HTTPCLIENT_NOSECURE + return _secure ? false : true; +#else return true; +#endif // HTTPCLIENT_NOSECURE } #ifdef HTTPCLIENT_1_1_COMPATIBLE +#ifndef HTTPCLIENT_NOSECURE bool HTTPClient::begin(String url, const char *CAcert) { if (_client && !_tcpDeprecated) { log_d("mix up of new and deprecated api"); @@ -199,6 +206,7 @@ bool HTTPClient::begin(String url, const char *CAcert) { return true; } +#endif // HTTPCLIENT_NOSECURE /** * parsing the url for all needed parameters @@ -214,7 +222,11 @@ bool HTTPClient::begin(String url) { clear(); _port = 80; if (!beginInternal(url, "http")) { +#ifdef HTTPCLIENT_NOSECURE + return false; +#else return begin(url, (const char *)NULL); +#endif // HTTPCLIENT_NOSECURE } _transportTraits = TransportTraitsPtr(new TransportTraits()); if (!_transportTraits) { @@ -299,6 +311,7 @@ bool HTTPClient::begin(String host, uint16_t port, String uri) { return true; } +#ifndef HTTPCLIENT_NOSECURE bool HTTPClient::begin(String host, uint16_t port, String uri, const char *CAcert) { if (_client && !_tcpDeprecated) { log_d("mix up of new and deprecated api"); @@ -338,6 +351,7 @@ bool HTTPClient::begin(String host, uint16_t port, String uri, const char *CAcer _transportTraits = TransportTraitsPtr(new TLSTraits(CAcert, cli_cert, cli_key)); return true; } +#endif // HTTPCLIENT_NOSECURE #endif // HTTPCLIENT_1_1_COMPATIBLE /** @@ -357,7 +371,7 @@ void HTTPClient::disconnect(bool preserveClient) { if (connected()) { if (_client->available() > 0) { log_d("still data in buffer (%d), clean up.\n", _client->available()); - _client->flush(); + _client->clear(); } if (_reuse && _canReuse) { @@ -408,6 +422,14 @@ void HTTPClient::setUserAgent(const String &userAgent) { _userAgent = userAgent; } +/** + * set Accept Encoding Header + * @param acceptEncoding const char * + */ +void HTTPClient::setAcceptEncoding(const String &acceptEncoding) { + _acceptEncoding = acceptEncoding; +} + /** * set the Authorizatio for the http request * @param user const char * @@ -969,8 +991,8 @@ String HTTPClient::errorToString(int error) { */ void HTTPClient::addHeader(const String &name, const String &value, bool first, bool replace) { // not allow set of Header handled by code - if (!name.equalsIgnoreCase(F("Connection")) && !name.equalsIgnoreCase(F("User-Agent")) && !name.equalsIgnoreCase(F("Host")) - && !(name.equalsIgnoreCase(F("Authorization")) && _base64Authorization.length())) { + if (!name.equalsIgnoreCase(F("Connection")) && !name.equalsIgnoreCase(F("User-Agent")) && !name.equalsIgnoreCase(F("Accept-Encoding")) + && !name.equalsIgnoreCase(F("Host")) && !(name.equalsIgnoreCase(F("Authorization")) && _base64Authorization.length())) { String headerLine = name; headerLine += ": "; @@ -1130,7 +1152,7 @@ bool HTTPClient::sendHeader(const char *type) { header += "\r\n"; if (!_useHTTP10) { - header += F("Accept-Encoding: identity;q=1,chunked;q=0.1,*;q=0\r\n"); + header += String(F("Accept-Encoding: ")) + _acceptEncoding + F("\r\n"); } if (_base64Authorization.length()) { @@ -1340,7 +1362,7 @@ int HTTPClient::writeToStreamDataBlock(Stream *stream, int size) { // some time for the stream delay(1); - int leftBytes = (readBytes - bytesWrite); + int leftBytes = (bytesRead - bytesWrite); // retry to send the missed bytes bytesWrite = stream->write((buff + bytesWrite), leftBytes); @@ -1363,7 +1385,7 @@ int HTTPClient::writeToStreamDataBlock(Stream *stream, int size) { // count bytes to read left if (len > 0) { - len -= readBytes; + len -= bytesRead; } delay(0); diff --git a/libraries/HTTPClient/src/HTTPClient.h b/libraries/HTTPClient/src/HTTPClient.h index 7841f355640..80f6da28599 100644 --- a/libraries/HTTPClient/src/HTTPClient.h +++ b/libraries/HTTPClient/src/HTTPClient.h @@ -34,7 +34,9 @@ #include #include #include +#ifndef HTTPCLIENT_NOSECURE #include +#endif // HTTPCLIENT_NOSECURE /// Cookie jar support #include @@ -182,10 +184,23 @@ class HTTPClient { #ifdef HTTPCLIENT_1_1_COMPATIBLE bool begin(String url); - bool begin(String url, const char *CAcert); bool begin(String host, uint16_t port, String uri = "/"); +#ifndef HTTPCLIENT_NOSECURE + bool begin(String url, const char *CAcert); bool begin(String host, uint16_t port, String uri, const char *CAcert); bool begin(String host, uint16_t port, String uri, const char *CAcert, const char *cli_cert, const char *cli_key); +#else + bool begin(String url, const char *CAcert) { + return false; + }; + bool begin(String host, uint16_t port, String uri, const char *CAcert) { + return false; + }; + bool begin(String host, uint16_t port, String uri, const char *CAcert, const char *cli_cert, const char *cli_key) { + return false; + }; +#endif // HTTPCLIENT_NOSECURE + #endif void end(void); @@ -194,6 +209,7 @@ class HTTPClient { void setReuse(bool reuse); /// keep-alive void setUserAgent(const String &userAgent); + void setAcceptEncoding(const String &acceptEncoding); void setAuthorization(const char *user, const char *password); void setAuthorization(const char *auth); void setAuthorizationType(const char *authType); @@ -285,6 +301,7 @@ class HTTPClient { String _userAgent = "ESP32HTTPClient"; String _base64Authorization; String _authorizationType = "Basic"; + String _acceptEncoding = "identity;q=1,chunked;q=0.1,*;q=0"; /// Response handling RequestArgument *_currentHeaders = nullptr; diff --git a/libraries/HTTPUpdate/examples/httpUpdate/ci.json b/libraries/HTTPUpdate/examples/httpUpdate/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/HTTPUpdate/examples/httpUpdate/ci.json +++ b/libraries/HTTPUpdate/examples/httpUpdate/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/HTTPUpdate/examples/httpUpdateSPIFFS/ci.json b/libraries/HTTPUpdate/examples/httpUpdateSPIFFS/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/HTTPUpdate/examples/httpUpdateSPIFFS/ci.json +++ b/libraries/HTTPUpdate/examples/httpUpdateSPIFFS/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json b/libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json index d8b3664bc65..cbdd28f773d 100644 --- a/libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json +++ b/libraries/HTTPUpdate/examples/httpUpdateSecure/ci.json @@ -1,5 +1,7 @@ { - "targets": { - "esp32h2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/HTTPUpdate/library.properties b/libraries/HTTPUpdate/library.properties index 0423e705093..419f3b97b3f 100644 --- a/libraries/HTTPUpdate/library.properties +++ b/libraries/HTTPUpdate/library.properties @@ -1,5 +1,5 @@ name=HTTPUpdate -version=2.0.0 +version=3.2.0 author=Markus Sattler maintainer=Markus Sattler sentence=Http Update for ESP32 diff --git a/libraries/HTTPUpdateServer/examples/WebUpdater/ci.json b/libraries/HTTPUpdateServer/examples/WebUpdater/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/HTTPUpdateServer/examples/WebUpdater/ci.json +++ b/libraries/HTTPUpdateServer/examples/WebUpdater/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/HTTPUpdateServer/library.properties b/libraries/HTTPUpdateServer/library.properties index e700659fa0a..9c793a26ac8 100644 --- a/libraries/HTTPUpdateServer/library.properties +++ b/libraries/HTTPUpdateServer/library.properties @@ -1,5 +1,5 @@ name=HTTPUpdateServer -version=2.0.0 +version=3.2.0 author=Hristo Kapanakov maintainer= sentence=Simple HTTP Update server based on the WebServer diff --git a/libraries/Insights/examples/DiagnosticsSmokeTest/DiagnosticsSmokeTest.ino b/libraries/Insights/examples/DiagnosticsSmokeTest/DiagnosticsSmokeTest.ino index 2178c9bcd17..7102dfb19af 100644 --- a/libraries/Insights/examples/DiagnosticsSmokeTest/DiagnosticsSmokeTest.ino +++ b/libraries/Insights/examples/DiagnosticsSmokeTest/DiagnosticsSmokeTest.ino @@ -36,7 +36,8 @@ static void smoke_test() { Insights.event(TAG, "[count][%d]", count); } else { log_e("[count][%d] [crash_count][%" PRIu32 "] [excvaddr][0x0f] Crashing...", count, s_reset_count); - *(int *)0x0F = 0x10; + //ToDo: find better way to crash + abort(); } } diff --git a/libraries/Insights/examples/DiagnosticsSmokeTest/README.md b/libraries/Insights/examples/DiagnosticsSmokeTest/README.md index 3938a9d1f6c..268e0704b09 100644 --- a/libraries/Insights/examples/DiagnosticsSmokeTest/README.md +++ b/libraries/Insights/examples/DiagnosticsSmokeTest/README.md @@ -23,8 +23,8 @@ Copy Auth Key to the example const char insights_auth_key[] = ""; ``` -### Enter WiFi Credentials -Inside the example sketch, enter your WiFi credentials in `WIFI_SSID` and `WIFI_PASSPHRASE` macros. +### Enter Wi-Fi Credentials +Inside the example sketch, enter your Wi-Fi credentials in `WIFI_SSID` and `WIFI_PASSPHRASE` macros. ### Setup * Build and flash the sketch and monitor the console diff --git a/libraries/Insights/examples/DiagnosticsSmokeTest/ci.json b/libraries/Insights/examples/DiagnosticsSmokeTest/ci.json index 90f5ecfe4d2..cbd69d50029 100644 --- a/libraries/Insights/examples/DiagnosticsSmokeTest/ci.json +++ b/libraries/Insights/examples/DiagnosticsSmokeTest/ci.json @@ -1,6 +1,9 @@ { - "targets": { - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_ESP_INSIGHTS_ENABLED=y" + ], + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/Insights/examples/MinimalDiagnostics/README.md b/libraries/Insights/examples/MinimalDiagnostics/README.md index 35faa8d1788..65a631d1236 100644 --- a/libraries/Insights/examples/MinimalDiagnostics/README.md +++ b/libraries/Insights/examples/MinimalDiagnostics/README.md @@ -5,9 +5,9 @@ ## What to expect in this example? - This example demonstrates the use of ESP Insights framework in minimal way -- Device will try to connect with the configured WiFi network +- Device will try to connect with the configured Wi-Fi network - ESP Insights is enabled in this example, so any error/warning logs, crashes will be reported to cloud -- This example collects heap and wifi metrics every 10 minutes and network variables are collected when they change +- This example collects heap and Wi-Fi metrics every 10 minutes and network variables are collected when they change ## Try out the example @@ -19,8 +19,8 @@ Copy Auth Key to the example const char insights_auth_key[] = ""; ``` -### Enter WiFi Credentials -Inside the example sketch, enter your WiFi credentials in `WIFI_SSID` and `WIFI_PASSPHRASE` macros. +### Enter Wi-Fi Credentials +Inside the example sketch, enter your Wi-Fi credentials in `WIFI_SSID` and `WIFI_PASSPHRASE` macros. ### Get the Node ID - Start the Serial monitor diff --git a/libraries/Insights/examples/MinimalDiagnostics/ci.json b/libraries/Insights/examples/MinimalDiagnostics/ci.json index 90f5ecfe4d2..cbd69d50029 100644 --- a/libraries/Insights/examples/MinimalDiagnostics/ci.json +++ b/libraries/Insights/examples/MinimalDiagnostics/ci.json @@ -1,6 +1,9 @@ { - "targets": { - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_ESP_INSIGHTS_ENABLED=y" + ], + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/Insights/library.properties b/libraries/Insights/library.properties index 8d7237cd626..fefe5aab177 100644 --- a/libraries/Insights/library.properties +++ b/libraries/Insights/library.properties @@ -1,5 +1,5 @@ name=ESP Insights -version=1.0.0 +version=3.2.0 author=Sanket Wadekar maintainer=Sanket Wadekar sentence=ESP Insights diff --git a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/.gitignore b/libraries/LittleFS/examples/LITTLEFS_PlatformIO/.gitignore deleted file mode 100644 index 653e92272d5..00000000000 --- a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.pio -.vscode -mklittlefs.exe -mklittlefs diff --git a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/README.md b/libraries/LittleFS/examples/LITTLEFS_PlatformIO/README.md deleted file mode 100644 index e3cecc6d2fe..00000000000 --- a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/README.md +++ /dev/null @@ -1,68 +0,0 @@ -# How to run on PlatformIO IDE - -- Download and extract to this project root a **mklittlefs** executable for your OS [from a zipped binary here](https://github.com/earlephilhower/mklittlefs/releases) -- Open **LITTLEFS_PlatformIO** folder -- Run PlatformIO project task: **Upload Filesystem Image** -- Run PlatformIO project task: **Upload and Monitor** -- You will see a Serial output like: -``` ---- Miniterm on COM5 115200,8,N,1 --- ---- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- -ets Jun 8 2016 00:22:57 - -rst:0x1 (POWERON_RESET),boot:0x13 (Snfigsip: 0, SPIWP:0xee -clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 -mode:DIO, clock div:2 -load:0x3fff0018,len:4 -load:0x3fff001c,len:1044 -load:0x40078000,len:10044 -load:0x40080400,len:5872 -entry 0x400806ac -Listing directory: / - FILE: /file1.txt SIZE: 3 LAST WRITE: 2020-10-06 15:10:33 - DIR : /testfolder LAST WRITE: 2020-10-06 15:10:33 -Creating Dir: /mydir -Dir created -Writing file: /mydir/hello2.txt -- file written -Listing directory: / - FILE: /file1.txt SIZE: 3 LAST WRITE: 2020-10-06 15:10:33 - DIR : /mydir LAST WRITE: 1970-01-01 00:00:00 -Listing directory: /mydir - FILE: /mydir/hello2.txt SIZE: 6 LAST WRITE: 1970-01-01 00:00:00 - DIR : /testfolder LAST WRITE: 2020-10-06 15:10:33 -Listing directory: /testfolder - FILE: /testfolder/test2.txt SIZE: 3 LAST WRITE: 2020-10-06 15:10:33 -Deleting file: /mydir/hello2.txt -- file deleted -Removing Dir: /mydir -Dir removed -Listing directory: / - FILE: /file1.txt SIZE: 3 LAST WRITE: 2020-10-06 15:10:33 - DIR : /testfolder LAST WRITE: 2020-10-06 15:10:33 -Listing directory: /testfolder - FILE: /testfolder/test2.txt SIZE: 3 LAST WRITE: 2020-10-06 15:10:33 -Writing file: /hello.txt -- file written -Appending to file: /hello.txt -- message appended -Reading file: /hello.txt -- read from file: -Hello World! -Renaming file /hello.txt to /foo.txt -- file renamed -Reading file: /foo.txt -- read from file: -Hello World! -Deleting file: /foo.txt -- file deleted -Testing file I/O with /test.txt -- writing................................................................ - - 1048576 bytes written in 12006 ms -- reading................................................................ -- 1048576 bytes read in 547 ms -Deleting file: /test.txt -- file deleted -Test complete -``` -- If you have a module with more than 4MB flash, you can uncomment **partitions_custom.csv** in **platformio.ini** and modify the csv file accordingly diff --git a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/data/file1.txt b/libraries/LittleFS/examples/LITTLEFS_PlatformIO/data/file1.txt deleted file mode 100644 index 72943a16fb2..00000000000 --- a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/data/file1.txt +++ /dev/null @@ -1 +0,0 @@ -aaa diff --git a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/data/testfolder/test2.txt b/libraries/LittleFS/examples/LITTLEFS_PlatformIO/data/testfolder/test2.txt deleted file mode 100644 index f761ec192d9..00000000000 --- a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/data/testfolder/test2.txt +++ /dev/null @@ -1 +0,0 @@ -bbb diff --git a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/include/.placeholder.txt b/libraries/LittleFS/examples/LITTLEFS_PlatformIO/include/.placeholder.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/lib/.placeholder.txt b/libraries/LittleFS/examples/LITTLEFS_PlatformIO/lib/.placeholder.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/partitions_custom.csv b/libraries/LittleFS/examples/LITTLEFS_PlatformIO/partitions_custom.csv deleted file mode 100644 index 97846fa59bb..00000000000 --- a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/partitions_custom.csv +++ /dev/null @@ -1,6 +0,0 @@ -# Name, Type, SubType, Offset, Size, Flags -ota_0, app, ota_0, 0x10000, 0x1A0000, -ota_1, app, ota_1, , 0x1A0000, -otadata, data, ota, 0x350000, 0x2000, -nvs, data, nvs, , 0x6000, -data, data, spiffs, , 0xA8000, diff --git a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/platformio.ini b/libraries/LittleFS/examples/LITTLEFS_PlatformIO/platformio.ini deleted file mode 100644 index dce1ac84456..00000000000 --- a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/platformio.ini +++ /dev/null @@ -1,22 +0,0 @@ -; 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] -default_envs = esp32 - -[env] -framework = arduino - -[env:esp32] -platform = espressif32 -board = esp32dev -board_build.partitions = partitions_custom.csv -monitor_filters = esp32_exception_decoder -monitor_speed = 115200 diff --git a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/src/main.cpp b/libraries/LittleFS/examples/LITTLEFS_PlatformIO/src/main.cpp deleted file mode 100644 index 5ae9e8d7dfc..00000000000 --- a/libraries/LittleFS/examples/LITTLEFS_PlatformIO/src/main.cpp +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include "FS.h" -#include -#include - -/* You only need to format LittleFS the first time you run a - test or else use the LITTLEFS plugin to create a partition - https://github.com/lorol/arduino-esp32littlefs-plugin */ - -#define FORMAT_LITTLEFS_IF_FAILED true - -void listDir(fs::FS &fs, const char *dirname, uint8_t levels) { - Serial.printf("Listing directory: %s\r\n", dirname); - - File root = fs.open(dirname); - if (!root) { - Serial.println("- failed to open directory"); - return; - } - if (!root.isDirectory()) { - Serial.println(" - not a directory"); - return; - } - - File file = root.openNextFile(); - while (file) { - if (file.isDirectory()) { - Serial.print(" DIR : "); - - Serial.print(file.name()); - time_t t = file.getLastWrite(); - struct tm *tmstruct = localtime(&t); - Serial.printf( - " LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, - tmstruct->tm_min, tmstruct->tm_sec - ); - - if (levels) { - listDir(fs, file.name(), levels - 1); - } - } else { - Serial.print(" FILE: "); - Serial.print(file.name()); - Serial.print(" SIZE: "); - - Serial.print(file.size()); - time_t t = file.getLastWrite(); - struct tm *tmstruct = localtime(&t); - Serial.printf( - " LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, - tmstruct->tm_min, tmstruct->tm_sec - ); - } - file = root.openNextFile(); - } -} - -void createDir(fs::FS &fs, const char *path) { - Serial.printf("Creating Dir: %s\n", path); - if (fs.mkdir(path)) { - Serial.println("Dir created"); - } else { - Serial.println("mkdir failed"); - } -} - -void removeDir(fs::FS &fs, const char *path) { - Serial.printf("Removing Dir: %s\n", path); - if (fs.rmdir(path)) { - Serial.println("Dir removed"); - } else { - Serial.println("rmdir failed"); - } -} - -void readFile(fs::FS &fs, const char *path) { - Serial.printf("Reading file: %s\r\n", path); - - File file = fs.open(path); - if (!file || file.isDirectory()) { - Serial.println("- failed to open file for reading"); - return; - } - - Serial.println("- read from file:"); - while (file.available()) { - Serial.write(file.read()); - } - file.close(); -} - -void writeFile(fs::FS &fs, const char *path, const char *message) { - Serial.printf("Writing file: %s\r\n", path); - - File file = fs.open(path, FILE_WRITE); - if (!file) { - Serial.println("- failed to open file for writing"); - return; - } - if (file.print(message)) { - Serial.println("- file written"); - } else { - Serial.println("- write failed"); - } - file.close(); -} - -void appendFile(fs::FS &fs, const char *path, const char *message) { - Serial.printf("Appending to file: %s\r\n", path); - - File file = fs.open(path, FILE_APPEND); - if (!file) { - Serial.println("- failed to open file for appending"); - return; - } - if (file.print(message)) { - Serial.println("- message appended"); - } else { - Serial.println("- append failed"); - } - file.close(); -} - -void renameFile(fs::FS &fs, const char *path1, const char *path2) { - Serial.printf("Renaming file %s to %s\r\n", path1, path2); - if (fs.rename(path1, path2)) { - Serial.println("- file renamed"); - } else { - Serial.println("- rename failed"); - } -} - -void deleteFile(fs::FS &fs, const char *path) { - Serial.printf("Deleting file: %s\r\n", path); - if (fs.remove(path)) { - Serial.println("- file deleted"); - } else { - Serial.println("- delete failed"); - } -} - -// SPIFFS-like write and delete file - -// See: https://github.com/esp8266/Arduino/blob/master/libraries/LittleFS/src/LittleFS.cpp#L60 -void writeFile2(fs::FS &fs, const char *path, const char *message) { - if (!fs.exists(path)) { - if (strchr(path, '/')) { - Serial.printf("Create missing folders of: %s\r\n", path); - char *pathStr = strdup(path); - if (pathStr) { - char *ptr = strchr(pathStr, '/'); - while (ptr) { - *ptr = 0; - fs.mkdir(pathStr); - *ptr = '/'; - ptr = strchr(ptr + 1, '/'); - } - } - free(pathStr); - } - } - - Serial.printf("Writing file to: %s\r\n", path); - File file = fs.open(path, FILE_WRITE); - if (!file) { - Serial.println("- failed to open file for writing"); - return; - } - if (file.print(message)) { - Serial.println("- file written"); - } else { - Serial.println("- write failed"); - } - file.close(); -} - -// See: https://github.com/esp8266/Arduino/blob/master/libraries/LittleFS/src/LittleFS.h#L149 -void deleteFile2(fs::FS &fs, const char *path) { - Serial.printf("Deleting file and empty folders on path: %s\r\n", path); - - if (fs.remove(path)) { - Serial.println("- file deleted"); - } else { - Serial.println("- delete failed"); - } - - char *pathStr = strdup(path); - if (pathStr) { - char *ptr = strrchr(pathStr, '/'); - if (ptr) { - Serial.printf("Removing all empty folders on path: %s\r\n", path); - } - while (ptr) { - *ptr = 0; - fs.rmdir(pathStr); - ptr = strrchr(pathStr, '/'); - } - free(pathStr); - } -} - -void testFileIO(fs::FS &fs, const char *path) { - Serial.printf("Testing file I/O with %s\r\n", path); - - static uint8_t buf[512]; - size_t len = 0; - File file = fs.open(path, FILE_WRITE); - if (!file) { - Serial.println("- failed to open file for writing"); - return; - } - - size_t i; - Serial.print("- writing"); - uint32_t start = millis(); - for (i = 0; i < 2048; i++) { - if ((i & 0x001F) == 0x001F) { - Serial.print("."); - } - file.write(buf, 512); - } - Serial.println(""); - uint32_t end = millis() - start; - Serial.printf(" - %u bytes written in %u ms\r\n", 2048 * 512, end); - file.close(); - - file = fs.open(path); - start = millis(); - end = start; - i = 0; - if (file && !file.isDirectory()) { - len = file.size(); - size_t flen = len; - start = millis(); - Serial.print("- reading"); - while (len) { - size_t toRead = len; - if (toRead > 512) { - toRead = 512; - } - file.read(buf, toRead); - if ((i++ & 0x001F) == 0x001F) { - Serial.print("."); - } - len -= toRead; - } - Serial.println(""); - end = millis() - start; - Serial.printf("- %u bytes read in %u ms\r\n", flen, end); - file.close(); - } else { - Serial.println("- failed to open file for reading"); - } -} - -void setup() { - Serial.begin(115200); - if (!LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED)) { - Serial.println("LittleFS Mount Failed"); - return; - } - - listDir(LittleFS, "/", 0); - createDir(LittleFS, "/mydir"); - writeFile(LittleFS, "/mydir/hello2.txt", "Hello2"); - //writeFile(LittleFS, "/mydir/newdir2/newdir3/hello3.txt", "Hello3"); - writeFile2(LittleFS, "/mydir/newdir2/newdir3/hello3.txt", "Hello3"); - listDir(LittleFS, "/", 3); - deleteFile(LittleFS, "/mydir/hello2.txt"); - //deleteFile(LittleFS, "/mydir/newdir2/newdir3/hello3.txt"); - deleteFile2(LittleFS, "/mydir/newdir2/newdir3/hello3.txt"); - removeDir(LittleFS, "/mydir"); - listDir(LittleFS, "/", 3); - writeFile(LittleFS, "/hello.txt", "Hello "); - appendFile(LittleFS, "/hello.txt", "World!\r\n"); - readFile(LittleFS, "/hello.txt"); - renameFile(LittleFS, "/hello.txt", "/foo.txt"); - readFile(LittleFS, "/foo.txt"); - deleteFile(LittleFS, "/foo.txt"); - testFileIO(LittleFS, "/test.txt"); - deleteFile(LittleFS, "/test.txt"); - - Serial.println("Test complete"); -} - -void loop() {} diff --git a/libraries/LittleFS/examples/LITTLEFS_time/ci.json b/libraries/LittleFS/examples/LITTLEFS_time/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/LittleFS/examples/LITTLEFS_time/ci.json +++ b/libraries/LittleFS/examples/LITTLEFS_time/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/LittleFS/library.properties b/libraries/LittleFS/library.properties index 562cfafe11a..a9dae69b7f8 100644 --- a/libraries/LittleFS/library.properties +++ b/libraries/LittleFS/library.properties @@ -1,5 +1,5 @@ name=LittleFS -version=2.0.0 +version=3.2.0 author= maintainer= sentence=LittleFS for esp32 diff --git a/libraries/LittleFS/src/LittleFS.cpp b/libraries/LittleFS/src/LittleFS.cpp index b5776372313..761d1ba4c24 100644 --- a/libraries/LittleFS/src/LittleFS.cpp +++ b/libraries/LittleFS/src/LittleFS.cpp @@ -12,18 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "LittleFS.h" + +#ifdef CONFIG_LITTLEFS_PAGE_SIZE #include "vfs_api.h" extern "C" { #include #include #include -} -#include "sdkconfig.h" -#include "LittleFS.h" - -#ifdef CONFIG_LITTLEFS_PAGE_SIZE -extern "C" { #include "esp_littlefs.h" } @@ -33,16 +30,10 @@ class LittleFSImpl : public VFSImpl { public: LittleFSImpl(); virtual ~LittleFSImpl() {} - virtual bool exists(const char *path); }; LittleFSImpl::LittleFSImpl() {} -bool LittleFSImpl::exists(const char *path) { - File f = open(path, "r", false); - return (f == true); -} - LittleFSFS::LittleFSFS() : FS(FSImplPtr(new LittleFSImpl())), partitionLabel_(NULL) {} LittleFSFS::~LittleFSFS() { @@ -104,9 +95,11 @@ void LittleFSFS::end() { } bool LittleFSFS::format() { - disableCore0WDT(); + bool wdt_active = disableCore0WDT(); esp_err_t err = esp_littlefs_format(partitionLabel_); - enableCore0WDT(); + if (wdt_active) { + enableCore0WDT(); + } if (err) { log_e("Formatting LittleFS failed! Error: %d", err); return false; @@ -131,4 +124,4 @@ size_t LittleFSFS::usedBytes() { } LittleFSFS LittleFS; -#endif +#endif /* CONFIG_LITTLEFS_PAGE_SIZE */ diff --git a/libraries/LittleFS/src/LittleFS.h b/libraries/LittleFS/src/LittleFS.h index 47220b30b33..da4ab7d1f6f 100644 --- a/libraries/LittleFS/src/LittleFS.h +++ b/libraries/LittleFS/src/LittleFS.h @@ -14,6 +14,10 @@ #ifndef _LITTLEFS_H_ #define _LITTLEFS_H_ +#include "sdkconfig.h" + +#ifdef CONFIG_LITTLEFS_PAGE_SIZE + #include "FS.h" namespace fs { @@ -36,4 +40,5 @@ class LittleFSFS : public FS { extern fs::LittleFSFS LittleFS; +#endif /* CONFIG_LITTLEFS_PAGE_SIZE */ #endif diff --git a/libraries/Matter/examples/MatterColorLight/MatterColorLight.ino b/libraries/Matter/examples/MatterColorLight/MatterColorLight.ino new file mode 100644 index 00000000000..f3e45887576 --- /dev/null +++ b/libraries/Matter/examples/MatterColorLight/MatterColorLight.ino @@ -0,0 +1,184 @@ +// 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 { +#ifndef RGB_BUILTIN + // after analogWrite(), it is necessary to set the GPIO to digital mode first + pinMode(ledPin, OUTPUT); +#endif + 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/libraries/Matter/examples/MatterColorLight/ci.json b/libraries/Matter/examples/MatterColorLight/ci.json new file mode 100644 index 00000000000..d5f63487506 --- /dev/null +++ b/libraries/Matter/examples/MatterColorLight/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] + } diff --git a/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino b/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino new file mode 100644 index 00000000000..0e93ed6d155 --- /dev/null +++ b/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino @@ -0,0 +1,72 @@ +// 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 + +// List of Matter Endpoints for this Node +// On/Off Light Endpoint +MatterOnOffLight OnOffLight; + +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + +void setup() { + Serial.begin(115200); + + // 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 at least one Matter EndPoint + OnOffLight.begin(); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); +} + +void loop() { + // Check Matter Commissioning state + if (!Matter.isDeviceCommissioned()) { + Serial.println(""); + Serial.println("Matter Node is not commissioned yet."); + Serial.println("Initiate the device discovery in your Matter environment."); + Serial.println("Commission it to your Matter hub with the manual pairing code or QR code"); + Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str()); + Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str()); + // waits for Matter Light Commissioning. + while (!Matter.isDeviceCommissioned()) { + delay(5000); + Serial.println("Matter Fabric not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi."); + Serial.println("====> Decommissioning in 30 seconds. <===="); + delay(30000); + Matter.decommission(); + Serial.println("Matter Node is decommissioned. Commsssioning widget shall start over."); +} diff --git a/libraries/Matter/examples/MatterCommissionTest/ci.json b/libraries/Matter/examples/MatterCommissionTest/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterCommissionTest/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino b/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino new file mode 100644 index 00000000000..b98cc8e19c9 --- /dev/null +++ b/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino @@ -0,0 +1,137 @@ +// 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 + +// List of Matter Endpoints for this Node +// There will be 3 On/Off Light Endpoints in the same Node +MatterOnOffLight Light1; +MatterDimmableLight Light2; +MatterColorLight Light3; + +// 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 + +// set your board USER BUTTON pin here - USED to decommission the Matter Node +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 decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +// Matter Protocol Endpoint Callback for each Light Accessory +bool setLightOnOff1(bool state) { + Serial.printf("Light1 changed state to: %s\r\n", state ? "ON" : "OFF"); + return true; +} + +bool setLightOnOff2(bool state) { + Serial.printf("Light2 changed state to: %s\r\n", state ? "ON" : "OFF"); + return true; +} + +bool setLightOnOff3(bool state) { + Serial.printf("Light3 changed state to: %s\r\n", state ? "ON" : "OFF"); + return true; +} + +void setup() { + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + + 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(); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + delay(500); + + // Initialize all 3 Matter EndPoints + Light1.begin(); + Light2.begin(); + Light3.begin(); + Light1.onChangeOnOff(setLightOnOff1); + Light2.onChangeOnOff(setLightOnOff2); + Light3.onChangeOnOff(setLightOnOff3); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); +} + +void loop() { + static uint32_t timeCounter = 0; + + // Check Matter Light Commissioning state + if (!Matter.isDeviceCommissioned()) { + Serial.println(""); + Serial.println("Matter Node is not commissioned yet."); + Serial.println("Initiate the device discovery in your Matter environment."); + Serial.println("Commission it to your Matter hub with the manual pairing code or QR code"); + Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str()); + Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str()); + // waits for Matter Light Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } + + //displays the Light state every 5 seconds + if (!(timeCounter++ % 10)) { // delaying for 500ms x 10 = 5s + Serial.println("======================"); + Serial.printf("Matter Light #1 is %s\r\n", Light1.getOnOff() ? "ON" : "OFF"); + Serial.printf("Matter Light #2 is %s\r\n", Light2.getOnOff() ? "ON" : "OFF"); + Serial.printf("Matter Light #3 is %s\r\n", Light3.getOnOff() ? "ON" : "OFF"); + } + + // 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. + } + + if (digitalRead(buttonPin) == HIGH && button_state) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning the Composed Light Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } + + delay(500); +} diff --git a/libraries/Matter/examples/MatterComposedLights/ci.json b/libraries/Matter/examples/MatterComposedLights/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterComposedLights/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterContactSensor/MatterContactSensor.ino b/libraries/Matter/examples/MatterContactSensor/MatterContactSensor.ino new file mode 100644 index 00000000000..e4c41460d3a --- /dev/null +++ b/libraries/Matter/examples/MatterContactSensor/MatterContactSensor.ino @@ -0,0 +1,152 @@ +// 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. + +/* + * This example is an example code that will create a Matter Device which can be + * commissioned and controlled from a Matter Environment APP. + * Additionally the ESP32 will send debug messages indicating the Matter activity. + * Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages. + * + * The example will create a Matter Contact Sensor Device. + * The Contact Sensor state can be toggled by pressing the onboard button. + * The Contact Sensor state will be indicated by the onboard LED. + * The Contact Sensor state will be simulated to change every 20 seconds. + * + * The onboard button can be kept pressed for 5 seconds to decommission the Matter Node. + * The example will also show the manual commissioning code and QR code to be used in the Matter environment. + * + */ + +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// Matter Contact Sensor Endpoint +MatterContactSensor ContactSensor; + +// 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 + +// LED will be used to indicate the Contact Sensor state +// 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 - decommissioning and Manual Contact Sensor toggle button +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 + +void setup() { + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node + // The button will also be used to manually toggle the Contact Sensor state + pinMode(buttonPin, INPUT_PULLUP); + // Initialize the LED (light) GPIO and Matter End Point + pinMode(ledPin, OUTPUT); + + Serial.begin(115200); + + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + + // set initial contact sensor state as false (default) + ContactSensor.begin(); + digitalWrite(ledPin, LOW); // LED OFF + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + + // Check Matter Accessory 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 Contact Sensor Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } +} + +bool simulatedHWContactSensor() { + // Simulated Contact Sensor + static bool contactState = false; + static uint32_t lastTime = 0; + + // Simulate a Contact Sensor state change every 20 seconds + if (millis() - lastTime > 20000) { + contactState = !contactState; + lastTime = millis(); + } + return contactState; +} + +void loop() { + // 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. + } + + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > debouceTime && digitalRead(buttonPin) == HIGH) { + button_state = false; // released + // button is released - toggle Contact State (Open/Closed) + ContactSensor.setContact(!ContactSensor.getContact()); // same as ContactSensor = !ContactSensor; + Serial.printf("User button released. Setting the Contact Sensor to %s.\r\n", ContactSensor ? "Closed" : "Open"); + // LED will indicate the Contact Sensor state + if (ContactSensor) { + digitalWrite(ledPin, HIGH); // LED ON + } else { + digitalWrite(ledPin, LOW); // LED OFF + } + } + + // 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 Contact Sensor Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } + + // Simulated Contact Sensor + ContactSensor.setContact(simulatedHWContactSensor()); + + delay(50); +} diff --git a/libraries/Matter/examples/MatterContactSensor/ci.json b/libraries/Matter/examples/MatterContactSensor/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterContactSensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterDimmableLight/MatterDimmableLight.ino b/libraries/Matter/examples/MatterDimmableLight/MatterDimmableLight.ino new file mode 100644 index 00000000000..79751905c20 --- /dev/null +++ b/libraries/Matter/examples/MatterDimmableLight/MatterDimmableLight.ino @@ -0,0 +1,173 @@ +// 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 +// Dimmable Light Endpoint +MatterDimmableLight DimmableLight; + +// 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 & Brightness state stored, using Preferences +Preferences matterPref; +const char *onOffPrefKey = "OnOff"; +const char *brightnessPrefKey = "Brightness"; + +// 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 Dimmable Light +bool setLightState(bool state, uint8_t brightness) { + if (state) { +#ifdef RGB_BUILTIN + rgbLedWrite(ledPin, brightness, brightness, brightness); +#else + analogWrite(ledPin, brightness); +#endif + } else { +#ifndef RGB_BUILTIN + // after analogWrite(), it is necessary to set the GPIO to digital mode first + pinMode(ledPin, OUTPUT); +#endif + digitalWrite(ledPin, LOW); + } + // store last Brightness and OnOff state for when the Light is restarted / power goes off + matterPref.putUChar(brightnessPrefKey, brightness); + matterPref.putBool(onOffPrefKey, state); + // 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 brightness ~= 6% (15/255) + uint8_t lastBrightness = matterPref.getUChar(brightnessPrefKey, 15); + DimmableLight.begin(lastOnOffState, lastBrightness); + // set the callback function to handle the Light state change + DimmableLight.onChange(setLightState); + + // lambda functions are used to set the attribute change callbacks + DimmableLight.onChangeOnOff([](bool state) { + Serial.printf("Light OnOff changed to %s\r\n", state ? "ON" : "OFF"); + return true; + }); + DimmableLight.onChangeBrightness([](uint8_t level) { + Serial.printf("Light Brightness changed to %d\r\n", level); + 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 | brightness: %d\r\n", DimmableLight ? "ON" : "OFF", DimmableLight.getBrightness()); + // configure the Light based on initial on-off state and brightness + DimmableLight.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 | brightness: %d\r\n", DimmableLight ? "ON" : "OFF", DimmableLight.getBrightness()); + // configure the Light based on initial on-off state and brightness + DimmableLight.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!"); + DimmableLight.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."); + DimmableLight = false; // turn the light off + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } +} diff --git a/libraries/Matter/examples/MatterDimmableLight/ci.json b/libraries/Matter/examples/MatterDimmableLight/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterDimmableLight/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterEnhancedColorLight/MatterEnhancedColorLight.ino b/libraries/Matter/examples/MatterEnhancedColorLight/MatterEnhancedColorLight.ino new file mode 100644 index 00000000000..8e12581fdf2 --- /dev/null +++ b/libraries/Matter/examples/MatterEnhancedColorLight/MatterEnhancedColorLight.ino @@ -0,0 +1,206 @@ +// 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 +MatterEnhancedColorLight EnhancedColorLight; + +// 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 use HSV color to control all Matter Attribute Changes +HsvColor_t currentHSVColor = {0, 0, 0}; + +// 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 Enhanced Color Light +bool setLightState(bool state, espHsvColor_t colorHSV, uint8_t brighteness, uint16_t temperature_Mireds) { + + if (state) { +#ifdef RGB_BUILTIN + // currentHSVColor keeps final color result + espRgbColor_t rgbColor = espHsvColorToRgbColor(currentHSVColor); + // 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 { +#ifndef RGB_BUILTIN + // after analogWrite(), it is necessary to set the GPIO to digital mode first + pinMode(ledPin, OUTPUT); +#endif + 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, currentHSVColor.h << 16 | currentHSVColor.s << 8 | currentHSVColor.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 (21, 216, 25) - Warm White Color at 10% intensity + uint32_t prefHsvColor = matterPref.getUInt(hsvColorPrefKey, 21 << 16 | 216 << 8 | 25); + currentHSVColor = {uint8_t(prefHsvColor >> 16), uint8_t(prefHsvColor >> 8), uint8_t(prefHsvColor)}; + EnhancedColorLight.begin(lastOnOffState, currentHSVColor); + // set the callback function to handle the Light state change + EnhancedColorLight.onChange(setLightState); + + // lambda functions are used to set the attribute change callbacks + EnhancedColorLight.onChangeOnOff([](bool state) { + Serial.printf("Light OnOff changed to %s\r\n", state ? "ON" : "OFF"); + return true; + }); + EnhancedColorLight.onChangeColorTemperature([](uint16_t colorTemperature) { + Serial.printf("Light Color Temperature changed to %d\r\n", colorTemperature); + // get correspondent Hue and Saturation of the color temperature + HsvColor_t hsvTemperature = espRgbColorToHsvColor(espCTToRgbColor(colorTemperature)); + // keep previous the brightness and just change the Hue and Saturation + currentHSVColor.h = hsvTemperature.h; + currentHSVColor.s = hsvTemperature.s; + return true; + }); + EnhancedColorLight.onChangeBrightness([](uint8_t brightness) { + Serial.printf("Light brightness changed to %d\r\n", brightness); + // change current brightness (HSV value) + currentHSVColor.v = brightness; + return true; + }); + EnhancedColorLight.onChangeColorHSV([](HsvColor_t hsvColor) { + Serial.printf("Light HSV Color changed to (%d,%d,%d)\r\n", hsvColor.h, hsvColor.s, hsvColor.v); + // keep the current brightness and just change Hue and Saturation + currentHSVColor.h = hsvColor.h; + currentHSVColor.s = hsvColor.s; + 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", EnhancedColorLight ? "ON" : "OFF", EnhancedColorLight.getColorRGB().r, + EnhancedColorLight.getColorRGB().g, EnhancedColorLight.getColorRGB().b + ); + // configure the Light based on initial on-off state and its color + EnhancedColorLight.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", EnhancedColorLight ? "ON" : "OFF", EnhancedColorLight.getColorRGB().r, + EnhancedColorLight.getColorRGB().g, EnhancedColorLight.getColorRGB().b + ); + // configure the Light based on initial on-off state and its color + EnhancedColorLight.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 (button_state && time_diff > debouceTime && digitalRead(buttonPin) == HIGH) { + button_state = false; // released + // Toggle button is released - toggle the light + Serial.println("User button released. Toggling Light!"); + EnhancedColorLight.toggle(); // Matter Controller also can see the change + } + + // 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."); + EnhancedColorLight = false; // turn the light off + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } +} diff --git a/libraries/Matter/examples/MatterEnhancedColorLight/ci.json b/libraries/Matter/examples/MatterEnhancedColorLight/ci.json new file mode 100644 index 00000000000..0665800b12b --- /dev/null +++ b/libraries/Matter/examples/MatterEnhancedColorLight/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterFan/MatterFan.ino b/libraries/Matter/examples/MatterFan/MatterFan.ino new file mode 100644 index 00000000000..705aa4853da --- /dev/null +++ b/libraries/Matter/examples/MatterFan/MatterFan.ino @@ -0,0 +1,202 @@ +// 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 + +// List of Matter Endpoints for this Node +// Fan Endpoint - On/Off control + Speed Percent Control + Fan Modes +MatterFan Fan; + +// 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 + +// set your board USER BUTTON pin here - used for toggling On/Off and decommission the Matter Node +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 your board Analog Pin here - used for changing the Fan speed +const uint8_t analogPin = A0; // Analog Pin depends on each board + +// set your board PWM Pin here - used for controlling the Fan speed (DC motor example) +// for this example, it will use the builtin board RGB LED to simulate the Fan DC motor using its brightness +#ifdef RGB_BUILTIN +const uint8_t dcMotorPin = RGB_BUILTIN; +#else +const uint8_t dcMotorPin = 2; // Set your pin here if your board has not defined LED_BUILTIN +#warning "Do not forget to set the RGB LED pin" +#endif + +void fanDCMotorDrive(bool fanState, uint8_t speedPercent) { + // drive the Fan DC motor + if (fanState == false) { + // turn off the Fan +#ifndef RGB_BUILTIN + // after analogWrite(), it is necessary to set the GPIO to digital mode first + pinMode(dcMotorPin, OUTPUT); +#endif + digitalWrite(dcMotorPin, LOW); + } else { + // set the Fan speed + uint8_t fanDCMotorPWM = map(speedPercent, 0, 100, 0, 255); +#ifdef RGB_BUILTIN + rgbLedWrite(dcMotorPin, fanDCMotorPWM, fanDCMotorPWM, fanDCMotorPWM); +#else + analogWrite(dcMotorPin, fanDCMotorPWM); +#endif + } +} + +void setup() { + // Initialize the USER BUTTON (Boot button) GPIO that will toggle the Fan (On/Off) and decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + // Initialize the Analog Pin A0 used to read input voltage and to set the Fan speed accordingly + pinMode(analogPin, INPUT); + analogReadResolution(10); // 10 bits resolution reading 0..1023 + // Initialize the PWM output pin for a Fan DC motor + pinMode(dcMotorPin, 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); + + // On Boot or Reset, Fan is set at 0% speed, OFF, changing between OFF, ON, SMART and HIGH + Fan.begin(0, MatterFan::FAN_MODE_OFF, MatterFan::FAN_MODE_SEQ_OFF_HIGH); + + // callback functions would control Fan motor + // the Matter Controller will send new data whenever the User APP or Automation request + + // single feature callbacks take place before the generic (all features) callback + // This callback will be executed whenever the speed percent matter attribute is updated + Fan.onChangeSpeedPercent([](uint8_t speedPercent) { + // setting speed to Zero, while the Fan is ON, shall turn the Fan OFF + if (speedPercent == MatterFan::OFF_SPEED && Fan.getMode() != MatterFan::FAN_MODE_OFF) { + // ATTR_SET do not update the attribute, just SET it to avoid infinite loop + return Fan.setOnOff(false, Fan.ATTR_SET); + } + // changing the speed to higher than Zero, while the Fan is OFF, shall turn the Fan ON + if (speedPercent > MatterFan::OFF_SPEED && Fan.getMode() == MatterFan::FAN_MODE_OFF) { + // ATTR_SET do not update the attribute, just SET it to avoid infinite loop + return Fan.setOnOff(true, Fan.ATTR_SET); + } + // for other case, just return true + return true; + }); + + // This callback will be executed whenever the fan mode matter attribute is updated + // This will take action when user APP starts the Fan by changing the mode + Fan.onChangeMode([](MatterFan::FanMode_t fanMode) { + // when the Fan is turned ON using Mode Selection, while it is OFF, shall start it by setting the speed to 50% + if (Fan.getSpeedPercent() == MatterFan::OFF_SPEED && fanMode != MatterFan::FAN_MODE_OFF) { + Serial.printf("Fan set to %s mode -- speed percentage will go to 50%%\r\n", Fan.getFanModeString(fanMode)); + // ATTR_SET do not update the attribute, just SET it to avoid infinite loop + return Fan.setSpeedPercent(50, Fan.ATTR_SET); + } + return true; + }); + + // Generic callback will be executed as soon as a single feature callback is done + // In this example, it will just print status messages + Fan.onChange([](MatterFan::FanMode_t fanMode, uint8_t speedPercent) { + // just report state + Serial.printf("Fan State: Mode %s | %d%% speed.\r\n", Fan.getFanModeString(fanMode), speedPercent); + // drive the Fan DC motor + fanDCMotorDrive(fanMode != MatterFan::FAN_MODE_OFF, speedPercent); + // returns success + 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."); + } +} + +void loop() { + // Check Matter Accessory 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 Generic Switch Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } + + // A builtin button is used to trigger and send a command to the Matter Controller + // 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 smart button or to decommission it + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > debouceTime && digitalRead(buttonPin) == HIGH) { + button_state = false; // released + // button is released - toggle Fan On/Off + Fan.toggle(); + Serial.printf("User button released. Setting the Fan %s.\r\n", Fan > 0 ? "ON" : "OFF"); + } + + // 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 Fan Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } + + // checks Analog pin and adjust the speed only if it has changed + static int lastRead = 0; + // analog values (0..1023) / 103 => mapped into 10 steps (0..9) + int anaVal = analogRead(analogPin) / 103; + if (lastRead != anaVal) { + // speed percent moves in steps of 10. Range is 10..100 + if (Fan.setSpeedPercent((anaVal + 1) * 10)) { + lastRead = anaVal; + } + } +} diff --git a/libraries/Matter/examples/MatterFan/ci.json b/libraries/Matter/examples/MatterFan/ci.json new file mode 100644 index 00000000000..0665800b12b --- /dev/null +++ b/libraries/Matter/examples/MatterFan/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterHumiditySensor/MatterHumiditySensor.ino b/libraries/Matter/examples/MatterHumiditySensor/MatterHumiditySensor.ino new file mode 100644 index 00000000000..1c7889db849 --- /dev/null +++ b/libraries/Matter/examples/MatterHumiditySensor/MatterHumiditySensor.ino @@ -0,0 +1,130 @@ +// 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. + +/* + * This example is an example code that will create a Matter Device which can be + * commissioned and controlled from a Matter Environment APP. + * Additionally the ESP32 will send debug messages indicating the Matter activity. + * Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages. + */ + +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// Matter Humidity Sensor Endpoint +MatterHumiditySensor SimulatedHumiditySensor; + +// 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 + +// set your board USER BUTTON pin here - decommissioning button +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + +// Button control - decommision the Matter Node +uint32_t button_time_stamp = 0; // debouncing control +bool button_state = false; // false = released | true = pressed +const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +// Simulate a humidity sensor - add your preferred humidity sensor library code here +float getSimulatedHumidity() { + // The Endpoint implementation keeps an uint16_t as internal value information, + // which stores data in 1/100th of humidity percent + static float simulatedHumidityHWSensor = 10.0; + + // it will increase from 10% to 30% in 0.5% steps to simulate a humidity sensor + simulatedHumidityHWSensor = simulatedHumidityHWSensor + 0.5; + if (simulatedHumidityHWSensor > 30) { + simulatedHumidityHWSensor = 10; + } + + return simulatedHumidityHWSensor; +} + +void setup() { + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + + Serial.begin(115200); + + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + + // set initial humidity sensor measurement + // Simulated Sensor - it shall initially print 95% and then move to the 10% to 30% humidity range + SimulatedHumiditySensor.begin(95.00); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + + // Check Matter Accessory 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 Humidity Sensor Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } +} + +void loop() { + static uint32_t timeCounter = 0; + + // Print the current humidity value every 5s + if (!(timeCounter++ % 10)) { // delaying for 500ms x 10 = 5s + // Print the current humidity value + Serial.printf("Current Humidity is %.02f%%\r\n", SimulatedHumiditySensor.getHumidity()); + // Update Humidity from the (Simulated) Hardware Sensor + // Matter APP shall display the updated humidity percent + SimulatedHumiditySensor.setHumidity(getSimulatedHumidity()); + } + + // 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. + } + + if (digitalRead(buttonPin) == HIGH && button_state) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning Humidity Sensor Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + } + + delay(500); +} diff --git a/libraries/Matter/examples/MatterHumiditySensor/ci.json b/libraries/Matter/examples/MatterHumiditySensor/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterHumiditySensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterMinimum/MatterMinimum.ino b/libraries/Matter/examples/MatterMinimum/MatterMinimum.ino new file mode 100644 index 00000000000..db591ee2226 --- /dev/null +++ b/libraries/Matter/examples/MatterMinimum/MatterMinimum.ino @@ -0,0 +1,116 @@ +// 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. + +/* + * This example is the smallest code that will create a Matter Device which can be + * commissioned and controlled from a Matter Environment APP. + * It controls a GPIO that could be attached to a LED for visualization. + * Additionally the ESP32 will send debug messages indicating the Matter activity. + * Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages. + */ + +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// Single On/Off Light Endpoint - at least one per node +MatterOnOffLight OnOffLight; + +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + +// Light GPIO that can be controlled by Matter APP +#ifdef LED_BUILTIN +const uint8_t ledPin = LED_BUILTIN; +#else +const uint8_t ledPin = 2; // Set your pin here if your board has not defined LED_BUILTIN +#endif + +// set your board USER BUTTON pin here - decommissioning button +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + +// Button control - decommision the Matter Node +uint32_t button_time_stamp = 0; // debouncing control +bool button_state = false; // false = released | true = pressed +const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +// Matter Protocol Endpoint (On/OFF Light) Callback +bool onOffLightCallback(bool state) { + digitalWrite(ledPin, state ? HIGH : LOW); + // This callback must return the success state to Matter core + return true; +} + +void setup() { + Serial.begin(115200); + + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + // Initialize the LED GPIO + pinMode(ledPin, OUTPUT); + + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + while (WiFi.status() != WL_CONNECTED) { + Serial.print('.'); + delay(500); + } + Serial.println(); + + // Initialize at least one Matter EndPoint + OnOffLight.begin(); + + // Associate a callback to the Matter Controller + OnOffLight.onChange(onOffLightCallback); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + + if (!Matter.isDeviceCommissioned()) { + 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()); + } +} + +void loop() { + // 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. + } + + if (digitalRead(buttonPin) == HIGH && button_state) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } + + delay(500); +} diff --git a/libraries/Matter/examples/MatterMinimum/ci.json b/libraries/Matter/examples/MatterMinimum/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterMinimum/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterOccupancySensor/MatterOccupancySensor.ino b/libraries/Matter/examples/MatterOccupancySensor/MatterOccupancySensor.ino new file mode 100644 index 00000000000..333f178e9de --- /dev/null +++ b/libraries/Matter/examples/MatterOccupancySensor/MatterOccupancySensor.ino @@ -0,0 +1,128 @@ +// 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. + +/* + * This example is an example code that will create a Matter Device which can be + * commissioned and controlled from a Matter Environment APP. + * Additionally the ESP32 will send debug messages indicating the Matter activity. + * Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages. + * + * The example will create a Matter Occupancy Sensor Device. + * The Occupancy Sensor will be simulated to change its state every 2 minutes. + * + * The onboard button can be kept pressed for 5 seconds to decommission the Matter Node. + * The example will also show the manual commissioning code and QR code to be used in the Matter environment. + * + */ + +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// Matter Occupancy Sensor Endpoint +MatterOccupancySensor OccupancySensor; + +// 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 + +// set your board USER BUTTON pin here - decommissioning only +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 decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +void setup() { + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + + Serial.begin(115200); + + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + + // set initial occupancy sensor state as false and connected to a PIR sensor type (default) + OccupancySensor.begin(); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + + // Check Matter Accessory 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 Occupancy Sensor Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } +} + +bool simulatedHWOccupancySensor() { + // Simulated Occupancy Sensor + static bool occupancyState = false; + static uint32_t lastTime = millis(); + const uint32_t occupancyTimeout = 120000; // 2 minutes to toggle the state + + // Simulate a Occupancy Sensor state change every 2 minutes + if (millis() - lastTime > occupancyTimeout) { + occupancyState = !occupancyState; + lastTime = millis(); + } + return occupancyState; +} + +void loop() { + // 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. + } + + if (button_state && digitalRead(buttonPin) == HIGH) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning Occupancy Sensor Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } + + // Check Simulated Occupancy Sensor and set Matter Attribute + OccupancySensor.setOccupancy(simulatedHWOccupancySensor()); + + delay(50); +} diff --git a/libraries/Matter/examples/MatterOccupancySensor/ci.json b/libraries/Matter/examples/MatterOccupancySensor/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterOccupancySensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterOnIdentify/MatterOnIdentify.ino b/libraries/Matter/examples/MatterOnIdentify/MatterOnIdentify.ino new file mode 100644 index 00000000000..b2e77900e95 --- /dev/null +++ b/libraries/Matter/examples/MatterOnIdentify/MatterOnIdentify.ino @@ -0,0 +1,164 @@ +// 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. + +/* + * This example is the smallest code that will create a Matter Device which can be + * commissioned and controlled from a Matter Environment APP. + * It controls a GPIO that could be attached to a LED for visualization. + * Additionally the ESP32 will send debug messages indicating the Matter activity. + * Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages. + * + * This example is a simple Matter On/Off Light that can be controlled by a Matter Controller. + * It demonstrates how to use On Identify callback when the Identify Cluster is called. + * The Matter user APP can be used to request the device to identify itself by blinking the LED. + */ + +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// Single On/Off Light Endpoint - at least one per node +MatterOnOffLight OnOffLight; + +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + +// Light GPIO that can be controlled by Matter APP +#ifdef LED_BUILTIN +const uint8_t ledPin = LED_BUILTIN; +#else +const uint8_t ledPin = 2; // Set your pin here if your board has not defined LED_BUILTIN +#endif + +// set your board USER BUTTON pin here - decommissioning button +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + +// Button control - decommision the Matter Node +uint32_t button_time_stamp = 0; // debouncing control +bool button_state = false; // false = released | true = pressed +const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +// Identify Flag and blink time - Blink the LED +const uint8_t identifyLedPin = ledPin; // uses the same LED as the Light - change if needed +volatile bool identifyFlag = false; // Flag to start the Blink when in Identify state +bool identifyBlink = false; // Blink state when in Identify state + +// Matter Protocol Endpoint (On/OFF Light) Callback +bool onOffLightCallback(bool state) { + digitalWrite(ledPin, state ? HIGH : LOW); + // This callback must return the success state to Matter core + return true; +} + +// Identification shall be done by Blink in Red or just the GPIO when no LED_BUILTIN is not defined +bool onIdentifyLightCallback(bool identifyIsActive) { + Serial.printf("Identify Cluster is %s\r\n", identifyIsActive ? "Active" : "Inactive"); + if (identifyIsActive) { + // Start Blinking the light in loop() + identifyFlag = true; + identifyBlink = !OnOffLight; // Start with the inverted light state + } else { + // Stop Blinking and restore the light to the its last state + identifyFlag = false; + // force returning to the original state by toggling the light twice + OnOffLight.toggle(); + OnOffLight.toggle(); + } + return true; +} + +void setup() { + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + // Initialize the LED GPIO + pinMode(ledPin, OUTPUT); + + Serial.begin(115200); + + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + + // Initialize at least one Matter EndPoint + OnOffLight.begin(); + + // On Identify Callback - Blink the LED + OnOffLight.onIdentify(onIdentifyLightCallback); + + // Associate a callback to the Matter Controller + OnOffLight.onChange(onOffLightCallback); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + + // Check Matter Accessory 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 Occupancy Sensor Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } +} + +void loop() { + // check if the Light is in identify state and blink it every 500ms (delay loop time) + if (identifyFlag) { +#ifdef LED_BUILTIN + uint8_t brightness = 32 * identifyBlink; + rgbLedWrite(identifyLedPin, brightness, 0, 0); +#else + digitalWrite(identifyLedPin, identifyBlink ? HIGH : LOW); +#endif + identifyBlink = !identifyBlink; + } + + // 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. + } + + if (digitalRead(buttonPin) == HIGH && button_state) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } + + delay(500); // works as a debounce for the button and also for the LED blink +} diff --git a/libraries/Matter/examples/MatterOnIdentify/ci.json b/libraries/Matter/examples/MatterOnIdentify/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterOnIdentify/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino b/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino new file mode 100644 index 00000000000..5faa0a385b0 --- /dev/null +++ b/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino @@ -0,0 +1,148 @@ +// 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 + +// 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 + +// List of Matter Endpoints for this Node +// On/Off Light Endpoint +MatterOnOffLight OnOffLight; + +// it will keep last OnOff state stored, using Preferences +Preferences matterPref; +const char *onOffPrefKey = "OnOff"; + +// set your board LED pin here +#ifdef LED_BUILTIN +const uint8_t ledPin = LED_BUILTIN; +#else +const uint8_t ledPin = 2; // Set your pin here if your board has not defined LED_BUILTIN +#warning "Do not forget to set the LED pin" +#endif + +// set your board USER BUTTON pin here +const uint8_t buttonPin = 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 + +// Matter Protocol Endpoint Callback +bool setLightOnOff(bool state) { + Serial.printf("User Callback :: New Light State = %s\r\n", state ? "ON" : "OFF"); + if (state) { + digitalWrite(ledPin, HIGH); + } else { + digitalWrite(ledPin, LOW); + } + // store last OnOff state for when the Light is restarted / power goes off + matterPref.putBool(onOffPrefKey, state); + // 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); + bool lastOnOffState = matterPref.getBool(onOffPrefKey, true); + OnOffLight.begin(lastOnOffState); + OnOffLight.onChange(setLightOnOff); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + // This may be a restart of a already commissioned Matter accessory + if (Matter.isDeviceCommissioned()) { + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + Serial.printf("Initial state: %s\r\n", OnOffLight.getOnOff() ? "ON" : "OFF"); + OnOffLight.updateAccessory(); // configure the Light based on initial state + } +} + +void loop() { + // Check Matter Light Commissioning state, which may change during execution of loop() + if (!Matter.isDeviceCommissioned()) { + Serial.println(""); + Serial.println("Matter Node is not commissioned yet."); + Serial.println("Initiate the device discovery in your Matter environment."); + Serial.println("Commission it to your Matter hub with the manual pairing code or QR code"); + Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str()); + Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str()); + // waits for Matter Light Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.printf("Initial state: %s\r\n", OnOffLight.getOnOff() ? "ON" : "OFF"); + OnOffLight.updateAccessory(); // configure the Light based on initial state + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } + + // A button is also used to control the light + // Check if the button has been pressed + if (digitalRead(buttonPin) == LOW && !button_state) { + // deals with button debouncing + button_time_stamp = millis(); // record the time while the button is pressed. + button_state = true; // pressed. + } + + // Onboard User Button is used as a Light toggle switch or to decommission it + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > debouceTime && digitalRead(buttonPin) == HIGH) { + button_state = false; // released + // Toggle button is released - toggle the light + Serial.println("User button released. Toggling Light!"); + OnOffLight.toggle(); // Matter Controller also can see the change + } + + // 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."); + OnOffLight.setOnOff(false); // turn the light off + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } +} diff --git a/libraries/Matter/examples/MatterOnOffLight/ci.json b/libraries/Matter/examples/MatterOnOffLight/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterOnOffLight/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterOnOffPlugin/MatterOnOffPlugin.ino b/libraries/Matter/examples/MatterOnOffPlugin/MatterOnOffPlugin.ino new file mode 100644 index 00000000000..d14e2189ec1 --- /dev/null +++ b/libraries/Matter/examples/MatterOnOffPlugin/MatterOnOffPlugin.ino @@ -0,0 +1,142 @@ +// 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 +// On/Off Plugin Endpoint +MatterOnOffPlugin OnOffPlugin; + +// 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 state stored, using Preferences +Preferences matterPref; +const char *onOffPrefKey = "OnOff"; + +// set your board Power Relay pin here - this example uses the built-in LED for easy visualization +#ifdef LED_BUILTIN +const uint8_t onoffPin = LED_BUILTIN; +#else +const uint8_t onoffPin = 2; // Set your pin here - usually a power relay +#warning "Do not forget to set the Power Relay pin" +#endif + +// board USER BUTTON pin necessary for Decommissioning +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 decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +// Matter Protocol Endpoint Callback +bool setPluginOnOff(bool state) { + Serial.printf("User Callback :: New Plugin State = %s\r\n", state ? "ON" : "OFF"); + if (state) { + digitalWrite(onoffPin, HIGH); + } else { + digitalWrite(onoffPin, LOW); + } + // store last OnOff state for when the Plugin is restarted / power goes off + matterPref.putBool(onOffPrefKey, state); + // This callback must return the success state to Matter core + return true; +} + +void setup() { + // Initialize the USER BUTTON + pinMode(buttonPin, INPUT_PULLUP); + // Initialize the Power Relay (plugin) GPIO + pinMode(onoffPin, OUTPUT); + + Serial.begin(115200); + + // We start by connecting to a WiFi network + Serial.print("Connecting to "); + Serial.println(ssid); + 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); + bool lastOnOffState = matterPref.getBool(onOffPrefKey, false); + OnOffPlugin.begin(lastOnOffState); + OnOffPlugin.onChange(setPluginOnOff); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + // This may be a restart of a already commissioned Matter accessory + if (Matter.isDeviceCommissioned()) { + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + Serial.printf("Initial state: %s\r\n", OnOffPlugin.getOnOff() ? "ON" : "OFF"); + OnOffPlugin.updateAccessory(); // configure the Plugin based on initial state + } +} + +void loop() { + // Check Matter Plugin 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 Plugin Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.printf("Initial state: %s\r\n", OnOffPlugin.getOnOff() ? "ON" : "OFF"); + OnOffPlugin.updateAccessory(); // configure the Plugin based on initial state + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } + + // 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 to decommission the Matter Node + if (button_state && digitalRead(buttonPin) == HIGH) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning the Plugin Matter Accessory. It shall be commissioned again."); + OnOffPlugin.setOnOff(false); // turn the plugin off + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } +} diff --git a/libraries/Matter/examples/MatterOnOffPlugin/ci.json b/libraries/Matter/examples/MatterOnOffPlugin/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterOnOffPlugin/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterPressureSensor/MatterPressureSensor.ino b/libraries/Matter/examples/MatterPressureSensor/MatterPressureSensor.ino new file mode 100644 index 00000000000..db035e951c9 --- /dev/null +++ b/libraries/Matter/examples/MatterPressureSensor/MatterPressureSensor.ino @@ -0,0 +1,131 @@ +// 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. + +/* + * This example is an example code that will create a Matter Device which can be + * commissioned and controlled from a Matter Environment APP. + * Additionally the ESP32 will send debug messages indicating the Matter activity. + * Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages. + */ + +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// Matter Pressure Sensor Endpoint +MatterPressureSensor SimulatedPressureSensor; + +// 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 + +// set your board USER BUTTON pin here - decommissioning button +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + +// Button control - decommision the Matter Node +uint32_t button_time_stamp = 0; // debouncing control +bool button_state = false; // false = released | true = pressed +const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +// Simulate a pressure sensor - add your preferred pressure sensor library code here +float getSimulatedPressure() { + // The Endpoint implementation keeps an uint16_t as internal value information, + // which stores data in hPa (pressure measurement unit) + static float simulatedPressureHWSensor = 950; + + // it will increase from 950 to 1100 hPa in steps of 10 hPa to simulate a pressure sensor + simulatedPressureHWSensor = simulatedPressureHWSensor + 10; + if (simulatedPressureHWSensor > 1100) { + simulatedPressureHWSensor = 950; + } + + return simulatedPressureHWSensor; +} + +void setup() { + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + + Serial.begin(115200); + + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + + // set initial pressure sensor measurement + // Simulated Sensor - it shall initially print 900hPa and then move to the 950 to 1100 hPa as pressure range + SimulatedPressureSensor.begin(900.00); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + + // Check Matter Accessory 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 Pressure Sensor Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } +} + +void loop() { + static uint32_t timeCounter = 0; + + // Print the current pressure value every 5s + if (!(timeCounter++ % 10)) { // delaying for 500ms x 10 = 5s + // Print the current pressure value + Serial.printf("Current Pressure is %.02fhPa\r\n", SimulatedPressureSensor.getPressure()); + // Update Pressure from the (Simulated) Hardware Sensor + // Matter APP shall display the updated pressure percent + SimulatedPressureSensor.setPressure(getSimulatedPressure()); + } + + // 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. + } + + if (digitalRead(buttonPin) == HIGH && button_state) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + // Factory reset is triggered if the button is pressed longer than 5 seconds + Serial.println("Decommissioning Pressure Sensor Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + } + + delay(500); +} diff --git a/libraries/Matter/examples/MatterPressureSensor/ci.json b/libraries/Matter/examples/MatterPressureSensor/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterPressureSensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterSmartButon/MatterSmartButon.ino b/libraries/Matter/examples/MatterSmartButon/MatterSmartButon.ino new file mode 100644 index 00000000000..f8da970595d --- /dev/null +++ b/libraries/Matter/examples/MatterSmartButon/MatterSmartButon.ino @@ -0,0 +1,113 @@ +// 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 + +// List of Matter Endpoints for this Node +// Generic Switch Endpoint - works as a smart button with a single click +MatterGenericSwitch SmartButton; + +// 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 + +// 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 + +void setup() { + // Initialize the USER BUTTON (Boot button) GPIO that will act as a smart button or to decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + + 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 the Matter EndPoint + SmartButton.begin(); + + // 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."); + } +} + +void loop() { + // Check Matter Accessory 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 Generic Switch Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } + + // A builtin button is used to trigger a command to the Matter Controller + // 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 smart button or to decommission it + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > debouceTime && digitalRead(buttonPin) == HIGH) { + button_state = false; // released + // builtin button is released - send a click event to the Matter Controller + Serial.println("User button released. Sending Click to the Matter Controller!"); + // Matter Controller will receive an event and, if programmed, it will trigger an action + SmartButton.click(); + } + + // 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 Generic Switch Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } +} diff --git a/libraries/Matter/examples/MatterSmartButon/ci.json b/libraries/Matter/examples/MatterSmartButon/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterSmartButon/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterTemperatureLight/MatterTemperatureLight.ino b/libraries/Matter/examples/MatterTemperatureLight/MatterTemperatureLight.ino new file mode 100644 index 00000000000..d46427591ab --- /dev/null +++ b/libraries/Matter/examples/MatterTemperatureLight/MatterTemperatureLight.ino @@ -0,0 +1,196 @@ +// 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 Temperature CW/WW Light Endpoint +MatterColorTemperatureLight CW_WW_Light; + +// 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 & Brightness state stored, using Preferences +Preferences matterPref; +const char *onOffPrefKey = "OnOff"; +const char *brightnessPrefKey = "Brightness"; +const char *temperaturePrefKey = "Temperature"; + +// 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 Temperature Light +bool setLightState(bool state, uint8_t brightness, uint16_t temperature_Mireds) { + + if (state) { +#ifdef RGB_BUILTIN + espRgbColor_t rgb_ct = espCTToRgbColor(temperature_Mireds); + // simple intensity correction + float brightnessPercent = (float)brightness / MatterColorTemperatureLight::MAX_BRIGHTNESS; + rgb_ct.r = brightnessPercent * rgb_ct.r; + rgb_ct.g = brightnessPercent * rgb_ct.g; + rgb_ct.b = brightnessPercent * rgb_ct.b; + // set the RGB LED + rgbLedWrite(ledPin, rgb_ct.r, rgb_ct.g, rgb_ct.b); +#else + // No Color RGB LED, just use the brightness to control the LED + analogWrite(ledPin, brightness); +#endif + } else { +#ifndef RGB_BUILTIN + // after analogWrite(), it is necessary to set the GPIO to digital mode first + pinMode(ledPin, OUTPUT); +#endif + digitalWrite(ledPin, LOW); + } + // store last Brightness and OnOff state for when the Light is restarted / power goes off + matterPref.putUChar(brightnessPrefKey, brightness); + matterPref.putBool(onOffPrefKey, state); + matterPref.putUShort(temperaturePrefKey, temperature_Mireds); + // 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 brightness ~= 6% (15/255) + uint8_t lastBrightness = matterPref.getUChar(brightnessPrefKey, 15); + // default temperature ~= 454 Mireds (Warm White) + uint16_t lastTemperature = matterPref.getUShort(temperaturePrefKey, WARM_WHITE_COLOR_TEMPERATURE.ctMireds); + CW_WW_Light.begin(lastOnOffState, lastBrightness, lastTemperature); + // set the callback function to handle the Light state change + CW_WW_Light.onChange(setLightState); + + // lambda functions are used to set the attribute change callbacks + CW_WW_Light.onChangeOnOff([](bool state) { + Serial.printf("Light OnOff changed to %s\r\n", state ? "ON" : "OFF"); + return true; + }); + CW_WW_Light.onChangeBrightness([](uint8_t level) { + Serial.printf("Light Brightness changed to %d\r\n", level); + return true; + }); + CW_WW_Light.onChangeColorTemperature([](uint16_t temperature) { + Serial.printf("Light Color Temperature changed to %d\r\n", temperature); + 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 | brightness: %d | Color Temperature: %d mireds \r\n", CW_WW_Light ? "ON" : "OFF", CW_WW_Light.getBrightness(), + CW_WW_Light.getColorTemperature() + ); + // configure the Light based on initial on-off state and brightness + CW_WW_Light.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 | brightness: %d | Color Temperature: %d mireds \r\n", CW_WW_Light ? "ON" : "OFF", CW_WW_Light.getBrightness(), + CW_WW_Light.getColorTemperature() + ); + // configure the Light based on initial on-off state and brightness + CW_WW_Light.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 (button_state && time_diff > debouceTime && digitalRead(buttonPin) == HIGH) { + button_state = false; // released + // Toggle button is released - toggle the light + Serial.println("User button released. Toggling Light!"); + CW_WW_Light.toggle(); // Matter Controller also can see the change + } + + // 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."); + CW_WW_Light = false; // turn the light off + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } +} diff --git a/libraries/Matter/examples/MatterTemperatureLight/ci.json b/libraries/Matter/examples/MatterTemperatureLight/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterTemperatureLight/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterTemperatureSensor/MatterTemperatureSensor.ino b/libraries/Matter/examples/MatterTemperatureSensor/MatterTemperatureSensor.ino new file mode 100644 index 00000000000..086155aeffe --- /dev/null +++ b/libraries/Matter/examples/MatterTemperatureSensor/MatterTemperatureSensor.ino @@ -0,0 +1,131 @@ +// 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. + +/* + * This example is an example code that will create a Matter Device which can be + * commissioned and controlled from a Matter Environment APP. + * Additionally the ESP32 will send debug messages indicating the Matter activity. + * Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages. + */ + +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// Matter Temperature Sensor Endpoint +MatterTemperatureSensor SimulatedTemperatureSensor; + +// 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 + +// set your board USER BUTTON pin here - decommissioning button +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + +// Button control - decommision the Matter Node +uint32_t button_time_stamp = 0; // debouncing control +bool button_state = false; // false = released | true = pressed +const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +// Simulate a temperature sensor - add your preferred temperature sensor library code here +float getSimulatedTemperature() { + // The Endpoint implementation keeps an int16_t as internal value information, + // which stores data in 1/100th Celsius. + static float simulatedTempHWSensor = -10.0; + + // it will increase from -10C to 10C in 0.5C steps to simulate a temperature sensor + simulatedTempHWSensor = simulatedTempHWSensor + 0.5; + if (simulatedTempHWSensor > 10) { + simulatedTempHWSensor = -10; + } + + return simulatedTempHWSensor; +} + +void setup() { + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + + Serial.begin(115200); + + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + + // set initial temperature sensor measurement + // Simulated Sensor - it shall initially print -25C and then move to the -10C to 10C range + SimulatedTemperatureSensor.begin(-25.00); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + + // Check Matter Accessory 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 Temperature Sensor Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } +} + +void loop() { + static uint32_t timeCounter = 0; + + // Print the current temperature value every 5s + if (!(timeCounter++ % 10)) { // delaying for 500ms x 10 = 5s + // Print the current temperature value + Serial.printf("Current Temperature is %.02fC\r\n", SimulatedTemperatureSensor.getTemperature()); + // Update Temperature from the (Simulated) Hardware Sensor + // Matter APP shall display the updated temperature percent + SimulatedTemperatureSensor.setTemperature(getSimulatedTemperature()); + } + + // 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. + } + + if (digitalRead(buttonPin) == HIGH && button_state) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning Temperature Sensor Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } + + delay(500); +} diff --git a/libraries/Matter/examples/MatterTemperatureSensor/ci.json b/libraries/Matter/examples/MatterTemperatureSensor/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterTemperatureSensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterThermostat/MatterThermostat.ino b/libraries/Matter/examples/MatterThermostat/MatterThermostat.ino new file mode 100644 index 00000000000..bf76477c846 --- /dev/null +++ b/libraries/Matter/examples/MatterThermostat/MatterThermostat.ino @@ -0,0 +1,243 @@ +// 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. + +/* + This example is an example code that will create a Matter Device which can be + commissioned and controlled from a Matter Environment APP. + Additionally the ESP32 will send debug messages indicating the Matter activity. + Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages. +*/ + +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// Matter Thermostat Endpoint +MatterThermostat SimulatedThermostat; + +// 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 + +// set your board USER BUTTON pin here - decommissioning button +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + +// Button control - decommision the Matter Node +uint32_t button_time_stamp = 0; // debouncing control +bool button_state = false; // false = released | true = pressed +const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +// Simulate a system that will activate heating/cooling in addition to a temperature sensor - add your preferred code here +float getSimulatedTemperature(bool isHeating, bool isCooling) { + // read sensor temperature and apply heating/cooling + float simulatedTempHWSensor = SimulatedThermostat.getLocalTemperature(); + + if (isHeating) { + // it will increase to simulate a heating system + simulatedTempHWSensor = simulatedTempHWSensor + 0.5; + } + if (isCooling) { + // it will decrease to simulate a colling system + simulatedTempHWSensor = simulatedTempHWSensor - 0.5; + } + // otherwise, it will keep the temperature stable + return simulatedTempHWSensor; +} + +void setup() { + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + + Serial.begin(115200); + + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + + // Simulated Thermostat in COOLING and HEATING mode with Auto Mode to keep the temperature between setpoints + // Auto Mode can only be used when the control sequence of operation is Cooling & Heating + SimulatedThermostat.begin(MatterThermostat::THERMOSTAT_SEQ_OP_COOLING_HEATING, MatterThermostat::THERMOSTAT_AUTO_MODE_ENABLED); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + + // Check Matter Accessory 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 Thermostat Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + + // after commissioning, set initial thermostat parameters + // start the thermostat in AUTO mode + SimulatedThermostat.setMode(MatterThermostat::THERMOSTAT_MODE_AUTO); + // cooling setpoint must be lower than heating setpoint by at least 2.5C (deadband), in auto mode + SimulatedThermostat.setCoolingHeatingSetpoints(20.0, 23.00); // the target cooler and heating setpoint + // set the local temperature sensor in Celsius + SimulatedThermostat.setLocalTemperature(12.50); + + Serial.println(); + Serial.printf( + "Initial Setpoints are %.01fC to %.01fC with a minimum 2.5C difference\r\n", SimulatedThermostat.getHeatingSetpoint(), + SimulatedThermostat.getCoolingSetpoint() + ); + Serial.printf("Auto mode is ON. Initial Temperature of %.01fC \r\n", SimulatedThermostat.getLocalTemperature()); + Serial.println("Local Temperature Sensor will be simulated every 10 seconds and changed by a simulated heater and cooler to move in between setpoints."); + } +} + +// This will simulate the thermostat control system (heating and cooling) +// User can set a local temperature using the Serial input (type a number and press Enter) +// New temperature can be an positive or negative temperature in Celsius, between -50C and 50C +// Initial local temperature is 10C as defined in getSimulatedTemperature() function +void readSerialForNewTemperature() { + static String newTemperatureStr; + + while (Serial.available()) { + char c = Serial.read(); + if (c == '\n' || c == '\r') { + if (newTemperatureStr.length() > 0) { + // convert the string to a float value + float newTemperature = newTemperatureStr.toFloat(); + // check if the new temperature is valid + if (newTemperature >= -50.0 && newTemperature <= 50.0) { + // set the new temperature + SimulatedThermostat.setLocalTemperature(newTemperature); + Serial.printf("New Temperature is %.01fC\r\n", newTemperature); + } else { + Serial.println("Invalid Temperature value. Please type a number between -50 and 50"); + } + newTemperatureStr = ""; + } + } else { + if (c == '+' || c == '-' || (c >= '0' && c <= '9') || c == '.') { + newTemperatureStr += c; + } else { + Serial.println("Invalid character. Please type a number between -50 and 50"); + newTemperatureStr = ""; + } + } + } +} + +// loop will simulate the thermostat control system +// User can set a local temperature using the Serial input (type a number and press Enter) +// User can change the thermostat mode using the Matter APP (smartphone) +// The loop will simulate a heating and cooling system and the associated local temperature change +void loop() { + static uint32_t timeCounter = 0; + + // Simulate the heating and cooling systems + static bool isHeating = false; + static bool isCooling = false; + + // check if a new temperature is typed in the Serial Monitor + readSerialForNewTemperature(); + + // simulate thermostat with heating/cooling system and the associated local temperature change, every 10s + if (!(timeCounter++ % 20)) { // delaying for 500ms x 20 = 10s + float localTemperature = getSimulatedTemperature(isHeating, isCooling); + // Print the current thermostat local temperature value + Serial.printf("Current Local Temperature is %.01fC\r\n", localTemperature); + SimulatedThermostat.setLocalTemperature(localTemperature); // publish the new temperature value + + // Simulate the thermostat control system - User has 4 modes: OFF, HEAT, COOL, AUTO + switch (SimulatedThermostat.getMode()) { + case MatterThermostat::THERMOSTAT_MODE_OFF: + // turn off the heating and cooling systems + isHeating = false; + isCooling = false; + break; + case MatterThermostat::THERMOSTAT_MODE_AUTO: + // User APP has set the thermostat to AUTO mode -- keeping the tempeature between both setpoints + // check if the heating system should be turned on or off + if (localTemperature < SimulatedThermostat.getHeatingSetpoint() + SimulatedThermostat.getDeadBand()) { + // turn on the heating system and turn off the cooling system + isHeating = true; + isCooling = false; + } + if (localTemperature > SimulatedThermostat.getCoolingSetpoint() - SimulatedThermostat.getDeadBand()) { + // turn off the heating system and turn on the cooling system + isHeating = false; + isCooling = true; + } + break; + case MatterThermostat::THERMOSTAT_MODE_HEAT: + // Simulate the heating system - User has turned the heating system ON + isHeating = true; + isCooling = false; // keep the cooling system off as it is in heating mode + // when the heating system is in HEATING mode, it will be turned off as soon as the local temperature is above the setpoint + if (localTemperature > SimulatedThermostat.getHeatingSetpoint()) { + // turn off the heating system + isHeating = false; + } + break; + case MatterThermostat::THERMOSTAT_MODE_COOL: + // Simulate the cooling system - User has turned the cooling system ON + if (SimulatedThermostat.getMode() == MatterThermostat::THERMOSTAT_MODE_COOL) { + isCooling = true; + isHeating = false; // keep the heating system off as it is in cooling mode + // when the cooling system is in COOLING mode, it will be turned off as soon as the local temperature is bellow the setpoint + if (localTemperature < SimulatedThermostat.getCoolingSetpoint()) { + // turn off the cooling system + isCooling = false; + } + } + break; + default: log_e("Invalid Thermostat Mode %d", SimulatedThermostat.getMode()); + } + // Reporting Heating and Cooling status + Serial.printf( + "\tThermostat Mode: %s >>> Heater is %s -- Cooler is %s\r\n", MatterThermostat::getThermostatModeString(SimulatedThermostat.getMode()), + isHeating ? "ON" : "OFF", isCooling ? "ON" : "OFF" + ); + } + // 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. + } + + if (digitalRead(buttonPin) == HIGH && button_state) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning Thermostat Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } + + delay(500); +} diff --git a/libraries/Matter/examples/MatterThermostat/ci.json b/libraries/Matter/examples/MatterThermostat/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterThermostat/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/WiFiProvWithinMatter/WiFiProvWithinMatter.ino b/libraries/Matter/examples/WiFiProvWithinMatter/WiFiProvWithinMatter.ino new file mode 100644 index 00000000000..3434217624d --- /dev/null +++ b/libraries/Matter/examples/WiFiProvWithinMatter/WiFiProvWithinMatter.ino @@ -0,0 +1,152 @@ +/* + Please read README.md file in this folder, or on the web: + https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFiProv/examples/WiFiProv + + Note: This sketch takes up a lot of space for the app and may not be able to flash with default setting on some chips. + If you see Error like this: "Sketch too big" + In Arduino IDE go to: Tools > Partition scheme > chose anything that has more than 1.4MB APP + - for example "No OTA (2MB APP/2MB SPIFFS)" + + This example demonstrates that it is possible to provision WiFi using BLE or Software AP using + the ESP BLE Prov APP or ESP SoftAP Provisioning APP from Android Play or/and iOS APP Store + + Once the WiFi is provisioned, Matter will start its process as usual. + + This same Example could be used for any other WiFi Provisioning method. +*/ + +// Matter Manager +#include +#include +#include + +#if !CONFIG_BLUEDROID_ENABLED +#define USE_SOFT_AP // ESP32-S2 has no BLE, therefore, it shall use SoftAP Provisioning +#endif +//#define USE_SOFT_AP // Uncomment if you want to enforce using the Soft AP method instead of BLE + +const char *pop = "abcd1234"; // Proof of possession - otherwise called a PIN - string provided by the device, entered by the user in the phone app +const char *service_name = "PROV_123"; // Name of your device (the Espressif apps expects by default device name starting with "Prov_") +const char *service_key = NULL; // Password used for SofAP method (NULL = no password needed) +bool reset_provisioned = true; // When true the library will automatically delete previously provisioned data. + +// List of Matter Endpoints for this Node +// Single On/Off Light Endpoint - at least one per node +MatterOnOffLight OnOffLight; + +// Light GPIO that can be controlled by Matter APP +#ifdef LED_BUILTIN +const uint8_t ledPin = LED_BUILTIN; +#else +const uint8_t ledPin = 2; // Set your pin here if your board has not defined LED_BUILTIN +#endif + +// set your board USER BUTTON pin here - decommissioning button +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + +// Button control - decommision the Matter Node +uint32_t button_time_stamp = 0; // debouncing control +bool button_state = false; // false = released | true = pressed +const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +// Matter Protocol Endpoint (On/OFF Light) Callback +bool matterCB(bool state) { + digitalWrite(ledPin, state ? HIGH : LOW); + // This callback must return the success state to Matter core + return true; +} + +void setup() { + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + + Serial.begin(115200); + // Initialize the LED GPIO + pinMode(ledPin, OUTPUT); + + WiFi.begin(); // no SSID/PWD - get it from the Provisioning APP or from NVS (last successful connection) + + // BLE Provisioning using the ESP SoftAP Prov works fine for any BLE SoC, including ESP32, ESP32S3 and ESP32C3. +#if CONFIG_BLUEDROID_ENABLED && !defined(USE_SOFT_AP) + Serial.println("Begin Provisioning using BLE"); + // Sample uuid that user can pass during provisioning using BLE + uint8_t uuid[16] = {0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02}; + WiFiProv.beginProvision( + NETWORK_PROV_SCHEME_BLE, NETWORK_PROV_SCHEME_HANDLER_FREE_BLE, NETWORK_PROV_SECURITY_1, pop, service_name, service_key, uuid, reset_provisioned + ); + Serial.println("You may use this BLE QRCode:"); + WiFiProv.printQR(service_name, pop, "ble"); +#else + Serial.println("Begin Provisioning using Soft AP"); + WiFiProv.beginProvision(NETWORK_PROV_SCHEME_SOFTAP, NETWORK_PROV_SCHEME_HANDLER_NONE, NETWORK_PROV_SECURITY_1, pop, service_name, service_key); + Serial.println("You may use this WiFi QRCode:"); + WiFiProv.printQR(service_name, pop, "softap"); +#endif + + // Wait for WiFi connection + uint32_t counter = 0; + while (WiFi.status() != WL_CONNECTED) { + // resets the device after 10 minutes + if (counter > 2 * 60 * 10) { + Serial.println("\r\n================================================"); + Serial.println("Already 10 minutes past. The device will reboot."); + Serial.println("================================================\r\n"); + Serial.flush(); // wait until the Serial has sent the whole message. + ESP.restart(); + } + // WiFi searching feedback + Serial.print("."); + delay(500); + // adds a new line every 30 seconds + counter++; + if (!(counter % 60)) { + Serial.println(); + } + } + + // WiFi shall be connected by now + Serial.println(); + + // Initialize at least one Matter EndPoint + OnOffLight.begin(); + + // Associate a callback to the Matter Controller + OnOffLight.onChange(matterCB); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + + while (!Matter.isDeviceCommissioned()) { + 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()); + Serial.println(); + // waits 30 seconds for Matter Commissioning, keeping it blocked until done + delay(30000); + } +} + +void loop() { + // 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. + } + + if (digitalRead(buttonPin) == HIGH && button_state) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } + + delay(500); +} diff --git a/libraries/Matter/examples/WiFiProvWithinMatter/ci.json b/libraries/Matter/examples/WiFiProvWithinMatter/ci.json new file mode 100644 index 00000000000..0665800b12b --- /dev/null +++ b/libraries/Matter/examples/WiFiProvWithinMatter/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/keywords.txt b/libraries/Matter/keywords.txt new file mode 100644 index 00000000000..a63d9a65acb --- /dev/null +++ b/libraries/Matter/keywords.txt @@ -0,0 +1,148 @@ +####################################### +# Syntax Coloring Map For Matter +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Matter KEYWORD1 +ArduinoMatter KEYWORD1 +MatterGenericSwitch KEYWORD1 +MatterOnOffLight KEYWORD1 +MatterDimmableLight KEYWORD1 +MatterColorTemperatureLight KEYWORD1 +MatterColorLight KEYWORD1 +MatterEnhancedColorLight KEYWORD1 +MatterEndPoint KEYWORD1 +MatterFan KEYWORD1 +FanMode_t KEYWORD1 +FanModeSequence_t KEYWORD1 +MatterTemperatureSensor KEYWORD1 +MatterHumiditySensor KEYWORD1 +MatterContactSensor KEYWORD1 +MatterPressureSensor KEYWORD1 +MatterOccupancySensor KEYWORD1 +MatterOnOffPlugin KEYWORD1 +MatterThermostat KEYWORD1 +ControlSequenceOfOperation_t KEYWORD1 +ThermostatMode_t KEYWORD1 +EndPointCB KEYWORD1 +EndPointHeatingSetpointCB KEYWORD1 +EndPointCoolingSetpointCB KEYWORD1 +EndPointTemperatureCB KEYWORD1 +EndPointModeCB KEYWORD1 +EndPointSpeedCB KEYWORD1 +EndPointOnOffCB KEYWORD1 +EndPointBrightnessCB KEYWORD1 +EndPointRGBColorCB KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +end KEYWORD2 +getManualPairingCode KEYWORD2 +getOnboardingQRCodeUrl KEYWORD2 +isDeviceCommissioned KEYWORD2 +isWiFiConnected KEYWORD2 +isThreadConnected KEYWORD2 +isDeviceConnected KEYWORD2 +decommission KEYWORD2 +attributeChangeCB KEYWORD2 +setOnOff KEYWORD2 +getOnOff KEYWORD2 +toggle KEYWORD2 +setBrightness KEYWORD2 +getBrightness KEYWORD2 +setColorTemperature KEYWORD2 +getColorTemperature KEYWORD2 +setColorRGB KEYWORD2 +getColorRGB KEYWORD2 +setColorHSV KEYWORD2 +getColorHSV KEYWORD2 +updateAccessory KEYWORD2 +onChange KEYWORD2 +onChangeOnOff KEYWORD2 +onChangeBrightness KEYWORD2 +onChangeColorTemperature KEYWORD2 +onChangeColorHSV KEYWORD2 +click KEYWORD2 +getAttribute KEYWORD2 +getAttributeVal KEYWORD2 +setAttributeVal KEYWORD2 +updateAttributeVal KEYWORD2 +getFanModeString KEYWORD2 +setSpeedPercent KEYWORD2 +getSpeedPercent KEYWORD2 +setMode KEYWORD2 +getMode KEYWORD2 +onChangeMode KEYWORD2 +onChangeSpeedPercent KEYWORD2 +setTemperature KEYWORD2 +getTemperature KEYWORD2 +setHumidity KEYWORD2 +getHumidity KEYWORD2 +setContact KEYWORD2 +getContact KEYWORD2 +setPressure KEYWORD2 +getPressure KEYWORD2 +setOccupancy KEYWORD2 +getOccupancy KEYWORD2 +getControlSequence KEYWORD2 +getMinHeatSetpoint KEYWORD2 +getMaxHeatSetpoint KEYWORD2 +getMinCoolSetpoint KEYWORD2 +getMaxCoolSetpoint KEYWORD2 +getDeadBand KEYWORD2 +setCoolingSetpoint KEYWORD2 +getCoolingSetpoint KEYWORD2 +setHeatingSetpoint KEYWORD2 +getHeatingSetpoint KEYWORD2 +setCoolingHeatingSetpoints KEYWORD2 +setLocalTemperature KEYWORD2 +getLocalTemperature KEYWORD2 +getThermostatModeString KEYWORD2 +onChangeMode KEYWORD2 +onChangeLocalTemperature KEYWORD2 +onChangeCoolingSetpoint KEYWORD2 +onChangeHeatingSetpoint KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +MAX_BRIGHTNESS LITERAL1 +MAX_COLOR_TEMPERATURE LITERAL1 +MIN_COLOR_TEMPERATURE LITERAL1 +ATTR_SET LITERAL1 +ATTR_UPDATE LITERAL1 +MAX_SPEED LITERAL1 +MIN_SPEED LITERAL1 +OFF_SPEED LITERAL1 +FAN_MODE_OFF LITERAL1 +FAN_MODE_LOW LITERAL1 +FAN_MODE_MEDIUM LITERAL1 +FAN_MODE_HIGH LITERAL1 +FAN_MODE_ON LITERAL1 +FAN_MODE_AUTO LITERAL1 +FAN_MODE_SMART LITERAL1 +FAN_MODE_SEQ_OFF_LOW_MED_HIGH LITERAL1 +FAN_MODE_SEQ_OFF_LOW_HIGH LITERAL1 +FAN_MODE_SEQ_OFF_LOW_MED_HIGH_AUTO LITERAL1 +FAN_MODE_SEQ_OFF_LOW_HIGH_AUTO LITERAL1 +FAN_MODE_SEQ_OFF_HIGH_AUTO LITERAL1 +FAN_MODE_SEQ_OFF_HIGH LITERAL1 +THERMOSTAT_SEQ_OP_COOLING LITERAL1 +THERMOSTAT_SEQ_OP_COOLING_REHEAT LITERAL1 +THERMOSTAT_SEQ_OP_HEATING LITERAL1 +THERMOSTAT_SEQ_OP_HEATING_REHEAT LITERAL1 +THERMOSTAT_SEQ_OP_COOLING_HEATING LITERAL1 +THERMOSTAT_SEQ_OP_COOLING_HEATING_REHEAT LITERAL1 +THERMOSTAT_MODE_OFF LITERAL1 +THERMOSTAT_MODE_AUTO LITERAL1 +THERMOSTAT_MODE_COOL LITERAL1 +THERMOSTAT_MODE_HEAT LITERAL1 +THERMOSTAT_AUTO_MODE_DISABLED LITERAL1 +THERMOSTAT_AUTO_MODE_ENABLED LITERAL1 diff --git a/libraries/Matter/library.properties b/libraries/Matter/library.properties new file mode 100644 index 00000000000..ac9e0964ab5 --- /dev/null +++ b/libraries/Matter/library.properties @@ -0,0 +1,9 @@ +name=Matter +version=3.2.0 +author=Rodrigo Garcia | GitHub @SuGlider +maintainer=Rodrigo Garcia +sentence=Library for supporting Matter environment on ESP32. +paragraph=This library implements Matter accessories using WiFi network. +category=Communication +url=https://github.com/espressif/arduino-esp32/ +architectures=esp32 diff --git a/libraries/Matter/src/Matter.cpp b/libraries/Matter/src/Matter.cpp new file mode 100644 index 00000000000..af7c4c8657e --- /dev/null +++ b/libraries/Matter/src/Matter.cpp @@ -0,0 +1,191 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +using namespace esp_matter; +using namespace esp_matter::attribute; +using namespace esp_matter::endpoint; +using namespace esp_matter::identification; +using namespace chip::app::Clusters; + +constexpr auto k_timeout_seconds = 300; + +static bool _matter_has_started = false; +static node::config_t node_config; +static node_t *deviceNode = NULL; + +// 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 +) { + log_d("Attribute update callback: type: %u, endpoint: %u, cluster: %u, attribute: %u, val: %u", type, endpoint_id, cluster_id, attribute_id, val->val.u32); + esp_err_t err = ESP_OK; + MatterEndPoint *ep = (MatterEndPoint *)priv_data; // endpoint pointer to base class + switch (type) { + case PRE_UPDATE: // Callback before updating the value in the database + log_v("Attribute update callback: PRE_UPDATE"); + if (ep != NULL) { + err = ep->attributeChangeCB(endpoint_id, cluster_id, attribute_id, val) ? ESP_OK : ESP_FAIL; + } + break; + case POST_UPDATE: // Callback after updating the value in the database + log_v("Attribute update callback: POST_UPDATE"); + break; + case READ: // Callback for reading the attribute value. This is used when the `ATTRIBUTE_FLAG_OVERRIDE` is set. + log_v("Attribute update callback: READ"); + break; + case WRITE: // Callback for writing the attribute value. This is used when the `ATTRIBUTE_FLAG_OVERRIDE` is set. + log_v("Attribute update callback: WRITE"); + break; + default: log_v("Attribute update callback: Unknown type %d", type); + } + return err; +} + +// This callback is invoked when clients interact with the Identify Cluster. +// In the callback implementation, an endpoint can identify itself. (e.g., by flashing an LED or light). +static esp_err_t app_identification_cb(identification::callback_type_t type, uint16_t endpoint_id, uint8_t effect_id, uint8_t effect_variant, void *priv_data) { + log_d("Identification callback to endpoint %d: type: %u, effect: %u, variant: %u", endpoint_id, type, effect_id, effect_variant); + esp_err_t err = ESP_OK; + MatterEndPoint *ep = (MatterEndPoint *)priv_data; // endpoint pointer to base class + // Identify the endpoint sending a counter to the application + bool identifyIsActive = false; + + if (type == identification::callback_type_t::START) { + log_v("Identification callback: START"); + identifyIsActive = true; + } else if (type == identification::callback_type_t::EFFECT) { + log_v("Identification callback: EFFECT"); + } else if (type == identification::callback_type_t::STOP) { + identifyIsActive = false; + log_v("Identification callback: STOP"); + } + if (ep != NULL) { + err = ep->endpointIdentifyCB(endpoint_id, identifyIsActive) ? ESP_OK : ESP_FAIL; + } + + return err; +} + +// This callback is invoked for all Matter events. The application can handle the events as required. +static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) { + switch (event->Type) { + case chip::DeviceLayer::DeviceEventType::kInterfaceIpAddressChanged: + log_i( + "Interface %s Address changed", event->InterfaceIpAddressChanged.Type == chip::DeviceLayer::InterfaceIpChangeType::kIpV4_Assigned ? "IPv4" : "IPV6" + ); + break; + case chip::DeviceLayer::DeviceEventType::kCommissioningComplete: log_i("Commissioning complete"); break; + case chip::DeviceLayer::DeviceEventType::kFailSafeTimerExpired: log_i("Commissioning failed, fail safe timer expired"); break; + case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStarted: log_i("Commissioning session started"); break; + case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStopped: log_i("Commissioning session stopped"); break; + case chip::DeviceLayer::DeviceEventType::kCommissioningWindowOpened: log_i("Commissioning window opened"); break; + case chip::DeviceLayer::DeviceEventType::kCommissioningWindowClosed: log_i("Commissioning window closed"); break; + case chip::DeviceLayer::DeviceEventType::kFabricRemoved: + { + log_i("Fabric removed successfully"); + if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0) { + log_i("No fabric left, opening commissioning window"); + chip::CommissioningWindowManager &commissionMgr = chip::Server::GetInstance().GetCommissioningWindowManager(); + constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds16(k_timeout_seconds); + if (!commissionMgr.IsCommissioningWindowOpen()) { + // After removing last fabric, it does not remove the Wi-Fi credentials and still has IP connectivity so, only advertising on DNS-SD. + CHIP_ERROR err = commissionMgr.OpenBasicCommissioningWindow(kTimeoutSeconds, chip::CommissioningWindowAdvertisement::kDnssdOnly); + if (err != CHIP_NO_ERROR) { + log_e("Failed to open commissioning window, err:%" CHIP_ERROR_FORMAT, err.Format()); + } + } + } + break; + } + case chip::DeviceLayer::DeviceEventType::kFabricWillBeRemoved: log_i("Fabric will be removed"); break; + case chip::DeviceLayer::DeviceEventType::kFabricUpdated: log_i("Fabric is updated"); break; + case chip::DeviceLayer::DeviceEventType::kFabricCommitted: log_i("Fabric is committed"); break; + case chip::DeviceLayer::DeviceEventType::kBLEDeinitialized: log_i("BLE deinitialized and memory reclaimed"); break; + default: break; + } +} + +void ArduinoMatter::_init() { + if (_matter_has_started) { + return; + } + + // Create a Matter node and add the mandatory Root Node device type on endpoint 0 + // node handle can be used to add/modify other endpoints. + deviceNode = node::create(&node_config, app_attribute_update_cb, app_identification_cb); + if (deviceNode == nullptr) { + log_e("Failed to create Matter node"); + return; + } + + _matter_has_started = true; +} + +void ArduinoMatter::begin() { + if (!_matter_has_started) { + log_e("No Matter endpoint has been created. Please create an endpoint first."); + return; + } + + /* Matter start */ + esp_err_t err = esp_matter::start(app_event_cb); + if (err != ESP_OK) { + log_e("Failed to start Matter, err:%d", err); + _matter_has_started = false; + } +} + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +bool ArduinoMatter::isThreadConnected() { + return false; // Thread Network TBD +} +#endif + +bool ArduinoMatter::isDeviceCommissioned() { + return chip::Server::GetInstance().GetFabricTable().FabricCount() > 0; +} + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION +bool ArduinoMatter::isWiFiConnected() { + return chip::DeviceLayer::ConnectivityMgr().IsWiFiStationConnected(); +} +#endif + +bool ArduinoMatter::isDeviceConnected() { + bool retCode = false; +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + retCode |= ArduinoMatter::isThreadConnected(); +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION + retCode |= ArduinoMatter::isWiFiConnected(); +#endif + return retCode; +} + +void ArduinoMatter::decommission() { + esp_matter::factory_reset(); +} + +// Global Matter Object +ArduinoMatter Matter; + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/Matter.h b/libraries/Matter/src/Matter.h new file mode 100644 index 00000000000..e54ceb47e5e --- /dev/null +++ b/libraries/Matter/src/Matter.h @@ -0,0 +1,82 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace esp_matter; + +class ArduinoMatter { +public: + static inline String getManualPairingCode() { + // return the pairing code for manual pairing + return String("34970112332"); + } + static inline String getOnboardingQRCodeUrl() { + // return the URL for the QR code for onboarding + return String("https://project-chip.github.io/connectedhomeip/qrcode.html?data=MT:Y.K9042C00KA0648G00"); + } + static void begin(); + static bool isDeviceCommissioned(); +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION + static bool isWiFiConnected(); +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + static bool isThreadConnected(); +#endif + static bool isDeviceConnected(); + static void decommission(); + + // list of Matter EndPoints Friend Classes + friend class MatterGenericSwitch; + friend class MatterOnOffLight; + friend class MatterDimmableLight; + friend class MatterColorTemperatureLight; + friend class MatterColorLight; + friend class MatterEnhancedColorLight; + friend class MatterFan; + friend class MatterTemperatureSensor; + friend class MatterHumiditySensor; + friend class MatterContactSensor; + friend class MatterPressureSensor; + friend class MatterOccupancySensor; + friend class MatterOnOffPlugin; + friend class MatterThermostat; + +protected: + static void _init(); +}; + +extern ArduinoMatter Matter; + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndPoint.h b/libraries/Matter/src/MatterEndPoint.h new file mode 100644 index 00000000000..5baa4747d18 --- /dev/null +++ b/libraries/Matter/src/MatterEndPoint.h @@ -0,0 +1,122 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +using namespace esp_matter; + +// Matter Endpoint Base Class. Controls the endpoint ID and allows the child class to overwrite attribute change call +class MatterEndPoint { +public: + enum attrOperation_t { + ATTR_SET = false, + ATTR_UPDATE = true + }; + + uint16_t getEndPointId() { + return endpoint_id; + } + + void setEndPointId(uint16_t ep) { + endpoint_id = ep; + } + + // helper functions for attribute manipulation + esp_matter::attribute_t *getAttribute(uint32_t cluster_id, uint32_t attribute_id) { + if (endpoint_id == 0) { + log_e("Endpoint ID is not set"); + return NULL; + } + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + if (endpoint == NULL) { + log_e("Endpoint [%d] not found", endpoint_id); + return NULL; + } + cluster_t *cluster = cluster::get(endpoint, cluster_id); + if (cluster == NULL) { + log_e("Cluster [%d] not found", cluster_id); + return NULL; + } + esp_matter::attribute_t *attribute = attribute::get(cluster, attribute_id); + if (attribute == NULL) { + log_e("Attribute [%d] not found", attribute_id); + return NULL; + } + return attribute; + } + + // get the value of an attribute from its cluster id and attribute it + bool getAttributeVal(uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *attrVal) { + esp_matter::attribute_t *attribute = getAttribute(cluster_id, attribute_id); + if (attribute == NULL) { + return false; + } + if (attribute::get_val(attribute, attrVal) == ESP_OK) { + log_v("GET_VAL Success for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + return true; + } + log_e("GET_VAL FAILED! for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + return false; + } + + // set the value of an attribute from its cluster id and attribute it + bool setAttributeVal(uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *attrVal) { + esp_matter::attribute_t *attribute = getAttribute(cluster_id, attribute_id); + if (attribute == NULL) { + return false; + } + if (attribute::set_val(attribute, attrVal) == ESP_OK) { + log_v("SET_VAL Success for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + return true; + } + log_e("SET_VAL FAILED! for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + return false; + } + + // update the value of an attribute from its cluster id and attribute it + bool updateAttributeVal(uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *attrVal) { + if (attribute::update(endpoint_id, cluster_id, attribute_id, attrVal) == ESP_OK) { + log_v("Update Success for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + return true; + } + log_e("Update FAILED! for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + return false; + } + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + virtual bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) = 0; + + // This callback is invoked when clients interact with the Identify Cluster of an specific endpoint. + bool endpointIdentifyCB(uint16_t endpoint_id, bool identifyIsEnabled) { + if (_onEndPointIdentifyCB) { + return _onEndPointIdentifyCB(identifyIsEnabled); + } + return true; + } + // User callaback for the Identify Cluster functionality + using EndPointIdentifyCB = std::function; + void onIdentify(EndPointIdentifyCB onEndPointIdentifyCB) { + _onEndPointIdentifyCB = onEndPointIdentifyCB; + } + +protected: + uint16_t endpoint_id = 0; + EndPointIdentifyCB _onEndPointIdentifyCB = NULL; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp b/libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp new file mode 100644 index 00000000000..39d79e86325 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp @@ -0,0 +1,312 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +// endpoint for color light device +namespace esp_matter { +using namespace cluster; +namespace endpoint { +namespace rgb_color_light { +typedef struct config { + cluster::descriptor::config_t descriptor; + cluster::identify::config_t identify; + cluster::groups::config_t groups; + cluster::scenes_management::config_t scenes_management; + cluster::on_off::config_t on_off; + cluster::level_control::config_t level_control; + cluster::color_control::config_t color_control; +} config_t; + +uint32_t get_device_type_id() { + return ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_ID; +} + +uint8_t get_device_type_version() { + return ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_VERSION; +} + +esp_err_t add(endpoint_t *endpoint, config_t *config) { + if (!endpoint) { + log_e("Endpoint cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + esp_err_t err = add_device_type(endpoint, get_device_type_id(), get_device_type_version()); + if (err != ESP_OK) { + log_e("Failed to add device type id:%" PRIu32 ",err: %d", get_device_type_id(), err); + return err; + } + + descriptor::create(endpoint, &(config->descriptor), CLUSTER_FLAG_SERVER); + cluster_t *identify_cluster = identify::create(endpoint, &(config->identify), CLUSTER_FLAG_SERVER); + identify::command::create_trigger_effect(identify_cluster); + groups::create(endpoint, &(config->groups), CLUSTER_FLAG_SERVER); + cluster_t *scenes_cluster = scenes_management::create(endpoint, &(config->scenes_management), CLUSTER_FLAG_SERVER); + scenes_management::command::create_copy_scene(scenes_cluster); + scenes_management::command::create_copy_scene_response(scenes_cluster); + + on_off::create(endpoint, &(config->on_off), CLUSTER_FLAG_SERVER, on_off::feature::lighting::get_id()); + level_control::create( + endpoint, &(config->level_control), CLUSTER_FLAG_SERVER, level_control::feature::on_off::get_id() | level_control::feature::lighting::get_id() + ); + color_control::create(endpoint, &(config->color_control), CLUSTER_FLAG_SERVER, color_control::feature::hue_saturation::get_id()); + return ESP_OK; +} + +endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { + endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + add(endpoint, config); + return endpoint; +} +} // namespace rgb_color_light +} // namespace endpoint +} // namespace esp_matter + +bool MatterColorLight::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter RGB Color Light device has not begun."); + return false; + } + + log_d( + "RGB Color Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u, type: %u", endpoint_id, cluster_id, attribute_id, val->val.u32, + val->type + ); + + if (endpoint_id == getEndPointId()) { + switch (cluster_id) { + case OnOff::Id: + if (attribute_id == OnOff::Attributes::OnOff::Id) { + log_d("RGB Color Light On/Off State changed to %d", val->val.b); + if (_onChangeOnOffCB != NULL) { + ret &= _onChangeOnOffCB(val->val.b); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(val->val.b, colorHSV); + } + if (ret == true) { + onOffState = val->val.b; + } + } + break; + case LevelControl::Id: + if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) { + log_d("RGB Color Light Brightness changed to %d", val->val.u8); + if (_onChangeColorCB != NULL) { + ret &= _onChangeColorCB({colorHSV.h, colorHSV.s, val->val.u8}); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(onOffState, {colorHSV.h, colorHSV.s, val->val.u8}); + } + if (ret == true) { + colorHSV.v = val->val.u8; + } + } + break; + case ColorControl::Id: + { + if (attribute_id != ColorControl::Attributes::CurrentHue::Id && attribute_id != ColorControl::Attributes::CurrentSaturation::Id) { + log_i("Color Control Attribute ID [%x] not processed.", attribute_id); + break; + } + espHsvColor_t hsvColor = {colorHSV.h, colorHSV.s, colorHSV.v}; + if (attribute_id == ColorControl::Attributes::CurrentHue::Id) { + log_d("RGB Light Hue changed to %d", val->val.u8); + hsvColor.h = val->val.u8; + } else { // attribute_id == ColorControl::Attributes::CurrentSaturation::Id) + log_d("RGB Light Saturation changed to %d", val->val.u8); + hsvColor.s = val->val.u8; + } + if (_onChangeColorCB != NULL) { + ret &= _onChangeColorCB(hsvColor); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(onOffState, hsvColor); + } + if (ret == true) { + colorHSV = {hsvColor.h, hsvColor.s, hsvColor.v}; + } + break; + } + } + } + return ret; +} + +MatterColorLight::MatterColorLight() {} + +MatterColorLight::~MatterColorLight() { + end(); +} + +bool MatterColorLight::begin(bool initialState, espHsvColor_t _colorHSV) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter RGB Color Light with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + rgb_color_light::config_t light_config; + light_config.on_off.on_off = initialState; + light_config.on_off.lighting.start_up_on_off = nullptr; + onOffState = initialState; + + light_config.level_control.current_level = _colorHSV.v; + light_config.level_control.lighting.start_up_current_level = nullptr; + + light_config.color_control.color_mode = (uint8_t)ColorControl::ColorMode::kCurrentHueAndCurrentSaturation; + light_config.color_control.enhanced_color_mode = (uint8_t)ColorControl::ColorMode::kCurrentHueAndCurrentSaturation; + light_config.color_control.hue_saturation.current_hue = _colorHSV.h; + light_config.color_control.hue_saturation.current_saturation = _colorHSV.s; + colorHSV = {_colorHSV.h, _colorHSV.s, _colorHSV.v}; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = rgb_color_light::create(node::get(), &light_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create RGB Color light endpoint"); + return false; + } + + setEndPointId(endpoint::get_id(endpoint)); + log_i("RGB Color Light created with endpoint_id %d", getEndPointId()); + + /* Mark deferred persistence for some attributes that might be changed rapidly */ + cluster_t *level_control_cluster = cluster::get(endpoint, LevelControl::Id); + esp_matter::attribute_t *current_level_attribute = attribute::get(level_control_cluster, LevelControl::Attributes::CurrentLevel::Id); + attribute::set_deferred_persistence(current_level_attribute); + + started = true; + return true; +} + +void MatterColorLight::end() { + started = false; +} + +bool MatterColorLight::setOnOff(bool newState) { + if (!started) { + log_e("Matter RGB Color Light device has not begun."); + return false; + } + + // avoid processing if there was no change + if (onOffState == newState) { + return true; + } + + onOffState = newState; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, OnOff::Id); + esp_matter::attribute_t *attribute = attribute::get(cluster, OnOff::Attributes::OnOff::Id); + + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + + if (val.val.b != onOffState) { + val.val.b = onOffState; + attribute::update(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, &val); + } + return true; +} + +void MatterColorLight::updateAccessory() { + if (_onChangeCB != NULL) { + _onChangeCB(onOffState, colorHSV); + } +} + +bool MatterColorLight::getOnOff() { + return onOffState; +} + +bool MatterColorLight::toggle() { + return setOnOff(!onOffState); +} + +bool MatterColorLight::setColorRGB(espRgbColor_t _rgbColor) { + return setColorHSV(espRgbColorToHsvColor(_rgbColor)); +} + +espRgbColor_t MatterColorLight::getColorRGB() { + return espHsvColorToRgbColor(colorHSV); +} + +bool MatterColorLight::setColorHSV(espHsvColor_t _hsvColor) { + + if (!started) { + log_w("Matter RGB Color Light device has not begun."); + return false; + } + + // avoid processing if there was no change + if (colorHSV.h == _hsvColor.h && colorHSV.s == _hsvColor.s && colorHSV.v == _hsvColor.v) { + return true; + } + + colorHSV = {_hsvColor.h, _hsvColor.s, _hsvColor.v}; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, ColorControl::Id); + // update hue + esp_matter::attribute_t *attribute = attribute::get(cluster, ColorControl::Attributes::CurrentHue::Id); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + if (val.val.u8 != colorHSV.h) { + val.val.u8 = colorHSV.h; + attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentHue::Id, &val); + } + // update saturation + attribute = attribute::get(cluster, ColorControl::Attributes::CurrentSaturation::Id); + val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + if (val.val.u8 != colorHSV.s) { + val.val.u8 = colorHSV.s; + attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentSaturation::Id, &val); + } + // update value (brightness) + cluster = cluster::get(endpoint, LevelControl::Id); + attribute = attribute::get(cluster, LevelControl::Attributes::CurrentLevel::Id); + val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + if (val.val.u8 != colorHSV.v) { + val.val.u8 = colorHSV.v; + attribute::update(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, &val); + } + return true; +} + +espHsvColor_t MatterColorLight::getColorHSV() { + return colorHSV; +} + +MatterColorLight::operator bool() { + return getOnOff(); +} + +void MatterColorLight::operator=(bool newState) { + setOnOff(newState); +} +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h new file mode 100644 index 00000000000..99449addd50 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h @@ -0,0 +1,75 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterColorLight : public MatterEndPoint { +public: + MatterColorLight(); + ~MatterColorLight(); + // default initial state is off, color is red 12% intensity HSV(0, 254, 31) + virtual bool begin(bool initialState = false, espHsvColor_t colorHSV = {0, 254, 31}); + // this will just stop processing Light Matter events + void end(); + + bool setOnOff(bool newState); // returns true if successful + bool getOnOff(); // returns current light state + bool toggle(); // returns true if successful + + bool setColorRGB(espRgbColor_t rgbColor); // returns true if successful + espRgbColor_t getColorRGB(); // returns current RGB Color + bool setColorHSV(espHsvColor_t hsvColor); // returns true if successful + espHsvColor_t getColorHSV(); // returns current HSV Color + + // User Callback for whenever the Light On/Off state is changed by the Matter Controller + using EndPointOnOffCB = std::function; + void onChangeOnOff(EndPointOnOffCB onChangeCB) { + _onChangeOnOffCB = onChangeCB; + } + // User Callback for whenever the HSV Color value is changed by the Matter Controller + using EndPointRGBColorCB = std::function; + void onChangeColorHSV(EndPointRGBColorCB onChangeCB) { + _onChangeColorCB = onChangeCB; + } + + // User Callback for whenever any parameter is changed by the Matter Controller + using EndPointCB = std::function; + void onChange(EndPointCB onChangeCB) { + _onChangeCB = onChangeCB; + } + + // used to update the state of the light using the current Matter Light internal state + // It is necessary to set a user callback function using onChange() to handle the physical light state + void updateAccessory(); + + operator bool(); // returns current on/off light state + void operator=(bool state); // turns light on or off + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) + espHsvColor_t colorHSV = {0, 0, 0}; // default initial color HSV is black, but it can be changed by begin(bool, espHsvColor_t) + EndPointOnOffCB _onChangeOnOffCB = NULL; + EndPointRGBColorCB _onChangeColorCB = NULL; + EndPointCB _onChangeCB = NULL; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp b/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp new file mode 100644 index 00000000000..3c4fccfa046 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp @@ -0,0 +1,250 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +bool MatterColorTemperatureLight::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter Temperature Light device has not begun."); + return false; + } + + log_d("Temperature Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + + if (endpoint_id == getEndPointId()) { + switch (cluster_id) { + case OnOff::Id: + if (attribute_id == OnOff::Attributes::OnOff::Id) { + log_d("Temperature Light On/Off State changed to %d", val->val.b); + if (_onChangeOnOffCB != NULL) { + ret &= _onChangeOnOffCB(val->val.b); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(val->val.b, brightnessLevel, colorTemperatureLevel); + } + if (ret == true) { + onOffState = val->val.b; + } + } + break; + case LevelControl::Id: + if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) { + log_d("Temperature Light Brightness changed to %d", val->val.u8); + if (_onChangeBrightnessCB != NULL) { + ret &= _onChangeBrightnessCB(val->val.u8); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(onOffState, val->val.u8, colorTemperatureLevel); + } + if (ret == true) { + brightnessLevel = val->val.u8; + } + } + break; + case ColorControl::Id: + if (attribute_id == ColorControl::Attributes::ColorTemperatureMireds::Id) { + log_d("Temperature Light Temperature changed to %d", val->val.u16); + if (_onChangeTemperatureCB != NULL) { + ret &= _onChangeTemperatureCB(val->val.u16); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(onOffState, brightnessLevel, val->val.u16); + } + if (ret == true) { + colorTemperatureLevel = val->val.u16; + } + } + break; + } + } + return ret; +} + +MatterColorTemperatureLight::MatterColorTemperatureLight() {} + +MatterColorTemperatureLight::~MatterColorTemperatureLight() { + end(); +} + +bool MatterColorTemperatureLight::begin(bool initialState, uint8_t brightness, uint16_t ColorTemperature) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter Temperature Light with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + color_temperature_light::config_t light_config; + light_config.on_off.on_off = initialState; + light_config.on_off.lighting.start_up_on_off = nullptr; + onOffState = initialState; + + light_config.level_control.current_level = brightness; + light_config.level_control.lighting.start_up_current_level = nullptr; + brightnessLevel = 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.color_temperature_mireds = ColorTemperature; + light_config.color_control.color_temperature.startup_color_temperature_mireds = nullptr; + colorTemperatureLevel = ColorTemperature; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = color_temperature_light::create(node::get(), &light_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create Temperature Light endpoint"); + return false; + } + + setEndPointId(endpoint::get_id(endpoint)); + log_i("Temperature Light created with endpoint_id %d", getEndPointId()); + + /* Mark deferred persistence for some attributes that might be changed rapidly */ + cluster_t *level_control_cluster = cluster::get(endpoint, LevelControl::Id); + esp_matter::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); + esp_matter::attribute_t *color_temp_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::ColorTemperatureMireds::Id); + attribute::set_deferred_persistence(color_temp_attribute); + + started = true; + return true; +} + +void MatterColorTemperatureLight::end() { + started = false; +} + +bool MatterColorTemperatureLight::setOnOff(bool newState) { + if (!started) { + log_e("Matter Temperature Light device has not begun."); + return false; + } + + // avoid processing if there was no change + if (onOffState == newState) { + return true; + } + + onOffState = newState; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, OnOff::Id); + esp_matter::attribute_t *attribute = attribute::get(cluster, OnOff::Attributes::OnOff::Id); + + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + + if (val.val.b != onOffState) { + val.val.b = onOffState; + attribute::update(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, &val); + } + return true; +} + +void MatterColorTemperatureLight::updateAccessory() { + if (_onChangeCB != NULL) { + _onChangeCB(onOffState, brightnessLevel, colorTemperatureLevel); + } +} + +bool MatterColorTemperatureLight::getOnOff() { + return onOffState; +} + +bool MatterColorTemperatureLight::toggle() { + return setOnOff(!onOffState); +} + +bool MatterColorTemperatureLight::setBrightness(uint8_t newBrightness) { + if (!started) { + log_w("Matter Temperature Light device has not begun."); + return false; + } + + // avoid processing if there was no change + if (brightnessLevel == newBrightness) { + return true; + } + + brightnessLevel = newBrightness; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, LevelControl::Id); + esp_matter::attribute_t *attribute = attribute::get(cluster, LevelControl::Attributes::CurrentLevel::Id); + + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + + if (val.val.u8 != brightnessLevel) { + val.val.u8 = brightnessLevel; + attribute::update(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, &val); + } + return true; +} + +uint8_t MatterColorTemperatureLight::getBrightness() { + return brightnessLevel; +} + +bool MatterColorTemperatureLight::setColorTemperature(uint16_t newTemperature) { + if (!started) { + log_w("Matter Temperature Light device has not begun."); + return false; + } + + // avoid processing if there was no change + if (colorTemperatureLevel == newTemperature) { + return true; + } + + colorTemperatureLevel = newTemperature; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, ColorControl::Id); + esp_matter::attribute_t *attribute = attribute::get(cluster, ColorControl::Attributes::ColorTemperatureMireds::Id); + + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + + if (val.val.u16 != colorTemperatureLevel) { + val.val.u16 = colorTemperatureLevel; + attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::ColorTemperatureMireds::Id, &val); + } + return true; +} + +uint16_t MatterColorTemperatureLight::getColorTemperature() { + return colorTemperatureLevel; +} + +MatterColorTemperatureLight::operator bool() { + return getOnOff(); +} + +void MatterColorTemperatureLight::operator=(bool newState) { + setOnOff(newState); +} +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h b/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h new file mode 100644 index 00000000000..539bc386e92 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h @@ -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. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterColorTemperatureLight : public MatterEndPoint { +public: + static const uint8_t MAX_BRIGHTNESS = 255; + static const uint16_t MAX_COLOR_TEMPERATURE = 500; + static const uint16_t MIN_COLOR_TEMPERATURE = 100; + + MatterColorTemperatureLight(); + ~MatterColorTemperatureLight(); + // default initial state is off, brightness is 64 (25%) and temperature is 370 (Soft White) + virtual bool begin(bool initialState = false, uint8_t brightness = 64, uint16_t colorTemperature = 370); + // this will just stop processing Light Matter events + void end(); + + bool setOnOff(bool newState); // returns true if successful + bool getOnOff(); // returns current light state + bool toggle(); // returns true if successful + + bool setBrightness(uint8_t newBrightness); // returns true if successful + uint8_t getBrightness(); // returns current brightness + + bool setColorTemperature(uint16_t newTemperature); // returns true if successful + uint16_t getColorTemperature(); // returns current temperature + + // User Callback for whenever the Light On/Off state is changed by the Matter Controller + using EndPointOnOffCB = std::function; + void onChangeOnOff(EndPointOnOffCB onChangeCB) { + _onChangeOnOffCB = onChangeCB; + } + + // User Callback for whenever the Light brightness value [0..255] is changed by the Matter Controller + using EndPointBrightnessCB = std::function; + void onChangeBrightness(EndPointBrightnessCB onChangeCB) { + _onChangeBrightnessCB = onChangeCB; + } + + // User Callbqck for whenever the Light temperature value is changed by the Matter Controller + using EndPointTemperatureCB = std::function; + void onChangeColorTemperature(EndPointTemperatureCB onChangeCB) { + _onChangeTemperatureCB = onChangeCB; + } + + // User Callback for whenever any parameter is changed by the Matter Controller + using EndPointCB = std::function; + void onChange(EndPointCB onChangeCB) { + _onChangeCB = onChangeCB; + } + + // used to update the state of the light using the current Matter Light internal state + // It is necessary to set a user callback function using onChange() to handle the physical light state + void updateAccessory(); + + operator bool(); // returns current on/off light state + void operator=(bool state); // turns light on or off + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) + uint8_t brightnessLevel = 0; // default initial brightness is 0, but it can be changed by begin(bool, uint8_t) + uint16_t colorTemperatureLevel = 0; // default initial color temperature is 0, but it can be changed by begin(bool, uint8_t, uint16_t) + EndPointOnOffCB _onChangeOnOffCB = NULL; + EndPointBrightnessCB _onChangeBrightnessCB = NULL; + EndPointTemperatureCB _onChangeTemperatureCB = NULL; + EndPointCB _onChangeCB = NULL; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterContactSensor.cpp b/libraries/Matter/src/MatterEndpoints/MatterContactSensor.cpp new file mode 100644 index 00000000000..17b0fe7a247 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterContactSensor.cpp @@ -0,0 +1,103 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +bool MatterContactSensor::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter Contact Sensor device has not begun."); + return false; + } + + log_d("Contact Sensor Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + return ret; +} + +MatterContactSensor::MatterContactSensor() {} + +MatterContactSensor::~MatterContactSensor() { + end(); +} + +bool MatterContactSensor::begin(bool _contactState) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter Contact Sensor with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + contact_sensor::config_t contact_sensor_config; + contact_sensor_config.boolean_state.state_value = _contactState; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = contact_sensor::create(node::get(), &contact_sensor_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create Contact Sensor endpoint"); + return false; + } + contactState = _contactState; + setEndPointId(endpoint::get_id(endpoint)); + log_i("Contact Sensor created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterContactSensor::end() { + started = false; +} + +bool MatterContactSensor::setContact(bool _contactState) { + if (!started) { + log_e("Matter Contact Sensor device has not begun."); + return false; + } + + // avoid processing if there was no change + if (contactState == _contactState) { + return true; + } + + esp_matter_attr_val_t contactVal = esp_matter_invalid(NULL); + + if (!getAttributeVal(BooleanState::Id, BooleanState::Attributes::StateValue::Id, &contactVal)) { + log_e("Failed to get Contact Sensor Attribute."); + return false; + } + if (contactVal.val.u8 != _contactState) { + contactVal.val.u8 = _contactState; + bool ret; + ret = updateAttributeVal(BooleanState::Id, BooleanState::Attributes::StateValue::Id, &contactVal); + if (!ret) { + log_e("Failed to update Contact Sensor Attribute."); + return false; + } + contactState = _contactState; + } + log_v("Contact Sensor set to %s", _contactState ? "Closed" : "Open"); + + return true; +} + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterContactSensor.h b/libraries/Matter/src/MatterEndpoints/MatterContactSensor.h new file mode 100644 index 00000000000..257da785e53 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterContactSensor.h @@ -0,0 +1,54 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterContactSensor : public MatterEndPoint { +public: + MatterContactSensor(); + ~MatterContactSensor(); + // begin Matter Contact Sensor endpoint with initial contact state + bool begin(bool _contactState = false); + // this will just stop processing Contact Sensor Matter events + void end(); + + // set the contact state + bool setContact(bool _contactState); + // returns the contact state + bool getContact() { + return contactState; + } + + // bool conversion operator + void operator=(bool _contactState) { + setContact(_contactState); + } + // bool conversion operator + operator bool() { + return getContact(); + } + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + bool contactState = false; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp b/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp new file mode 100644 index 00000000000..5167cf1f21c --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp @@ -0,0 +1,194 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +bool MatterDimmableLight::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter DimmableLight device has not begun."); + return false; + } + + log_d("Dimmable Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + + if (endpoint_id == getEndPointId()) { + switch (cluster_id) { + case OnOff::Id: + if (attribute_id == OnOff::Attributes::OnOff::Id) { + log_d("DimmableLight On/Off State changed to %d", val->val.b); + if (_onChangeOnOffCB != NULL) { + ret &= _onChangeOnOffCB(val->val.b); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(val->val.b, brightnessLevel); + } + if (ret == true) { + onOffState = val->val.b; + } + } + break; + case LevelControl::Id: + if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) { + log_d("DimmableLight Brightness changed to %d", val->val.u8); + if (_onChangeBrightnessCB != NULL) { + ret &= _onChangeBrightnessCB(val->val.u8); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(onOffState, val->val.u8); + } + if (ret == true) { + brightnessLevel = val->val.u8; + } + } + break; + } + } + return ret; +} + +MatterDimmableLight::MatterDimmableLight() {} + +MatterDimmableLight::~MatterDimmableLight() { + end(); +} + +bool MatterDimmableLight::begin(bool initialState, uint8_t brightness) { + ArduinoMatter::_init(); + if (getEndPointId() != 0) { + log_e("Matter Dimmable Light with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + dimmable_light::config_t light_config; + light_config.on_off.on_off = initialState; + light_config.on_off.lighting.start_up_on_off = nullptr; + onOffState = initialState; + + light_config.level_control.current_level = brightness; + light_config.level_control.lighting.start_up_current_level = nullptr; + brightnessLevel = brightness; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = dimmable_light::create(node::get(), &light_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create dimmable light endpoint"); + return false; + } + + setEndPointId(endpoint::get_id(endpoint)); + log_i("Dimmable Light created with endpoint_id %d", getEndPointId()); + + /* Mark deferred persistence for some attributes that might be changed rapidly */ + cluster_t *level_control_cluster = cluster::get(endpoint, LevelControl::Id); + esp_matter::attribute_t *current_level_attribute = attribute::get(level_control_cluster, LevelControl::Attributes::CurrentLevel::Id); + attribute::set_deferred_persistence(current_level_attribute); + + started = true; + return true; +} + +void MatterDimmableLight::end() { + started = false; +} + +bool MatterDimmableLight::setOnOff(bool newState) { + if (!started) { + log_e("Matter Dimmable Light device has not begun."); + return false; + } + + // avoid processing if there was no change + if (onOffState == newState) { + return true; + } + + onOffState = newState; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, OnOff::Id); + esp_matter::attribute_t *attribute = attribute::get(cluster, OnOff::Attributes::OnOff::Id); + + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + + if (val.val.b != onOffState) { + val.val.b = onOffState; + attribute::update(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, &val); + } + return true; +} + +void MatterDimmableLight::updateAccessory() { + if (_onChangeCB != NULL) { + _onChangeCB(onOffState, brightnessLevel); + } +} + +bool MatterDimmableLight::getOnOff() { + return onOffState; +} + +bool MatterDimmableLight::toggle() { + return setOnOff(!onOffState); +} + +bool MatterDimmableLight::setBrightness(uint8_t newBrightness) { + if (!started) { + log_w("Matter Dimmable Light device has not begun."); + return false; + } + + // avoid processing if there was no change + if (brightnessLevel == newBrightness) { + return true; + } + + brightnessLevel = newBrightness; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, LevelControl::Id); + esp_matter::attribute_t *attribute = attribute::get(cluster, LevelControl::Attributes::CurrentLevel::Id); + + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + + if (val.val.u8 != brightnessLevel) { + val.val.u8 = brightnessLevel; + attribute::update(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, &val); + } + return true; +} + +uint8_t MatterDimmableLight::getBrightness() { + return brightnessLevel; +} + +MatterDimmableLight::operator bool() { + return getOnOff(); +} + +void MatterDimmableLight::operator=(bool newState) { + setOnOff(newState); +} +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.h b/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.h new file mode 100644 index 00000000000..4497edd2fe2 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.h @@ -0,0 +1,75 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterDimmableLight : public MatterEndPoint { +public: + static const uint8_t MAX_BRIGHTNESS = 255; + + MatterDimmableLight(); + ~MatterDimmableLight(); + // default initial state is off and brightness is 64 (25%) + virtual bool begin(bool initialState = false, uint8_t brightness = 64); + // this will just stop processing Light Matter events + void end(); + + bool setOnOff(bool newState); // returns true if successful + bool getOnOff(); // returns current light state + bool toggle(); // returns true if successful + + bool setBrightness(uint8_t newBrightness); // returns true if successful + uint8_t getBrightness(); // returns current brightness + + // User Callback for whenever the Light On/Off state is changed by the Matter Controller + using EndPointOnOffCB = std::function; + void onChangeOnOff(EndPointOnOffCB onChangeCB) { + _onChangeOnOffCB = onChangeCB; + } + + // User Callback for whenever the Light brightness value [0..255] is changed by the Matter Controller + using EndPointBrightnessCB = std::function; + void onChangeBrightness(EndPointBrightnessCB onChangeCB) { + _onChangeBrightnessCB = onChangeCB; + } + + // User Callback for whenever any parameter is changed by the Matter Controller + using EndPointCB = std::function; + void onChange(EndPointCB onChangeCB) { + _onChangeCB = onChangeCB; + } + + // used to update the state of the light using the current Matter Light internal state + // It is necessary to set a user callback function using onChange() to handle the physical light state + void updateAccessory(); + + operator bool(); // returns current on/off light state + void operator=(bool state); // turns light on or off + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) + uint8_t brightnessLevel = 0; // default initial brightness is 0, but it can be changed by begin(bool, uint8_t) + EndPointOnOffCB _onChangeOnOffCB = NULL; + EndPointBrightnessCB _onChangeBrightnessCB = NULL; + EndPointCB _onChangeCB = NULL; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp b/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp new file mode 100644 index 00000000000..9b245fb9408 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp @@ -0,0 +1,394 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +// endpoint for enhanced color light device +namespace esp_matter { +using namespace cluster; +namespace endpoint { +namespace enhanced_color_light { +typedef struct config { + cluster::descriptor::config_t descriptor; + cluster::identify::config_t identify; + cluster::groups::config_t groups; + cluster::scenes_management::config_t scenes_management; + cluster::on_off::config_t on_off; + cluster::level_control::config_t level_control; + cluster::color_control::config_t color_control; +} config_t; + +uint32_t get_device_type_id() { + return ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_ID; +} + +uint8_t get_device_type_version() { + return ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_VERSION; +} + +esp_err_t add(endpoint_t *endpoint, config_t *config) { + if (!endpoint) { + log_e("Endpoint cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + esp_err_t err = add_device_type(endpoint, get_device_type_id(), get_device_type_version()); + if (err != ESP_OK) { + log_e("Failed to add device type id:%" PRIu32 ",err: %d", get_device_type_id(), err); + return err; + } + + descriptor::create(endpoint, &(config->descriptor), CLUSTER_FLAG_SERVER); + cluster_t *identify_cluster = identify::create(endpoint, &(config->identify), CLUSTER_FLAG_SERVER); + identify::command::create_trigger_effect(identify_cluster); + groups::create(endpoint, &(config->groups), CLUSTER_FLAG_SERVER); + cluster_t *scenes_cluster = scenes_management::create(endpoint, &(config->scenes_management), CLUSTER_FLAG_SERVER); + scenes_management::command::create_copy_scene(scenes_cluster); + scenes_management::command::create_copy_scene_response(scenes_cluster); + + on_off::create(endpoint, &(config->on_off), CLUSTER_FLAG_SERVER, on_off::feature::lighting::get_id()); + level_control::create( + endpoint, &(config->level_control), CLUSTER_FLAG_SERVER, level_control::feature::on_off::get_id() | level_control::feature::lighting::get_id() + ); + color_control::create( + endpoint, &(config->color_control), CLUSTER_FLAG_SERVER, + color_control::feature::hue_saturation::get_id() | color_control::feature::color_temperature::get_id() + ); + return ESP_OK; +} + +endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { + endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + add(endpoint, config); + return endpoint; +} +} // namespace enhanced_color_light +} // namespace endpoint +} // namespace esp_matter + +bool MatterEnhancedColorLight::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter Enhanced ColorLight device has not begun."); + return false; + } + + log_d( + "Enhanced ColorAttr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u, type: %u", endpoint_id, cluster_id, attribute_id, val->val.u32, + val->type + ); + + if (endpoint_id == getEndPointId()) { + switch (cluster_id) { + case OnOff::Id: + if (attribute_id == OnOff::Attributes::OnOff::Id) { + log_d("Enhanced ColorLight On/Off State changed to %d", val->val.b); + if (_onChangeOnOffCB != NULL) { + ret &= _onChangeOnOffCB(val->val.b); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(val->val.b, colorHSV, brightnessLevel, colorTemperatureLevel); + } + if (ret == true) { + onOffState = val->val.b; + } + } + break; + case LevelControl::Id: + if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) { + log_d("Enhanced ColorLight Brightness changed to %d", val->val.u8); + if (_onChangeBrightnessCB != NULL) { + ret &= _onChangeBrightnessCB(val->val.u8); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(onOffState, colorHSV, val->val.u8, colorTemperatureLevel); + } + if (ret == true) { + colorHSV.v = val->val.u8; + } + } + break; + case ColorControl::Id: + { + if (attribute_id == ColorControl::Attributes::ColorTemperatureMireds::Id) { + log_d("Enhanced ColorLight Temperature changed to %d", val->val.u16); + if (_onChangeTemperatureCB != NULL) { + ret &= _onChangeTemperatureCB(val->val.u16); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(onOffState, colorHSV, brightnessLevel, val->val.u16); + } + if (ret == true) { + colorTemperatureLevel = val->val.u16; + } + break; + } + if (attribute_id != ColorControl::Attributes::CurrentHue::Id && attribute_id != ColorControl::Attributes::CurrentSaturation::Id) { + log_i("Color Control Attribute ID [%x] not processed.", attribute_id); + break; + } + espHsvColor_t hsvColor = {colorHSV.h, colorHSV.s, colorHSV.v}; + if (attribute_id == ColorControl::Attributes::CurrentHue::Id) { + log_d("Enhanced ColorLight Hue changed to %d", val->val.u8); + hsvColor.h = val->val.u8; + } else { // attribute_id == ColorControl::Attributes::CurrentSaturation::Id) + log_d("Enhanced ColorLight Saturation changed to %d", val->val.u8); + hsvColor.s = val->val.u8; + } + if (_onChangeColorCB != NULL) { + ret &= _onChangeColorCB(hsvColor); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(onOffState, hsvColor, brightnessLevel, colorTemperatureLevel); + } + if (ret == true) { + colorHSV = {hsvColor.h, hsvColor.s, hsvColor.v}; + } + break; + } + } + } + return ret; +} + +MatterEnhancedColorLight::MatterEnhancedColorLight() {} + +MatterEnhancedColorLight::~MatterEnhancedColorLight() { + end(); +} + +bool MatterEnhancedColorLight::begin(bool initialState, espHsvColor_t _colorHSV, uint8_t brightness, uint16_t ColorTemperature) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter Enhanced ColorLight with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + enhanced_color_light::config_t light_config; + light_config.on_off.on_off = initialState; + light_config.on_off.lighting.start_up_on_off = nullptr; + onOffState = initialState; + + light_config.level_control.current_level = brightness; + light_config.level_control.lighting.start_up_current_level = nullptr; + + light_config.color_control.enhanced_color_mode = (uint8_t)ColorControl::ColorMode::kColorTemperature; + light_config.color_control.color_temperature.color_temperature_mireds = ColorTemperature; + light_config.color_control.color_temperature.startup_color_temperature_mireds = nullptr; + colorTemperatureLevel = ColorTemperature; + + light_config.color_control.color_mode = (uint8_t)ColorControl::ColorMode::kCurrentHueAndCurrentSaturation; + light_config.color_control.hue_saturation.current_hue = _colorHSV.h; + light_config.color_control.hue_saturation.current_saturation = _colorHSV.s; + colorHSV = {_colorHSV.h, _colorHSV.s, _colorHSV.v}; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = enhanced_color_light::create(node::get(), &light_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create Enhanced ColorLight endpoint"); + return false; + } + + setEndPointId(endpoint::get_id(endpoint)); + log_i("Enhanced ColorLight created with endpoint_id %d", getEndPointId()); + + /* Mark deferred persistence for some attributes that might be changed rapidly */ + cluster_t *level_control_cluster = cluster::get(endpoint, LevelControl::Id); + esp_matter::attribute_t *current_level_attribute = attribute::get(level_control_cluster, LevelControl::Attributes::CurrentLevel::Id); + attribute::set_deferred_persistence(current_level_attribute); + + started = true; + return true; +} + +void MatterEnhancedColorLight::end() { + started = false; +} + +bool MatterEnhancedColorLight::setOnOff(bool newState) { + if (!started) { + log_e("Matter Enhanced ColorLight device has not begun."); + return false; + } + + // avoid processing if there was no change + if (onOffState == newState) { + return true; + } + + onOffState = newState; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, OnOff::Id); + esp_matter::attribute_t *attribute = attribute::get(cluster, OnOff::Attributes::OnOff::Id); + + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + + if (val.val.b != onOffState) { + val.val.b = onOffState; + attribute::update(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, &val); + } + return true; +} + +void MatterEnhancedColorLight::updateAccessory() { + if (_onChangeCB != NULL) { + _onChangeCB(onOffState, colorHSV, brightnessLevel, colorTemperatureLevel); + } +} + +bool MatterEnhancedColorLight::getOnOff() { + return onOffState; +} + +bool MatterEnhancedColorLight::toggle() { + return setOnOff(!onOffState); +} + +bool MatterEnhancedColorLight::setBrightness(uint8_t newBrightness) { + if (!started) { + log_w("Matter Enhanced ColorLight device has not begun."); + return false; + } + + // avoid processing if there was no change + if (brightnessLevel == newBrightness) { + return true; + } + + brightnessLevel = newBrightness; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, LevelControl::Id); + esp_matter::attribute_t *attribute = attribute::get(cluster, LevelControl::Attributes::CurrentLevel::Id); + + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + + if (val.val.u8 != brightnessLevel) { + val.val.u8 = brightnessLevel; + attribute::update(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, &val); + } + return true; +} + +uint8_t MatterEnhancedColorLight::getBrightness() { + return brightnessLevel; +} + +bool MatterEnhancedColorLight::setColorTemperature(uint16_t newTemperature) { + if (!started) { + log_w("Matter Enhanced ColorLight device has not begun."); + return false; + } + + // avoid processing if there was no change + if (colorTemperatureLevel == newTemperature) { + return true; + } + + colorTemperatureLevel = newTemperature; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, ColorControl::Id); + esp_matter::attribute_t *attribute = attribute::get(cluster, ColorControl::Attributes::ColorTemperatureMireds::Id); + + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + + if (val.val.u16 != colorTemperatureLevel) { + val.val.u16 = colorTemperatureLevel; + attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::ColorTemperatureMireds::Id, &val); + } + return true; +} + +uint16_t MatterEnhancedColorLight::getColorTemperature() { + return colorTemperatureLevel; +} + +bool MatterEnhancedColorLight::setColorRGB(espRgbColor_t _rgbColor) { + return setColorHSV(espRgbColorToHsvColor(_rgbColor)); +} + +espRgbColor_t MatterEnhancedColorLight::getColorRGB() { + return espHsvColorToRgbColor(colorHSV); +} + +bool MatterEnhancedColorLight::setColorHSV(espHsvColor_t _hsvColor) { + + if (!started) { + log_w("Matter Enhanced ColorLight device has not begun."); + return false; + } + + // avoid processing if there was no change + if (colorHSV.h == _hsvColor.h && colorHSV.s == _hsvColor.s && colorHSV.v == _hsvColor.v) { + return true; + } + + colorHSV = {_hsvColor.h, _hsvColor.s, _hsvColor.v}; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, ColorControl::Id); + // update hue + esp_matter::attribute_t *attribute = attribute::get(cluster, ColorControl::Attributes::CurrentHue::Id); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + if (val.val.u8 != colorHSV.h) { + val.val.u8 = colorHSV.h; + attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentHue::Id, &val); + } + // update saturation + attribute = attribute::get(cluster, ColorControl::Attributes::CurrentSaturation::Id); + val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + if (val.val.u8 != colorHSV.s) { + val.val.u8 = colorHSV.s; + attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentSaturation::Id, &val); + } + // update value (brightness) + cluster = cluster::get(endpoint, LevelControl::Id); + attribute = attribute::get(cluster, LevelControl::Attributes::CurrentLevel::Id); + val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + if (val.val.u8 != colorHSV.v) { + val.val.u8 = colorHSV.v; + attribute::update(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, &val); + } + return true; +} + +espHsvColor_t MatterEnhancedColorLight::getColorHSV() { + return colorHSV; +} + +MatterEnhancedColorLight::operator bool() { + return getOnOff(); +} + +void MatterEnhancedColorLight::operator=(bool newState) { + setOnOff(newState); +} +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.h b/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.h new file mode 100644 index 00000000000..a4baef968a4 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.h @@ -0,0 +1,102 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterEnhancedColorLight : public MatterEndPoint { +public: + static const uint8_t MAX_BRIGHTNESS = 255; + static const uint16_t MAX_COLOR_TEMPERATURE = 500; + static const uint16_t MIN_COLOR_TEMPERATURE = 100; + + MatterEnhancedColorLight(); + ~MatterEnhancedColorLight(); + // default initial state is off, brightness = 25 (10%), HSV(21, 216, 25), color temperature is 454 (Warm White) + virtual bool begin(bool initialState = false, espHsvColor_t colorHSV = {21, 216, 25}, uint8_t newBrightness = 25, uint16_t colorTemperature = 454); + // this will just stop processing Light Matter events + void end(); + + bool setOnOff(bool newState); // returns true if successful + bool getOnOff(); // returns current light state + bool toggle(); // returns true if successful + + bool setColorTemperature(uint16_t newTemperature); // returns true if successful + uint16_t getColorTemperature(); // returns current temperature + + bool setBrightness(uint8_t newBrightness); // returns true if successful + uint8_t getBrightness(); // returns current brightness + + bool setColorRGB(espRgbColor_t rgbColor); // returns true if successful + espRgbColor_t getColorRGB(); // returns current RGB Color + bool setColorHSV(espHsvColor_t hsvColor); // returns true if successful + espHsvColor_t getColorHSV(); // returns current HSV Color + + // User Callback for whenever the Light On/Off state is changed by the Matter Controller + using EndPointOnOffCB = std::function; + void onChangeOnOff(EndPointOnOffCB onChangeCB) { + _onChangeOnOffCB = onChangeCB; + } + + // User Callback for whenever the Light brightness value [0..255] is changed by the Matter Controller + using EndPointBrightnessCB = std::function; + void onChangeBrightness(EndPointBrightnessCB onChangeCB) { + _onChangeBrightnessCB = onChangeCB; + } + + // User Callback for whenever the HSV Color value is changed by the Matter Controller + using EndPointRGBColorCB = std::function; + void onChangeColorHSV(EndPointRGBColorCB onChangeCB) { + _onChangeColorCB = onChangeCB; + } + + // User Callbqck for whenever the Light temperature value is changed by the Matter Controller + using EndPointTemperatureCB = std::function; + void onChangeColorTemperature(EndPointTemperatureCB onChangeCB) { + _onChangeTemperatureCB = onChangeCB; + } + + // User Callback for whenever any parameter is changed by the Matter Controller + using EndPointCB = std::function; + void onChange(EndPointCB onChangeCB) { + _onChangeCB = onChangeCB; + } + + // used to update the state of the light using the current Matter Light internal state + // It is necessary to set a user callback function using onChange() to handle the physical light state + void updateAccessory(); + + operator bool(); // returns current on/off light state + void operator=(bool state); // turns light on or off + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) + uint8_t brightnessLevel = 0; // default initial brightness is 0, but it can be changed by begin(bool, uint8_t) + espHsvColor_t colorHSV = {0, 0, 0}; // default initial color HSV is black, but it can be changed by begin(bool, uint8_t, espHsvColor_t) + uint16_t colorTemperatureLevel = 0; // default initial color temperature is 0, but it can be changed by begin(bool, uint8_t, espHsvColor_t, uint16_t) + EndPointOnOffCB _onChangeOnOffCB = NULL; + EndPointBrightnessCB _onChangeBrightnessCB = NULL; + EndPointRGBColorCB _onChangeColorCB = NULL; + EndPointTemperatureCB _onChangeTemperatureCB = NULL; + EndPointCB _onChangeCB = NULL; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.cpp b/libraries/Matter/src/MatterEndpoints/MatterFan.cpp new file mode 100644 index 00000000000..1647490aa05 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.cpp @@ -0,0 +1,235 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace esp_matter::cluster; +using namespace chip::app::Clusters; + +// string helper for the FAN MODE +const char *MatterFan::fanModeString[7] = {"OFF", "LOW", "MEDIUM", "HIGH", "ON", "AUTO", "SMART"}; +// bitmap for valid Fan Modes based on order defined in Zap Generated Cluster Enums +const uint8_t MatterFan::fanModeSequence[6] = {fanSeqModeOffLowMedHigh, fanSeqModeOffLowHigh, fanSeqModeOffLowMedHighAuto, + fanSeqModeOffLowHighAuto, fanSeqModeOffHighAuto, fanSeqModeOffHigh}; + +// Constructor and Method Definitions +MatterFan::MatterFan() {} + +MatterFan::~MatterFan() { + end(); +} + +bool MatterFan::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + + if (!started) { + log_e("Matter Fan device has not begun."); + return false; + } + + log_d("Fan Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + + if (endpoint_id == getEndPointId() && cluster_id == FanControl::Id) { + switch (attribute_id) { + case FanControl::Attributes::FanMode::Id: + log_v("FanControl Fan Mode changed to %s (%x)", val->val.u8 < 7 ? fanModeString[val->val.u8] : "Unknown", val->val.u8); + if (_onChangeModeCB != NULL) { + ret &= _onChangeModeCB((FanMode_t)val->val.u8); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB((FanMode_t)val->val.u8, currentPercent); + } + if (ret == true) { + currentFanMode = (FanMode_t)val->val.u8; + } + break; + case FanControl::Attributes::PercentSetting::Id: + case FanControl::Attributes::PercentCurrent::Id: + log_v("FanControl Percent %s changed to %d", attribute_id == FanControl::Attributes::PercentSetting::Id ? "SETTING" : "CURRENT", val->val.u8); + if (_onChangeSpeedCB != NULL) { + ret &= _onChangeSpeedCB(val->val.u8); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(currentFanMode, val->val.u8); + } + if (ret == true) { + // change setting speed percent + currentPercent = val->val.u8; + setAttributeVal(FanControl::Id, FanControl::Attributes::PercentSetting::Id, val); + setAttributeVal(FanControl::Id, FanControl::Attributes::PercentCurrent::Id, val); + } + break; + } + } + + return ret; +} + +bool MatterFan::begin(uint8_t percent, FanMode_t fanMode, FanModeSequence_t fanModeSeq) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter Fan with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + // endpoint handles can be used to add/modify clusters. + fan::config_t fan_config; + fan_config.fan_control.fan_mode = fanMode; + fan_config.fan_control.percent_current = percent; + fan_config.fan_control.percent_setting = percent; + fan_config.fan_control.fan_mode_sequence = fanModeSeq; + validFanModes = fanModeSequence[fanModeSeq]; + + endpoint_t *endpoint = fan::create(node::get(), &fan_config, ENDPOINT_FLAG_NONE, (void *)this); + + if (endpoint == nullptr) { + log_e("Failed to create Fan endpoint"); + return false; + } + + currentFanMode = fanMode; + currentPercent = percent; + + setEndPointId(endpoint::get_id(endpoint)); + log_i("Fan created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterFan::end() { + started = false; +} + +bool MatterFan::setMode(FanMode_t newMode, bool performUpdate) { + if (!started) { + log_w("Matter Fan device has not begun."); + return false; + } + // avoid processing if there was no change + if (currentFanMode == newMode) { + return true; + } + + // check if the mode is valid based on the sequence used in its creation + if (!(validFanModes & (1 << newMode))) { + log_e("Invalid Fan Mode %s for the current Fan Mode Sequence.", fanModeString[newMode]); + return false; + } + + esp_matter_attr_val_t modeVal = esp_matter_invalid(NULL); + if (!getAttributeVal(FanControl::Id, FanControl::Attributes::FanMode::Id, &modeVal)) { + log_e("Failed to get Fan Mode Attribute."); + return false; + } + if (modeVal.val.u8 != (uint8_t)newMode) { + modeVal.val.u8 = (uint8_t)newMode; + bool ret; + if (performUpdate) { + ret = updateAttributeVal(FanControl::Id, FanControl::Attributes::FanMode::Id, &modeVal); + } else { + ret = setAttributeVal(FanControl::Id, FanControl::Attributes::FanMode::Id, &modeVal); + } + if (!ret) { + log_e("Failed to %s Fan Mode Attribute.", performUpdate ? "update" : "set"); + return false; + } + } + currentFanMode = newMode; + log_v("Fan Mode %s to %s ==> onOffState[%s]", performUpdate ? "updated" : "set", fanModeString[currentFanMode], getOnOff() ? "ON" : "OFF"); + return true; +} + +// this function will change the Fan Speed by calling the user application callback +// it is up to the application to decide to turn on, off or change the speed of the fan +bool MatterFan::setSpeedPercent(uint8_t newPercent, bool performUpdate) { + if (!started) { + log_w("Matter Fan device has not begun."); + return false; + } + // avoid processing if there was no change + if (currentPercent == newPercent) { + return true; + } + + esp_matter_attr_val_t speedVal = esp_matter_invalid(NULL); + if (!getAttributeVal(FanControl::Id, FanControl::Attributes::PercentSetting::Id, &speedVal)) { + log_e("Failed to get Fan Speed Percent Attribute."); + return false; + } + if (speedVal.val.u8 != newPercent) { + speedVal.val.u8 = newPercent; + bool ret; + if (performUpdate) { + ret = updateAttributeVal(FanControl::Id, FanControl::Attributes::PercentSetting::Id, &speedVal); + } else { + ret = setAttributeVal(FanControl::Id, FanControl::Attributes::PercentSetting::Id, &speedVal); + ret = setAttributeVal(FanControl::Id, FanControl::Attributes::PercentCurrent::Id, &speedVal); + } + if (!ret) { + log_e("Failed to %s Fan Speed Percent Attribute.", performUpdate ? "update" : "set"); + return false; + } + } + currentPercent = newPercent; + log_v("Fan Speed %s to %d ==> onOffState[%s]", performUpdate ? "updated" : "set", currentPercent, getOnOff() ? "ON" : "OFF"); + return true; +} + +bool MatterFan::setOnOff(bool newState, bool performUpdate) { + if (!started) { + log_w("Matter Fan device has not begun."); + return false; + } + // avoid processing if there was no change + if (getOnOff() == newState) { + return true; + } + + esp_matter_attr_val_t modeVal = esp_matter_invalid(NULL); + if (!getAttributeVal(FanControl::Id, FanControl::Attributes::FanMode::Id, &modeVal)) { + log_e("Failed to get Fan Mode Attribute."); + return false; + } + if (modeVal.val.u8 != (uint8_t)newState) { + FanMode_t newMode = newState ? FAN_MODE_ON : FAN_MODE_OFF; + if (!setMode(newMode, performUpdate)) { + return false; + } + } + log_v( + "Fan State %s to %s :: Mode[%s]|Speed[%d]", performUpdate ? "updated" : "set", getOnOff() ? "ON" : "OFF", fanModeString[currentFanMode], currentPercent + ); + return true; +} + +bool MatterFan::getOnOff() { + return currentFanMode == FAN_MODE_OFF ? false : true; +} + +bool MatterFan::toggle(bool performUpdate) { + if (getOnOff() == true) { + return setOnOff(false, performUpdate); + } else { + return setOnOff(true, performUpdate); + } +} + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.h b/libraries/Matter/src/MatterEndpoints/MatterFan.h new file mode 100644 index 00000000000..a1cd6e42423 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.h @@ -0,0 +1,164 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace chip::app::Clusters::FanControl; + +// Matter Fan endpoint with On/Off, Mode and Speed control + +class MatterFan : public MatterEndPoint { +public: + // Fan feature constants + static const uint8_t MAX_SPEED = 100; // maximum High speed + static const uint8_t MIN_SPEED = 1; // minimum Low speed + static const uint8_t OFF_SPEED = 0; // speed set by Matter when FAN_MODE_OFF + + // Default Fan Modes: ON, SMART, HIGH and OFF + + // Other mode will depend on what is the configured Fan Mode Sequence + enum FanMode_t { + FAN_MODE_OFF = (uint8_t)FanModeEnum::kOff, + FAN_MODE_LOW = (uint8_t)FanModeEnum::kLow, + FAN_MODE_MEDIUM = (uint8_t)FanModeEnum::kMedium, + FAN_MODE_HIGH = (uint8_t)FanModeEnum::kHigh, + FAN_MODE_ON = (uint8_t)FanModeEnum::kOn, + FAN_MODE_AUTO = (uint8_t)FanModeEnum::kAuto, + FAN_MODE_SMART = (uint8_t)FanModeEnum::kSmart + }; + + // Menu will always have ON, OFF, HIGH and SMART. + // AUTO will show up only when a AUTO SEQ is CONFIGURED + // LOW and MEDIUM depend on the SEQ MODE configuration + enum FanModeSequence_t { + FAN_MODE_SEQ_OFF_LOW_MED_HIGH = (uint8_t)FanModeSequenceEnum::kOffLowMedHigh, + FAN_MODE_SEQ_OFF_LOW_HIGH = (uint8_t)FanModeSequenceEnum::kOffLowHigh, + FAN_MODE_SEQ_OFF_LOW_MED_HIGH_AUTO = (uint8_t)FanModeSequenceEnum::kOffLowMedHighAuto, + FAN_MODE_SEQ_OFF_LOW_HIGH_AUTO = (uint8_t)FanModeSequenceEnum::kOffLowHighAuto, + FAN_MODE_SEQ_OFF_HIGH_AUTO = (uint8_t)FanModeSequenceEnum::kOffHighAuto, + FAN_MODE_SEQ_OFF_HIGH = (uint8_t)FanModeSequenceEnum::kOffHigh + }; + + MatterFan(); + ~MatterFan(); + virtual bool begin(uint8_t percent = 0, FanMode_t fanMode = FAN_MODE_OFF, FanModeSequence_t fanModeSeq = FAN_MODE_SEQ_OFF_HIGH); + void end(); // this will just stop processing Matter events + + // returns a friendly string for the Fan Mode + static const char *getFanModeString(uint8_t mode) { + return fanModeString[mode]; + } + + // Fan Control of current On/Off state + + bool setOnOff(bool newState, bool performUpdate = true); // sets Fan On/Off state + bool getOnOff(); // returns current Fan state + bool toggle(bool performUpdate = true); // toggle Fun On/Off state + + // Fan Control of current speed percent + + bool setSpeedPercent(uint8_t newPercent, bool performUpdate = true); // returns true if successful + uint8_t getSpeedPercent() { // returns current Fan Speed Percent + return currentPercent; + } + + // Fan Control of current Fan Mode + + bool setMode(FanMode_t newMode, bool performUpdate = true); // returns true if successful + FanMode_t getMode() { // returns current Fan Mode + return currentFanMode; + } + // used to update the state of the Fan using the current Matter Fan internal state + // It is necessary to set a user callback function using onChange() to handle the physical Fan motor state + + void updateAccessory() { + if (_onChangeCB != NULL) { + _onChangeCB(currentFanMode, currentPercent); + } + } + + // returns current Fan speed percent + operator uint8_t() { + return getSpeedPercent(); + } + + // User Callback for whenever the Fan Mode (state) is changed by the Matter Controller + using EndPointModeCB = std::function; + void onChangeMode(EndPointModeCB onChangeCB) { + _onChangeModeCB = onChangeCB; + } + + // User Callback for whenever the Fan Speed Percentage value [0..100] is changed by the Matter Controller + using EndPointSpeedCB = std::function; + void onChangeSpeedPercent(EndPointSpeedCB onChangeCB) { + _onChangeSpeedCB = onChangeCB; + } + + // User Callback for whenever any parameter is changed by the Matter Controller + using EndPointCB = std::function; + void onChange(EndPointCB onChangeCB) { + _onChangeCB = onChangeCB; + } + + // sets Fan speed percent + void operator=(uint8_t speedPercent) { + setSpeedPercent(speedPercent); + } + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + uint8_t validFanModes = 0; // bitmap for valid Fan Modes - index of fanModeSequence[] + + uint8_t currentPercent = 0; // current speed percent + FanMode_t currentFanMode = FAN_MODE_OFF; // current Fan Mode + EndPointModeCB _onChangeModeCB = NULL; + EndPointSpeedCB _onChangeSpeedCB = NULL; + EndPointCB _onChangeCB = NULL; + + // bitmap for Fan Sequence Modes (OFF, LOW, MEDIUM, HIGH, AUTO) + static const uint8_t fanSeqModeOff = 0x01; + static const uint8_t fanSeqModeLow = 0x02; + static const uint8_t fanSeqModeMedium = 0x04; + static const uint8_t fanSeqModeHigh = 0x08; + static const uint8_t fanSeqModeOn = 0x10; + static const uint8_t fanSeqModeAuto = 0x20; + static const uint8_t fanSeqModeSmart = 0x40; + + // bitmap for common modes: ON, OFF, HIGH and SMART + static const uint8_t fanSeqCommonModes = fanSeqModeOff | fanSeqModeOn | fanSeqModeHigh | fanSeqModeSmart; + + static const uint8_t fanSeqModeOffLowMedHigh = fanSeqCommonModes | fanSeqModeLow | fanSeqModeMedium; + static const uint8_t fanSeqModeOffLowHigh = fanSeqCommonModes | fanSeqModeLow; + static const uint8_t fanSeqModeOffLowMedHighAuto = fanSeqCommonModes | fanSeqModeLow | fanSeqModeMedium | fanSeqModeAuto; + static const uint8_t fanSeqModeOffLowHighAuto = fanSeqCommonModes | fanSeqModeLow | fanSeqModeAuto; + static const uint8_t fanSeqModeOffHighAuto = fanSeqCommonModes | fanSeqModeAuto; + static const uint8_t fanSeqModeOffHigh = fanSeqCommonModes; + + // bitmap for valid Fan Modes based on order defined in Zap Generated Cluster Enums + static const uint8_t fanModeSequence[6]; + + // string helper for the FAN MODE + static const char *fanModeString[7]; +}; + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.cpp b/libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.cpp new file mode 100644 index 00000000000..e20479af088 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.cpp @@ -0,0 +1,105 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace esp_matter::cluster; +using namespace chip::app::Clusters; + +MatterGenericSwitch::MatterGenericSwitch() {} + +MatterGenericSwitch::~MatterGenericSwitch() { + end(); +} + +bool MatterGenericSwitch::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + if (!started) { + log_e("Matter Generic Switch device has not begun."); + return false; + } + + log_d("Generic Switch Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + return true; +} + +bool MatterGenericSwitch::begin() { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter Generic Switch with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + generic_switch::config_t switch_config; + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = generic_switch::create(node::get(), &switch_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create Generic Switch endpoint"); + return false; + } + // Add group cluster to the switch endpoint + cluster::groups::config_t groups_config; + cluster::groups::create(endpoint, &groups_config, CLUSTER_FLAG_SERVER | CLUSTER_FLAG_CLIENT); + + cluster_t *aCluster = cluster::get(endpoint, Descriptor::Id); + esp_matter::cluster::descriptor::feature::taglist::add(aCluster); + + cluster::fixed_label::config_t fl_config; + cluster::fixed_label::create(endpoint, &fl_config, CLUSTER_FLAG_SERVER); + + cluster::user_label::config_t ul_config; + cluster::user_label::create(endpoint, &ul_config, CLUSTER_FLAG_SERVER); + + aCluster = cluster::get(endpoint, Switch::Id); + switch_cluster::feature::momentary_switch::add(aCluster); + switch_cluster::event::create_initial_press(aCluster); + + switch_cluster::feature::momentary_switch::add(aCluster); + + switch_cluster::attribute::create_current_position(aCluster, 0); + switch_cluster::attribute::create_number_of_positions(aCluster, 2); + + setEndPointId(endpoint::get_id(endpoint)); + log_i("Generic Switch created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterGenericSwitch::end() { + started = false; +} + +void MatterGenericSwitch::click() { + if (!started) { + log_e("Matter Generic Switch device has not begun."); + return; + } + + int switch_endpoint_id = getEndPointId(); + uint8_t newPosition = 1; + // Press moves Position from 0 (off) to 1 (on) + chip::DeviceLayer::SystemLayer().ScheduleLambda([switch_endpoint_id, newPosition]() { + // InitialPress event takes newPosition as event data + switch_cluster::event::send_initial_press(switch_endpoint_id, newPosition); + }); +} + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.h b/libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.h new file mode 100644 index 00000000000..14118462932 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.h @@ -0,0 +1,39 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +// Matter Generic Switch Endpoint that works as a single click smart button +class MatterGenericSwitch : public MatterEndPoint { +public: + MatterGenericSwitch(); + ~MatterGenericSwitch(); + virtual bool begin(); + void end(); // this will just stop processing Matter events + + // send a simple click event to the Matter Controller + void click(); + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp b/libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp new file mode 100644 index 00000000000..d31d0e43728 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp @@ -0,0 +1,116 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +bool MatterHumiditySensor::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter Humidity Sensor device has not begun."); + return false; + } + + log_d("Humidity Sensor Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + return ret; +} + +MatterHumiditySensor::MatterHumiditySensor() {} + +MatterHumiditySensor::~MatterHumiditySensor() { + end(); +} + +bool MatterHumiditySensor::begin(uint16_t _rawHumidity) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter Humidity Sensor with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + // is it a valid percentage value? + if (_rawHumidity > 10000) { + log_e("Humidity Sensor Percentage value out of range [0..100]."); + return false; + } + + humidity_sensor::config_t humidity_sensor_config; + humidity_sensor_config.relative_humidity_measurement.measured_value = _rawHumidity; + humidity_sensor_config.relative_humidity_measurement.min_measured_value = nullptr; + humidity_sensor_config.relative_humidity_measurement.max_measured_value = nullptr; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = humidity_sensor::create(node::get(), &humidity_sensor_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create Humidity Sensor endpoint"); + return false; + } + rawHumidity = _rawHumidity; + setEndPointId(endpoint::get_id(endpoint)); + log_i("Humidity Sensor created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterHumiditySensor::end() { + started = false; +} + +bool MatterHumiditySensor::setRawHumidity(uint16_t _rawHumidity) { + if (!started) { + log_e("Matter Humidity Sensor device has not begun."); + return false; + } + // is it a valid percentage value? + if (_rawHumidity > 10000) { + log_e("Humidity Sensor Percentage value out of range [0..100]."); + return false; + } + + // avoid processing if there was no change + if (rawHumidity == _rawHumidity) { + return true; + } + + esp_matter_attr_val_t humidityVal = esp_matter_invalid(NULL); + + if (!getAttributeVal(RelativeHumidityMeasurement::Id, RelativeHumidityMeasurement::Attributes::MeasuredValue::Id, &humidityVal)) { + log_e("Failed to get Humidity Sensor Attribute."); + return false; + } + if (humidityVal.val.u16 != _rawHumidity) { + humidityVal.val.u16 = _rawHumidity; + bool ret; + ret = updateAttributeVal(RelativeHumidityMeasurement::Id, RelativeHumidityMeasurement::Attributes::MeasuredValue::Id, &humidityVal); + if (!ret) { + log_e("Failed to update Humidity Sensor Attribute."); + return false; + } + rawHumidity = _rawHumidity; + } + log_v("Humidity Sensor set to %.02f Percent", (float)_rawHumidity / 100.00); + + return true; +} + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.h b/libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.h new file mode 100644 index 00000000000..aed758b7b7a --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.h @@ -0,0 +1,69 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterHumiditySensor : public MatterEndPoint { +public: + MatterHumiditySensor(); + ~MatterHumiditySensor(); + // begin Matter Humidity Sensor endpoint with initial float humidity percent + bool begin(double humidityPercent = 0.00) { + if (humidityPercent < 0.0 || humidityPercent > 100.0) { + log_e("Humidity Sensor Percentage value out of range [0..100]."); + return false; + } + return begin(static_cast(humidityPercent * 100.0f)); + } + // this will just stop processing Humidity Sensor Matter events + void end(); + + // set the humidity percent with 1/100th of a percent precision + bool setHumidity(double humidityPercent) { + if (humidityPercent < 0.0 || humidityPercent > 100.0) { + log_e("Humidity Sensor Percentage value out of range [0..100]."); + return false; + } + return setRawHumidity(static_cast(humidityPercent * 100.0f)); + } + // returns the reported float humidity percent with 1/100th of precision + double getHumidity() { + return (double)rawHumidity / 100.0; + } + // double conversion operator + void operator=(double humidityPercent) { + setHumidity(humidityPercent); + } + // double conversion operator + operator double() { + return (double)getHumidity(); + } + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + // implementation keeps humidity relative percentage with 1/100th of a percent precision + uint16_t rawHumidity = 0; + // internal function to set the raw humidity value (Matter Cluster) + bool begin(uint16_t _rawHumidity); + bool setRawHumidity(uint16_t _rawHumidity); +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.cpp b/libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.cpp new file mode 100644 index 00000000000..0d55c37708a --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.cpp @@ -0,0 +1,114 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +// clang-format off +const uint8_t MatterOccupancySensor::occupancySensorTypeBitmap[4] = { + MatterOccupancySensor::occupancySensorTypePir, + MatterOccupancySensor::occupancySensorTypePir | MatterOccupancySensor::occupancySensorTypeUltrasonic, + MatterOccupancySensor::occupancySensorTypeUltrasonic, + MatterOccupancySensor::occupancySensorTypePhysicalContact +}; +// clang-format on + +bool MatterOccupancySensor::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter Occupancy Sensor device has not begun."); + return false; + } + + log_d("Occupancy Sensor Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + return ret; +} + +MatterOccupancySensor::MatterOccupancySensor() {} + +MatterOccupancySensor::~MatterOccupancySensor() { + end(); +} + +bool MatterOccupancySensor::begin(bool _occupancyState, OccupancySensorType_t _occupancySensorType) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter Occupancy Sensor with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + occupancy_sensor::config_t occupancy_sensor_config; + occupancy_sensor_config.occupancy_sensing.occupancy = _occupancyState; + occupancy_sensor_config.occupancy_sensing.occupancy_sensor_type = _occupancySensorType; + occupancy_sensor_config.occupancy_sensing.occupancy_sensor_type_bitmap = occupancySensorTypeBitmap[_occupancySensorType]; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = occupancy_sensor::create(node::get(), &occupancy_sensor_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create Occupancy Sensor endpoint"); + return false; + } + occupancyState = _occupancyState; + setEndPointId(endpoint::get_id(endpoint)); + log_i("Occupancy Sensor created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterOccupancySensor::end() { + started = false; +} + +bool MatterOccupancySensor::setOccupancy(bool _occupancyState) { + if (!started) { + log_e("Matter Occupancy Sensor device has not begun."); + return false; + } + + // avoid processing if there was no change + if (occupancyState == _occupancyState) { + return true; + } + + esp_matter_attr_val_t occupancyVal = esp_matter_invalid(NULL); + + if (!getAttributeVal(OccupancySensing::Id, OccupancySensing::Attributes::Occupancy::Id, &occupancyVal)) { + log_e("Failed to get Occupancy Sensor Attribute."); + return false; + } + if (occupancyVal.val.u8 != _occupancyState) { + occupancyVal.val.u8 = _occupancyState; + bool ret; + ret = updateAttributeVal(OccupancySensing::Id, OccupancySensing::Attributes::Occupancy::Id, &occupancyVal); + if (!ret) { + log_e("Failed to update Occupancy Sensor Attribute."); + return false; + } + occupancyState = _occupancyState; + } + log_v("Occupancy Sensor set to %s", _occupancyState ? "Occupied" : "Vacant"); + + return true; +} + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.h b/libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.h new file mode 100644 index 00000000000..30f312a9841 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.h @@ -0,0 +1,73 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace chip::app::Clusters::OccupancySensing; + +class MatterOccupancySensor : public MatterEndPoint { +public: + // Different Occupancy Sensor Types + enum OccupancySensorType_t { + OCCUPANCY_SENSOR_TYPE_PIR = (uint8_t)OccupancySensorTypeEnum::kPir, + OCCUPANCY_SENSOR_TYPE_ULTRASONIC = (uint8_t)OccupancySensorTypeEnum::kUltrasonic, + OCCUPANCY_SENSOR_TYPE_PIR_AND_ULTRASONIC = (uint8_t)OccupancySensorTypeEnum::kPIRAndUltrasonic, + OCCUPANCY_SENSOR_TYPE_PHYSICAL_CONTACT = (uint8_t)OccupancySensorTypeEnum::kPhysicalContact + }; + + MatterOccupancySensor(); + ~MatterOccupancySensor(); + // begin Matter Occupancy Sensor endpoint with initial occupancy state and default PIR sensor type + bool begin(bool _occupancyState = false, OccupancySensorType_t _occupancySensorType = OCCUPANCY_SENSOR_TYPE_PIR); + // this will just stop processing Occupancy Sensor Matter events + void end(); + + // set the occupancy state + bool setOccupancy(bool _occupancyState); + // returns the occupancy state + bool getOccupancy() { + return occupancyState; + } + + // bool conversion operator + void operator=(bool _occupancyState) { + setOccupancy(_occupancyState); + } + // bool conversion operator + operator bool() { + return getOccupancy(); + } + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + // bitmap for Occupancy Sensor Types + static const uint8_t occupancySensorTypePir = 0x01; + static const uint8_t occupancySensorTypeUltrasonic = 0x02; + static const uint8_t occupancySensorTypePhysicalContact = 0x04; + + // bitmap for Occupancy Sensor Type Bitmap mapped array + static const uint8_t occupancySensorTypeBitmap[4]; + + bool started = false; + bool occupancyState = false; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.cpp b/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.cpp new file mode 100644 index 00000000000..f400390f9a7 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.cpp @@ -0,0 +1,138 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +bool MatterOnOffLight::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter On-Off Light device has not begun."); + return false; + } + + log_d("OnOff Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + + if (endpoint_id == getEndPointId()) { + log_d("OnOffLight state changed to %d", val->val.b); + if (cluster_id == OnOff::Id) { + if (attribute_id == OnOff::Attributes::OnOff::Id) { + if (_onChangeOnOffCB != NULL) { + ret &= _onChangeOnOffCB(val->val.b); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(val->val.b); + } + if (ret == true) { + onOffState = val->val.b; + } + } + } + } + return ret; +} + +MatterOnOffLight::MatterOnOffLight() {} + +MatterOnOffLight::~MatterOnOffLight() { + end(); +} + +bool MatterOnOffLight::begin(bool initialState) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter On-Off Light with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + on_off_light::config_t light_config; + light_config.on_off.on_off = initialState; + light_config.on_off.lighting.start_up_on_off = nullptr; + onOffState = initialState; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = on_off_light::create(node::get(), &light_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create on-off light endpoint"); + return false; + } + + setEndPointId(endpoint::get_id(endpoint)); + log_i("On-Off Light created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterOnOffLight::end() { + started = false; +} + +void MatterOnOffLight::updateAccessory() { + if (_onChangeCB != NULL) { + _onChangeCB(onOffState); + } +} + +bool MatterOnOffLight::setOnOff(bool newState) { + if (!started) { + log_e("Matter On-Off Light device has not begun."); + return false; + } + + // avoid processing if there was no change + if (onOffState == newState) { + return true; + } + + onOffState = newState; + + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + cluster_t *cluster = cluster::get(endpoint, OnOff::Id); + esp_matter::attribute_t *attribute = attribute::get(cluster, OnOff::Attributes::OnOff::Id); + + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + attribute::get_val(attribute, &val); + + if (val.val.b != onOffState) { + val.val.b = onOffState; + attribute::update(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, &val); + } + return true; +} + +bool MatterOnOffLight::getOnOff() { + return onOffState; +} + +bool MatterOnOffLight::toggle() { + return setOnOff(!onOffState); +} + +MatterOnOffLight::operator bool() { + return getOnOff(); +} + +void MatterOnOffLight::operator=(bool newState) { + setOnOff(newState); +} +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.h b/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.h new file mode 100644 index 00000000000..ec524d2c300 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.h @@ -0,0 +1,60 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterOnOffLight : public MatterEndPoint { +public: + MatterOnOffLight(); + ~MatterOnOffLight(); + virtual bool begin(bool initialState = false); // default initial state is off + void end(); // this will just stop processing Light Matter events + + bool setOnOff(bool newState); // returns true if successful + bool getOnOff(); // returns current light state + bool toggle(); // returns true if successful + + // User Callback for whenever the Light state is changed by the Matter Controller + using EndPointCB = std::function; + void onChange(EndPointCB onChangeCB) { + _onChangeCB = onChangeCB; + } + + // User Callback for whenever the Light On/Off state is changed by the Matter Controller + void onChangeOnOff(EndPointCB onChangeCB) { + _onChangeOnOffCB = onChangeCB; + } + + // used to update the state of the light using the current Matter Light internal state + // It is necessary to set a user callback function using onChange() to handle the physical light state + void updateAccessory(); + + operator bool(); // returns current light state + void operator=(bool state); // turns light on or off + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) + EndPointCB _onChangeCB = NULL; + EndPointCB _onChangeOnOffCB = NULL; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.cpp b/libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.cpp new file mode 100644 index 00000000000..9b08958684c --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.cpp @@ -0,0 +1,141 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +bool MatterOnOffPlugin::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter On-Off Plugin device has not begun."); + return false; + } + + log_d("OnOff Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + + if (endpoint_id == getEndPointId()) { + log_d("OnOffPlugin state changed to %d", val->val.b); + if (cluster_id == OnOff::Id) { + if (attribute_id == OnOff::Attributes::OnOff::Id) { + if (_onChangeOnOffCB != NULL) { + ret &= _onChangeOnOffCB(val->val.b); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(val->val.b); + } + if (ret == true) { + onOffState = val->val.b; + } + } + } + } + return ret; +} + +MatterOnOffPlugin::MatterOnOffPlugin() {} + +MatterOnOffPlugin::~MatterOnOffPlugin() { + end(); +} + +bool MatterOnOffPlugin::begin(bool initialState) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter On-Off Plugin with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + on_off_plugin_unit::config_t plugin_config; + plugin_config.on_off.on_off = initialState; + plugin_config.on_off.lighting.start_up_on_off = nullptr; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = on_off_plugin_unit::create(node::get(), &plugin_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create on-off plugin endpoint"); + return false; + } + onOffState = initialState; + setEndPointId(endpoint::get_id(endpoint)); + log_i("On-Off Plugin created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterOnOffPlugin::end() { + started = false; +} + +void MatterOnOffPlugin::updateAccessory() { + if (_onChangeCB != NULL) { + _onChangeCB(onOffState); + } +} + +bool MatterOnOffPlugin::setOnOff(bool newState) { + if (!started) { + log_e("Matter On-Off Plugin device has not begun."); + return false; + } + + // avoid processing if there was no change + if (onOffState == newState) { + return true; + } + + esp_matter_attr_val_t onoffVal = esp_matter_invalid(NULL); + + if (!getAttributeVal(OnOff::Id, OnOff::Attributes::OnOff::Id, &onoffVal)) { + log_e("Failed to get Pressure Sensor Attribute."); + return false; + } + if (onoffVal.val.b != newState) { + onoffVal.val.b = newState; + bool ret; + ret = updateAttributeVal(OnOff::Id, OnOff::Attributes::OnOff::Id, &onoffVal); + if (!ret) { + log_e("Failed to update Pressure Sensor Measurement Attribute."); + return false; + } + onOffState = newState; + } + log_v("Plugin OnOff state set to %s", newState ? "ON" : "OFF"); + return true; +} + +bool MatterOnOffPlugin::getOnOff() { + return onOffState; +} + +bool MatterOnOffPlugin::toggle() { + return setOnOff(!onOffState); +} + +MatterOnOffPlugin::operator bool() { + return getOnOff(); +} + +void MatterOnOffPlugin::operator=(bool newState) { + setOnOff(newState); +} +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.h b/libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.h new file mode 100644 index 00000000000..0b05c0944c4 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.h @@ -0,0 +1,60 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterOnOffPlugin : public MatterEndPoint { +public: + MatterOnOffPlugin(); + ~MatterOnOffPlugin(); + virtual bool begin(bool initialState = false); // default initial state is off + void end(); // this will just stop processing Plugin Matter events + + bool setOnOff(bool newState); // returns true if successful + bool getOnOff(); // returns current plugin state + bool toggle(); // returns true if successful + + // User Callback for whenever the Plugin state is changed by the Matter Controller + using EndPointCB = std::function; + void onChange(EndPointCB onChangeCB) { + _onChangeCB = onChangeCB; + } + + // User Callback for whenever the On/Off state is changed by the Matter Controller + void onChangeOnOff(EndPointCB onChangeCB) { + _onChangeOnOffCB = onChangeCB; + } + + // used to update the state of the plugin using the current Matter Plugin internal state + // It is necessary to set a user callback function using onChange() to handle the physical plugin state + void updateAccessory(); + + operator bool(); // returns current plugin state + void operator=(bool state); // turns plugin on or off + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) + EndPointCB _onChangeCB = NULL; + EndPointCB _onChangeOnOffCB = NULL; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.cpp b/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.cpp new file mode 100644 index 00000000000..86d245d4041 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.cpp @@ -0,0 +1,104 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +bool MatterPressureSensor::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter Pressure Sensor device has not begun."); + return false; + } + + log_d("Pressure Sensor Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + return ret; +} + +MatterPressureSensor::MatterPressureSensor() {} + +MatterPressureSensor::~MatterPressureSensor() { + end(); +} + +bool MatterPressureSensor::begin(int16_t _rawPressure) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter Pressure Sensor with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + pressure_sensor::config_t pressure_sensor_config; + pressure_sensor_config.pressure_measurement.pressure_measured_value = _rawPressure; + pressure_sensor_config.pressure_measurement.pressure_min_measured_value = nullptr; + pressure_sensor_config.pressure_measurement.pressure_max_measured_value = nullptr; + + // endpoint handles can be used to add/modify clusters + endpoint_t *endpoint = pressure_sensor::create(node::get(), &pressure_sensor_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create Pressure Sensor endpoint"); + return false; + } + rawPressure = _rawPressure; + setEndPointId(endpoint::get_id(endpoint)); + log_i("Pressure Sensor created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterPressureSensor::end() { + started = false; +} + +bool MatterPressureSensor::setRawPressure(int16_t _rawPressure) { + if (!started) { + log_e("Matter Pressure Sensor device has not begun."); + return false; + } + + // avoid processing if there was no change + if (rawPressure == _rawPressure) { + return true; + } + + esp_matter_attr_val_t pressureVal = esp_matter_invalid(NULL); + + if (!getAttributeVal(PressureMeasurement::Id, PressureMeasurement::Attributes::MeasuredValue::Id, &pressureVal)) { + log_e("Failed to get Pressure Sensor Attribute."); + return false; + } + if (pressureVal.val.i16 != _rawPressure) { + pressureVal.val.i16 = _rawPressure; + bool ret; + ret = updateAttributeVal(PressureMeasurement::Id, PressureMeasurement::Attributes::MeasuredValue::Id, &pressureVal); + if (!ret) { + log_e("Failed to update Pressure Sensor Measurement Attribute."); + return false; + } + rawPressure = _rawPressure; + } + log_v("Pressure Sensor set to %.02f Degrees", (float)_rawPressure / 100.00); + + return true; +} + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.h b/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.h new file mode 100644 index 00000000000..0715c05609d --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.h @@ -0,0 +1,63 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterPressureSensor : public MatterEndPoint { +public: + MatterPressureSensor(); + ~MatterPressureSensor(); + // begin Matter Pressure Sensor endpoint with initial float pressure + bool begin(double pressure = 0.00) { + return begin(static_cast(pressure)); + } + // this will stop processing Pressure Sensor Matter events + void end(); + + // set the reported raw pressure in hPa + bool setPressure(double pressure) { + int16_t rawValue = static_cast(pressure); + return setRawPressure(rawValue); + } + // returns the reported float pressure in hPa + double getPressure() { + return (double)rawPressure; + } + + // double conversion operator + void operator=(double pressure) { + setPressure(pressure); + } + // double conversion operator + operator double() { + return (double)getPressure(); + } + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + // implementation keeps pressure in hPa + int16_t rawPressure = 0; + // internal function to set the raw pressure value (Matter Cluster) + bool setRawPressure(int16_t _rawPressure); + bool begin(int16_t _rawPressure); +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp b/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp new file mode 100644 index 00000000000..863f86386c1 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp @@ -0,0 +1,104 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +bool MatterTemperatureSensor::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter Temperature Sensor device has not begun."); + return false; + } + + log_d("Temperature Sensor Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + return ret; +} + +MatterTemperatureSensor::MatterTemperatureSensor() {} + +MatterTemperatureSensor::~MatterTemperatureSensor() { + end(); +} + +bool MatterTemperatureSensor::begin(int16_t _rawTemperature) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Temperature Sensor with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + temperature_sensor::config_t temperature_sensor_config; + temperature_sensor_config.temperature_measurement.measured_value = _rawTemperature; + temperature_sensor_config.temperature_measurement.min_measured_value = nullptr; + temperature_sensor_config.temperature_measurement.max_measured_value = nullptr; + + // endpoint handles can be used to add/modify clusters + endpoint_t *endpoint = temperature_sensor::create(node::get(), &temperature_sensor_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create Temperature Sensor endpoint"); + return false; + } + rawTemperature = _rawTemperature; + setEndPointId(endpoint::get_id(endpoint)); + log_i("Temperature Sensor created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterTemperatureSensor::end() { + started = false; +} + +bool MatterTemperatureSensor::setRawTemperature(int16_t _rawTemperature) { + if (!started) { + log_e("Matter Temperature Sensor device has not begun."); + return false; + } + + // avoid processing if there was no change + if (rawTemperature == _rawTemperature) { + return true; + } + + esp_matter_attr_val_t temperatureVal = esp_matter_invalid(NULL); + + if (!getAttributeVal(TemperatureMeasurement::Id, TemperatureMeasurement::Attributes::MeasuredValue::Id, &temperatureVal)) { + log_e("Failed to get Temperature Sensor Attribute."); + return false; + } + if (temperatureVal.val.i16 != _rawTemperature) { + temperatureVal.val.i16 = _rawTemperature; + bool ret; + ret = updateAttributeVal(TemperatureMeasurement::Id, TemperatureMeasurement::Attributes::MeasuredValue::Id, &temperatureVal); + if (!ret) { + log_e("Failed to update Temperature Sensor Attribute."); + return false; + } + rawTemperature = _rawTemperature; + } + log_v("Temperature Sensor set to %.02fC", (float)_rawTemperature / 100.00); + + return true; +} + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.h b/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.h new file mode 100644 index 00000000000..3be6101166c --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.h @@ -0,0 +1,64 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterTemperatureSensor : public MatterEndPoint { +public: + MatterTemperatureSensor(); + ~MatterTemperatureSensor(); + // begin Matter Temperature Sensor endpoint with initial float temperature in Celsius + bool begin(double temperature = 0.00) { + return begin(static_cast(temperature * 100.0f)); + } + // this will stop processing Temperature Sensor Matter events + void end(); + + // set the reported raw temperature + bool setTemperature(double temperature) { + // stores up to 1/100th Celsius precision + int16_t rawValue = static_cast(temperature * 100.0f); + return setRawTemperature(rawValue); + } + // returns the reported float temperature with 1/100th Celsius precision + double getTemperature() { + return (double)rawTemperature / 100.0; + } + + // double conversion operator + void operator=(double temperature) { + setTemperature(temperature); + } + // double conversion operator + operator double() { + return (double)getTemperature(); + } + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + // implementation keeps temperature in 1/100th Celsius x 100 (int16_t) normalized value + int16_t rawTemperature = 0; + // internal function to set the raw temperature value (Matter Cluster) + bool setRawTemperature(int16_t _rawTemperature); + bool begin(int16_t _rawTemperature); +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterThermostat.cpp b/libraries/Matter/src/MatterEndpoints/MatterThermostat.cpp new file mode 100644 index 00000000000..5a68421bd8a --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterThermostat.cpp @@ -0,0 +1,370 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +// string helper for the THERMOSTAT MODE +const char *MatterThermostat::thermostatModeString[5] = {"OFF", "AUTO", "UNKNOWN", "COOL", "HEAT"}; + +// endpoint for color light device +namespace esp_matter { +using namespace cluster; +namespace endpoint { +namespace multi_mode_thermostat { +typedef struct config { + cluster::descriptor::config_t descriptor; + cluster::identify::config_t identify; + cluster::scenes_management::config_t scenes_management; + cluster::groups::config_t groups; + cluster::thermostat::config_t thermostat; +} config_t; + +uint32_t get_device_type_id() { + return ESP_MATTER_THERMOSTAT_DEVICE_TYPE_ID; +} + +uint8_t get_device_type_version() { + return ESP_MATTER_THERMOSTAT_DEVICE_TYPE_VERSION; +} + +esp_err_t add(endpoint_t *endpoint, config_t *config) { + if (!endpoint) { + log_e("Endpoint cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + esp_err_t err = add_device_type(endpoint, get_device_type_id(), get_device_type_version()); + if (err != ESP_OK) { + log_e("Failed to add device type id:%" PRIu32 ",err: %d", get_device_type_id(), err); + return err; + } + + descriptor::create(endpoint, &(config->descriptor), CLUSTER_FLAG_SERVER); + identify::create(endpoint, &(config->identify), CLUSTER_FLAG_SERVER); + groups::create(endpoint, &(config->groups), CLUSTER_FLAG_SERVER); + uint32_t thermostatFeatures = 0; + switch (config->thermostat.control_sequence_of_operation) { + case MatterThermostat::THERMOSTAT_SEQ_OP_COOLING: + case MatterThermostat::THERMOSTAT_SEQ_OP_COOLING_REHEAT: thermostatFeatures = cluster::thermostat::feature::cooling::get_id(); break; + case MatterThermostat::THERMOSTAT_SEQ_OP_HEATING: + case MatterThermostat::THERMOSTAT_SEQ_OP_HEATING_REHEAT: thermostatFeatures = cluster::thermostat::feature::heating::get_id(); break; + case MatterThermostat::THERMOSTAT_SEQ_OP_COOLING_HEATING: + case MatterThermostat::THERMOSTAT_SEQ_OP_COOLING_HEATING_REHEAT: + thermostatFeatures = cluster::thermostat::feature::cooling::get_id() | cluster::thermostat::feature::heating::get_id(); + break; + } + cluster::thermostat::create(endpoint, &(config->thermostat), CLUSTER_FLAG_SERVER, thermostatFeatures); + return ESP_OK; +} + +endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { + endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + add(endpoint, config); + return endpoint; +} +} // namespace multi_mode_thermostat +} // namespace endpoint +} // namespace esp_matter + +bool MatterThermostat::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter Thermostat device has not begun."); + return false; + } + log_d("Thermostat Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + + if (cluster_id == Thermostat::Id) { + switch (attribute_id) { + case Thermostat::Attributes::SystemMode::Id: + if (_onChangeModeCB != NULL) { + ret &= _onChangeModeCB((ThermostatMode_t)val->val.u8); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(); + } + if (ret == true) { + currentMode = (ThermostatMode_t)val->val.u8; + log_v("Thermostat Mode updated to %d", val->val.u8); + } + break; + case Thermostat::Attributes::LocalTemperature::Id: + if (_onChangeTemperatureCB != NULL) { + ret &= _onChangeTemperatureCB((float)val->val.i16 / 100.00); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(); + } + if (ret == true) { + localTemperature = val->val.i16; + log_v("Local Temperature updated to %.01fC", (float)val->val.i16 / 100.00); + } + break; + case Thermostat::Attributes::OccupiedCoolingSetpoint::Id: + if (_onChangeCoolingSetpointCB != NULL) { + ret &= _onChangeCoolingSetpointCB((float)val->val.i16 / 100.00); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(); + } + if (ret == true) { + coolingSetpointTemperature = val->val.i16; + log_v("Cooling Setpoint updated to %.01fC", (float)val->val.i16 / 100.00); + } + break; + case Thermostat::Attributes::OccupiedHeatingSetpoint::Id: + if (_onChangeHeatingSetpointCB != NULL) { + ret &= _onChangeHeatingSetpointCB((float)val->val.i16 / 100.00); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(); + } + if (ret == true) { + heatingSetpointTemperature = val->val.i16; + log_v("Heating Setpoint updated to %.01fC", (float)val->val.i16 / 100.00); + } + break; + default: log_w("Unhandled Thermostat Attribute ID: %u", attribute_id); break; + } + } + return ret; +} + +MatterThermostat::MatterThermostat() {} + +MatterThermostat::~MatterThermostat() { + end(); +} + +bool MatterThermostat::begin(ControlSequenceOfOperation_t _controlSequence, ThermostatAutoMode_t _autoMode) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter Thermostat with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + // check if auto mode is allowed with the control sequence of operation - only allowed for Cooling & Heating + if (_autoMode == THERMOSTAT_AUTO_MODE_ENABLED && _controlSequence != THERMOSTAT_SEQ_OP_COOLING_HEATING + && _controlSequence != THERMOSTAT_SEQ_OP_COOLING_HEATING_REHEAT) { + log_e("Thermostat in Auto Mode requires a Cooling & Heating Control Sequence of Operation."); + return false; + } + + const int16_t _localTemperature = 2000; // initial value to be automatically changed by the Matter Thermostat + const int16_t _coolingSetpointTemperature = 2400; // 24C cooling setpoint + const int16_t _heatingSetpointTemperature = 1600; // 16C heating setpoint + const ThermostatMode_t _currentMode = THERMOSTAT_MODE_OFF; + + multi_mode_thermostat::config_t thermostat_config; + thermostat_config.thermostat.control_sequence_of_operation = (uint8_t)_controlSequence; + thermostat_config.thermostat.cooling.occupied_cooling_setpoint = _coolingSetpointTemperature; + thermostat_config.thermostat.heating.occupied_heating_setpoint = _heatingSetpointTemperature; + thermostat_config.thermostat.system_mode = (uint8_t)_currentMode; + thermostat_config.thermostat.local_temperature = _localTemperature; + + // endpoint handles can be used to add/modify clusters + endpoint_t *endpoint = multi_mode_thermostat::create(node::get(), &thermostat_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create Thermostat endpoint"); + return false; + } + if (_autoMode == THERMOSTAT_AUTO_MODE_ENABLED) { + cluster_t *cluster = cluster::get(endpoint, Thermostat::Id); + thermostat_config.thermostat.auto_mode.min_setpoint_dead_band = kDefaultDeadBand; // fixed by default to 2.5C + cluster::thermostat::feature::auto_mode::add(cluster, &thermostat_config.thermostat.auto_mode); + } + + controlSequence = _controlSequence; + autoMode = _autoMode; + coolingSetpointTemperature = _coolingSetpointTemperature; + heatingSetpointTemperature = _heatingSetpointTemperature; + localTemperature = _localTemperature; + currentMode = _currentMode; + + setEndPointId(endpoint::get_id(endpoint)); + log_i("Thermostat created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterThermostat::end() { + started = false; +} + +bool MatterThermostat::setMode(ThermostatMode_t _mode) { + if (!started) { + log_e("Matter Thermostat device has not begun."); + return false; + } + + if (autoMode == THERMOSTAT_AUTO_MODE_DISABLED && _mode == THERMOSTAT_MODE_AUTO) { + log_e("Thermostat can't set Auto Mode."); + return false; + } + // check if the requested mode is valid based on the control sequence of operation + // no restrictions for OFF mode + if (_mode != THERMOSTAT_MODE_OFF) { + // check HEAT, COOL and AUTO modes + switch (controlSequence) { + case THERMOSTAT_SEQ_OP_COOLING: + case THERMOSTAT_SEQ_OP_COOLING_REHEAT: + if (_mode == THERMOSTAT_MODE_HEAT || _mode == THERMOSTAT_MODE_AUTO) { + break; + } + log_e("Invalid Thermostat Mode for Cooling Control Sequence of Operation."); + return false; + case THERMOSTAT_SEQ_OP_HEATING: + case THERMOSTAT_SEQ_OP_HEATING_REHEAT: + if (_mode == THERMOSTAT_MODE_COOL || _mode == THERMOSTAT_MODE_AUTO) { + break; + } + log_e("Invalid Thermostat Mode for Heating Control Sequence of Operation."); + return false; + default: + // compiler warning about not handling all enum values + break; + } + } + + // avoid processing if there was no change + if (currentMode == _mode) { + return true; + } + + esp_matter_attr_val_t modeVal = esp_matter_invalid(NULL); + if (!getAttributeVal(Thermostat::Id, Thermostat::Attributes::SystemMode::Id, &modeVal)) { + log_e("Failed to get Thermostat Mode Attribute."); + return false; + } + if (modeVal.val.u8 != _mode) { + modeVal.val.u8 = _mode; + bool ret; + ret = updateAttributeVal(Thermostat::Id, Thermostat::Attributes::SystemMode::Id, &modeVal); + if (!ret) { + log_e("Failed to update Thermostat Mode Attribute."); + return false; + } + currentMode = _mode; + } + log_v("Thermostat Mode set to %d", _mode); + + return true; +} + +bool MatterThermostat::setRawTemperature(int16_t _rawTemperature, uint32_t attribute_id, int16_t *internalValue) { + if (!started) { + log_e("Matter Thermostat device has not begun."); + return false; + } + + // avoid processing if there was no change + if (*internalValue == _rawTemperature) { + return true; + } + + esp_matter_attr_val_t temperatureVal = esp_matter_invalid(NULL); + if (!getAttributeVal(Thermostat::Id, attribute_id, &temperatureVal)) { + log_e("Failed to get Thermostat Temperature or Setpoint Attribute."); + return false; + } + if (temperatureVal.val.i16 != _rawTemperature) { + temperatureVal.val.i16 = _rawTemperature; + bool ret; + ret = updateAttributeVal(Thermostat::Id, attribute_id, &temperatureVal); + if (!ret) { + log_e("Failed to update Thermostat Temperature or Setpoint Attribute."); + return false; + } + *internalValue = _rawTemperature; + } + log_v("Temperature set to %.01fC", (float)_rawTemperature / 100.00); + + return true; +} + +bool MatterThermostat::setCoolingHeatingSetpoints(double _setpointHeatingTemperature, double _setpointCollingTemperature) { + // at least one of the setpoints must be valid + bool settingCooling = _setpointCollingTemperature != (float)0xffff; + bool settingHeating = _setpointHeatingTemperature != (float)0xffff; + if (!settingCooling && !settingHeating) { + log_e("Invalid Setpoints values. Set correctly at least one of them in Celsius."); + return false; + } + int16_t _rawHeatValue = static_cast(_setpointHeatingTemperature * 100.0f); + int16_t _rawCoolValue = static_cast(_setpointCollingTemperature * 100.0f); + + // check limits for the setpoints + if (settingHeating && (_rawHeatValue < kDefaultMinHeatSetpointLimit || _rawHeatValue > kDefaultMaxHeatSetpointLimit)) { + log_e( + "Invalid Heating Setpoint value: %.01fC - valid range %d..%d", _setpointHeatingTemperature, kDefaultMinHeatSetpointLimit / 100, + kDefaultMaxHeatSetpointLimit / 100 + ); + return false; + } + if (settingCooling && (_rawCoolValue < kDefaultMinCoolSetpointLimit || _rawCoolValue > kDefaultMaxCoolSetpointLimit)) { + log_e( + "Invalid Cooling Setpoint value: %.01fC - valid range %d..%d", _setpointCollingTemperature, kDefaultMinCoolSetpointLimit / 100, + kDefaultMaxCoolSetpointLimit / 100 + ); + return false; + } + + // AUTO mode requires both setpoints to be valid to each other and respect the deadband + if (currentMode == THERMOSTAT_MODE_AUTO) { +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR + float deadband = getDeadBand(); +#endif + // only setting Cooling Setpoint + if (settingCooling && !settingHeating && _rawCoolValue < (heatingSetpointTemperature + (kDefaultDeadBand * 10))) { + log_e( + "AutoMode :: Invalid Cooling Setpoint value: %.01fC - must be higher or equal than %.01fC", _setpointCollingTemperature, getHeatingSetpoint() + deadband + ); + return false; + } + // only setting Heating Setpoint + if (!settingCooling && settingHeating && _rawHeatValue > (coolingSetpointTemperature - (kDefaultDeadBand * 10))) { + log_e( + "AutoMode :: Invalid Heating Setpoint value: %.01fC - must be lower or equal than %.01fC", _setpointHeatingTemperature, getCoolingSetpoint() - deadband + ); + return false; + } + // setting both setpoints + if (settingCooling && settingHeating && (_rawCoolValue <= _rawHeatValue || _rawCoolValue - _rawHeatValue < kDefaultDeadBand * 10.0)) { + log_e( + "AutoMode :: Error - Heating Setpoint %.01fC must be lower than Cooling Setpoint %.01fC with a minimum difference of %0.1fC", + _setpointHeatingTemperature, _setpointCollingTemperature, deadband + ); + return false; + } + } + + bool ret = true; + if (settingCooling) { + ret &= setRawTemperature(_rawCoolValue, Thermostat::Attributes::OccupiedCoolingSetpoint::Id, &coolingSetpointTemperature); + } + if (settingHeating) { + ret &= setRawTemperature(_rawHeatValue, Thermostat::Attributes::OccupiedHeatingSetpoint::Id, &heatingSetpointTemperature); + } + return ret; +} + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterThermostat.h b/libraries/Matter/src/MatterEndpoints/MatterThermostat.h new file mode 100644 index 00000000000..2d64bdf3b01 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterThermostat.h @@ -0,0 +1,207 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace chip::app::Clusters; + +class MatterThermostat : public MatterEndPoint { +public: + // clang-format off + enum ControlSequenceOfOperation_t { + THERMOSTAT_SEQ_OP_COOLING = (uint8_t) Thermostat::ControlSequenceOfOperationEnum::kCoolingOnly, + THERMOSTAT_SEQ_OP_COOLING_REHEAT = (uint8_t) Thermostat::ControlSequenceOfOperationEnum::kCoolingWithReheat, + THERMOSTAT_SEQ_OP_HEATING = (uint8_t) Thermostat::ControlSequenceOfOperationEnum::kHeatingOnly, + THERMOSTAT_SEQ_OP_HEATING_REHEAT = (uint8_t) Thermostat::ControlSequenceOfOperationEnum::kHeatingWithReheat, + THERMOSTAT_SEQ_OP_COOLING_HEATING = (uint8_t) Thermostat::ControlSequenceOfOperationEnum::kCoolingAndHeating, + THERMOSTAT_SEQ_OP_COOLING_HEATING_REHEAT = (uint8_t) Thermostat::ControlSequenceOfOperationEnum::kCoolingAndHeatingWithReheat, + }; + + enum ThermostatMode_t { + THERMOSTAT_MODE_OFF = (uint8_t) Thermostat::SystemModeEnum::kOff, + THERMOSTAT_MODE_AUTO = (uint8_t) Thermostat::SystemModeEnum::kAuto, + THERMOSTAT_MODE_COOL = (uint8_t) Thermostat::SystemModeEnum::kCool, + THERMOSTAT_MODE_HEAT = (uint8_t) Thermostat::SystemModeEnum::kHeat, + THERMOSTAT_MODE_EMERGENCY_HEAT = (uint8_t) Thermostat::SystemModeEnum::kEmergencyHeat, + THERMOSTAT_MODE_PRECOOLING = (uint8_t) Thermostat::SystemModeEnum::kPrecooling, + THERMOSTAT_MODE_FAN_ONLY = (uint8_t) Thermostat::SystemModeEnum::kFanOnly, + THERMOSTAT_MODE_DRY = (uint8_t) Thermostat::SystemModeEnum::kDry, + THERMOSTAT_MODE_SLEEP = (uint8_t) Thermostat::SystemModeEnum::kSleep + }; + + enum ThermostatAutoMode_t { + THERMOSTAT_AUTO_MODE_DISABLED = (uint8_t) Thermostat::SystemModeEnum::kOff, + THERMOSTAT_AUTO_MODE_ENABLED = (uint8_t) Thermostat::SystemModeEnum::kAuto, + }; + // clang-format on + + MatterThermostat(); + ~MatterThermostat(); + // begin Matter Thermostat endpoint with initial Operation Mode + bool begin(ControlSequenceOfOperation_t controlSequence = THERMOSTAT_SEQ_OP_COOLING, ThermostatAutoMode_t autoMode = THERMOSTAT_AUTO_MODE_DISABLED); + // this will stop processing Thermostat Matter events + void end(); + + // set the Thermostat Mode + bool setMode(ThermostatMode_t mode); + // get the Thermostat Mode + ThermostatMode_t getMode() { + return currentMode; + } + // returns a friendly string for the Fan Mode + static const char *getThermostatModeString(uint8_t mode) { + return thermostatModeString[mode]; + } + + // get the Thermostat Control Sequence of Operation + ControlSequenceOfOperation_t getControlSequence() { + return controlSequence; + } + + // get the minimum heating setpoint in 1/100th of a Celsio degree + float getMinHeatSetpoint() { + return (float)kDefaultMinHeatSetpointLimit / 100.00; + } + // get the maximum heating setpoint in 1/100th of a Celsio degree + float getMaxHeatSetpoint() { + return (float)kDefaultMaxHeatSetpointLimit / 100.00; + } + // get the minimum cooling setpoint in 1/100th of a Celsio degree + float getMinCoolSetpoint() { + return (float)kDefaultMinCoolSetpointLimit / 100.00; + } + // get the maximum cooling setpoint in 1/100th of a Celsio degree + float getMaxCoolSetpoint() { + return (float)kDefaultMaxCoolSetpointLimit / 100.00; + } + // get the deadband in 1/10th of a Celsio degree + float getDeadBand() { + return (float)kDefaultDeadBand / 10.00; + } + + // generic function for setting the cooling and heating setpoints - checks if the setpoints are valid + // it can be used to set both setpoints at the same time or only one of them, by setting the other to (float)0xffff + // Heating Setpoint must be lower than Cooling Setpoint + // When using AUTO mode the Cooling Setpoint must be higher than Heating Setpoint by at least the 2.5C (deadband) + // Thermostat Matter Server will enforce those rules and the Max/Min setpoints limits as in the Matter Specification + bool setCoolingHeatingSetpoints(double _setpointHeatingTemperature, double _setpointCollingTemperature); + + // set the heating setpoint in 1/100th of a Celsio degree + bool setHeatingSetpoint(double _setpointHeatingTemperature) { + return setCoolingHeatingSetpoints((double)0xffff, _setpointHeatingTemperature); + } + // get the heating setpoint in 1/100th of a Celsio degree + double getHeatingSetpoint() { + return heatingSetpointTemperature / 100.0; + } + // set the cooling setpoint in 1/100th of a Celsio degree + bool setCoolingSetpoint(double _setpointCollingTemperature) { + return setCoolingHeatingSetpoints(_setpointCollingTemperature, (double)0xffff); + } + // get the cooling setpoint in 1/100th of a Celsio degree + double getCoolingSetpoint() { + return coolingSetpointTemperature / 100.0; + } + + // set the local Thermostat temperature in Celsio degrees + bool setLocalTemperature(double temperature) { + // stores up to 1/100th of a Celsio degree precision + int16_t rawValue = static_cast(temperature * 100.0f); + return setRawTemperature(rawValue, Thermostat::Attributes::LocalTemperature::Id, &localTemperature); + } + // returns the local Thermostat float temperature with 1/100th of a Celsio degree precision + double getLocalTemperature() { + return (double)localTemperature / 100.0; + } + + // User Callback for whenever the Thermostat Mode is changed by the Matter Controller + using EndPointModeCB = std::function; + void onChangeMode(EndPointModeCB onChangeCB) { + _onChangeModeCB = onChangeCB; + } + + // User Callback for whenever the Local Temperature is changed by the Matter Controller + using EndPointTemperatureCB = std::function; + void onChangeLocalTemperature(EndPointTemperatureCB onChangeCB) { + _onChangeTemperatureCB = onChangeCB; + } + + // User Callback for whenever the Cooling or Heating Setpoint is changed by the Matter Controller + using EndPointCoolingSetpointCB = std::function; + void onChangeCoolingSetpoint(EndPointCoolingSetpointCB onChangeCB) { + _onChangeCoolingSetpointCB = onChangeCB; + } + + // User Callback for whenever the Cooling or Heating Setpoint is changed by the Matter Controller + using EndPointHeatingSetpointCB = std::function; + void onChangeHeatingSetpoint(EndPointHeatingSetpointCB onChangeCB) { + _onChangeHeatingSetpointCB = onChangeCB; + } + + // User Callback for whenever any parameter is changed by the Matter Controller + // Main parameters are Thermostat Mode, Local Temperature, Cooling Setpoint and Heating Setpoint + // Those can be obtained using getMode(), getTemperature(), getCoolingSetpoint() and getHeatingSetpoint() + using EndPointCB = std::function; + void onChange(EndPointCB onChangeCB) { + _onChangeCB = onChangeCB; + } + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + // implementation keeps temperature in 1/100th of a Celsio degree + int16_t coolingSetpointTemperature = 2400; // 24C cooling setpoint + int16_t localTemperature = 2000; // 20C local temperature + int16_t heatingSetpointTemperature = 1600; // 16C heating setpoint + + ThermostatMode_t currentMode = THERMOSTAT_MODE_OFF; + ControlSequenceOfOperation_t controlSequence = THERMOSTAT_SEQ_OP_COOLING; + ThermostatAutoMode_t autoMode = THERMOSTAT_AUTO_MODE_DISABLED; + + EndPointModeCB _onChangeModeCB = NULL; + EndPointTemperatureCB _onChangeTemperatureCB = NULL; + EndPointCoolingSetpointCB _onChangeCoolingSetpointCB = NULL; + EndPointHeatingSetpointCB _onChangeHeatingSetpointCB = NULL; + EndPointCB _onChangeCB = NULL; + + // internal function to set the raw temperature value (Matter Cluster) + bool setRawTemperature(int16_t _rawTemperature, uint32_t attribute_id, int16_t *internalValue); + + // clang-format off + // Default Thermostat values - can't be changed - defined in the Thermostat Cluster Server code + static const int16_t kDefaultAbsMinHeatSetpointLimit = 700; // 7C (44.5 F) + static const int16_t kDefaultMinHeatSetpointLimit = 700; // 7C (44.5 F) + static const int16_t kDefaultAbsMaxHeatSetpointLimit = 3000; // 30C (86 F) + static const int16_t kDefaultMaxHeatSetpointLimit = 3000; // 30C (86 F) + + static const int16_t kDefaultAbsMinCoolSetpointLimit = 1600; // 16C (61 F) + static const int16_t kDefaultMinCoolSetpointLimit = 1600; // 16C (61 F) + static const int16_t kDefaultAbsMaxCoolSetpointLimit = 3200; // 32C (90 F) + static const int16_t kDefaultMaxCoolSetpointLimit = 3200; // 32C (90 F) + + static const int8_t kDefaultDeadBand = 25; // 2.5C when in AUTO mode + // clang-format on + + // string helper for the THERMOSTAT MODE + static const char *thermostatModeString[5]; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/NetBIOS/examples/ESP_NBNST/ci.json b/libraries/NetBIOS/examples/ESP_NBNST/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/NetBIOS/examples/ESP_NBNST/ci.json +++ b/libraries/NetBIOS/examples/ESP_NBNST/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/NetBIOS/library.properties b/libraries/NetBIOS/library.properties index c1ca95d1c5b..5f134bfdc55 100644 --- a/libraries/NetBIOS/library.properties +++ b/libraries/NetBIOS/library.properties @@ -1,5 +1,5 @@ name=NetBIOS -version=2.0.0 +version=3.2.0 author=Pablo@xpablo.cz maintainer=Hristo Gochkov sentence=Enables NBNS (NetBIOS) name resolution. diff --git a/libraries/NetBIOS/src/NetBIOS.cpp b/libraries/NetBIOS/src/NetBIOS.cpp index 6d3f274a137..647f0940898 100644 --- a/libraries/NetBIOS/src/NetBIOS.cpp +++ b/libraries/NetBIOS/src/NetBIOS.cpp @@ -1,5 +1,8 @@ #include "NetBIOS.h" #include +extern "C" { +#include +}; // extern "C" #define NBNS_PORT 137 #define NBNS_MAX_HOSTNAME_LEN 32 @@ -9,7 +12,7 @@ typedef struct { uint8_t flags1; uint8_t flags2; uint16_t qcount; - uint16_t acount; + uint16_t acount; // codespell:ignore acount uint16_t nscount; uint16_t adcount; uint8_t name_len; @@ -23,7 +26,7 @@ typedef struct { uint8_t flags1; uint8_t flags2; uint16_t qcount; - uint16_t acount; + uint16_t acount; // codespell:ignore acount uint16_t nscount; uint16_t adcount; uint8_t name_len; @@ -81,7 +84,7 @@ void NetBIOS::_onPacket(AsyncUDPPacket &packet) { nbnsa.flags1 = 0x85; nbnsa.flags2 = 0; append_16((void *)&nbnsa.qcount, 0); - append_16((void *)&nbnsa.acount, 1); + append_16((void *)&nbnsa.acount, 1); // codespell:ignore acount append_16((void *)&nbnsa.nscount, 0); append_16((void *)&nbnsa.adcount, 0); nbnsa.name_len = question->name_len; @@ -91,7 +94,16 @@ void NetBIOS::_onPacket(AsyncUDPPacket &packet) { append_32((void *)&nbnsa.ttl, 300000); append_16((void *)&nbnsa.data_len, 6); append_16((void *)&nbnsa.flags, 0); - nbnsa.addr = packet.localIP(); + nbnsa.addr = packet.localIP(); // By default, should be overridden below + // Iterate over all netifs, see if the incoming address matches one of the netmaskes networks + for (auto netif = netif_list; netif; netif = netif->next) { + auto maskedip = ip4_addr_get_u32(netif_ip4_addr(netif)) & ip4_addr_get_u32(netif_ip4_netmask(netif)); + auto maskedin = ((uint32_t)packet.localIP()) & ip4_addr_get_u32(netif_ip4_netmask(netif)); + if (maskedip == maskedin) { + nbnsa.addr = ip4_addr_get_u32(netif_ip4_addr(netif)); + break; + } + } _udp.writeTo((uint8_t *)&nbnsa, sizeof(nbnsa), packet.remoteIP(), NBNS_PORT); } } diff --git a/libraries/Network/library.properties b/libraries/Network/library.properties index 8143c8045bc..0b821e08d77 100644 --- a/libraries/Network/library.properties +++ b/libraries/Network/library.properties @@ -1,5 +1,5 @@ name=Networking -version=1.0.0 +version=3.2.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=General network management library. diff --git a/libraries/Network/src/NetworkClient.cpp b/libraries/Network/src/NetworkClient.cpp index 9f4806df18a..89411a42453 100644 --- a/libraries/Network/src/NetworkClient.cpp +++ b/libraries/Network/src/NetworkClient.cpp @@ -23,7 +23,11 @@ #include #include -#define IN6_IS_ADDR_V4MAPPED(a) ((((__const uint32_t *)(a))[0] == 0) && (((__const uint32_t *)(a))[1] == 0) && (((__const uint32_t *)(a))[2] == htonl(0xffff))) +// It is already defined in IDF as: +//#define IN6_IS_ADDR_V4MAPPED(a) ip6_addr_isipv4mappedipv6((ip6_addr_t*)(a)) +//#define ip6_addr_isipv4mappedipv6(ip6addr) (((ip6addr)->addr[0] == 0) && ((ip6addr)->addr[1] == 0) && (((ip6addr)->addr[2]) == PP_HTONL(0x0000FFFFUL))) +// Keeping as a memory of the change. +//#define _IN6_IS_ADDR_V4MAPPED(a) ((((__const uint32_t *)(a))[0] == 0) && (((__const uint32_t *)(a))[1] == 0) && (((__const uint32_t *)(a))[2] == htonl(0xffff))) #define WIFI_CLIENT_DEF_CONN_TIMEOUT_MS (3000) #define WIFI_CLIENT_MAX_WRITE_RETRY (10) @@ -148,9 +152,13 @@ class NetworkClientRxBuffer { void clear() { if (r_available()) { - fillBuffer(); + _pos = _fill; + while (fillBuffer()) { + _pos = _fill; + } } - _pos = _fill; + _pos = 0; + _fill = 0; } }; @@ -206,6 +214,7 @@ int NetworkClient::connect(IPAddress ip, uint16_t port, int32_t timeout_ms) { _timeout = timeout_ms; int sockfd = -1; +#if CONFIG_LWIP_IPV6 if (ip.type() == IPv6) { struct sockaddr_in6 *tmpaddr = (struct sockaddr_in6 *)&serveraddr; sockfd = socket(AF_INET6, SOCK_STREAM, 0); @@ -214,12 +223,15 @@ int NetworkClient::connect(IPAddress ip, uint16_t port, int32_t timeout_ms) { tmpaddr->sin6_port = htons(port); tmpaddr->sin6_scope_id = ip.zone(); } else { +#endif struct sockaddr_in *tmpaddr = (struct sockaddr_in *)&serveraddr; sockfd = socket(AF_INET, SOCK_STREAM, 0); tmpaddr->sin_family = AF_INET; tmpaddr->sin_addr.s_addr = ip; tmpaddr->sin_port = htons(port); +#if CONFIG_LWIP_IPV6 } +#endif if (sockfd < 0) { log_e("socket: %d", errno); return 0; @@ -369,7 +381,9 @@ int NetworkClient::read() { return data; } -void NetworkClient::flush() {} +void NetworkClient::flush() { + clear(); +} size_t NetworkClient::write(const uint8_t *buf, size_t size) { int res = 0; @@ -543,7 +557,7 @@ uint8_t NetworkClient::connected() { } if (_connected) { uint8_t dummy; - int res = recv(fd(), &dummy, 0, MSG_DONTWAIT); + int res = recv(fd(), &dummy, 1, MSG_DONTWAIT | MSG_PEEK); // avoid unused var warning by gcc (void)res; // recv only sets errno if res is <= 0 @@ -584,6 +598,7 @@ IPAddress NetworkClient::remoteIP(int fd) const { return IPAddress((uint32_t)(s->sin_addr.s_addr)); } +#if CONFIG_LWIP_IPV6 // IPv6, but it might be IPv4 mapped address if (((struct sockaddr *)&addr)->sa_family == AF_INET6) { struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr; @@ -594,6 +609,7 @@ IPAddress NetworkClient::remoteIP(int fd) const { } } log_e("NetworkClient::remoteIP Not AF_INET or AF_INET6?"); +#endif return (IPAddress(0, 0, 0, 0)); } @@ -624,6 +640,7 @@ IPAddress NetworkClient::localIP(int fd) const { return IPAddress((uint32_t)(s->sin_addr.s_addr)); } +#if CONFIG_LWIP_IPV6 // IPv6, but it might be IPv4 mapped address if (((struct sockaddr *)&addr)->sa_family == AF_INET6) { struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr; @@ -634,6 +651,7 @@ IPAddress NetworkClient::localIP(int fd) const { } } log_e("NetworkClient::localIP Not AF_INET or AF_INET6?"); +#endif return (IPAddress(0, 0, 0, 0)); } diff --git a/libraries/Network/src/NetworkClient.h b/libraries/Network/src/NetworkClient.h index 572292a7a99..52df868a0b0 100644 --- a/libraries/Network/src/NetworkClient.h +++ b/libraries/Network/src/NetworkClient.h @@ -28,20 +28,21 @@ class NetworkClientRxBuffer; class ESPLwIPClient : public Client { public: + virtual void setConnectionTimeout(uint32_t milliseconds) = 0; + using Client::connect; virtual int connect(IPAddress ip, uint16_t port, int32_t timeout) = 0; virtual int connect(const char *host, uint16_t port, int32_t timeout) = 0; - virtual void setConnectionTimeout(uint32_t milliseconds) = 0; }; class NetworkClient : public ESPLwIPClient { protected: - std::shared_ptr clientSocketHandle; - std::shared_ptr _rxBuffer; - bool _connected; - bool _sse; + std::shared_ptr clientSocketHandle = nullptr; + std::shared_ptr _rxBuffer = nullptr; + bool _connected = false; + bool _sse = false; int _timeout; - int _lastWriteTimeout; - int _lastReadTimeout; + int _lastWriteTimeout = 0; + int _lastReadTimeout = 0; public: NetworkClient *next; @@ -56,6 +57,7 @@ class NetworkClient : public ESPLwIPClient { size_t write(const uint8_t *buf, size_t size); size_t write_P(PGM_P buf, size_t size); size_t write(Stream &stream); + [[deprecated("Use clear() instead.")]] void flush(); // Print::flush tx int available(); int read(); diff --git a/libraries/Network/src/NetworkEvents.cpp b/libraries/Network/src/NetworkEvents.cpp index 9ebf00b476a..161e55c5d01 100644 --- a/libraries/Network/src/NetworkEvents.cpp +++ b/libraries/Network/src/NetworkEvents.cpp @@ -8,27 +8,9 @@ #include "esp_task.h" #include "esp32-hal.h" -typedef struct NetworkEventCbList { - static network_event_handle_t current_id; - network_event_handle_t id; - NetworkEventCb cb; - NetworkEventFuncCb fcb; - NetworkEventSysCb scb; - arduino_event_id_t event; - - NetworkEventCbList() : id(current_id++), cb(NULL), fcb(NULL), scb(NULL), event(ARDUINO_EVENT_NONE) {} -} NetworkEventCbList_t; -network_event_handle_t NetworkEventCbList::current_id = 1; - -// arduino dont like std::vectors move static here -static std::vector cbEventList; - -static void _network_event_task(void *arg) { - for (;;) { - ((NetworkEvents *)arg)->checkForEvent(); - } - vTaskDelete(NULL); -} +#ifndef ARDUINO_NETWORK_EVENT_TASK_STACK_SIZE +#define ARDUINO_NETWORK_EVENT_TASK_STACK_SIZE 4096 +#endif NetworkEvents::NetworkEvents() : _arduino_event_group(NULL), _arduino_event_queue(NULL), _arduino_event_task_handle(NULL) {} @@ -43,8 +25,9 @@ NetworkEvents::~NetworkEvents() { } if (_arduino_event_queue != NULL) { arduino_event_t *event = NULL; + // consume queue while (xQueueReceive(_arduino_event_queue, &event, 0) == pdTRUE) { - free(event); + delete event; } vQueueDelete(_arduino_event_queue); _arduino_event_queue = NULL; @@ -78,7 +61,14 @@ bool NetworkEvents::initNetworkEvents() { } if (!_arduino_event_task_handle) { - xTaskCreateUniversal(_network_event_task, "arduino_events", 4096, this, ESP_TASKD_EVENT_PRIO - 1, &_arduino_event_task_handle, ARDUINO_EVENT_RUNNING_CORE); + xTaskCreateUniversal( + [](void *self) { + static_cast(self)->_checkForEvent(); + }, + "arduino_events", // label + ARDUINO_NETWORK_EVENT_TASK_STACK_SIZE, // event task's stack size + this, ESP_TASKD_EVENT_PRIO - 1, &_arduino_event_task_handle, ARDUINO_EVENT_RUNNING_CORE + ); if (!_arduino_event_task_handle) { log_e("Network Event Task Start Failed!"); return false; @@ -88,128 +78,163 @@ bool NetworkEvents::initNetworkEvents() { return true; } -bool NetworkEvents::postEvent(arduino_event_t *data) { +bool NetworkEvents::postEvent(const arduino_event_t *data) { if (data == NULL || _arduino_event_queue == NULL) { return false; } - arduino_event_t *event = (arduino_event_t *)malloc(sizeof(arduino_event_t)); + arduino_event_t *event = new arduino_event_t(); if (event == NULL) { log_e("Arduino Event Malloc Failed!"); return false; } + memcpy(event, data, sizeof(arduino_event_t)); if (xQueueSend(_arduino_event_queue, &event, portMAX_DELAY) != pdPASS) { log_e("Arduino Event Send Failed!"); + delete event; // release mem on error return false; } return true; } -void NetworkEvents::checkForEvent() { - arduino_event_t *event = NULL; +void NetworkEvents::_checkForEvent() { + // this task can't run without the queue if (_arduino_event_queue == NULL) { + _arduino_event_task_handle = NULL; + vTaskDelete(NULL); return; } - if (xQueueReceive(_arduino_event_queue, &event, portMAX_DELAY) != pdTRUE) { - return; - } - if (event == NULL) { - return; - } - log_v("Network Event: %d - %s", event->event_id, eventName(event->event_id)); - for (uint32_t i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (entry.cb || entry.fcb || entry.scb) { - if (entry.event == (arduino_event_id_t)event->event_id || entry.event == ARDUINO_EVENT_MAX) { - if (entry.cb) { - entry.cb((arduino_event_id_t)event->event_id); - } else if (entry.fcb) { - entry.fcb((arduino_event_id_t)event->event_id, (arduino_event_info_t)event->event_info); - } else { - entry.scb(event); + + for (;;) { + arduino_event_t *event = NULL; + // wait for an event on a queue + if (xQueueReceive(_arduino_event_queue, &event, portMAX_DELAY) != pdTRUE) { + continue; + } + if (event == NULL) { + continue; + } + log_v("Network Event: %d - %s", event->event_id, eventName(event->event_id)); + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::unique_lock lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + // iterate over registered callbacks + for (auto &i : _cbEventList) { + if (i.cb || i.fcb || i.scb) { + if (i.event == (arduino_event_id_t)event->event_id || i.event == ARDUINO_EVENT_MAX) { + if (i.cb) { + i.cb((arduino_event_id_t)event->event_id); + continue; + } + + if (i.fcb) { + i.fcb((arduino_event_id_t)event->event_id, (arduino_event_info_t)event->event_info); + continue; + } + + i.scb(event); } } } + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + lock.unlock(); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + // release the event object's memory + delete event; + } + + vTaskDelete(NULL); +} + +template static size_t getStdFunctionAddress(std::function f) { + typedef T(fnType)(U...); + fnType **fnPointer = f.template target(); + if (fnPointer != nullptr) { + return (size_t)*fnPointer; } - free(event); + return (size_t)fnPointer; } network_event_handle_t NetworkEvents::onEvent(NetworkEventCb cbEvent, arduino_event_id_t event) { if (!cbEvent) { return 0; } - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = cbEvent; - newEventHandler.fcb = NULL; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); - return newEventHandler.id; + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + _cbEventList.emplace_back(++_current_id, cbEvent, nullptr, nullptr, event); + return _cbEventList.back().id; } network_event_handle_t NetworkEvents::onEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event) { if (!cbEvent) { return 0; } - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = cbEvent; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); - return newEventHandler.id; + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + _cbEventList.emplace_back(++_current_id, nullptr, cbEvent, nullptr, event); + return _cbEventList.back().id; } network_event_handle_t NetworkEvents::onEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event) { if (!cbEvent) { return 0; } - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = NULL; - newEventHandler.scb = cbEvent; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); - return newEventHandler.id; + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + _cbEventList.emplace_back(++_current_id, nullptr, nullptr, cbEvent, event); + return _cbEventList.back().id; } network_event_handle_t NetworkEvents::onSysEvent(NetworkEventCb cbEvent, arduino_event_id_t event) { if (!cbEvent) { return 0; } - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = cbEvent; - newEventHandler.fcb = NULL; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.insert(cbEventList.begin(), newEventHandler); - return newEventHandler.id; + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + _cbEventList.emplace(_cbEventList.begin(), ++_current_id, cbEvent, nullptr, nullptr, event); + return _cbEventList.front().id; } network_event_handle_t NetworkEvents::onSysEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event) { if (!cbEvent) { return 0; } - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = cbEvent; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.insert(cbEventList.begin(), newEventHandler); - return newEventHandler.id; + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + _cbEventList.emplace(_cbEventList.begin(), ++_current_id, nullptr, cbEvent, nullptr, event); + return _cbEventList.front().id; } network_event_handle_t NetworkEvents::onSysEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event) { if (!cbEvent) { return 0; } - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = NULL; - newEventHandler.scb = cbEvent; - newEventHandler.event = event; - cbEventList.insert(cbEventList.begin(), newEventHandler); - return newEventHandler.id; + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + _cbEventList.emplace(_cbEventList.begin(), ++_current_id, nullptr, nullptr, cbEvent, event); + return _cbEventList.front().id; } void NetworkEvents::removeEvent(NetworkEventCb cbEvent, arduino_event_id_t event) { @@ -217,18 +242,19 @@ void NetworkEvents::removeEvent(NetworkEventCb cbEvent, arduino_event_id_t event return; } - for (uint32_t i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (entry.cb == cbEvent && entry.event == event) { - cbEventList.erase(cbEventList.begin() + i); - } - } -} +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 -template static size_t getStdFunctionAddress(std::function f) { - typedef T(fnType)(U...); - fnType **fnPointer = f.template target(); - return (size_t)*fnPointer; + _cbEventList.erase( + std::remove_if( + _cbEventList.begin(), _cbEventList.end(), + [cbEvent, event](const NetworkEventCbList_t &e) { + return e.cb == cbEvent && e.event == event; + } + ), + _cbEventList.end() + ); } void NetworkEvents::removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event) { @@ -236,12 +262,19 @@ void NetworkEvents::removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t e return; } - for (uint32_t i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (getStdFunctionAddress(entry.fcb) == getStdFunctionAddress(cbEvent) && entry.event == event) { - cbEventList.erase(cbEventList.begin() + i); - } - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + _cbEventList.erase( + std::remove_if( + _cbEventList.begin(), _cbEventList.end(), + [cbEvent, event](const NetworkEventCbList_t &e) { + return getStdFunctionAddress(e.fcb) == getStdFunctionAddress(cbEvent) && e.event == event; + } + ), + _cbEventList.end() + ); } void NetworkEvents::removeEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event) { @@ -249,21 +282,35 @@ void NetworkEvents::removeEvent(NetworkEventSysCb cbEvent, arduino_event_id_t ev return; } - for (uint32_t i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (entry.scb == cbEvent && entry.event == event) { - cbEventList.erase(cbEventList.begin() + i); - } - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + _cbEventList.erase( + std::remove_if( + _cbEventList.begin(), _cbEventList.end(), + [cbEvent, event](const NetworkEventCbList_t &e) { + return e.scb == cbEvent && e.event == event; + } + ), + _cbEventList.end() + ); } void NetworkEvents::removeEvent(network_event_handle_t id) { - for (uint32_t i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (entry.id == id) { - cbEventList.erase(cbEventList.begin() + i); - } - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + _cbEventList.erase( + std::remove_if( + _cbEventList.begin(), _cbEventList.end(), + [id](const NetworkEventCbList_t &e) { + return e.id == id; + } + ), + _cbEventList.end() + ); } int NetworkEvents::setStatusBits(int bits) { @@ -282,7 +329,7 @@ int NetworkEvents::clearStatusBits(int bits) { return xEventGroupClearBits(_arduino_event_group, bits); } -int NetworkEvents::getStatusBits() { +int NetworkEvents::getStatusBits() const { if (!_arduino_event_group) { return _initial_bits; } @@ -325,7 +372,7 @@ const char *NetworkEvents::eventName(arduino_event_id_t id) { case ARDUINO_EVENT_PPP_GOT_IP: return "PPP_GOT_IP"; case ARDUINO_EVENT_PPP_LOST_IP: return "PPP_LOST_IP"; case ARDUINO_EVENT_PPP_GOT_IP6: return "PPP_GOT_IP6"; -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED case ARDUINO_EVENT_WIFI_OFF: return "WIFI_OFF"; case ARDUINO_EVENT_WIFI_READY: return "WIFI_READY"; case ARDUINO_EVENT_WIFI_SCAN_DONE: return "SCAN_DONE"; diff --git a/libraries/Network/src/NetworkEvents.h b/libraries/Network/src/NetworkEvents.h index 6c0e82f4d81..34a54cab092 100644 --- a/libraries/Network/src/NetworkEvents.h +++ b/libraries/Network/src/NetworkEvents.h @@ -5,27 +5,35 @@ */ #pragma once +#include "sdkconfig.h" #include "soc/soc_caps.h" #include "esp_err.h" #include "esp_event.h" #include "esp_netif_types.h" +#if CONFIG_ETH_ENABLED #include "esp_eth_driver.h" +#endif #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "freertos/semphr.h" #include "freertos/event_groups.h" +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 +#include +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "esp_wifi_types.h" #include "esp_smartconfig.h" -#include "wifi_provisioning/wifi_config.h" +#if CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#include "network_provisioning/network_config.h" +#endif #endif -#if SOC_WIFI_SUPPORTED -static const int WIFI_SCANNING_BIT = BIT0; -static const int WIFI_SCAN_DONE_BIT = BIT1; +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED +constexpr int WIFI_SCANNING_BIT = BIT0; +constexpr int WIFI_SCAN_DONE_BIT = BIT1; #endif #define NET_HAS_IP6_GLOBAL_BIT 0 @@ -33,7 +41,7 @@ static const int WIFI_SCAN_DONE_BIT = BIT1; ESP_EVENT_DECLARE_BASE(ARDUINO_EVENTS); typedef enum { - ARDUINO_EVENT_NONE, + ARDUINO_EVENT_NONE = 0, ARDUINO_EVENT_ETH_START, ARDUINO_EVENT_ETH_STOP, ARDUINO_EVENT_ETH_CONNECTED, @@ -41,11 +49,12 @@ typedef enum { ARDUINO_EVENT_ETH_GOT_IP, ARDUINO_EVENT_ETH_LOST_IP, ARDUINO_EVENT_ETH_GOT_IP6, -#if SOC_WIFI_SUPPORTED - ARDUINO_EVENT_WIFI_OFF, +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED + ARDUINO_EVENT_WIFI_OFF = 100, ARDUINO_EVENT_WIFI_READY, ARDUINO_EVENT_WIFI_SCAN_DONE, - ARDUINO_EVENT_WIFI_STA_START, + ARDUINO_EVENT_WIFI_FTM_REPORT, + ARDUINO_EVENT_WIFI_STA_START = 110, ARDUINO_EVENT_WIFI_STA_STOP, ARDUINO_EVENT_WIFI_STA_CONNECTED, ARDUINO_EVENT_WIFI_STA_DISCONNECTED, @@ -53,24 +62,23 @@ typedef enum { ARDUINO_EVENT_WIFI_STA_GOT_IP, ARDUINO_EVENT_WIFI_STA_GOT_IP6, ARDUINO_EVENT_WIFI_STA_LOST_IP, - ARDUINO_EVENT_WIFI_AP_START, + ARDUINO_EVENT_WIFI_AP_START = 130, ARDUINO_EVENT_WIFI_AP_STOP, ARDUINO_EVENT_WIFI_AP_STACONNECTED, ARDUINO_EVENT_WIFI_AP_STADISCONNECTED, ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED, ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED, ARDUINO_EVENT_WIFI_AP_GOT_IP6, - ARDUINO_EVENT_WIFI_FTM_REPORT, - ARDUINO_EVENT_WPS_ER_SUCCESS, + ARDUINO_EVENT_WPS_ER_SUCCESS = 140, ARDUINO_EVENT_WPS_ER_FAILED, ARDUINO_EVENT_WPS_ER_TIMEOUT, ARDUINO_EVENT_WPS_ER_PIN, ARDUINO_EVENT_WPS_ER_PBC_OVERLAP, - ARDUINO_EVENT_SC_SCAN_DONE, + ARDUINO_EVENT_SC_SCAN_DONE = 150, ARDUINO_EVENT_SC_FOUND_CHANNEL, ARDUINO_EVENT_SC_GOT_SSID_PSWD, ARDUINO_EVENT_SC_SEND_ACK_DONE, - ARDUINO_EVENT_PROV_INIT, + ARDUINO_EVENT_PROV_INIT = 160, ARDUINO_EVENT_PROV_DEINIT, ARDUINO_EVENT_PROV_START, ARDUINO_EVENT_PROV_END, @@ -78,7 +86,7 @@ typedef enum { ARDUINO_EVENT_PROV_CRED_FAIL, ARDUINO_EVENT_PROV_CRED_SUCCESS, #endif - ARDUINO_EVENT_PPP_START, + ARDUINO_EVENT_PPP_START = 200, ARDUINO_EVENT_PPP_STOP, ARDUINO_EVENT_PPP_CONNECTED, ARDUINO_EVENT_PPP_DISCONNECTED, @@ -92,8 +100,10 @@ typedef union { ip_event_ap_staipassigned_t wifi_ap_staipassigned; ip_event_got_ip_t got_ip; ip_event_got_ip6_t got_ip6; +#if CONFIG_ETH_ENABLED esp_eth_handle_t eth_connected; -#if SOC_WIFI_SUPPORTED +#endif +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED wifi_event_sta_scan_done_t wifi_scan_done; wifi_event_sta_authmode_change_t wifi_sta_authmode_change; wifi_event_sta_connected_t wifi_sta_connected; @@ -104,42 +114,133 @@ typedef union { wifi_event_ap_staconnected_t wifi_ap_staconnected; wifi_event_ap_stadisconnected_t wifi_ap_stadisconnected; wifi_event_ftm_report_t wifi_ftm_report; +#endif +#if SOC_WIFI_SUPPORTED wifi_sta_config_t prov_cred_recv; - wifi_prov_sta_fail_reason_t prov_fail_reason; +#if CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + network_prov_wifi_sta_fail_reason_t prov_fail_reason; +#endif smartconfig_event_got_ssid_pswd_t sc_got_ssid_pswd; #endif } arduino_event_info_t; -typedef struct { +/** + * @brief struct combines arduino event id and event's data object + * + */ +struct arduino_event_t { arduino_event_id_t event_id; arduino_event_info_t event_info; -} arduino_event_t; - -typedef void (*NetworkEventCb)(arduino_event_id_t event); -typedef std::function NetworkEventFuncCb; -typedef void (*NetworkEventSysCb)(arduino_event_t *event); +}; -typedef size_t network_event_handle_t; +// type aliases +using NetworkEventCb = void (*)(arduino_event_id_t event); +using NetworkEventFuncCb = std::function; +using NetworkEventSysCb = void (*)(arduino_event_t *event); +using network_event_handle_t = size_t; +/** + * @brief Class that provides network events callback handling + * it registers user callback functions for event handling, + * maintains the queue of events and propagates the event among subscribed callbacks + * callback are called in the context of a dedicated task consuming the queue + * + */ class NetworkEvents { public: NetworkEvents(); ~NetworkEvents(); + /** + * @brief register callback function to be executed on arduino event(s) + * @note if same handler is registered twice or more than same handler would be called twice or more times + * + * @param cbEvent static callback function + * @param event event to process, any event by default + * @return network_event_handle_t + */ network_event_handle_t onEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief register functional callback to be executed on arduino event(s) + * also used for lambda callbacks + * @note if same handler is registered twice or more than same handler would be called twice or more times + * + * @param cbEvent static callback function + * @param event event to process, any event by default + * @return network_event_handle_t + */ network_event_handle_t onEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief register static system callback to be executed on arduino event(s) + * callback function would be supplied with a pointer to arduino_event_t structure as an argument + * + * @note if same handler is registered twice or more than same handler would be called twice or more times + * + * @param cbEvent static callback function + * @param event event to process, any event by default + * @return network_event_handle_t + */ network_event_handle_t onEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief unregister static function callback + * @note a better way to unregister callbacks is to save/unregister via network_event_handle_t + * + * @param cbEvent static callback function + * @param event event to process, any event by default + */ void removeEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); - void removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief unregister functional callback + * @note a better way to unregister callbacks is to save/unregister via network_event_handle_t + * @note this does not work for lambda's! Do unregister via network_event_handle_t + * + * @param cbEvent functional callback + * @param event event to process, any event by default + */ + void removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX) + __attribute__((deprecated("removing functional callbacks via pointer is deprecated, use removeEvent(network_event_handle_t) instead"))); + + /** + * @brief unregister static system function callback + * @note a better way to unregister callbacks is to save/unregister via network_event_handle_t + * + * @param cbEvent static callback function + * @param event event to process, any event by default + */ void removeEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief unregister event callback via handler + * + * @param cbEvent static callback function + * @param event event to process, any event by default + */ void removeEvent(network_event_handle_t event_handle); - const char *eventName(arduino_event_id_t id); + /** + * @brief get a human-readable name of an event by it's id + * + * @param id event id code + * @return const char* event name string + */ + static const char *eventName(arduino_event_id_t id); - void checkForEvent(); - bool postEvent(arduino_event_t *event); + /** + * @brief post an event to the queue + * and propagade and event to subscribed handlers + * @note posting an event will trigger context switch from a lower priority task + * + * @param event a pointer to arduino_event_t struct + * @return true if event was queued susccessfuly + * @return false on memrory allocation error or queue is full + */ + bool postEvent(const arduino_event_t *event); - int getStatusBits(); + int getStatusBits() const; int waitStatusBits(int bits, uint32_t timeout_ms); int setStatusBits(int bits); int clearStatusBits(int bits); @@ -147,7 +248,7 @@ class NetworkEvents { friend class ESP_NetworkInterface; friend class ETHClass; friend class PPPClass; -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED friend class STAClass; friend class APClass; friend class WiFiGenericClass; @@ -155,12 +256,53 @@ class NetworkEvents { protected: bool initNetworkEvents(); + // same as onEvent() but places newly added handler at the beginning of registered events list network_event_handle_t onSysEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + // same as onEvent() but places newly added handler at the beginning of registered events list network_event_handle_t onSysEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + // same as onEvent() but places newly added handler at the beginning of registered events list network_event_handle_t onSysEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); private: + /** + * @brief an object holds callback's definitions: + * - callback id + * - callback function pointers + * - binded event id + * + */ + struct NetworkEventCbList_t { + network_event_handle_t id; + NetworkEventCb cb; + NetworkEventFuncCb fcb; + NetworkEventSysCb scb; + arduino_event_id_t event; + + explicit NetworkEventCbList_t( + network_event_handle_t id, NetworkEventCb cb = nullptr, NetworkEventFuncCb fcb = nullptr, NetworkEventSysCb scb = nullptr, + arduino_event_id_t event = ARDUINO_EVENT_MAX + ) + : id(id), cb(cb), fcb(fcb), scb(scb), event(event) {} + }; + + // define initial id's value + network_event_handle_t _current_id{0}; + EventGroupHandle_t _arduino_event_group; QueueHandle_t _arduino_event_queue; TaskHandle_t _arduino_event_task_handle; + + // registered events callbacks container + std::vector _cbEventList; + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + // container access mutex + std::mutex _mtx; +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + /** + * @brief task function that picks events from an event queue and calls registered callbacks + * + */ + void _checkForEvent(); }; diff --git a/libraries/Network/src/NetworkInterface.cpp b/libraries/Network/src/NetworkInterface.cpp index 777fefe9cb0..01790ec2493 100644 --- a/libraries/Network/src/NetworkInterface.cpp +++ b/libraries/Network/src/NetworkInterface.cpp @@ -34,6 +34,18 @@ NetworkInterface *getNetifByID(Network_Interface_ID id) { return NULL; } +#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM +extern "C" int lwip_hook_ip6_input(struct pbuf *p, struct netif *inp) __attribute__((weak)); +extern "C" int lwip_hook_ip6_input(struct pbuf *p, struct netif *inp) { + if (ip6_addr_isany_val(inp->ip6_addr[0].u_addr.ip6)) { + // We don't have an LL address -> eat this packet here, so it won't get accepted on input netif + pbuf_free(p); + return 1; + } + return 0; +} +#endif + static void _ip_event_cb(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { if (event_base == IP_EVENT) { NetworkInterface *netif = NULL; @@ -69,7 +81,7 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void *event_data) { ); #endif memcpy(&arduino_event.event_info.got_ip, event_data, sizeof(ip_event_got_ip_t)); -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED if (_interface_id == ESP_NETIF_ID_STA) { arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_GOT_IP; } else @@ -84,7 +96,7 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void *event_data) { #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE log_v("%s Lost IP", desc()); #endif -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED if (_interface_id == ESP_NETIF_ID_STA) { arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_LOST_IP; } else @@ -94,6 +106,7 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void *event_data) { } else if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) { arduino_event.event_id = ARDUINO_EVENT_ETH_LOST_IP; } +#if CONFIG_LWIP_IPV6 } else if (event_id == IP_EVENT_GOT_IP6) { ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data; esp_ip6_addr_type_t addr_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip); @@ -103,18 +116,14 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void *event_data) { setStatusBits(ESP_NETIF_HAS_LOCAL_IP6_BIT); } #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE - char if_name[NETIF_NAMESIZE] = { - 0, - }; - netif_index_to_name(event->ip6_info.ip.zone, if_name); static const char *addr_types[] = {"UNKNOWN", "GLOBAL", "LINK_LOCAL", "SITE_LOCAL", "UNIQUE_LOCAL", "IPV4_MAPPED_IPV6"}; log_v( - "IF %s Got IPv6: Interface: %d, IP Index: %d, Type: %s, Zone: %d (%s), Address: " IPV6STR, desc(), _interface_id, event->ip_index, addr_types[addr_type], - event->ip6_info.ip.zone, if_name, IPV62STR(event->ip6_info.ip) + "IF %s Got IPv6: Interface: %d, IP Index: %d, Type: %s, Zone: %d, Address: " IPV6STR, desc(), _interface_id, event->ip_index, addr_types[addr_type], + event->ip6_info.ip.zone, IPV62STR(event->ip6_info.ip) ); #endif memcpy(&arduino_event.event_info.got_ip6, event_data, sizeof(ip_event_got_ip6_t)); -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED if (_interface_id == ESP_NETIF_ID_STA) { arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_GOT_IP6; } else if (_interface_id == ESP_NETIF_ID_AP) { @@ -126,7 +135,8 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void *event_data) { } else if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) { arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP6; } -#if SOC_WIFI_SUPPORTED +#endif /* CONFIG_LWIP_IPV6 */ +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED } else if (event_id == IP_EVENT_AP_STAIPASSIGNED && _interface_id == ESP_NETIF_ID_AP) { setStatusBits(ESP_NETIF_HAS_IP_BIT); #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE @@ -318,12 +328,25 @@ bool NetworkInterface::hasGlobalIPv6() const { } bool NetworkInterface::enableIPv6(bool en) { +#if CONFIG_LWIP_IPV6 if (en) { setStatusBits(ESP_NETIF_WANT_IP6_BIT); + if (_esp_netif != NULL && connected()) { + // If we are already connected, try to enable IPv6 immediately + esp_err_t err = esp_netif_create_ip6_linklocal(_esp_netif); + if (err != ESP_OK) { + log_e("Failed to enable IPv6 Link Local on %s: [%d] %s", desc(), err, esp_err_to_name(err)); + } else { + log_v("Enabled IPv6 Link Local on %s", desc()); + } + } } else { clearStatusBits(ESP_NETIF_WANT_IP6_BIT); } return true; +#else + return false; +#endif } bool NetworkInterface::dnsIP(uint8_t dns_no, IPAddress ip) { @@ -722,6 +745,7 @@ uint8_t NetworkInterface::subnetCIDR() const { return calculateSubnetCIDR(IPAddress(ip.netmask.addr)); } +#if CONFIG_LWIP_IPV6 IPAddress NetworkInterface::linkLocalIPv6() const { if (_esp_netif == NULL) { return IPAddress(IPv6); @@ -743,6 +767,7 @@ IPAddress NetworkInterface::globalIPv6() const { } return IPAddress(IPv6, (const uint8_t *)addr.addr, addr.zone); } +#endif size_t NetworkInterface::printTo(Print &out) const { size_t bytes = 0; @@ -817,6 +842,7 @@ size_t NetworkInterface::printTo(Print &out) const { bytes += out.print(dnsIP()); bytes += out.println(); +#if CONFIG_LWIP_IPV6 static const char *types[] = {"UNKNOWN", "GLOBAL", "LINK_LOCAL", "SITE_LOCAL", "UNIQUE_LOCAL", "IPV4_MAPPED_IPV6"}; esp_ip6_addr_t if_ip6[CONFIG_LWIP_IPV6_NUM_ADDRESSES]; int v6addrs = esp_netif_get_all_ip6(_esp_netif, if_ip6); @@ -828,6 +854,7 @@ size_t NetworkInterface::printTo(Print &out) const { bytes += out.print(types[esp_netif_ip6_get_addr_type(&if_ip6[i])]); bytes += out.println(); } +#endif return bytes; } diff --git a/libraries/Network/src/NetworkInterface.h b/libraries/Network/src/NetworkInterface.h index 323cf3bfc72..4f97181d4fd 100644 --- a/libraries/Network/src/NetworkInterface.h +++ b/libraries/Network/src/NetworkInterface.h @@ -70,8 +70,10 @@ class NetworkInterface : public Printable { IPAddress broadcastIP() const; IPAddress networkID() const; uint8_t subnetCIDR() const; +#if CONFIG_LWIP_IPV6 IPAddress linkLocalIPv6() const; IPAddress globalIPv6() const; +#endif size_t printTo(Print &out) const; diff --git a/libraries/Network/src/NetworkManager.cpp b/libraries/Network/src/NetworkManager.cpp index 88059a60562..12276b2e242 100644 --- a/libraries/Network/src/NetworkManager.cpp +++ b/libraries/Network/src/NetworkManager.cpp @@ -87,6 +87,7 @@ int NetworkManager::hostByName(const char *aHostname, IPAddress &aResult) { memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; +#if CONFIG_LWIP_IPV6 // **Workaround** // LWIP AF_UNSPEC always prefers IPv4 and doesn't check what network is // available. See https://github.com/espressif/esp-idf/issues/13255 @@ -106,22 +107,27 @@ int NetworkManager::hostByName(const char *aHostname, IPAddress &aResult) { } } // **End Workaround** +#endif hints.ai_family = AF_UNSPEC; err = lwip_getaddrinfo(aHostname, servname, &hints, &res); if (err == ERR_OK) { +#if CONFIG_LWIP_IPV6 if (res->ai_family == AF_INET6) { struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr; // As an array of u8_t aResult = IPAddress(IPv6, ipv6->sin6_addr.s6_addr); log_d("DNS found IPv6 %s", aResult.toString().c_str()); } else { +#endif struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr; // As a single u32_t aResult = IPAddress(ipv4->sin_addr.s_addr); log_d("DNS found IPv4 %s", aResult.toString().c_str()); +#if CONFIG_LWIP_IPV6 } +#endif lwip_freeaddrinfo(res); return 1; diff --git a/libraries/Network/src/NetworkServer.cpp b/libraries/Network/src/NetworkServer.cpp index 4609757255e..ce8ef952ea7 100644 --- a/libraries/Network/src/NetworkServer.cpp +++ b/libraries/Network/src/NetworkServer.cpp @@ -46,8 +46,13 @@ NetworkClient NetworkServer::accept() { client_sock = _accepted_sockfd; _accepted_sockfd = -1; } else { +#if CONFIG_LWIP_IPV6 struct sockaddr_in6 _client; int cs = sizeof(struct sockaddr_in6); +#else + struct sockaddr_in _client; + int cs = sizeof(struct sockaddr_in); +#endif #ifdef ESP_IDF_VERSION_MAJOR client_sock = lwip_accept(sockfd, (struct sockaddr *)&_client, (socklen_t *)&cs); #else @@ -77,6 +82,7 @@ void NetworkServer::begin(uint16_t port, int enable) { if (port) { _port = port; } +#if CONFIG_LWIP_IPV6 struct sockaddr_in6 server; sockfd = socket(AF_INET6, SOCK_STREAM, 0); if (sockfd < 0) { @@ -93,6 +99,18 @@ void NetworkServer::begin(uint16_t port, int enable) { } memset(server.sin6_addr.s6_addr, 0x0, 16); server.sin6_port = htons(_port); +#else + struct sockaddr_in server; + memset(&server, 0x0, sizeof(sockaddr_in)); + server.sin_family = AF_INET; + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + return; + } + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); + memcpy((uint8_t *)&(server.sin_addr.s_addr), (uint8_t *)&_addr[0], 4); + server.sin_port = htons(_port); +#endif if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) { return; } @@ -117,8 +135,13 @@ bool NetworkServer::hasClient() { if (_accepted_sockfd >= 0) { return true; } +#if CONFIG_LWIP_IPV6 struct sockaddr_in6 _client; int cs = sizeof(struct sockaddr_in6); +#else + struct sockaddr _client; + int cs = sizeof(struct sockaddr); +#endif #ifdef ESP_IDF_VERSION_MAJOR _accepted_sockfd = lwip_accept(sockfd, (struct sockaddr *)&_client, (socklen_t *)&cs); #else diff --git a/libraries/Network/src/NetworkUdp.cpp b/libraries/Network/src/NetworkUdp.cpp index 6134ba49967..51579910ded 100644 --- a/libraries/Network/src/NetworkUdp.cpp +++ b/libraries/Network/src/NetworkUdp.cpp @@ -255,6 +255,7 @@ int NetworkUDP::endPacket() { log_e("could not send data: %d", errno); return 0; } +#if LWIP_IPV6 } else { struct sockaddr_in6 recipient; recipient.sin6_flowinfo = 0; @@ -267,6 +268,7 @@ int NetworkUDP::endPacket() { log_e("could not send data: %d", errno); return 0; } +#endif } return 1; } @@ -288,7 +290,9 @@ size_t NetworkUDP::write(const uint8_t *buffer, size_t size) { return i; } -void NetworkUDP::flush() {} +void NetworkUDP::flush() { + clear(); +} int NetworkUDP::parsePacket() { if (rx_buffer) { @@ -296,7 +300,14 @@ int NetworkUDP::parsePacket() { } struct sockaddr_storage si_other_storage; // enough storage for v4 and v6 socklen_t slen = sizeof(sockaddr_storage); - int len; + int len = 0; + if (ioctl(udp_server, FIONREAD, &len) == -1) { + log_e("could not check for data in buffer length: %d", errno); + return 0; + } + if (!len) { + return 0; + } char *buf = (char *)malloc(1460); if (!buf) { return 0; @@ -327,12 +338,16 @@ int NetworkUDP::parsePacket() { remote_ip.from_ip_addr_t(&addr); } remote_port = ntohs(si_other.sin6_port); + } else { + remote_ip = ip_addr_any.u_addr.ip4.addr; + remote_port = 0; } -#endif // LWIP_IPV6=1 +#else else { - remote_ip = ip_addr_any.u_addr.ip4.addr; + remote_ip = ip_addr_any.addr; remote_port = 0; } +#endif // LWIP_IPV6=1 if (len > 0) { rx_buffer = new (std::nothrow) cbuf(len); rx_buffer->write(buf, len); diff --git a/libraries/Network/src/NetworkUdp.h b/libraries/Network/src/NetworkUdp.h index ec05991b7e3..e70ec9b2127 100644 --- a/libraries/Network/src/NetworkUdp.h +++ b/libraries/Network/src/NetworkUdp.h @@ -64,6 +64,7 @@ class NetworkUDP : public UDP { int endPacket(); size_t write(uint8_t); size_t write(const uint8_t *buffer, size_t size); + [[deprecated("Use clear() instead.")]] void flush(); // Print::flush tx int parsePacket(); int available(); diff --git a/libraries/NetworkClientSecure/README.md b/libraries/NetworkClientSecure/README.md index 0710d3f5b80..f83cf246287 100644 --- a/libraries/NetworkClientSecure/README.md +++ b/libraries/NetworkClientSecure/README.md @@ -32,25 +32,11 @@ This method is similar to the single root certificate verification above, but it root certificates from Mozilla to authenticate against, while the previous method only accepts a single certificate for a given server. This allows the client to connect to all public SSL servers. -To use this feature in PlatformIO: -1. create a certificate bundle as described in the document below, or obtain a pre-built one you trust: -https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_crt_bundle.html -(gen_crt_bundle.py can be found in the /tools folder) - a. note: the full bundle will take up around 64k of flash space, but has minimal RAM usage, as only - the index of the certificates is kept in RAM -2. Place the bundle under the file name "data/cert/x509_crt_bundle.bin" in your platformio project -3. add "board_build.embed_files = data/cert/x509_crt_bundle.bin" in your platformio.ini -4. add the following global declaration in your project: - extern const uint8_t rootca_crt_bundle_start[] asm("_binary_data_cert_x509_crt_bundle_bin_start"); -5. before initiating the first SSL connection, call - my_client.setCACertBundle(rootca_crt_bundle_start); - To use this feature in Arduino IDE: If the Arduino IDE added support for embedding files in the meantime, then follow the instructions above. -If not, you have three choices: -1. convert your project to PlatformIO -2. create a makefile where you can add the idf_component_register() declaration to include the certificate bundle -3. Store the bundle as a SPIFFS file, but then you have to load it into RAM in runtime and waste 64k of precious memory +If not, you have two choices: +1. create a makefile where you can add the idf_component_register() declaration to include the certificate bundle +2. Store the bundle as a SPIFFS file, but then you have to load it into RAM in runtime and waste 64k of precious memory Using a root CA cert and client cert/keys ----------------------------------------- @@ -113,14 +99,14 @@ Examples #### NetworkClientInsecure Demonstrates usage of insecure connection using `NetworkClientSecure::setInsecure()` #### NetworkClientPSK -Wifi secure connection example for ESP32 using a pre-shared key (PSK) +Wi-Fi secure connection example for ESP32 using a pre-shared key (PSK) This is useful with MQTT servers instead of using a self-signed cert, tested with mosquitto. Running on TLS 1.2 using mbedTLS #### NetworkClientSecure -Wifi secure connection example for ESP32 +Wi-Fi secure connection example for ESP32 Running on TLS 1.2 using mbedTLS #### NetworkClientSecureEnterprise -This example demonstrates a secure connection to a WiFi network using WPA/WPA2 Enterprise (for example eduroam), +This example demonstrates a secure connection to a Wi-Fi network using WPA/WPA2 Enterprise (for example eduroam), and establishing a secure HTTPS connection with an external server (for example arduino.php5.sk) using the defined anonymous identity, user identity, and password. .. note:: diff --git a/libraries/NetworkClientSecure/examples/WiFiClientInsecure/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientInsecure/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientInsecure/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientInsecure/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientPSK/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientPSK/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientPSK/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientPSK/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino b/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino index 3339068698b..0f95826decb 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino +++ b/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino @@ -18,27 +18,37 @@ const char *server = "www.howsmyssl.com"; // Server URL // change it to your server root CA // SHA1 fingerprint is broken now! -const char *test_root_ca = "-----BEGIN CERTIFICATE-----\n" - "MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\n" - "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" - "DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\n" - "PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\n" - "Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" - "AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\n" - "rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\n" - "OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\n" - "xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n" - "7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\n" - "aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n" - "HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\n" - "SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\n" - "ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n" - "AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\n" - "R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\n" - "JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\n" - "Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n" - "-----END CERTIFICATE-----\n"; - +const char *test_root_ca = R"literal( +-----BEGIN CERTIFICATE----- +MIIFBTCCAu2gAwIBAgIQS6hSk/eaL6JzBkuoBI110DANBgkqhkiG9w0BAQsFADBP +MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy +Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa +Fw0yNzAzMTIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF +bmNyeXB0MQwwCgYDVQQDEwNSMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQDPV+XmxFQS7bRH/sknWHZGUCiMHT6I3wWd1bUYKb3dtVq/+vbOo76vACFL +YlpaPAEvxVgD9on/jhFD68G14BQHlo9vH9fnuoE5CXVlt8KvGFs3Jijno/QHK20a +/6tYvJWuQP/py1fEtVt/eA0YYbwX51TGu0mRzW4Y0YCF7qZlNrx06rxQTOr8IfM4 +FpOUurDTazgGzRYSespSdcitdrLCnF2YRVxvYXvGLe48E1KGAdlX5jgc3421H5KR +mudKHMxFqHJV8LDmowfs/acbZp4/SItxhHFYyTr6717yW0QrPHTnj7JHwQdqzZq3 +DZb3EoEmUVQK7GH29/Xi8orIlQ2NAgMBAAGjgfgwgfUwDgYDVR0PAQH/BAQDAgGG +MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/ +AgEAMB0GA1UdDgQWBBS7vMNHpeS8qcbDpHIMEI2iNeHI6DAfBgNVHSMEGDAWgBR5 +tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKG +Fmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0gBAwwCjAIBgZngQwBAgEwJwYD +VR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVuY3Iub3JnLzANBgkqhkiG9w0B +AQsFAAOCAgEAkrHnQTfreZ2B5s3iJeE6IOmQRJWjgVzPw139vaBw1bGWKCIL0vIo +zwzn1OZDjCQiHcFCktEJr59L9MhwTyAWsVrdAfYf+B9haxQnsHKNY67u4s5Lzzfd +u6PUzeetUK29v+PsPmI2cJkxp+iN3epi4hKu9ZzUPSwMqtCceb7qPVxEbpYxY1p9 +1n5PJKBLBX9eb9LU6l8zSxPWV7bK3lG4XaMJgnT9x3ies7msFtpKK5bDtotij/l0 +GaKeA97pb5uwD9KgWvaFXMIEt8jVTjLEvwRdvCn294GPDF08U8lAkIv7tghluaQh +1QnlE4SEN4LOECj8dsIGJXpGUk3aU3KkJz9icKy+aUgA+2cP21uh6NcDIS3XyfaZ +QjmDQ993ChII8SXWupQZVBiIpcWO4RqZk3lr7Bz5MUCwzDIA359e57SSq5CCkY0N +4B6Vulk7LktfwrdGNVI5BsC9qqxSwSKgRJeZ9wygIaehbHFHFhcBaMDKpiZlBHyz +rsnnlFXCb5s8HKn5LsUgGvB24L7sGNZP2CX7dhHov+YhD+jozLW2p9W4959Bz2Ei +RmqDtmiXLnzqTpXbI+suyCsohKRg6Un0RC47+cpiVwHiXZAW+cn8eiNIjqbVgXLx +KPpdzvvtTnOPlC7SQZSYmdunr3Bf9b77AiC/ZidstK36dRILKz7OA54= +-----END CERTIFICATE----- +)literal"; // You can use x.509 client certificates if you want //const char* test_client_key = ""; //to verify the client //const char* test_client_cert = ""; //to verify the client diff --git a/libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json index d8b3664bc65..cbdd28f773d 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientSecure/ci.json @@ -1,5 +1,7 @@ { - "targets": { - "esp32h2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/WiFiClientSecureEnterprise.ino b/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/WiFiClientSecureEnterprise.ino index a7149e05e6e..b9e01d15682 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/WiFiClientSecureEnterprise.ino +++ b/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/WiFiClientSecureEnterprise.ino @@ -13,6 +13,11 @@ // Note: this example is outdated and may not work! // For more examples see https://github.com/martinius96/ESP32-eduroam +#include "sdkconfig.h" +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +#error "WPA-Enterprise is only supported in SoCs with native Wi-Fi support" +#endif + #include #include #if __has_include("esp_eap_client.h") diff --git a/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/ci.json index d8b3664bc65..04eb62b977a 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientSecureEnterprise/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientSecureProtocolUpgrade/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientSecureProtocolUpgrade/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientSecureProtocolUpgrade/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientSecureProtocolUpgrade/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientShowPeerCredentials/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientShowPeerCredentials/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientShowPeerCredentials/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientShowPeerCredentials/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/NetworkClientSecure/examples/WiFiClientTrustOnFirstUse/WiFiClientTrustOnFirstUse.ino b/libraries/NetworkClientSecure/examples/WiFiClientTrustOnFirstUse/WiFiClientTrustOnFirstUse.ino index 5b683814d05..afc588af76c 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientTrustOnFirstUse/WiFiClientTrustOnFirstUse.ino +++ b/libraries/NetworkClientSecure/examples/WiFiClientTrustOnFirstUse/WiFiClientTrustOnFirstUse.ino @@ -22,7 +22,7 @@ https://en.wikipedia.org/wiki/Trust_on_first_use). In this scheme; we start the very first time without any security checks - but once we have our first connection; we store the public crytpographic + but once we have our first connection; we store the public cryptographic details (or a proxy, such as a sha256 of this). And then we use this for any subsequent connections. diff --git a/libraries/NetworkClientSecure/examples/WiFiClientTrustOnFirstUse/ci.json b/libraries/NetworkClientSecure/examples/WiFiClientTrustOnFirstUse/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/NetworkClientSecure/examples/WiFiClientTrustOnFirstUse/ci.json +++ b/libraries/NetworkClientSecure/examples/WiFiClientTrustOnFirstUse/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/NetworkClientSecure/library.properties b/libraries/NetworkClientSecure/library.properties index dd4b6a195dc..455dea6a2bf 100644 --- a/libraries/NetworkClientSecure/library.properties +++ b/libraries/NetworkClientSecure/library.properties @@ -1,5 +1,5 @@ name=NetworkClientSecure -version=2.0.0 +version=3.2.0 author=Evandro Luis Copercini maintainer=Github Community sentence=Enables secure network connection (local and Internet) using the ESP32 built-in WiFi. diff --git a/libraries/NetworkClientSecure/src/NetworkClientSecure.cpp b/libraries/NetworkClientSecure/src/NetworkClientSecure.cpp index d5e3b63c5be..87917e58b8f 100644 --- a/libraries/NetworkClientSecure/src/NetworkClientSecure.cpp +++ b/libraries/NetworkClientSecure/src/NetworkClientSecure.cpp @@ -305,9 +305,11 @@ int NetworkClientSecure::available() { res = data_to_read(sslclient.get()); if (res < 0 && !_stillinPlainStart) { - log_e("Closing connection on failed available check"); + if (res != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + log_e("Closing connection on failed available check"); + } stop(); - return peeked ? peeked : res; + return peeked; } return res + peeked; } @@ -337,9 +339,9 @@ void NetworkClientSecure::setCACert(const char *rootCA) { _use_insecure = false; } -void NetworkClientSecure::setCACertBundle(const uint8_t *bundle) { - if (bundle != NULL) { - esp_crt_bundle_set(bundle, sizeof(bundle)); +void NetworkClientSecure::setCACertBundle(const uint8_t *bundle, size_t size) { + if (bundle != NULL && size > 0) { + esp_crt_bundle_set(bundle, size); attach_ssl_certificate_bundle(sslclient.get(), true); _use_ca_bundle = true; } else { diff --git a/libraries/NetworkClientSecure/src/NetworkClientSecure.h b/libraries/NetworkClientSecure/src/NetworkClientSecure.h index 147acbe37fd..46f725d5633 100644 --- a/libraries/NetworkClientSecure/src/NetworkClientSecure.h +++ b/libraries/NetworkClientSecure/src/NetworkClientSecure.h @@ -73,7 +73,7 @@ class NetworkClientSecure : public NetworkClient { void setCertificate(const char *client_ca); void setPrivateKey(const char *private_key); bool loadCACert(Stream &stream, size_t size); - void setCACertBundle(const uint8_t *bundle); + void setCACertBundle(const uint8_t *bundle, size_t size); bool loadCertificate(Stream &stream, size_t size); bool loadPrivateKey(Stream &stream, size_t size); bool verify(const char *fingerprint, const char *domain_name); diff --git a/libraries/NetworkClientSecure/src/WiFiClientSecure.h b/libraries/NetworkClientSecure/src/WiFiClientSecure.h index b4d6962fb35..56e7f28aa52 100644 --- a/libraries/NetworkClientSecure/src/WiFiClientSecure.h +++ b/libraries/NetworkClientSecure/src/WiFiClientSecure.h @@ -1,3 +1,3 @@ #pragma once #include "NetworkClientSecure.h" -#define WiFiClientSecure NetworkClientSecure +typedef NetworkClientSecure WiFiClientSecure; diff --git a/libraries/NetworkClientSecure/src/ssl_client.cpp b/libraries/NetworkClientSecure/src/ssl_client.cpp index c8d5bbd21ea..19f75673133 100644 --- a/libraries/NetworkClientSecure/src/ssl_client.cpp +++ b/libraries/NetworkClientSecure/src/ssl_client.cpp @@ -27,7 +27,7 @@ const char *pers = "esp32-tls"; static int _handle_error(int err, const char *function, int line) { - if (err == -30848) { + if (err == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { return err; } #ifdef MBEDTLS_ERROR_C @@ -83,6 +83,7 @@ int start_ssl_client( fcntl(ssl_client->socket, F_SETFL, fcntl(ssl_client->socket, F_GETFL, 0) | O_NONBLOCK); struct sockaddr_storage serv_addr = {}; +#if CONFIG_LWIP_IPV6 if (domain == AF_INET6) { struct sockaddr_in6 *tmpaddr = (struct sockaddr_in6 *)&serv_addr; tmpaddr->sin6_family = AF_INET6; @@ -92,11 +93,14 @@ int start_ssl_client( tmpaddr->sin6_port = htons(port); tmpaddr->sin6_scope_id = ip.zone(); } else { +#endif struct sockaddr_in *tmpaddr = (struct sockaddr_in *)&serv_addr; tmpaddr->sin_family = AF_INET; tmpaddr->sin_addr.s_addr = ip; tmpaddr->sin_port = htons(port); +#if CONFIG_LWIP_IPV6 } +#endif if (timeout <= 0) { timeout = 30000; // Milli seconds. diff --git a/libraries/OpenThread/README.md b/libraries/OpenThread/README.md new file mode 100644 index 00000000000..cd9deb9ebf6 --- /dev/null +++ b/libraries/OpenThread/README.md @@ -0,0 +1,72 @@ +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +# ESP32 Arduino OpenThreadCLI + +The `OpenThreadCLI` class is an Arduino API for interacting with the OpenThread Command Line Interface (CLI). It allows you to manage and configure the Thread stack using a command-line interface. + +There is one main class called `OpenThreadCLI` and a global object used to operate OpenThread CLI, called `OThreadCLI`.\ +Some [helper functions](helper_functions.md) were made available for working with the OpenThread CLI environment. + +The available OpenThread Commands are documented in the [OpenThread CLI Reference Page](https://openthread.io/reference/cli/commands) + +It is important to note that the current implementation can only be used with Espressif SoC that has support to IEEE 802.15.4, such as **ESP32-C6** and **ESP32-H2**. + +Below are the details of the class: + +## Class Definition + +```cpp +class OpenThreadCLI : public Stream { +private: + static size_t setBuffer(QueueHandle_t &queue, size_t len); + bool otStarted = false; + +public: + OpenThreadCLI(); + ~OpenThreadCLI(); + operator bool() const; + + // Starts a task to read/write otStream. Default prompt is "ot> ". Set it to NULL to make it invisible. + void startConsole(Stream& otStream, bool echoback = true, const char* prompt = "ot> "); + void stopConsole(); + void setPrompt(char* prompt); // Changes the console prompt. NULL is an empty prompt. + void setEchoBack(bool echoback); // Changes the console echoback option + void setStream(Stream& otStream); // Changes the console Stream object + void onReceive(OnReceiveCb_t func); // Called on a complete line of output from OT CLI, as OT Response + + void begin(bool OThreadAutoStart = true); + void end(); + + // Default size is 256 bytes + size_t setTxBufferSize(size_t tx_queue_len); + // Default size is 1024 bytes + size_t setRxBufferSize(size_t rx_queue_len); + + size_t write(uint8_t); + int available(); + int read(); + int peek(); + void flush(); +}; + +extern OpenThreadCLI OThreadCLI; +``` + +## Class Overview +- The `OpenThreadCLI` class inherits from the `Stream` class, making it compatible with Arduino's standard I/O functions. +- It provides methods for managing the OpenThread CLI, including starting and stopping the console, setting prompts, and handling received data. +- You can customize the console behavior by adjusting parameters such as echoback and buffer sizes. + +## Public Methods +- `startConsole(Stream& otStream, bool echoback = true, const char* prompt = "ot> ")`: Starts the OpenThread console with the specified stream, echoback option, and prompt. +- `stopConsole()`: Stops the OpenThread console. +- `setPrompt(char* prompt)`: Changes the console prompt (set to NULL for an empty prompt). +- `setEchoBack(bool echoback)`: Changes the console echoback option. +- `setStream(Stream& otStream)`: Changes the console Stream object. +- `onReceive(OnReceiveCb_t func)`: Sets a callback function to handle complete lines of output from the OT CLI. +- `begin(bool OThreadAutoStart = true)`: Initializes the OpenThread stack (optional auto-start). +- `end()`: Deinitializes the OpenThread stack. +- `setTxBufferSize(size_t tx_queue_len)`: Sets the transmit buffer size (default is 256 bytes). +- `setRxBufferSize(size_t rx_queue_len)`: Sets the receive buffer size (default is 1024 bytes). +- `write(uint8_t)`, `available()`, `read()`, `peek()`, `flush()`: Standard Stream methods implementation for OpenThread CLI object. diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/ci.json b/libraries/OpenThread/examples/COAP/coap_lamp/ci.json new file mode 100644 index 00000000000..2ee6af3490e --- /dev/null +++ b/libraries/OpenThread/examples/COAP/coap_lamp/ci.json @@ -0,0 +1,6 @@ +{ + "requires": [ + "CONFIG_OPENTHREAD_ENABLED=y", + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino new file mode 100644 index 00000000000..51483bb4c7c --- /dev/null +++ b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino @@ -0,0 +1,163 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +#define OT_CHANNEL "24" +#define OT_NETWORK_KEY "00112233445566778899aabbccddeeff" +#define OT_MCAST_ADDR "ff05::abcd" +#define OT_COAP_RESOURCE_NAME "Lamp" + +const char *otSetupLeader[] = { + // -- clear/disable all + // stop CoAP + "coap", "stop", + // stop Thread + "thread", "stop", + // stop the interface + "ifconfig", "down", + // clear the dataset + "dataset", "clear", + // -- set dataset + // create a new complete dataset with random data + "dataset", "init new", + // set the channel + "dataset channel", OT_CHANNEL, + // set the network key + "dataset networkkey", OT_NETWORK_KEY, + // commit the dataset + "dataset", "commit active", + // -- network start + // start the interface + "ifconfig", "up", + // start the Thread network + "thread", "start" +}; + +const char *otCoapLamp[] = { + // -- create a multicast IPv6 Address for this device + "ipmaddr add", OT_MCAST_ADDR, + // -- start and create a CoAP resource + // start CoAP as server + "coap", "start", + // create a CoAP resource + "coap resource", OT_COAP_RESOURCE_NAME, + // set the CoAP resource initial value + "coap set", "0" +}; + +bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoapCmds, uint8_t nCmds2, ot_device_role_t expectedRole) { + Serial.println("Starting OpenThread."); + Serial.println("Running as Lamp (RGB LED) - use the other C6/H2 as a Switch"); + uint8_t i; + for (i = 0; i < nCmds1; i++) { + if (!otExecCommand(otSetupCmds[i * 2], otSetupCmds[i * 2 + 1])) { + break; + } + } + if (i != nCmds1) { + log_e("Sorry, OpenThread Network setup failed!"); + rgbLedWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! + return false; + } + Serial.println("OpenThread started.\r\nWaiting for activating correct Device Role."); + // wait for the expected Device Role to start + uint8_t tries = 24; // 24 x 2.5 sec = 1 min + while (tries && otGetDeviceRole() != expectedRole) { + Serial.print("."); + delay(2500); + tries--; + } + Serial.println(); + if (!tries) { + log_e("Sorry, Device Role failed by timeout! Current Role: %s.", otGetStringDeviceRole()); + rgbLedWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! + return false; + } + Serial.printf("Device is %s.\r\n", otGetStringDeviceRole()); + for (i = 0; i < nCmds2; i++) { + if (!otExecCommand(otCoapCmds[i * 2], otCoapCmds[i * 2 + 1])) { + break; + } + } + if (i != nCmds2) { + log_e("Sorry, OpenThread CoAP setup failed!"); + rgbLedWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! + return false; + } + Serial.println("OpenThread setup done. Node is ready."); + // all fine! LED goes Green + rgbLedWrite(RGB_BUILTIN, 0, 64, 8); // GREEN ... Lamp is ready! + return true; +} + +void setupNode() { + // tries to set the Thread Network node and only returns when succeeded + bool startedCorrectly = false; + while (!startedCorrectly) { + startedCorrectly |= + otDeviceSetup(otSetupLeader, sizeof(otSetupLeader) / sizeof(char *) / 2, otCoapLamp, sizeof(otCoapLamp) / sizeof(char *) / 2, OT_ROLE_LEADER); + if (!startedCorrectly) { + Serial.println("Setup Failed...\r\nTrying again..."); + } + } +} + +// this function is used by the Lamp mode to listen for CoAP frames from the Switch Node +void otCOAPListen() { + // waits for the client to send a CoAP request + char cliResp[256] = {0}; + size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); + cliResp[len - 1] = '\0'; + if (strlen(cliResp)) { + String sResp(cliResp); + // cliResp shall be something like: + // "coap request from fd0c:94df:f1ae:b39a:ec47:ec6d:15e8:804a PUT with payload: 30" + // payload may be 30 or 31 (HEX) '0' or '1' (ASCII) + log_d("Msg[%s]", cliResp); + if (sResp.startsWith("coap request from") && sResp.indexOf("PUT") > 0) { + char payload = sResp.charAt(sResp.length() - 1); // last character in the payload + log_i("CoAP PUT [%s]\r\n", payload == '0' ? "OFF" : "ON"); + if (payload == '0') { + for (int16_t c = 248; c > 16; c -= 8) { + rgbLedWrite(RGB_BUILTIN, c, c, c); // ramp down + delay(5); + } + rgbLedWrite(RGB_BUILTIN, 0, 0, 0); // Lamp Off + } else { + for (int16_t c = 16; c < 248; c += 8) { + rgbLedWrite(RGB_BUILTIN, c, c, c); // ramp up + delay(5); + } + rgbLedWrite(RGB_BUILTIN, 255, 255, 255); // Lamp On + } + } + } +} + +void setup() { + Serial.begin(115200); + // LED starts RED, indicating not connected to Thread network. + rgbLedWrite(RGB_BUILTIN, 64, 0, 0); + OThreadCLI.begin(false); // No AutoStart is necessary + OThreadCLI.setTimeout(250); // waits 250ms for the OpenThread CLI response + setupNode(); + // LED goes Green when all is ready and Red when failed. +} + +void loop() { + otCOAPListen(); + delay(10); +} diff --git a/libraries/OpenThread/examples/COAP/coap_switch/ci.json b/libraries/OpenThread/examples/COAP/coap_switch/ci.json new file mode 100644 index 00000000000..2ee6af3490e --- /dev/null +++ b/libraries/OpenThread/examples/COAP/coap_switch/ci.json @@ -0,0 +1,6 @@ +{ + "requires": [ + "CONFIG_OPENTHREAD_ENABLED=y", + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino new file mode 100644 index 00000000000..aac5db0bc82 --- /dev/null +++ b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino @@ -0,0 +1,188 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +#define USER_BUTTON 9 // C6/H2 Boot button +#define OT_CHANNEL "24" +#define OT_NETWORK_KEY "00112233445566778899aabbccddeeff" +#define OT_MCAST_ADDR "ff05::abcd" +#define OT_COAP_RESOURCE_NAME "Lamp" + +const char *otSetupChild[] = { + // -- clear/disable all + // stop CoAP + "coap", "stop", + // stop Thread + "thread", "stop", + // stop the interface + "ifconfig", "down", + // clear the dataset + "dataset", "clear", + // -- set dataset + // set the channel + "dataset channel", OT_CHANNEL, + // set the network key + "dataset networkkey", OT_NETWORK_KEY, + // commit the dataset + "dataset", "commit active", + // -- network start + // start the interface + "ifconfig", "up", + // start the Thread network + "thread", "start" +}; + +const char *otCoapSwitch[] = { + // -- start CoAP as client + "coap", "start" +}; + +bool otDeviceSetup( + const char **otSetupCmds, uint8_t nCmds1, const char **otCoapCmds, uint8_t nCmds2, ot_device_role_t expectedRole1, ot_device_role_t expectedRole2 +) { + Serial.println("Starting OpenThread."); + Serial.println("Running as Switch - use the BOOT button to toggle the other C6/H2 as a Lamp"); + uint8_t i; + for (i = 0; i < nCmds1; i++) { + if (!otExecCommand(otSetupCmds[i * 2], otSetupCmds[i * 2 + 1])) { + break; + } + } + if (i != nCmds1) { + log_e("Sorry, OpenThread Network setup failed!"); + rgbLedWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! + return false; + } + Serial.println("OpenThread started.\r\nWaiting for activating correct Device Role."); + // wait for the expected Device Role to start + uint8_t tries = 24; // 24 x 2.5 sec = 1 min + while (tries && otGetDeviceRole() != expectedRole1 && otGetDeviceRole() != expectedRole2) { + Serial.print("."); + delay(2500); + tries--; + } + Serial.println(); + if (!tries) { + log_e("Sorry, Device Role failed by timeout! Current Role: %s.", otGetStringDeviceRole()); + rgbLedWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! + return false; + } + Serial.printf("Device is %s.\r\n", otGetStringDeviceRole()); + for (i = 0; i < nCmds2; i++) { + if (!otExecCommand(otCoapCmds[i * 2], otCoapCmds[i * 2 + 1])) { + break; + } + } + if (i != nCmds2) { + log_e("Sorry, OpenThread CoAP setup failed!"); + rgbLedWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! + return false; + } + Serial.println("OpenThread setup done. Node is ready."); + // all fine! LED goes and stays Blue + rgbLedWrite(RGB_BUILTIN, 0, 0, 64); // BLUE ... Switch is ready! + return true; +} + +void setupNode() { + // tries to set the Thread Network node and only returns when succeeded + bool startedCorrectly = false; + while (!startedCorrectly) { + startedCorrectly |= otDeviceSetup( + otSetupChild, sizeof(otSetupChild) / sizeof(char *) / 2, otCoapSwitch, sizeof(otCoapSwitch) / sizeof(char *) / 2, OT_ROLE_CHILD, OT_ROLE_ROUTER + ); + if (!startedCorrectly) { + Serial.println("Setup Failed...\r\nTrying again..."); + } + } +} + +// Sends the CoAP frame to the Lamp node +bool otCoapPUT(bool lampState) { + bool gotDone = false, gotConfirmation = false; + String coapMsg = "coap put "; + coapMsg += OT_MCAST_ADDR; + coapMsg += " "; + coapMsg += OT_COAP_RESOURCE_NAME; + coapMsg += " con 0"; + + // final command is "coap put ff05::abcd Lamp con 1" or "coap put ff05::abcd Lamp con 0" + if (lampState) { + coapMsg[coapMsg.length() - 1] = '1'; + } + OThreadCLI.println(coapMsg.c_str()); + log_d("Send CLI CMD:[%s]", coapMsg.c_str()); + + char cliResp[256]; + // waits for the CoAP confirmation and Done message for about 1.25 seconds + // timeout is based on Stream::setTimeout() + // Example of the expected confirmation response: "coap response from fdae:3289:1783:5c3f:fd84:c714:7e83:6122" + uint8_t tries = 5; + *cliResp = '\0'; + while (tries && !(gotDone && gotConfirmation)) { + size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); + cliResp[len - 1] = '\0'; + log_d("Try[%d]::MSG[%s]", tries, cliResp); + if (strlen(cliResp)) { + if (!strncmp(cliResp, "coap response from", 18)) { + gotConfirmation = true; + } + if (!strncmp(cliResp, "Done", 4)) { + gotDone = true; + } + } + tries--; + } + if (gotDone && gotConfirmation) { + return true; + } + return false; +} + +// this function is used by the Switch mode to check the BOOT Button and send the user action to the Lamp node +void checkUserButton() { + static long unsigned int lastPress = 0; + const long unsigned int debounceTime = 500; + static bool lastLampState = true; // first button press will turn the Lamp OFF from initial Green + + pinMode(USER_BUTTON, INPUT_PULLUP); // C6/H2 User Button + if (millis() > lastPress + debounceTime && digitalRead(USER_BUTTON) == LOW) { + lastLampState = !lastLampState; + if (!otCoapPUT(lastLampState)) { // failed: Lamp Node is not responding due to be off or unreachable + // timeout from the CoAP PUT message... restart the node. + rgbLedWrite(RGB_BUILTIN, 255, 0, 0); // RED ... something failed! + Serial.println("Resetting the Node as Switch... wait."); + // start over... + setupNode(); + } + lastPress = millis(); + } +} + +void setup() { + Serial.begin(115200); + // LED starts RED, indicating not connected to Thread network. + rgbLedWrite(RGB_BUILTIN, 64, 0, 0); + OThreadCLI.begin(false); // No AutoStart is necessary + OThreadCLI.setTimeout(250); // waits 250ms for the OpenThread CLI response + setupNode(); + // LED goes and keeps Blue when all is ready and Red when failed. +} + +void loop() { + checkUserButton(); + delay(10); +} diff --git a/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino b/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino new file mode 100644 index 00000000000..feef800c0fa --- /dev/null +++ b/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino @@ -0,0 +1,34 @@ +// 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. + +/* + * OpenThread.begin(false) will not automatically start a node in a Thread Network + * The user will need to start it manually using the OpenThread CLI commands + * Use the Serial Monitor to interact with the OpenThread CLI + * + * Type 'help' for a list of commands. + * Documentation: https://openthread.io/reference/cli/commands + * + */ + +#include "OThreadCLI.h" + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(false); // No AutoStart - fresh start + Serial.println("OpenThread CLI started - type 'help' for a list of commands."); + OThreadCLI.startConsole(Serial); +} + +void loop() {} diff --git a/libraries/OpenThread/examples/SimpleCLI/ci.json b/libraries/OpenThread/examples/SimpleCLI/ci.json new file mode 100644 index 00000000000..2ee6af3490e --- /dev/null +++ b/libraries/OpenThread/examples/SimpleCLI/ci.json @@ -0,0 +1,6 @@ +{ + "requires": [ + "CONFIG_OPENTHREAD_ENABLED=y", + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino b/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino new file mode 100644 index 00000000000..95bf7a2401a --- /dev/null +++ b/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino @@ -0,0 +1,46 @@ +// 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. + +/* + * OpenThread.begin() will automatically start a node in a Thread Network + * If NVS is empty, default configuration will be as follow: + * + * NETWORK_NAME "OpenThread-ESP" + * MESH_LOCAL_PREFIX "fd00:db8:a0:0::/64" + * NETWORK_CHANNEL 15 + * NETWORK_PANID 0x1234 + * NETWORK_EXTPANID "dead00beef00cafe" + * NETWORK_KEY "00112233445566778899aabbccddeeff" + * NETWORK_PSKC "104810e2315100afd6bc9215a6bfac53" + * + * If NVS has already a dataset information, it will load it from there. + */ + +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +// The first device to start Thread will be the Leader +// Next devices will be Router or Child + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(); // AutoStart using Thread default settings + otPrintNetworkInformation(Serial); // Print Current Thread Network Information +} + +void loop() { + Serial.print("Thread Node State: "); + Serial.println(otGetStringDeviceRole()); + delay(5000); +} diff --git a/libraries/OpenThread/examples/SimpleNode/ci.json b/libraries/OpenThread/examples/SimpleNode/ci.json new file mode 100644 index 00000000000..2ee6af3490e --- /dev/null +++ b/libraries/OpenThread/examples/SimpleNode/ci.json @@ -0,0 +1,6 @@ +{ + "requires": [ + "CONFIG_OPENTHREAD_ENABLED=y", + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ExtendedRouterNode.ino b/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ExtendedRouterNode.ino new file mode 100644 index 00000000000..4fc8a921584 --- /dev/null +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ExtendedRouterNode.ino @@ -0,0 +1,79 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +// Leader node shall use the same Network Key and channel +#define CLI_NETWORK_KEY "00112233445566778899aabbccddeeff" +#define CLI_NETWORK_CHANEL "24" +bool otStatus = true; + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(false); // No AutoStart - fresh start + Serial.println("Setting up OpenThread Node as Router/Child"); + Serial.println("Make sure the Leader Node is already running"); + + otStatus &= otExecCommand("dataset", "clear"); + otStatus &= otExecCommand("dataset networkkey", CLI_NETWORK_KEY); + otStatus &= otExecCommand("dataset channel", CLI_NETWORK_CHANEL); + otStatus &= otExecCommand("dataset", "commit active"); + otStatus &= otExecCommand("ifconfig", "up"); + otStatus &= otExecCommand("thread", "start"); + + if (!otStatus) { + Serial.println("\r\n\t===> Failed starting Thread Network!"); + return; + } + // wait for the node to enter in the router state + uint32_t timeout = millis() + 90000; // waits 90 seconds to + while (otGetDeviceRole() != OT_ROLE_CHILD && otGetDeviceRole() != OT_ROLE_ROUTER) { + Serial.print("."); + if (millis() > timeout) { + Serial.println("\r\n\t===> Timeout! Failed."); + otStatus = false; + break; + } + delay(500); + } + + if (otStatus) { + // print the PanID using 2 methods + + // CLI + char resp[256]; + if (otGetRespCmd("panid", resp)) { + Serial.printf("\r\nPanID[using CLI]: %s\r\n", resp); + } else { + Serial.printf("\r\nPanID[using CLI]: FAILED!\r\n"); + } + + // OpenThread API + Serial.printf("PanID[using OT API]: 0x%x\r\n", (uint16_t)otLinkGetPanId(esp_openthread_get_instance())); + } + Serial.println("\r\n"); +} + +void loop() { + if (otStatus) { + Serial.println("Thread NetworkInformation: "); + Serial.println("---------------------------"); + otPrintNetworkInformation(Serial); + Serial.println("---------------------------"); + } else { + Serial.println("Some OpenThread operation has failed..."); + } + delay(10000); +} diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json new file mode 100644 index 00000000000..2ee6af3490e --- /dev/null +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json @@ -0,0 +1,6 @@ +{ + "requires": [ + "CONFIG_OPENTHREAD_ENABLED=y", + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino new file mode 100644 index 00000000000..7b709717692 --- /dev/null +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino @@ -0,0 +1,101 @@ +// 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. + +/* + OpenThread.begin(false) will not automatically start a node in a Thread Network + A Leader node is the first device, that has a complete dataset, to start Thread + A complete dataset is easily achieved by using the OpenThread CLI command "dataset init new" + + In order to allow other node to join the network, + all of them shall use the same network master key + The network master key is a 16-byte key that is used to secure the network + + Using the same channel will make the process faster + +*/ + +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +#define CLI_NETWORK_KEY "dataset networkkey 00112233445566778899aabbccddeeff" +#define CLI_NETWORK_CHANEL "dataset channel 24" + +otInstance *aInstance = NULL; + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(false); // No AutoStart - fresh start + Serial.println(); + Serial.println("Setting up OpenThread Node as Leader"); + aInstance = esp_openthread_get_instance(); + + OThreadCLI.println("dataset init new"); + OThreadCLI.println(CLI_NETWORK_KEY); + OThreadCLI.println(CLI_NETWORK_CHANEL); + OThreadCLI.println("dataset commit active"); + OThreadCLI.println("ifconfig up"); + OThreadCLI.println("thread start"); +} + +void loop() { + Serial.println("============================================="); + Serial.print("Thread Node State: "); + Serial.println(otGetStringDeviceRole()); + + // Native OpenThread API calls: + // wait until the node become Child or Router + if (otGetDeviceRole() == OT_ROLE_LEADER) { + // Network Name + const char *networkName = otThreadGetNetworkName(aInstance); + Serial.printf("Network Name: %s\r\n", networkName); + // Channel + uint8_t channel = otLinkGetChannel(aInstance); + Serial.printf("Channel: %d\r\n", channel); + // PAN ID + uint16_t panId = otLinkGetPanId(aInstance); + Serial.printf("PanID: 0x%04x\r\n", panId); + // Extended PAN ID + const otExtendedPanId *extPanId = otThreadGetExtendedPanId(aInstance); + Serial.printf("Extended PAN ID: "); + for (int i = 0; i < OT_EXT_PAN_ID_SIZE; i++) { + Serial.printf("%02x", extPanId->m8[i]); + } + Serial.println(); + // Network Key + otNetworkKey networkKey; + otThreadGetNetworkKey(aInstance, &networkKey); + Serial.printf("Network Key: "); + for (int i = 0; i < OT_NETWORK_KEY_SIZE; i++) { + Serial.printf("%02x", networkKey.m8[i]); + } + Serial.println(); + // IP Addresses + char buf[OT_IP6_ADDRESS_STRING_SIZE]; + const otNetifAddress *address = otIp6GetUnicastAddresses(aInstance); + while (address != NULL) { + otIp6AddressToString(&address->mAddress, buf, sizeof(buf)); + Serial.printf("IP Address: %s\r\n", buf); + address = address->mNext; + } + // Multicast IP Addresses + const otNetifMulticastAddress *mAddress = otIp6GetMulticastAddresses(aInstance); + while (mAddress != NULL) { + otIp6AddressToString(&mAddress->mAddress, buf, sizeof(buf)); + printf("Multicast IP Address: %s\n", buf); + mAddress = mAddress->mNext; + } + } + + delay(5000); +} diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json new file mode 100644 index 00000000000..2ee6af3490e --- /dev/null +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json @@ -0,0 +1,6 @@ +{ + "requires": [ + "CONFIG_OPENTHREAD_ENABLED=y", + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino new file mode 100644 index 00000000000..45475fa0c6a --- /dev/null +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino @@ -0,0 +1,101 @@ +// 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. + +/* + OpenThread.begin(false) will not automatically start a node in a Thread Network + A Router/Child node is the device that will join an existing Thread Network + + In order to allow this node to join the network, + it shall use the same network master key as used by the Leader Node + The network master key is a 16-byte key that is used to secure the network + + Using the same channel will make the process faster + +*/ + +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +#define CLI_NETWORK_KEY "dataset networkkey 00112233445566778899aabbccddeeff" +#define CLI_NETWORK_CHANEL "dataset channel 24" + +otInstance *aInstance = NULL; + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(false); // No AutoStart - fresh start + Serial.println(); + Serial.println("Setting up OpenThread Node as Router/Child"); + Serial.println("Make sure the Leader Node is already running"); + aInstance = esp_openthread_get_instance(); + + OThreadCLI.println("dataset clear"); + OThreadCLI.println(CLI_NETWORK_KEY); + OThreadCLI.println(CLI_NETWORK_CHANEL); + OThreadCLI.println("dataset commit active"); + OThreadCLI.println("ifconfig up"); + OThreadCLI.println("thread start"); +} + +void loop() { + Serial.println("============================================="); + Serial.print("Thread Node State: "); + Serial.println(otGetStringDeviceRole()); + + // Native OpenThread API calls: + // wait until the node become Child or Router + if (otGetDeviceRole() == OT_ROLE_CHILD || otGetDeviceRole() == OT_ROLE_ROUTER) { + // Network Name + const char *networkName = otThreadGetNetworkName(aInstance); + Serial.printf("Network Name: %s\r\n", networkName); + // Channel + uint8_t channel = otLinkGetChannel(aInstance); + Serial.printf("Channel: %d\r\n", channel); + // PAN ID + uint16_t panId = otLinkGetPanId(aInstance); + Serial.printf("PanID: 0x%04x\r\n", panId); + // Extended PAN ID + const otExtendedPanId *extPanId = otThreadGetExtendedPanId(aInstance); + Serial.printf("Extended PAN ID: "); + for (int i = 0; i < OT_EXT_PAN_ID_SIZE; i++) { + Serial.printf("%02x", extPanId->m8[i]); + } + Serial.println(); + // Network Key + otNetworkKey networkKey; + otThreadGetNetworkKey(aInstance, &networkKey); + Serial.printf("Network Key: "); + for (int i = 0; i < OT_NETWORK_KEY_SIZE; i++) { + Serial.printf("%02x", networkKey.m8[i]); + } + Serial.println(); + // IP Addresses + char buf[OT_IP6_ADDRESS_STRING_SIZE]; + const otNetifAddress *address = otIp6GetUnicastAddresses(aInstance); + while (address != NULL) { + otIp6AddressToString(&address->mAddress, buf, sizeof(buf)); + Serial.printf("IP Address: %s\r\n", buf); + address = address->mNext; + } + // Multicast IP Addresses + const otNetifMulticastAddress *mAddress = otIp6GetMulticastAddresses(aInstance); + while (mAddress != NULL) { + otIp6AddressToString(&mAddress->mAddress, buf, sizeof(buf)); + printf("Multicast IP Address: %s\n", buf); + mAddress = mAddress->mNext; + } + } + + delay(5000); +} diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json new file mode 100644 index 00000000000..2ee6af3490e --- /dev/null +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json @@ -0,0 +1,6 @@ +{ + "requires": [ + "CONFIG_OPENTHREAD_ENABLED=y", + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino b/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino new file mode 100644 index 00000000000..9d0074bb180 --- /dev/null +++ b/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino @@ -0,0 +1,55 @@ +// 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. + +/* + OpenThread.begin(true) will automatically start a node in a Thread Network + Full scanning requires the thread node to be at least in Child state. + + This will scan the IEEE 802.14.5 devices in the local area using CLI "scan" command + As soon as this device turns into a Child, Router or Leader, it will be able to + scan for Local Thread Networks as well. + +*/ + +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(true); // For scanning, AutoStart must be active, any setup + OThreadCLI.setTimeout(100); // Set a timeout for the CLI response + Serial.println(); + Serial.println("This sketch will continuously scan the Thread Local Network and all devices IEEE 802.15.4 compatible"); +} + +void loop() { + Serial.println(); + Serial.println("Scanning for nearby IEEE 802.15.4 devices:"); + // 802.15.4 Scan just needs a previous OThreadCLI.begin() + if (!otPrintRespCLI("scan", Serial, 3000)) { + Serial.println("Scan Failed..."); + } + delay(5000); + if (otGetDeviceRole() < OT_ROLE_CHILD) { + Serial.println(); + Serial.println("This device has not started Thread yet, bypassing Discovery Scan"); + return; + } + Serial.println(); + Serial.println("Scanning MLE Discover:"); + if (!otPrintRespCLI("discover", Serial, 3000)) { + Serial.println("Discover Failed..."); + } + delay(5000); +} diff --git a/libraries/OpenThread/examples/ThreadScan/ci.json b/libraries/OpenThread/examples/ThreadScan/ci.json new file mode 100644 index 00000000000..2ee6af3490e --- /dev/null +++ b/libraries/OpenThread/examples/ThreadScan/ci.json @@ -0,0 +1,6 @@ +{ + "requires": [ + "CONFIG_OPENTHREAD_ENABLED=y", + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/OpenThread/examples/onReceive/ci.json b/libraries/OpenThread/examples/onReceive/ci.json new file mode 100644 index 00000000000..2ee6af3490e --- /dev/null +++ b/libraries/OpenThread/examples/onReceive/ci.json @@ -0,0 +1,6 @@ +{ + "requires": [ + "CONFIG_OPENTHREAD_ENABLED=y", + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/OpenThread/examples/onReceive/onReceive.ino b/libraries/OpenThread/examples/onReceive/onReceive.ino new file mode 100644 index 00000000000..b37c2fc7931 --- /dev/null +++ b/libraries/OpenThread/examples/onReceive/onReceive.ino @@ -0,0 +1,51 @@ +// 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. + +/* + OpenThread.begin() will automatically start a node in a Thread Network + This will demonstrate how to capture the CLI response in a callback function + The device state shall change from "disabled" to valid Thread states along time +*/ + +#include "OThreadCLI.h" + +// reads all the lines sent by CLI, one by one +// ignores some lines that are just a sequence of \r\n +void otReceivedLine() { + String line = ""; + while (OThreadCLI.available() > 0) { + char ch = OThreadCLI.read(); + if (ch != '\r' && ch != '\n') { + line += ch; + } + } + // ignores empty lines, usually EOL sequence + if (line.length() > 0) { + Serial.print("OpenThread CLI RESP===> "); + Serial.println(line.c_str()); + } +} + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(); // AutoStart + OThreadCLI.onReceive(otReceivedLine); +} + +void loop() { + // sends the "state" command to the CLI every second + // the onReceive() Callback Function will read and process the response + OThreadCLI.println("state"); + delay(1000); +} diff --git a/libraries/OpenThread/helper_functions.md b/libraries/OpenThread/helper_functions.md new file mode 100644 index 00000000000..db8b7db29e9 --- /dev/null +++ b/libraries/OpenThread/helper_functions.md @@ -0,0 +1,59 @@ +# OpenThread Helper Functions and Types + +The following helper functions and types are designed to simplify writing Arduino sketches for OpenThread.\ +They provide useful utilities for managing OpenThread stack behavior and interacting with the Thread network. + +### Enumerated Type: `ot_device_role_t` + +This enumeration defines the possible roles of a Thread device within the network: + +- `OT_ROLE_DISABLED`: The Thread stack is disabled. +- `OT_ROLE_DETACHED`: The device is not currently participating in a Thread network/partition. +- `OT_ROLE_CHILD`: The device operates as a Thread Child. +- `OT_ROLE_ROUTER`: The device operates as a Thread Router. +- `OT_ROLE_LEADER`: The device operates as a Thread Leader. + +### Struct: `ot_cmd_return_t` + +This structure represents the return status of an OpenThread CLI command: + +- `errorCode`: An integer representing the error code (if any). +- `errorMessage`: A string containing an error message (if applicable). + +### Function: `otGetDeviceRole()` + +- Returns the current role of the device as an `ot_device_role_t` value. + +### Function: `otGetStringDeviceRole()` + +- Returns a human-readable string representation of the device role (e.g., "Child," "Router," etc.). + +### Function: `otGetRespCmd(const char* cmd, char* resp = NULL, uint32_t respTimeout = 5000)` + +- Executes an OpenThread CLI command and retrieves the response. +- Parameters: + - `cmd`: The OpenThread CLI command to execute. + - `resp`: Optional buffer to store the response (if provided). + - `respTimeout`: Timeout (in milliseconds) for waiting for the response. + +### Function: `otExecCommand(const char* cmd, const char* arg, ot_cmd_return_t* returnCode = NULL)` + +- Executes an OpenThread CLI command with an argument. +- Parameters: + - `cmd`: The OpenThread CLI command to execute. + - `arg`: The argument for the command. + - `returnCode`: Optional pointer to an `ot_cmd_return_t` structure to store the return status. + +### Function: `otPrintRespCLI(const char* cmd, Stream& output, uint32_t respTimeout)` + +- Executes an OpenThread CLI command and prints the response to the specified output stream. +- Parameters: + - `cmd`: The OpenThread CLI command to execute. + - `output`: The output stream (e.g., Serial) to print the response. + - `respTimeout`: Timeout (in milliseconds) for waiting for the response. + +### Function: `otPrintNetworkInformation(Stream& output)` + +- Prints information about the current Thread network to the specified output stream. +- Parameters: + - `output`: The output stream (e.g., Serial) to print the network information. diff --git a/libraries/OpenThread/keywords.txt b/libraries/OpenThread/keywords.txt new file mode 100644 index 00000000000..d7193de188d --- /dev/null +++ b/libraries/OpenThread/keywords.txt @@ -0,0 +1,47 @@ +####################################### +# Syntax Coloring Map For OpenThread +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +OThreadCLI KEYWORD1 +OpenThreadCLI KEYWORD1 +ot_cmd_return_t KEYWORD1 +ot_device_role_t KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +startConsole KEYWORD2 +stopConsole KEYWORD2 +setPrompt KEYWORD2 +setEchoBack KEYWORD2 +setStream KEYWORD2 +onReceive KEYWORD2 +begin KEYWORD2 +setTxBufferSize KEYWORD2 +setRxBufferSize KEYWORD2 +write KEYWORD2 +available KEYWORD2 +read KEYWORD2 +peek KEYWORD2 +flush KEYWORD2 +otGetDeviceRole KEYWORD2 +otGetStringDeviceRole KEYWORD2 +otGetRespCmd KEYWORD2 +otExecCommand KEYWORD2 +otPrintRespCLI KEYWORD2 +otPrintNetworkInformation KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +OT_ROLE_DISABLED LITERAL1 +OT_ROLE_DETACHED LITERAL1 +OT_ROLE_CHILD LITERAL1 +OT_ROLE_ROUTER LITERAL1 +OT_ROLE_LEADER LITERAL1 diff --git a/libraries/OpenThread/library.properties b/libraries/OpenThread/library.properties new file mode 100644 index 00000000000..0e547d188aa --- /dev/null +++ b/libraries/OpenThread/library.properties @@ -0,0 +1,9 @@ +name=OpenThread +version=3.2.0 +author=Rodrigo Garcia | GitHub @SuGlider +maintainer=Rodrigo Garcia +sentence=Library for OpenThread Network on ESP32. +paragraph=This library is a wrapper for OpenThread CLI. It provides a simple way to interact with OpenThread Network. +category=Communication +url=https://github.com/espressif/arduino-esp32/ +architectures=esp32 diff --git a/libraries/OpenThread/src/OThreadCLI.cpp b/libraries/OpenThread/src/OThreadCLI.cpp new file mode 100644 index 00000000000..85ba03563e8 --- /dev/null +++ b/libraries/OpenThread/src/OThreadCLI.cpp @@ -0,0 +1,469 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "OThreadCLI.h" +#if SOC_IEEE802154_SUPPORTED +#if CONFIG_OPENTHREAD_ENABLED + +#include "Arduino.h" +#include "OThreadCLI.h" + +#include "esp_err.h" +#include "esp_event.h" +#include "esp_netif.h" +#include "esp_netif_types.h" +#include "esp_vfs_eventfd.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" + +#include "esp_netif_net_stack.h" +#include "lwip/netif.h" + +static TaskHandle_t s_cli_task = NULL; +static TaskHandle_t s_console_cli_task = NULL; +static QueueHandle_t rx_queue = NULL; +static QueueHandle_t tx_queue = NULL; + +static esp_openthread_platform_config_t ot_native_config; +static TaskHandle_t s_ot_task = NULL; +static esp_netif_t *openthread_netif = NULL; +#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM +static struct netif *ot_lwip_netif = NULL; +#endif + +#define OT_CLI_MAX_LINE_LENGTH 512 + +typedef struct { + Stream *cliStream; + bool echoback; + String prompt; + OnReceiveCb_t responseCallBack; +} ot_cli_console_t; +static ot_cli_console_t otConsole = {NULL, false, (const char *)NULL, NULL}; + +#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM +extern "C" int lwip_hook_ip6_input(struct pbuf *p, struct netif *inp) { + if (ot_lwip_netif && ot_lwip_netif == inp) { + return 0; + } + if (ip6_addr_isany_val(inp->ip6_addr[0].u_addr.ip6)) { + // We don't have an LL address -> eat this packet here, so it won't get accepted on input netif + pbuf_free(p); + return 1; + } + return 0; +} +#endif + +// process the CLI commands sent to the OpenThread stack +static void ot_cli_loop(void *context) { + String sTxString(""); + + while (true) { + if (tx_queue != NULL) { + uint8_t c; + if (xQueueReceive(tx_queue, &c, portMAX_DELAY)) { + // avoids sending a empty command, specially when the terminal send "\r\n" together + if (sTxString.length() > 0 && (c == '\r' || c == '\n')) { + esp_openthread_cli_input(sTxString.c_str()); + xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); + sTxString = ""; + } else { + if (c == '\b' || c == 127) { + if (sTxString.length() > 0) { + sTxString.remove(sTxString.length() - 1); + } + } else { + // only allow printable characters + if (c > 31 && c < 127) { + sTxString += (char)c; + } + } + } + } + } + } +} + +// process the CLI responses received from the OpenThread stack +static int ot_cli_output_callback(void *context, const char *format, va_list args) { + char prompt_check[3]; + int ret = 0; + + vsnprintf(prompt_check, sizeof(prompt_check), format, args); + if (!strncmp(prompt_check, "> ", sizeof(prompt_check))) { + if (s_cli_task) { + xTaskNotifyGive(s_cli_task); + } + if (s_console_cli_task) { + xTaskNotifyGive(s_console_cli_task); + } + } else { + char buf[OT_CLI_MAX_LINE_LENGTH]; + ret = vsnprintf(buf, sizeof(buf), format, args); + if (ret) { + // store received data in the RX buffer + if (rx_queue != NULL) { + size_t freeSpace = uxQueueSpacesAvailable(rx_queue); + if (freeSpace < ret) { + // Drop the oldest data to make room for the new data + for (int i = 0; i < (ret - freeSpace); i++) { + uint8_t c; + xQueueReceive(rx_queue, &c, 0); + } + } + for (int i = 0; i < ret; i++) { + xQueueSend(rx_queue, &buf[i], 0); + } + // if there is a user callback function in place, it shall have the priority + // to process/consume the Stream data received from OpenThread CLI, which is available in its RX Buffer + if (otConsole.responseCallBack != NULL) { + otConsole.responseCallBack(); + } + } + } + } + return ret; +} + +// helper task to process CLI from a Stream (e.g. Serial) +static void ot_cli_console_worker(void *context) { + ot_cli_console_t *cli = (ot_cli_console_t *)context; + + // prints the prompt as first action + if (cli->prompt && cli->echoback) { + cli->cliStream->print(cli->prompt.c_str()); + } + // manages and synchronizes the Stream flow with OpenThread CLI response + char lastReadChar; + char c = '\n'; + while (true) { + if (cli->cliStream->available() > 0) { + lastReadChar = c; + c = cli->cliStream->read(); + // if EOL is received, it may contain a combination of '\n' + // and/or '\r' depending on the Host OS and Terminal used. + // remove all leading '\r' '\n' + if (c == '\r') { + c = '\n'; // just mark it as New Line + } + if (c == '\n' && lastReadChar == '\n') { + continue; + } + + // echo it back to the console + if (cli->echoback) { + if (c == '\n') { + cli->cliStream->println(); // follows whatever is defined as EOL in Arduino + } else { + cli->cliStream->write(c); + } + } + // send it to be processed by Open Thread CLI + OThreadCLI.write(c); + // if EOL, it shall wait for the command to be processed in background + if (c == '\n' && lastReadChar != '\n') { + // wait for the OpenThread CLI to finish processing the command + xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); + // read response from OpenThread CLI and send it to the Stream + while (OThreadCLI.available() > 0) { + char c = OThreadCLI.read(); + // echo it back to the console + if (cli->echoback) { + if (c == '\n') { + cli->cliStream->println(); // follows whatever is defined as EOL in Arduino + } else { + cli->cliStream->write(c); + } + } + } + // print the prompt + if (cli->prompt && cli->echoback) { + cli->cliStream->printf(cli->prompt.c_str()); + } + } + } + } +} + +void OpenThreadCLI::setEchoBack(bool echoback) { + otConsole.echoback = echoback; +} + +void OpenThreadCLI::setPrompt(char *prompt) { + otConsole.prompt = prompt; // NULL will make the prompt not visible +} + +void OpenThreadCLI::setStream(Stream &otStream) { + otConsole.cliStream = &otStream; +} + +void OpenThreadCLI::onReceive(OnReceiveCb_t func) { + otConsole.responseCallBack = func; // NULL will set it off +} + +// Stream object shall be already started and configured before calling this function +void OpenThreadCLI::startConsole(Stream &otStream, bool echoback, const char *prompt) { + if (!otStarted) { + log_e("OpenThread CLI has not started. Please begin() it before starting the console."); + return; + } + + if (s_console_cli_task == NULL) { + otConsole.cliStream = &otStream; + otConsole.echoback = echoback; + otConsole.prompt = prompt; // NULL will invalidate the String + // it will run in the same priority (1) as the Arduino setup()/loop() task + xTaskCreate(ot_cli_console_worker, "ot_cli_console", 4096, &otConsole, 1, &s_console_cli_task); + } else { + log_w("A console is already running. Please stop it before starting a new one."); + } +} + +void OpenThreadCLI::stopConsole() { + if (s_console_cli_task) { + vTaskDelete(s_console_cli_task); + s_console_cli_task = NULL; + } +} + +OpenThreadCLI::OpenThreadCLI() { + memset(&ot_native_config, 0, sizeof(esp_openthread_platform_config_t)); + ot_native_config.radio_config.radio_mode = RADIO_MODE_NATIVE; + ot_native_config.host_config.host_connection_mode = HOST_CONNECTION_MODE_NONE; + ot_native_config.port_config.storage_partition_name = "nvs"; + ot_native_config.port_config.netif_queue_size = 10; + ot_native_config.port_config.task_queue_size = 10; + //sTxString = ""; +} + +OpenThreadCLI::~OpenThreadCLI() { + end(); +} + +OpenThreadCLI::operator bool() const { + return otStarted; +} + +static void ot_task_worker(void *aContext) { + esp_vfs_eventfd_config_t eventfd_config = { + .max_fds = 3, + }; + bool err = false; + if (ESP_OK != esp_event_loop_create_default()) { + log_e("Failed to create OpentThread event loop"); + err = true; + } + if (!err && ESP_OK != esp_netif_init()) { + log_e("Failed to initialize OpentThread netif"); + err = true; + } + if (!err && ESP_OK != esp_vfs_eventfd_register(&eventfd_config)) { + log_e("Failed to register OpentThread eventfd"); + err = true; + } + + // Initialize the OpenThread stack + if (!err && ESP_OK != esp_openthread_init(&ot_native_config)) { + log_e("Failed to initialize OpenThread stack"); + err = true; + } + if (!err) { + // Initialize the OpenThread cli + otCliInit(esp_openthread_get_instance(), ot_cli_output_callback, NULL); + + // Initialize the esp_netif bindings + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); + openthread_netif = esp_netif_new(&cfg); +#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM + // Get LwIP Netif + if (openthread_netif != NULL) { + ot_lwip_netif = (struct netif *)esp_netif_get_netif_impl(openthread_netif); + if (ot_lwip_netif == NULL) { + log_e("Failed to get OpenThread LwIP netif"); + } + } +#endif + } + if (!err && openthread_netif == NULL) { + log_e("Failed to create OpenThread esp_netif"); + err = true; + } + if (!err && ESP_OK != esp_netif_attach(openthread_netif, esp_openthread_netif_glue_init(&ot_native_config))) { + log_e("Failed to attach OpenThread esp_netif"); + err = true; + } + if (!err && ESP_OK != esp_netif_set_default_netif(openthread_netif)) { + log_e("Failed to set default OpenThread esp_netif"); + err = true; + } + if (!err) { + // only returns in case there is an OpenThread Stack failure... + esp_openthread_launch_mainloop(); + } + // Clean up + esp_openthread_netif_glue_deinit(); + esp_netif_destroy(openthread_netif); + esp_vfs_eventfd_unregister(); + vTaskDelete(NULL); +} + +void OpenThreadCLI::begin(bool OThreadAutoStart) { + if (otStarted) { + log_w("OpenThread CLI already started. Please end() it before starting again."); + return; + } + + xTaskCreate(ot_task_worker, "ot_main_loop", 10240, NULL, 20, &s_ot_task); + + //RX Buffer default has 1024 bytes if not preset + if (rx_queue == NULL) { + if (!setRxBufferSize(1024)) { + log_e("HW CDC RX Buffer error"); + } + } + //TX Buffer default has 256 bytes if not preset + if (tx_queue == NULL) { + if (!setTxBufferSize(256)) { + log_e("HW CDC RX Buffer error"); + } + } + xTaskCreate(ot_cli_loop, "ot_cli", 4096, xTaskGetCurrentTaskHandle(), 2, &s_cli_task); + + // starts Thread with default dataset from NVS or from IDF default settings + if (OThreadAutoStart) { + otOperationalDatasetTlvs dataset; + otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset); + // error = OT_ERROR_FAILED; // teste para forçar NULL dataset + if (error != OT_ERROR_NONE) { + log_i("Failed to get active NVS dataset from OpenThread"); + } else { + log_i("Got active NVS dataset from OpenThread"); + } + esp_err_t err = esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL); + if (err != ESP_OK) { + log_i("Failed to AUTO start OpenThread"); + } else { + log_i("AUTO start OpenThread done"); + } + } + otStarted = true; + return; +} + +void OpenThreadCLI::end() { + if (!otStarted) { + log_w("OpenThread CLI already stopped. Please begin() it before stopping again."); + return; + } + if (s_ot_task != NULL) { + vTaskDelete(s_ot_task); + // Clean up + esp_openthread_deinit(); + esp_openthread_netif_glue_deinit(); +#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM + ot_lwip_netif = NULL; +#endif + esp_netif_destroy(openthread_netif); + esp_vfs_eventfd_unregister(); + } + if (s_cli_task != NULL) { + vTaskDelete(s_cli_task); + } + if (s_console_cli_task != NULL) { + vTaskDelete(s_console_cli_task); + } + esp_event_loop_delete_default(); + setRxBufferSize(0); + setTxBufferSize(0); + otStarted = false; +} + +size_t OpenThreadCLI::write(uint8_t c) { + if (tx_queue == NULL) { + return 0; + } + if (xQueueSend(tx_queue, &c, 0) != pdPASS) { + return 0; + } + return 1; +} + +size_t OpenThreadCLI::setBuffer(QueueHandle_t &queue, size_t queue_len) { + if (queue) { + vQueueDelete(queue); + queue = NULL; + } + if (!queue_len) { + return 0; + } + queue = xQueueCreate(queue_len, sizeof(uint8_t)); + if (!queue) { + return 0; + } + return queue_len; +} + +size_t OpenThreadCLI::setTxBufferSize(size_t tx_queue_len) { + return setBuffer(tx_queue, tx_queue_len); +} + +size_t OpenThreadCLI::setRxBufferSize(size_t rx_queue_len) { + return setBuffer(rx_queue, rx_queue_len); +} + +int OpenThreadCLI::available(void) { + if (rx_queue == NULL) { + return -1; + } + return uxQueueMessagesWaiting(rx_queue); +} + +int OpenThreadCLI::peek(void) { + if (rx_queue == NULL) { + return -1; + } + uint8_t c; + if (xQueuePeek(rx_queue, &c, 0)) { + return c; + } + return -1; +} + +int OpenThreadCLI::read(void) { + if (rx_queue == NULL) { + return -1; + } + uint8_t c = 0; + if (xQueueReceive(rx_queue, &c, 0) == pdTRUE) { + return c; + } + return -1; +} + +void OpenThreadCLI::flush() { + if (tx_queue == NULL) { + return; + } + // wait for the TX Queue to be empty + while (uxQueueMessagesWaiting(tx_queue)); +} + +OpenThreadCLI OThreadCLI; + +#endif /* CONFIG_OPENTHREAD_ENABLED */ +#endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThreadCLI.h b/libraries/OpenThread/src/OThreadCLI.h new file mode 100644 index 00000000000..bc8dc5d2b19 --- /dev/null +++ b/libraries/OpenThread/src/OThreadCLI.h @@ -0,0 +1,74 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if SOC_IEEE802154_SUPPORTED +#if CONFIG_OPENTHREAD_ENABLED + +#include "esp_openthread.h" +#include "esp_openthread_cli.h" +#include "esp_openthread_lock.h" +#include "esp_openthread_netif_glue.h" +#include "esp_openthread_types.h" + +#include "openthread/cli.h" +#include "openthread/instance.h" +#include "openthread/logging.h" +#include "openthread/tasklet.h" +#include "openthread/dataset_ftd.h" + +#include "Arduino.h" + +typedef std::function OnReceiveCb_t; + +class OpenThreadCLI : public Stream { +private: + static size_t setBuffer(QueueHandle_t &queue, size_t len); + bool otStarted = false; + +public: + OpenThreadCLI(); + ~OpenThreadCLI(); + // returns true if OpenThread CLI is running + operator bool() const; + + // starts a task to read/write otStream. Default prompt is "ot> ". Set it to NULL to make it invisible. + void startConsole(Stream &otStream, bool echoback = true, const char *prompt = "ot> "); + void stopConsole(); + void setPrompt(char *prompt); // changes the console prompt. NULL is an empty prompt. + void setEchoBack(bool echoback); // changes the console echoback option + void setStream(Stream &otStream); // changes the console Stream object + void onReceive(OnReceiveCb_t func); // called on a complete line of output from OT CLI, as OT Response + + void begin(bool OThreadAutoStart = true); + void end(); + + // default size is 256 bytes + size_t setTxBufferSize(size_t tx_queue_len); + // default size is 1024 bytes + size_t setRxBufferSize(size_t rx_queue_len); + + size_t write(uint8_t); + int available(); + int read(); + int peek(); + void flush(); +}; + +extern OpenThreadCLI OThreadCLI; + +#endif /* CONFIG_OPENTHREAD_ENABLED */ +#endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThreadCLI_Util.cpp b/libraries/OpenThread/src/OThreadCLI_Util.cpp new file mode 100644 index 00000000000..d21daa1effc --- /dev/null +++ b/libraries/OpenThread/src/OThreadCLI_Util.cpp @@ -0,0 +1,212 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "OThreadCLI.h" +#if SOC_IEEE802154_SUPPORTED +#if CONFIG_OPENTHREAD_ENABLED + +#include "OThreadCLI_Util.h" +#include + +static const char *otRoleString[] = { + "Disabled", ///< The Thread stack is disabled. + "Detached", ///< Not currently participating in a Thread network/partition. + "Child", ///< The Thread Child role. + "Router", ///< The Thread Router role. + "Leader", ///< The Thread Leader role. +}; + +ot_device_role_t otGetDeviceRole() { + if (!OThreadCLI) { + return OT_ROLE_DISABLED; + } + otInstance *instance = esp_openthread_get_instance(); + return (ot_device_role_t)otThreadGetDeviceRole(instance); +} + +const char *otGetStringDeviceRole() { + return otRoleString[otGetDeviceRole()]; +} + +bool otGetRespCmd(const char *cmd, char *resp, uint32_t respTimeout) { + if (!OThreadCLI) { + return false; + } + StreamString cliRespAllLines; + char cliResp[256] = {0}; + if (resp != NULL) { + *resp = '\0'; + } + if (cmd == NULL) { + return true; + } + OThreadCLI.println(cmd); + log_d("CMD[%s]", cmd); + uint32_t timeout = millis() + respTimeout; + while (millis() < timeout) { + size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); + // clip it on EOL + for (int i = 0; i < len; i++) { + if (cliResp[i] == '\r' || cliResp[i] == '\n') { + cliResp[i] = '\0'; + } + } + log_d("Resp[%s]", cliResp); + if (strncmp(cliResp, "Done", 4) && strncmp(cliResp, "Error", 4)) { + cliRespAllLines += cliResp; + cliRespAllLines.println(); // Adds whatever EOL is for the OS + } else { + break; + } + } + if (!strncmp(cliResp, "Error", 4) || millis() > timeout) { + return false; + } + if (resp != NULL) { + strcpy(resp, cliRespAllLines.c_str()); + } + return true; +} + +bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode) { + if (!OThreadCLI) { + return false; + } + char cliResp[256] = {0}; + if (cmd == NULL) { + return true; + } + if (arg == NULL) { + OThreadCLI.println(cmd); + } else { + OThreadCLI.print(cmd); + OThreadCLI.print(" "); + OThreadCLI.println(arg); + } + size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); + // clip it on EOL + for (int i = 0; i < len; i++) { + if (cliResp[i] == '\r' || cliResp[i] == '\n') { + cliResp[i] = '\0'; + } + } + log_d("CMD[%s %s] Resp[%s]", cmd, arg, cliResp); + // initial returnCode is success values + if (returnCode) { + returnCode->errorCode = 0; + returnCode->errorMessage = "Done"; + } + if (!strncmp(cliResp, "Done", 4)) { + return true; + } else { + if (returnCode) { + // initial setting is a bad error message or it is something else... + // return -1 and the full returned message + returnCode->errorCode = -1; + returnCode->errorMessage = cliResp; + // parse cliResp looking for errorCode and errorMessage + // OT CLI error message format is "Error ##: msg\n" - Example: + //Error 35: InvalidCommand + //Error 7: InvalidArgs + char *i = cliResp; + char *m = cliResp; + while (*i && *i != ':') { + i++; + } + if (*i) { + *i = '\0'; + m = i + 2; // message is 2 characters after ':' + while (i > cliResp && *i != ' ') { + i--; // search for ' ' before ":' + } + if (*i == ' ') { + i++; // move it forward to the number beginning + returnCode->errorCode = atoi(i); + returnCode->errorMessage = m; + } // otherwise, it will keep the "bad error message" information + } // otherwise, it will keep the "bad error message" information + } // returnCode is NULL pointer + return false; + } +} + +bool otPrintRespCLI(const char *cmd, Stream &output, uint32_t respTimeout) { + char cliResp[256] = {0}; + if (cmd == NULL) { + return true; + } + OThreadCLI.println(cmd); + uint32_t timeout = millis() + respTimeout; + while (millis() < timeout) { + size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); + if (cliResp[0] == '\0') { + // Straem has timed out and it should try again using parameter respTimeout + continue; + } + // clip it on EOL + for (int i = 0; i < len; i++) { + if (cliResp[i] == '\r' || cliResp[i] == '\n') { + cliResp[i] = '\0'; + } + } + if (strncmp(cliResp, "Done", 4) && strncmp(cliResp, "Error", 4)) { + output.println(cliResp); + memset(cliResp, 0, sizeof(cliResp)); + timeout = millis() + respTimeout; // renew timeout, line per line + } else { + break; + } + } + if (!strncmp(cliResp, "Error", 4) || millis() > timeout) { + return false; + } + return true; +} + +void otPrintNetworkInformation(Stream &output) { + if (!OThreadCLI) { + return; + } + char resp[512]; + output.println("Thread Setup:"); + if (otGetRespCmd("state", resp)) { + output.printf("Node State: \t%s", resp); + } + if (otGetRespCmd("networkname", resp)) { + output.printf("Network Name: \t%s", resp); + } + if (otGetRespCmd("channel", resp)) { + output.printf("Channel: \t%s", resp); + } + if (otGetRespCmd("panid", resp)) { + output.printf("Pan ID: \t%s", resp); + } + if (otGetRespCmd("extpanid", resp)) { + output.printf("Ext Pan ID: \t%s", resp); + } + if (otGetRespCmd("networkkey", resp)) { + output.printf("Network Key: \t%s", resp); + } + if (otGetRespCmd("ipaddr", resp)) { + output.println("Node IP Addresses are:"); + output.printf("%s", resp); + } + if (otGetRespCmd("ipmaddr", resp)) { + output.println("Node Multicast Addresses are:"); + output.printf("%s", resp); + } +} + +#endif /* CONFIG_OPENTHREAD_ENABLED */ +#endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThreadCLI_Util.h b/libraries/OpenThread/src/OThreadCLI_Util.h new file mode 100644 index 00000000000..1ab2e061dfc --- /dev/null +++ b/libraries/OpenThread/src/OThreadCLI_Util.h @@ -0,0 +1,42 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if SOC_IEEE802154_SUPPORTED +#if CONFIG_OPENTHREAD_ENABLED + +typedef enum { + OT_ROLE_DISABLED = 0, ///< The Thread stack is disabled. + OT_ROLE_DETACHED = 1, ///< Not currently participating in a Thread network/partition. + OT_ROLE_CHILD = 2, ///< The Thread Child role. + OT_ROLE_ROUTER = 3, ///< The Thread Router role. + OT_ROLE_LEADER = 4, ///< The Thread Leader role. +} ot_device_role_t; + +typedef struct { + int errorCode; + String errorMessage; +} ot_cmd_return_t; + +ot_device_role_t otGetDeviceRole(); +const char *otGetStringDeviceRole(); +bool otGetRespCmd(const char *cmd, char *resp = NULL, uint32_t respTimeout = 5000); +bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode = NULL); +bool otPrintRespCLI(const char *cmd, Stream &output, uint32_t respTimeout); +void otPrintNetworkInformation(Stream &output); + +#endif /* CONFIG_OPENTHREAD_ENABLED */ +#endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/PPP/examples/PPP_Basic/PPP_Basic.ino b/libraries/PPP/examples/PPP_Basic/PPP_Basic.ino index 95d59975bb4..1b5776d18ed 100644 --- a/libraries/PPP/examples/PPP_Basic/PPP_Basic.ino +++ b/libraries/PPP/examples/PPP_Basic/PPP_Basic.ino @@ -4,14 +4,15 @@ #define PPP_MODEM_PIN "0000" // or NULL // WaveShare SIM7600 HW Flow Control -#define PPP_MODEM_RST 25 -#define PPP_MODEM_RST_LOW false //active HIGH -#define PPP_MODEM_TX 21 -#define PPP_MODEM_RX 22 -#define PPP_MODEM_RTS 26 -#define PPP_MODEM_CTS 27 -#define PPP_MODEM_FC ESP_MODEM_FLOW_CONTROL_HW -#define PPP_MODEM_MODEL PPP_MODEM_SIM7600 +#define PPP_MODEM_RST 25 +#define PPP_MODEM_RST_LOW false //active HIGH +#define PPP_MODEM_RST_DELAY 200 +#define PPP_MODEM_TX 21 +#define PPP_MODEM_RX 22 +#define PPP_MODEM_RTS 26 +#define PPP_MODEM_CTS 27 +#define PPP_MODEM_FC ESP_MODEM_FLOW_CONTROL_HW +#define PPP_MODEM_MODEL PPP_MODEM_SIM7600 // SIM800 basic module with just TX,RX and RST // #define PPP_MODEM_RST 0 @@ -60,7 +61,7 @@ void setup() { // Configure the modem PPP.setApn(PPP_MODEM_APN); PPP.setPin(PPP_MODEM_PIN); - PPP.setResetPin(PPP_MODEM_RST, PPP_MODEM_RST_LOW); + PPP.setResetPin(PPP_MODEM_RST, PPP_MODEM_RST_LOW, PPP_MODEM_RST_DELAY); PPP.setPins(PPP_MODEM_TX, PPP_MODEM_RX, PPP_MODEM_RTS, PPP_MODEM_CTS, PPP_MODEM_FC); Serial.println("Starting the modem. It might take a while!"); diff --git a/libraries/PPP/examples/PPP_Basic/ci.json b/libraries/PPP/examples/PPP_Basic/ci.json new file mode 100644 index 00000000000..314587edcf6 --- /dev/null +++ b/libraries/PPP/examples/PPP_Basic/ci.json @@ -0,0 +1,5 @@ +{ + "requires": [ + "CONFIG_LWIP_PPP_SUPPORT=y" + ] +} diff --git a/libraries/PPP/examples/PPP_WIFI_BRIDGE/PPP_WIFI_BRIDGE.ino b/libraries/PPP/examples/PPP_WIFI_BRIDGE/PPP_WIFI_BRIDGE.ino new file mode 100644 index 00000000000..1e3f9f9bb98 --- /dev/null +++ b/libraries/PPP/examples/PPP_WIFI_BRIDGE/PPP_WIFI_BRIDGE.ino @@ -0,0 +1,153 @@ +#include +#include + +#define PPP_MODEM_APN "internet" +#define PPP_MODEM_PIN "0000" // or NULL + +// WaveShare SIM7600 HW Flow Control +#define PPP_MODEM_RST 25 +#define PPP_MODEM_RST_LOW false //active HIGH +#define PPP_MODEM_RST_DELAY 200 +#define PPP_MODEM_TX 21 +#define PPP_MODEM_RX 22 +#define PPP_MODEM_RTS 26 +#define PPP_MODEM_CTS 27 +#define PPP_MODEM_FC ESP_MODEM_FLOW_CONTROL_HW +#define PPP_MODEM_MODEL PPP_MODEM_SIM7600 + +// SIM800 basic module with just TX,RX and RST +// #define PPP_MODEM_RST 0 +// #define PPP_MODEM_RST_LOW true //active LOW +// #define PPP_MODEM_TX 2 +// #define PPP_MODEM_RX 19 +// #define PPP_MODEM_RTS -1 +// #define PPP_MODEM_CTS -1 +// #define PPP_MODEM_FC ESP_MODEM_FLOW_CONTROL_NONE +// #define PPP_MODEM_MODEL PPP_MODEM_SIM800 + +// WiFi Access Point Config +#define AP_SSID "ESP32-ETH-WIFI-BRIDGE" +#define AP_PASS "password" + +IPAddress ap_ip(192, 168, 4, 1); +IPAddress ap_mask(255, 255, 255, 0); +IPAddress ap_leaseStart(192, 168, 4, 2); +IPAddress ap_dns(8, 8, 4, 4); + +void setup() { + Serial.begin(115200); + Serial.setDebugOutput(true); + + // Listen for modem events + Network.onEvent(onEvent); + + // Start the Access Point + WiFi.AP.begin(); + WiFi.AP.config(ap_ip, ap_ip, ap_mask, ap_leaseStart, ap_dns); + WiFi.AP.create(AP_SSID, AP_PASS); + if (!WiFi.AP.waitStatusBits(ESP_NETIF_STARTED_BIT, 1000)) { + Serial.println("Failed to start AP!"); + return; + } + + // Configure the modem + PPP.setApn(PPP_MODEM_APN); + PPP.setPin(PPP_MODEM_PIN); + PPP.setResetPin(PPP_MODEM_RST, PPP_MODEM_RST_LOW, PPP_MODEM_RST_DELAY); + PPP.setPins(PPP_MODEM_TX, PPP_MODEM_RX, PPP_MODEM_RTS, PPP_MODEM_CTS, PPP_MODEM_FC); + + Serial.println("Starting the modem. It might take a while!"); + PPP.begin(PPP_MODEM_MODEL); + + Serial.print("Manufacturer: "); + Serial.println(PPP.cmd("AT+CGMI", 10000)); + Serial.print("Model: "); + Serial.println(PPP.moduleName()); + Serial.print("IMEI: "); + Serial.println(PPP.IMEI()); + + bool attached = PPP.attached(); + if (!attached) { + int i = 0; + unsigned int s = millis(); + Serial.print("Waiting to connect to network"); + while (!attached && ((++i) < 600)) { + Serial.print("."); + delay(100); + attached = PPP.attached(); + } + Serial.print((millis() - s) / 1000.0, 1); + Serial.println("s"); + attached = PPP.attached(); + } + + Serial.print("Attached: "); + Serial.println(attached); + Serial.print("State: "); + Serial.println(PPP.radioState()); + if (attached) { + Serial.print("Operator: "); + Serial.println(PPP.operatorName()); + Serial.print("IMSI: "); + Serial.println(PPP.IMSI()); + Serial.print("RSSI: "); + Serial.println(PPP.RSSI()); + int ber = PPP.BER(); + if (ber > 0) { + Serial.print("BER: "); + Serial.println(ber); + Serial.print("NetMode: "); + Serial.println(PPP.networkMode()); + } + + Serial.println("Switching to data mode..."); + PPP.mode(ESP_MODEM_MODE_CMUX); // Data and Command mixed mode + if (!PPP.waitStatusBits(ESP_NETIF_CONNECTED_BIT, 1000)) { + Serial.println("Failed to connect to internet!"); + } else { + Serial.println("Connected to internet!"); + } + } else { + Serial.println("Failed to connect to network!"); + } +} + +void loop() { + delay(20000); +} + +void onEvent(arduino_event_id_t event, arduino_event_info_t info) { + switch (event) { + case ARDUINO_EVENT_PPP_START: Serial.println("PPP Started"); break; + case ARDUINO_EVENT_PPP_CONNECTED: Serial.println("PPP Connected"); break; + case ARDUINO_EVENT_PPP_GOT_IP: + Serial.println("PPP Got IP"); + Serial.println(PPP); + WiFi.AP.enableNAPT(true); + break; + case ARDUINO_EVENT_PPP_LOST_IP: + Serial.println("PPP Lost IP"); + WiFi.AP.enableNAPT(false); + break; + case ARDUINO_EVENT_PPP_DISCONNECTED: + Serial.println("PPP Disconnected"); + WiFi.AP.enableNAPT(false); + break; + case ARDUINO_EVENT_PPP_STOP: Serial.println("PPP Stopped"); break; + + case ARDUINO_EVENT_WIFI_AP_START: + Serial.println("AP Started"); + Serial.println(WiFi.AP); + break; + case ARDUINO_EVENT_WIFI_AP_STACONNECTED: Serial.println("AP STA Connected"); break; + case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: Serial.println("AP STA Disconnected"); break; + case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED: + Serial.print("AP STA IP Assigned: "); + Serial.println(IPAddress(info.wifi_ap_staipassigned.ip.addr)); + break; + case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED: Serial.println("AP Probe Request Received"); break; + case ARDUINO_EVENT_WIFI_AP_STOP: Serial.println("AP Stopped"); break; + + default: break; + } +} diff --git a/libraries/PPP/examples/PPP_WIFI_BRIDGE/ci.json b/libraries/PPP/examples/PPP_WIFI_BRIDGE/ci.json new file mode 100644 index 00000000000..ccc62161c85 --- /dev/null +++ b/libraries/PPP/examples/PPP_WIFI_BRIDGE/ci.json @@ -0,0 +1,9 @@ +{ + "requires": [ + "CONFIG_LWIP_PPP_SUPPORT=y" + ], + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] +} diff --git a/libraries/PPP/library.properties b/libraries/PPP/library.properties index abc4fb21a71..7158a027b0a 100644 --- a/libraries/PPP/library.properties +++ b/libraries/PPP/library.properties @@ -1,5 +1,5 @@ name=PPP -version=1.0.0 +version=3.2.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables network connection using GSM Modem. diff --git a/libraries/PPP/src/PPP.cpp b/libraries/PPP/src/PPP.cpp index 3c7a887d672..87fee6920c3 100644 --- a/libraries/PPP/src/PPP.cpp +++ b/libraries/PPP/src/PPP.cpp @@ -1,12 +1,22 @@ #define ARDUINO_CORE_BUILD #include "PPP.h" -#if CONFIG_LWIP_PPP_SUPPORT +#if CONFIG_LWIP_PPP_SUPPORT && ARDUINO_HAS_ESP_MODEM #include "esp32-hal-periman.h" #include "esp_netif.h" #include "esp_netif_ppp.h" #include #include "driver/uart.h" #include "hal/uart_ll.h" +#include "esp_private/uart_share_hw_ctrl.h" + +#define PPP_CMD_MODE_CHECK(x) \ + if (_dce == NULL) { \ + return x; \ + } \ + if (_mode == ESP_MODEM_MODE_DATA) { \ + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); \ + return x; \ + } typedef struct { void *arg; @@ -141,8 +151,9 @@ esp_modem_dce_t *PPPClass::handle() const { } PPPClass::PPPClass() - : _dce(NULL), _pin_tx(-1), _pin_rx(-1), _pin_rts(-1), _pin_cts(-1), _flow_ctrl(ESP_MODEM_FLOW_CONTROL_NONE), _pin_rst(-1), _pin_rst_act_low(true), _pin(NULL), - _apn(NULL), _rx_buffer_size(4096), _tx_buffer_size(512), _mode(ESP_MODEM_MODE_COMMAND), _uart_num(UART_NUM_1) {} + : _dce(NULL), _pin_tx(-1), _pin_rx(-1), _pin_rts(-1), _pin_cts(-1), _flow_ctrl(ESP_MODEM_FLOW_CONTROL_NONE), _pin_rst(-1), _pin_rst_act_low(true), + _pin_rst_delay(200), _pin(NULL), _apn(NULL), _rx_buffer_size(4096), _tx_buffer_size(512), _mode(ESP_MODEM_MODE_COMMAND), _uart_num(UART_NUM_1), + _ppp_event_handle(0) {} PPPClass::~PPPClass() {} @@ -152,9 +163,10 @@ bool PPPClass::pppDetachBus(void *bus_pointer) { return true; } -void PPPClass::setResetPin(int8_t rst, bool active_low) { +void PPPClass::setResetPin(int8_t rst, bool active_low, uint32_t reset_delay) { _pin_rst = digitalPinToGPIONumber(rst); _pin_rst_act_low = active_low; + _pin_rst_delay = reset_delay; } bool PPPClass::setPins(int8_t tx, int8_t rx, int8_t rts, int8_t cts, esp_modem_flow_ctrl_t flow_ctrl) { @@ -216,7 +228,7 @@ bool PPPClass::setPins(int8_t tx, int8_t rx, int8_t rts, int8_t cts, esp_modem_f bool PPPClass::begin(ppp_modem_model_t model, uint8_t uart_num, int baud_rate) { esp_err_t ret = ESP_OK; bool pin_ok = false; - int trys = 0; + int tries = 0; if (_esp_netif != NULL || _dce != NULL) { log_w("PPP Already Started"); @@ -269,7 +281,7 @@ bool PPPClass::begin(ppp_modem_model_t model, uint8_t uart_num, int baud_rate) { dte_config.uart_config.flow_control = _flow_ctrl; dte_config.uart_config.rx_buffer_size = _rx_buffer_size; dte_config.uart_config.tx_buffer_size = _tx_buffer_size; - dte_config.uart_config.port_num = _uart_num; + dte_config.uart_config.port_num = (uart_port_t)_uart_num; dte_config.uart_config.baud_rate = baud_rate; /* Configure the DCE */ @@ -285,7 +297,7 @@ bool PPPClass::begin(ppp_modem_model_t model, uint8_t uart_num, int baud_rate) { } perimanSetPinBusExtraType(_pin_rst, "PPP_MODEM_RST"); digitalWrite(_pin_rst, !_pin_rst_act_low); - delay(200); + delay(_pin_rst_delay); digitalWrite(_pin_rst, _pin_rst_act_low); delay(100); } @@ -303,19 +315,28 @@ bool PPPClass::begin(ppp_modem_model_t model, uint8_t uart_num, int baud_rate) { if (_pin_rst >= 0) { // wait to be able to talk to the modem log_v("Waiting for response from the modem"); - while (esp_modem_sync(_dce) != ESP_OK && trys < 100) { - trys++; + while (esp_modem_sync(_dce) != ESP_OK && tries < 100) { + tries++; delay(500); } - if (trys >= 100) { + if (tries >= 100) { log_e("Failed to wait for communication"); goto err; } } else { // try to communicate with the modem if (esp_modem_sync(_dce) != ESP_OK) { - log_v("Modem does not respond to AT, maybe in DATA mode? ...exiting network mode"); + log_v("Modem does not respond to AT! Switching to COMMAND mode."); esp_modem_set_mode(_dce, ESP_MODEM_MODE_COMMAND); + if (esp_modem_sync(_dce) != ESP_OK) { + log_v("Modem does not respond to AT! Switching to CMUX mode."); + if (esp_modem_set_mode(_dce, ESP_MODEM_MODE_CMUX) != ESP_OK) { + log_v("Modem failed to switch to CMUX mode!"); + } else { + log_v("Switching back to COMMAND mode"); + esp_modem_set_mode(_dce, ESP_MODEM_MODE_COMMAND); + } + } if (esp_modem_sync(_dce) != ESP_OK) { log_e("Modem failed to respond to AT!"); goto err; @@ -340,7 +361,7 @@ bool PPPClass::begin(ppp_modem_model_t model, uint8_t uart_num, int baud_rate) { } } - Network.onSysEvent(onPppArduinoEvent); + _ppp_event_handle = Network.onSysEvent(onPppArduinoEvent); setStatusBits(ESP_NETIF_STARTED_BIT); arduino_event_t arduino_event; @@ -382,7 +403,8 @@ void PPPClass::end(void) { } _esp_modem = NULL; - Network.removeEvent(onPppArduinoEvent); + Network.removeEvent(_ppp_event_handle); + _ppp_event_handle = 0; if (_dce != NULL) { esp_modem_destroy(_dce); @@ -415,26 +437,13 @@ void PPPClass::end(void) { } bool PPPClass::sync() const { - if (_dce == NULL) { - return false; - } + PPP_CMD_MODE_CHECK(false); - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return false; - } return esp_modem_sync(_dce) == ESP_OK; } bool PPPClass::attached() const { - if (_dce == NULL) { - return false; - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return false; - } + PPP_CMD_MODE_CHECK(false); int m = 0; esp_err_t err = esp_modem_get_network_attachment_state(_dce, m); @@ -499,52 +508,31 @@ bool PPPClass::setPin(const char *pin) { } int PPPClass::RSSI() const { - if (_dce == NULL) { - return -1; - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return -1; - } + PPP_CMD_MODE_CHECK(-1); int rssi, ber; esp_err_t err = esp_modem_get_signal_quality(_dce, rssi, ber); if (err != ESP_OK) { - // log_e("esp_modem_get_signal_quality failed with %d %s", err, esp_err_to_name(err)); + log_e("esp_modem_get_signal_quality failed with %d %s", err, esp_err_to_name(err)); return -1; } return rssi; } int PPPClass::BER() const { - if (_dce == NULL) { - return -1; - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return -1; - } + PPP_CMD_MODE_CHECK(-1); int rssi, ber; esp_err_t err = esp_modem_get_signal_quality(_dce, rssi, ber); if (err != ESP_OK) { - // log_e("esp_modem_get_signal_quality failed with %d %s", err, esp_err_to_name(err)); + log_e("esp_modem_get_signal_quality failed with %d %s", err, esp_err_to_name(err)); return -1; } return ber; } String PPPClass::IMSI() const { - if (_dce == NULL) { - return String(); - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return String(); - } + PPP_CMD_MODE_CHECK(String()); char imsi[32]; esp_err_t err = esp_modem_get_imsi(_dce, (std::string &)imsi); @@ -557,14 +545,7 @@ String PPPClass::IMSI() const { } String PPPClass::IMEI() const { - if (_dce == NULL) { - return String(); - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return String(); - } + PPP_CMD_MODE_CHECK(String()); char imei[32]; esp_err_t err = esp_modem_get_imei(_dce, (std::string &)imei); @@ -577,14 +558,7 @@ String PPPClass::IMEI() const { } String PPPClass::moduleName() const { - if (_dce == NULL) { - return String(); - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return String(); - } + PPP_CMD_MODE_CHECK(String()); char name[32]; esp_err_t err = esp_modem_get_module_name(_dce, (std::string &)name); @@ -597,14 +571,7 @@ String PPPClass::moduleName() const { } String PPPClass::operatorName() const { - if (_dce == NULL) { - return String(); - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return String(); - } + PPP_CMD_MODE_CHECK(String()); char oper[32]; int act = 0; @@ -618,14 +585,7 @@ String PPPClass::operatorName() const { } int PPPClass::networkMode() const { - if (_dce == NULL) { - return -1; - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return -1; - } + PPP_CMD_MODE_CHECK(-1); int m = 0; esp_err_t err = esp_modem_get_network_system_mode(_dce, m); @@ -637,14 +597,7 @@ int PPPClass::networkMode() const { } int PPPClass::radioState() const { - if (_dce == NULL) { - return -1; - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return -1; - } + PPP_CMD_MODE_CHECK(-1); int m = 0; esp_err_t err = esp_modem_get_radio_state(_dce, m); @@ -656,14 +609,7 @@ int PPPClass::radioState() const { } bool PPPClass::powerDown() { - if (_dce == NULL) { - return false; - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return false; - } + PPP_CMD_MODE_CHECK(false); esp_err_t err = esp_modem_power_down(_dce); if (err != ESP_OK) { @@ -674,14 +620,7 @@ bool PPPClass::powerDown() { } bool PPPClass::reset() { - if (_dce == NULL) { - return false; - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return false; - } + PPP_CMD_MODE_CHECK(false); esp_err_t err = esp_modem_reset(_dce); if (err != ESP_OK) { @@ -692,14 +631,7 @@ bool PPPClass::reset() { } bool PPPClass::storeProfile() { - if (_dce == NULL) { - return false; - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return false; - } + PPP_CMD_MODE_CHECK(false); esp_err_t err = esp_modem_store_profile(_dce); if (err != ESP_OK) { @@ -710,14 +642,7 @@ bool PPPClass::storeProfile() { } bool PPPClass::setBaudrate(int baudrate) { - if (_dce == NULL) { - return false; - } - - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return false; - } + PPP_CMD_MODE_CHECK(false); esp_err_t err = esp_modem_set_baud(_dce, baudrate); if (err != ESP_OK) { @@ -731,20 +656,52 @@ bool PPPClass::setBaudrate(int baudrate) { log_e("uart_get_sclk_freq failed with %d %s", err, esp_err_to_name(err)); return false; } - uart_ll_set_baudrate(UART_LL_GET_HW(_uart_num), (uint32_t)baudrate, sclk_freq); + + HP_UART_SRC_CLK_ATOMIC() { + uart_ll_set_baudrate(UART_LL_GET_HW(_uart_num), (uint32_t)baudrate, sclk_freq); + } return true; } -bool PPPClass::sms(const char *num, const char *message) { - if (_dce == NULL) { - return false; +int PPPClass::batteryVoltage() const { + PPP_CMD_MODE_CHECK(-1); + + int volt, bcs, bcl; + esp_err_t err = esp_modem_get_battery_status(_dce, volt, bcs, bcl); + if (err != ESP_OK) { + log_e("esp_modem_get_battery_status failed with %d %s", err, esp_err_to_name(err)); + return -1; } + return volt; +} - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return false; +int PPPClass::batteryLevel() const { + PPP_CMD_MODE_CHECK(-1); + + int volt, bcs, bcl; + esp_err_t err = esp_modem_get_battery_status(_dce, volt, bcs, bcl); + if (err != ESP_OK) { + log_e("esp_modem_get_battery_status failed with %d %s", err, esp_err_to_name(err)); + return -1; } + return bcl; +} + +int PPPClass::batteryStatus() const { + PPP_CMD_MODE_CHECK(-1); + + int volt, bcs, bcl; + esp_err_t err = esp_modem_get_battery_status(_dce, volt, bcs, bcl); + if (err != ESP_OK) { + log_e("esp_modem_get_battery_status failed with %d %s", err, esp_err_to_name(err)); + return -1; + } + return bcs; +} + +bool PPPClass::sms(const char *num, const char *message) { + PPP_CMD_MODE_CHECK(false); for (int i = 0; i < strlen(num); i++) { if (num[i] != '+' && num[i] != '#' && num[i] != '*' && (num[i] < 0x30 || num[i] > 0x39)) { @@ -774,14 +731,8 @@ bool PPPClass::sms(const char *num, const char *message) { } String PPPClass::cmd(const char *at_command, int timeout) { - if (_dce == NULL) { - return String(); - } + PPP_CMD_MODE_CHECK(String()); - if (_mode == ESP_MODEM_MODE_DATA) { - log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); - return String(); - } char out[128] = {0}; esp_err_t err = _esp_modem_at(_dce, at_command, out, timeout); if (err != ESP_OK) { diff --git a/libraries/PPP/src/PPP.h b/libraries/PPP/src/PPP.h index 6e5ee58471e..b317f52aefc 100644 --- a/libraries/PPP/src/PPP.h +++ b/libraries/PPP/src/PPP.h @@ -1,7 +1,11 @@ #pragma once #include "sdkconfig.h" -#if CONFIG_LWIP_PPP_SUPPORT +#if defined __has_include && __has_include("esp_modem_c_api_types.h") +#define ARDUINO_HAS_ESP_MODEM 1 +#endif + +#if CONFIG_LWIP_PPP_SUPPORT && ARDUINO_HAS_ESP_MODEM #include "Network.h" #include "esp_modem_c_api_types.h" @@ -36,7 +40,7 @@ class PPPClass : public NetworkInterface { bool setPins(int8_t tx, int8_t rx, int8_t rts = -1, int8_t cts = -1, esp_modem_flow_ctrl_t flow_ctrl = ESP_MODEM_FLOW_CONTROL_NONE); // Using the reset pin of the module ensures that proper communication can be achieved - void setResetPin(int8_t rst, bool active_low = true); + void setResetPin(int8_t rst, bool active_low = true, uint32_t reset_delay = 200); // Modem DCE APIs int RSSI() const; @@ -49,6 +53,9 @@ class PPPClass : public NetworkInterface { int radioState() const; // 0:minimal, 1:full bool attached() const; // true is attached to network bool sync() const; // true if responds to 'AT' + int batteryVoltage() const; + int batteryLevel() const; + int batteryStatus() const; // Switch the communication mode bool mode(esp_modem_dce_mode_t m); @@ -94,16 +101,17 @@ class PPPClass : public NetworkInterface { esp_modem_flow_ctrl_t _flow_ctrl; int8_t _pin_rst; bool _pin_rst_act_low; + uint32_t _pin_rst_delay; const char *_pin; const char *_apn; int _rx_buffer_size; int _tx_buffer_size; esp_modem_dce_mode_t _mode; uint8_t _uart_num; + network_event_handle_t _ppp_event_handle; static bool pppDetachBus(void *bus_pointer); }; extern PPPClass PPP; - -#endif /* CONFIG_LWIP_PPP_SUPPORT */ +#endif /* CONFIG_LWIP_PPP_SUPPORT && ARDUINO_HAS_ESP_MODEM */ diff --git a/libraries/PPP/src/ppp.c b/libraries/PPP/src/ppp.c index db8ba0760bd..52896e76c8e 100644 --- a/libraries/PPP/src/ppp.c +++ b/libraries/PPP/src/ppp.c @@ -1,5 +1,5 @@ #include "sdkconfig.h" -#if CONFIG_LWIP_PPP_SUPPORT +#if CONFIG_LWIP_PPP_SUPPORT && defined __has_include && __has_include("esp_modem_api.h") #include "esp_modem_api.h" esp_err_t _esp_modem_at(esp_modem_dce_t *dce_wrap, const char *at, char *p_out, int timeout) { diff --git a/libraries/Preferences/library.properties b/libraries/Preferences/library.properties index bda63d82e09..eb0158e4932 100644 --- a/libraries/Preferences/library.properties +++ b/libraries/Preferences/library.properties @@ -1,5 +1,5 @@ name=Preferences -version=2.0.0 +version=3.2.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Provides friendly access to ESP32's Non-Volatile Storage diff --git a/libraries/README.md b/libraries/README.md index 7fe904b4467..aee5bb07614 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -1,9 +1,9 @@ # ESP32 Libraries -arduino-esp32 includes libraries for Arduino compatibility along with some object wrappers around hardware specific devices. Examples are included in the examples folder under each library folder. The ESP32 includes additional examples which need no special drivers. +arduino-esp32 includes libraries for Arduino compatibility along with some object wrappers around hardware specific devices. Examples are included in the examples folder under each library folder. The ESP32 includes additional examples which need no special drivers. ### ArduinoOTA - Over The Air firmware update daemon. Use espota.py to upload to the device. + Over The Air firmware update daemon. Use espota.py to upload to the device. ### AsyncUDP Asynchronous task driven UDP datagram client/server @@ -88,6 +88,9 @@ arduino-esp32 includes libraries for Arduino compatibility along with some objec ### SPIFFS SPI Flash Filesystem (see [spiffs-plugin](https://github.com/me-no-dev/arduino-esp32fs-plugin) to upload to device) +### SR + ESP-SR helps users build AI speech solutions based on ESP32-S3 or ESP32-P4 chips + ### Ticker A timer to call functions on an interval @@ -100,11 +103,13 @@ arduino-esp32 includes libraries for Arduino compatibility along with some objec ### WebServer A simple HTTP daemon + ### WiFi - Arduino compatible WiFi driver (includes Ethernet driver) + + Arduino compatible Wi-Fi driver ### NetworkClientSecure - Arduino compatible WiFi client object using embedded encryption + Arduino compatible Wi-Fi client object using embedded encryption ### Wire Arduino compatible I2C driver diff --git a/libraries/RainMaker/README.md b/libraries/RainMaker/README.md index b9eb5e6cded..2bfe7dd1a06 100644 --- a/libraries/RainMaker/README.md +++ b/libraries/RainMaker/README.md @@ -41,7 +41,7 @@ NOTE : ESP RainMaker library is currently supported for ESP32 board only. ## ESP RainMaker Agent API ### RMaker.initNode() -This initializes the ESP RainMaker agent, wifi and creates the node. +This initializes the ESP RainMaker agent, Wi-Fi and creates the node. ``` Node initNode(const char *name, const char *type); ``` @@ -67,7 +67,7 @@ esp_err_t start() > NOTE : > 1. ESP RainMaker agent should be initialized before this call. -> 2. Once ESP RainMaker agent starts, compulsorily call WiFi.beginProvision() API. +> 2. Once ESP RainMaker agent starts, compulsorily call `WiFi.beginProvision()` API. ### RMaker.stop() It stops the ESP RainMaker agent which was started using `RMaker.start()`. diff --git a/libraries/RainMaker/examples/README.md b/libraries/RainMaker/examples/README.md index fde16de13e8..f838736dad8 100644 --- a/libraries/RainMaker/examples/README.md +++ b/libraries/RainMaker/examples/README.md @@ -2,11 +2,13 @@ While building any examples for ESP RainMaker, take care of the following: -1. Change partition scheme in Arduino IDE to RainMaker (Tools -> Partition Scheme -> RainMaker). +1. Change the partition scheme that fits your flash size in Arduino IDE to `RainMaker 4MB`, `RainMaker 4MB no OTA` or `RainMaker 8MB` (Tools -> Partition Scheme -> RainMaker). 2. Once ESP RainMaker gets started, compulsorily call `WiFi.beginProvision()` which is responsible for user-node mapping. 3. Use the appropriate provisioning scheme as per the board. - ESP32 Board: BLE Provisioning - ESP32-C3 Board: BLE Provisioning - ESP32-S3 Board: BLE Provisioning - ESP32-S2 Board: SoftAP Provisioning -4. Set debug level to Info (Tools -> Core Debug Level -> Info). This is recommended debug level but not mandatory to run RainMaker. + - ESP32-C6 Board: BLE Provisioning + - ESP32-H2 Board: BLE Provisioning +4. Set debug level to Info (Tools -> Core Debug Level -> Info). This is the recommended debug level but not mandatory to run RainMaker. diff --git a/libraries/RainMaker/examples/RMakerCustom/RMakerCustom.ino b/libraries/RainMaker/examples/RMakerCustom/RMakerCustom.ino index efee936ab2c..a652f55ac34 100644 --- a/libraries/RainMaker/examples/RMakerCustom/RMakerCustom.ino +++ b/libraries/RainMaker/examples/RMakerCustom/RMakerCustom.ino @@ -9,7 +9,7 @@ const char *service_name = "PROV_1234"; const char *pop = "abcd1234"; //GPIO for push button -#if CONFIG_IDF_TARGET_ESP32C3 +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 static int gpio_0 = 9; static int gpio_dimmer = 7; #else @@ -30,14 +30,14 @@ void sysProvEvent(arduino_event_t *sys_event) { case ARDUINO_EVENT_PROV_START: #if CONFIG_IDF_TARGET_ESP32S2 Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop); - printQR(service_name, pop, "softap"); + WiFiProv.printQR(service_name, pop, "softap"); #else Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop); - printQR(service_name, pop, "ble"); + WiFiProv.printQR(service_name, pop, "ble"); #endif break; - case ARDUINO_EVENT_PROV_INIT: wifi_prov_mgr_disable_auto_stop(10000); break; - case ARDUINO_EVENT_PROV_CRED_SUCCESS: wifi_prov_mgr_stop_provisioning(); break; + case ARDUINO_EVENT_PROV_INIT: WiFiProv.disableAutoStop(10000); break; + case ARDUINO_EVENT_PROV_CRED_SUCCESS: WiFiProv.endProvision(); break; default: ; } } @@ -101,9 +101,9 @@ void setup() { WiFi.onEvent(sysProvEvent); // Will call sysProvEvent() from another thread. #if CONFIG_IDF_TARGET_ESP32S2 - WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name); + WiFiProv.beginProvision(NETWORK_PROV_SCHEME_SOFTAP, NETWORK_PROV_SCHEME_HANDLER_NONE, NETWORK_PROV_SECURITY_1, pop, service_name); #else - WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name); + WiFiProv.beginProvision(NETWORK_PROV_SCHEME_BLE, NETWORK_PROV_SCHEME_HANDLER_FREE_BTDM, NETWORK_PROV_SECURITY_1, pop, service_name); #endif } diff --git a/libraries/RainMaker/examples/RMakerCustom/ci.json b/libraries/RainMaker/examples/RMakerCustom/ci.json index 90f5ecfe4d2..ce63fe9ccf0 100644 --- a/libraries/RainMaker/examples/RMakerCustom/ci.json +++ b/libraries/RainMaker/examples/RMakerCustom/ci.json @@ -1,6 +1,13 @@ { "targets": { - "esp32c6": false, - "esp32h2": false - } + "esp32": false + }, + "fqbn_append": "PartitionScheme=rainmaker_4MB", + "requires": [ + "CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK=[1-9][0-9]*" + ], + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/RainMaker/examples/RMakerCustomAirCooler/RMakerCustomAirCooler.ino b/libraries/RainMaker/examples/RMakerCustomAirCooler/RMakerCustomAirCooler.ino index ad89af2446d..559d73e771c 100644 --- a/libraries/RainMaker/examples/RMakerCustomAirCooler/RMakerCustomAirCooler.ino +++ b/libraries/RainMaker/examples/RMakerCustomAirCooler/RMakerCustomAirCooler.ino @@ -11,7 +11,7 @@ const char *service_name = "PROV_1234"; const char *pop = "abcd1234"; -#if CONFIG_IDF_TARGET_ESP32C3 +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 //GPIO for push button static int gpio_reset = 9; //GPIO for virtual device @@ -46,14 +46,14 @@ void sysProvEvent(arduino_event_t *sys_event) { case ARDUINO_EVENT_PROV_START: #if CONFIG_IDF_TARGET_ESP32S2 Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop); - printQR(service_name, pop, "softap"); + WiFiProv.printQR(service_name, pop, "softap"); #else Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop); - printQR(service_name, pop, "ble"); + WiFiProv.printQR(service_name, pop, "ble"); #endif break; - case ARDUINO_EVENT_PROV_INIT: wifi_prov_mgr_disable_auto_stop(10000); break; - case ARDUINO_EVENT_PROV_CRED_SUCCESS: wifi_prov_mgr_stop_provisioning(); break; + case ARDUINO_EVENT_PROV_INIT: WiFiProv.disableAutoStop(10000); break; + case ARDUINO_EVENT_PROV_CRED_SUCCESS: WiFiProv.endProvision(); break; default: ; } } @@ -166,9 +166,9 @@ void setup() { WiFi.onEvent(sysProvEvent); // Will call sysProvEvent() from another thread. #if CONFIG_IDF_TARGET_ESP32S2 - WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name); + WiFiProv.beginProvision(NETWORK_PROV_SCHEME_SOFTAP, NETWORK_PROV_SCHEME_HANDLER_NONE, NETWORK_PROV_SECURITY_1, pop, service_name); #else - WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name); + WiFiProv.beginProvision(NETWORK_PROV_SCHEME_BLE, NETWORK_PROV_SCHEME_HANDLER_FREE_BTDM, NETWORK_PROV_SECURITY_1, pop, service_name); #endif } diff --git a/libraries/RainMaker/examples/RMakerCustomAirCooler/ci.json b/libraries/RainMaker/examples/RMakerCustomAirCooler/ci.json index 90f5ecfe4d2..ce63fe9ccf0 100644 --- a/libraries/RainMaker/examples/RMakerCustomAirCooler/ci.json +++ b/libraries/RainMaker/examples/RMakerCustomAirCooler/ci.json @@ -1,6 +1,13 @@ { "targets": { - "esp32c6": false, - "esp32h2": false - } + "esp32": false + }, + "fqbn_append": "PartitionScheme=rainmaker_4MB", + "requires": [ + "CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK=[1-9][0-9]*" + ], + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/RainMaker/examples/RMakerSonoffDualR3/RMakerSonoffDualR3.ino b/libraries/RainMaker/examples/RMakerSonoffDualR3/RMakerSonoffDualR3.ino index b39f6b70f1a..014da25c8f6 100644 --- a/libraries/RainMaker/examples/RMakerSonoffDualR3/RMakerSonoffDualR3.ino +++ b/libraries/RainMaker/examples/RMakerSonoffDualR3/RMakerSonoffDualR3.ino @@ -40,18 +40,18 @@ void sysProvEvent(arduino_event_t *sys_event) { case ARDUINO_EVENT_PROV_START: #if CONFIG_IDF_TARGET_ESP32 Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop); - printQR(service_name, pop, "ble"); + WiFiProv.printQR(service_name, pop, "ble"); #else Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop); - printQR(service_name, pop, "softap"); + WiFiProv.printQR(service_name, pop, "softap"); #endif break; case ARDUINO_EVENT_WIFI_STA_CONNECTED: Serial.printf("\nConnected to Wi-Fi!\n"); digitalWrite(gpio_led, true); break; - case ARDUINO_EVENT_PROV_INIT: wifi_prov_mgr_disable_auto_stop(10000); break; - case ARDUINO_EVENT_PROV_CRED_SUCCESS: wifi_prov_mgr_stop_provisioning(); break; + case ARDUINO_EVENT_PROV_INIT: WiFiProv.disableAutoStop(10000); break; + case ARDUINO_EVENT_PROV_CRED_SUCCESS: WiFiProv.endProvision(); break; default: ; } } @@ -151,9 +151,9 @@ void setup() { WiFi.onEvent(sysProvEvent); // Will call sysProvEvent() from another thread. #if CONFIG_IDF_TARGET_ESP32 - WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name); + WiFiProv.beginProvision(NETWORK_PROV_SCHEME_BLE, NETWORK_PROV_SCHEME_HANDLER_FREE_BTDM, NETWORK_PROV_SECURITY_1, pop, service_name); #else - WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name); + WiFiProv.beginProvision(NETWORK_PROV_SCHEME_SOFTAP, NETWORK_PROV_SCHEME_HANDLER_NONE, NETWORK_PROV_SECURITY_1, pop, service_name); #endif } diff --git a/libraries/RainMaker/examples/RMakerSonoffDualR3/ci.json b/libraries/RainMaker/examples/RMakerSonoffDualR3/ci.json index 90f5ecfe4d2..ce63fe9ccf0 100644 --- a/libraries/RainMaker/examples/RMakerSonoffDualR3/ci.json +++ b/libraries/RainMaker/examples/RMakerSonoffDualR3/ci.json @@ -1,6 +1,13 @@ { "targets": { - "esp32c6": false, - "esp32h2": false - } + "esp32": false + }, + "fqbn_append": "PartitionScheme=rainmaker_4MB", + "requires": [ + "CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK=[1-9][0-9]*" + ], + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/RainMaker/examples/RMakerSwitch/RMakerSwitch.ino b/libraries/RainMaker/examples/RMakerSwitch/RMakerSwitch.ino index 93ca173a1ab..21fe9cb064b 100644 --- a/libraries/RainMaker/examples/RMakerSwitch/RMakerSwitch.ino +++ b/libraries/RainMaker/examples/RMakerSwitch/RMakerSwitch.ino @@ -9,7 +9,7 @@ const char *service_name = "PROV_1234"; const char *pop = "abcd1234"; // GPIO for push button -#if CONFIG_IDF_TARGET_ESP32C3 +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 static int gpio_0 = 9; static int gpio_switch = 7; #else @@ -31,14 +31,14 @@ void sysProvEvent(arduino_event_t *sys_event) { case ARDUINO_EVENT_PROV_START: #if CONFIG_IDF_TARGET_ESP32S2 Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop); - printQR(service_name, pop, "softap"); + WiFiProv.printQR(service_name, pop, "softap"); #else Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop); - printQR(service_name, pop, "ble"); + WiFiProv.printQR(service_name, pop, "ble"); #endif break; - case ARDUINO_EVENT_PROV_INIT: wifi_prov_mgr_disable_auto_stop(10000); break; - case ARDUINO_EVENT_PROV_CRED_SUCCESS: wifi_prov_mgr_stop_provisioning(); break; + case ARDUINO_EVENT_PROV_INIT: WiFiProv.disableAutoStop(10000); break; + case ARDUINO_EVENT_PROV_CRED_SUCCESS: WiFiProv.endProvision(); break; default: ; } } @@ -94,13 +94,19 @@ void setup() { RMaker.enableSystemService(SYSTEM_SERV_FLAGS_ALL, 2, 2, 2); +#if CONFIG_IDF_TARGET_ESP32S2 + WiFiProv.initProvision(NETWORK_PROV_SCHEME_SOFTAP, NETWORK_PROV_SCHEME_HANDLER_NONE); +#else + WiFiProv.initProvision(NETWORK_PROV_SCHEME_BLE, NETWORK_PROV_SCHEME_HANDLER_FREE_BTDM); +#endif + RMaker.start(); WiFi.onEvent(sysProvEvent); // Will call sysProvEvent() from another thread. #if CONFIG_IDF_TARGET_ESP32S2 - WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name); + WiFiProv.beginProvision(NETWORK_PROV_SCHEME_SOFTAP, NETWORK_PROV_SCHEME_HANDLER_NONE, NETWORK_PROV_SECURITY_1, pop, service_name); #else - WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name); + WiFiProv.beginProvision(NETWORK_PROV_SCHEME_BLE, NETWORK_PROV_SCHEME_HANDLER_FREE_BTDM, NETWORK_PROV_SECURITY_1, pop, service_name); #endif } diff --git a/libraries/RainMaker/examples/RMakerSwitch/ci.json b/libraries/RainMaker/examples/RMakerSwitch/ci.json index 90f5ecfe4d2..ce63fe9ccf0 100644 --- a/libraries/RainMaker/examples/RMakerSwitch/ci.json +++ b/libraries/RainMaker/examples/RMakerSwitch/ci.json @@ -1,6 +1,13 @@ { "targets": { - "esp32c6": false, - "esp32h2": false - } + "esp32": false + }, + "fqbn_append": "PartitionScheme=rainmaker_4MB", + "requires": [ + "CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK=[1-9][0-9]*" + ], + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/RainMaker/library.properties b/libraries/RainMaker/library.properties index b144328fef2..95ce14d6708 100644 --- a/libraries/RainMaker/library.properties +++ b/libraries/RainMaker/library.properties @@ -1,5 +1,5 @@ name=ESP RainMaker -version=2.0.0 +version=3.2.0 author=Sweety Mhaiske maintainer=Hristo Gochkov sentence=ESP RainMaker Support diff --git a/libraries/RainMaker/src/RMaker.cpp b/libraries/RainMaker/src/RMaker.cpp index 0cba0a4bede..0f8f276cbb9 100644 --- a/libraries/RainMaker/src/RMaker.cpp +++ b/libraries/RainMaker/src/RMaker.cpp @@ -4,6 +4,7 @@ #include #include #include +#include bool wifiLowLevelInit(bool persistent); static esp_err_t err; @@ -20,6 +21,16 @@ static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_ case RMAKER_EVENT_CLAIM_FAILED: log_i("RainMaker Claim Failed."); break; default: log_i("Unhandled RainMaker Event:"); } + } else if (event_base == RMAKER_COMMON_EVENT) { + switch (event_id) { + case RMAKER_EVENT_REBOOT: log_i("Rebooting in %d seconds.", *((uint8_t *)event_data)); break; + case RMAKER_EVENT_WIFI_RESET: log_i("Wi-Fi credentials reset."); break; + case RMAKER_EVENT_FACTORY_RESET: log_i("Node reset to factory defaults."); break; + case RMAKER_MQTT_EVENT_CONNECTED: log_i("MQTT Connected."); break; + case RMAKER_MQTT_EVENT_DISCONNECTED: log_i("MQTT Disconnected."); break; + case RMAKER_MQTT_EVENT_PUBLISHED: log_i("MQTT Published. Msg id: %d.", *((int *)event_data)); break; + default: log_w("Unhandled RainMaker Common Event: %" PRIi32, event_id); + } } else if (event_base == RMAKER_OTA_EVENT) { if (event_data == NULL) { event_data = (void *)""; @@ -46,6 +57,7 @@ Node RMakerClass::initNode(const char *name, const char *type) { esp_rmaker_node_t *rnode = NULL; esp_event_handler_register(RMAKER_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL); esp_event_handler_register(RMAKER_OTA_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL); + esp_event_handler_register(RMAKER_COMMON_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL); rnode = esp_rmaker_node_init(&rainmaker_cfg, name, type); if (!rnode) { log_e("Node init failed"); diff --git a/libraries/RainMaker/src/RMakerDevice.cpp b/libraries/RainMaker/src/RMakerDevice.cpp index efeafac874a..db431ba10c1 100644 --- a/libraries/RainMaker/src/RMakerDevice.cpp +++ b/libraries/RainMaker/src/RMakerDevice.cpp @@ -52,7 +52,7 @@ void Device::addCb(deviceWriteCb writeCb, deviceReadCb readCb) { esp_err_t Device::addDeviceAttr(const char *attr_name, const char *val) { err = esp_rmaker_device_add_attribute(getDeviceHandle(), attr_name, val); if (err != ESP_OK) { - log_e("Failed to add attriute to the device"); + log_e("Failed to add attribute to the device"); return err; } return ESP_OK; diff --git a/libraries/SD/README.md b/libraries/SD/README.md index 4e0a05ee06d..eef61d8176c 100644 --- a/libraries/SD/README.md +++ b/libraries/SD/README.md @@ -37,7 +37,7 @@ Tip: If you are using a microSD card and have a spare adapter to full-sized SD, **What is the difference between SD and SD_MMC libraries?** SD runs on SPI, and SD_MMC uses the SDMMC hardware bus on the ESP32. -The SPI uses 4 communication pins + 2 power connections and operates on up to 80MHz. The SPI option offers flexibility on pin connection because the data connections can be routed through GPIO matrix to any data pin. +The SPI uses 4 communication pins + 2 power connections and operates on up to 80 MHz. The SPI option offers flexibility on pin connection because the data connections can be routed through GPIO matrix to any data pin. SD-SPI speed is approximately half of the SD-MMC even when used on 1-bit line. You can read more about SD SPI in the [documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/sdspi_host.html) diff --git a/libraries/SD/examples/SD_Test/SD_Test.ino b/libraries/SD/examples/SD_Test/SD_Test.ino index 57c2b740219..c22e6c3a933 100644 --- a/libraries/SD/examples/SD_Test/SD_Test.ino +++ b/libraries/SD/examples/SD_Test/SD_Test.ino @@ -209,9 +209,6 @@ void testFileIO(fs::FS &fs, const char *path) { void setup() { Serial.begin(115200); - while (!Serial) { - delay(10); - } #ifdef REASSIGN_PINS SPI.begin(sck, miso, mosi, cs); diff --git a/libraries/SD/examples/SD_time/ci.json b/libraries/SD/examples/SD_time/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/SD/examples/SD_time/ci.json +++ b/libraries/SD/examples/SD_time/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/SD/library.properties b/libraries/SD/library.properties index 449d0b087f5..66c4f5cfafd 100644 --- a/libraries/SD/library.properties +++ b/libraries/SD/library.properties @@ -1,5 +1,5 @@ name=SD -version=2.0.0 +version=3.2.0 author=Arduino, SparkFun maintainer=Arduino sentence=Enables reading and writing on SD cards. For all Arduino boards. diff --git a/libraries/SD/src/sd_diskio.cpp b/libraries/SD/src/sd_diskio.cpp index 497e27d326c..40d6ede9f81 100644 --- a/libraries/SD/src/sd_diskio.cpp +++ b/libraries/SD/src/sd_diskio.cpp @@ -671,8 +671,10 @@ uint8_t sdcard_uninit(uint8_t pdrv) { if (pdrv >= FF_VOLUMES || card == NULL) { return 1; } - AcquireSPI lock(card); - sdTransaction(pdrv, GO_IDLE_STATE, 0, NULL); + { + AcquireSPI lock(card); + sdTransaction(pdrv, GO_IDLE_STATE, 0, NULL); + } // lock is destructed here ff_diskio_register(pdrv, NULL); s_cards[pdrv] = NULL; esp_err_t err = ESP_OK; diff --git a/libraries/SD_MMC/README.md b/libraries/SD_MMC/README.md index 6d6bc69a11e..a41295c1228 100644 --- a/libraries/SD_MMC/README.md +++ b/libraries/SD_MMC/README.md @@ -102,7 +102,7 @@ Tip: If you are using a microSD card and have a spare adapter to full-sized SD, #### What is the difference between SD and SD_MMC libraries? SD runs on SPI, and SD_MMC uses the SDMMC hardware bus on the ESP32. -The SPI uses 4 communication pins + 2 power connections and operates on up to 80MHz. The SPI option offers flexibility on pin connection because the data connections can be routed through GPIO matrix to any data pin. +The SPI uses 4 communication pins + 2 power connections and operates on up to 80 MHz. The SPI option offers flexibility on pin connection because the data connections can be routed through GPIO matrix to any data pin. SD-SPI speed is approximately half of the SD-MMC even when used on 1-bit line. You can read more about SD SPI in the [documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/sdspi_host.html) diff --git a/libraries/SD_MMC/examples/SD2USBMSC/ci.json b/libraries/SD_MMC/examples/SD2USBMSC/ci.json index 2a5ca52e079..125eed2e476 100644 --- a/libraries/SD_MMC/examples/SD2USBMSC/ci.json +++ b/libraries/SD_MMC/examples/SD2USBMSC/ci.json @@ -1,9 +1,6 @@ { - "targets": { - "esp32": false, - "esp32s2": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_SDMMC_HOST_SUPPORTED=y", + "CONFIG_TINYUSB_MSC_ENABLED=y" + ] } diff --git a/libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino b/libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino index e85737c7152..e03f5ceb25e 100644 --- a/libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino +++ b/libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino @@ -14,6 +14,7 @@ * Connections for ║ ║ ╔═══╩═║═║═══╗ ║ ║ ║ * full-sized ║ ║ ║ ╔═╝ ║ ║ ║ ║ ║ * SD card ║ ║ ║ ║ ║ ║ ║ ║ ║ + * ESP32-P4 Func EV | 40 39 GND 43 3V3 GND 44 43 42 | SLOT 0 (IO_MUX) * ESP32-S3 DevKit | 21 47 GND 39 3V3 GND 40 41 42 | * ESP32-S3-USB-OTG | 38 37 GND 36 3V3 GND 35 34 33 | * ESP32 | 4 2 GND 14 3V3 GND 15 13 12 | @@ -42,6 +43,7 @@ #include "FS.h" #include "SD_MMC.h" +#ifdef CONFIG_IDF_TARGET_ESP32S3 // Default pins for ESP-S3 // Warning: ESP32-S3-WROOM-2 is using most of the default GPIOs (33-37) to interface with on-board OPI flash. // If the SD_MMC is initialized with default pins it will result in rebooting loop - please @@ -54,6 +56,7 @@ int d0 = 37; int d1 = 38; int d2 = 33; int d3 = 39; // GPIO 34 is not broken-out on ESP32-S3-DevKitC-1 v1.1 +#endif void listDir(fs::FS &fs, const char *dirname, uint8_t levels) { Serial.printf("Listing directory: %s\n", dirname); @@ -211,15 +214,16 @@ void testFileIO(fs::FS &fs, const char *path) { void setup() { Serial.begin(115200); /* - // If you want to change the pin assignment on ESP32-S3 uncomment this block and the appropriate + // If you want to change the pin assignment or you get an error that some pins + // are not assigned on ESP32-S3/ESP32-P4 uncomment this block and the appropriate // line depending if you want to use 1-bit or 4-bit line. - // Please note that ESP32 does not allow pin change and will always fail. - //if(! setPins(clk, cmd, d0)){ - //if(! setPins(clk, cmd, d0, d1, d2, d3)){ - Serial.println("Pin change failed!"); - return; - } - */ + // Please note that ESP32 does not allow pin change and setPins() will always fail. + //if(! SD_MMC.setPins(clk, cmd, d0)){ + //if(! SD_MMC.setPins(clk, cmd, d0, d1, d2, d3)){ + // Serial.println("Pin change failed!"); + // return; + //} + */ if (!SD_MMC.begin()) { Serial.println("Card Mount Failed"); @@ -262,4 +266,6 @@ void setup() { Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024)); } -void loop() {} +void loop() { + delay(10); +} diff --git a/libraries/SD_MMC/examples/SDMMC_Test/ci.json b/libraries/SD_MMC/examples/SDMMC_Test/ci.json index 35b6e255471..a5221dae538 100644 --- a/libraries/SD_MMC/examples/SDMMC_Test/ci.json +++ b/libraries/SD_MMC/examples/SDMMC_Test/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false - } + "requires": [ + "CONFIG_SOC_SDMMC_HOST_SUPPORTED=y" + ] } diff --git a/libraries/SD_MMC/examples/SDMMC_time/SDMMC_time.ino b/libraries/SD_MMC/examples/SDMMC_time/SDMMC_time.ino index bd9f150f3e8..d1e933e4f4b 100644 --- a/libraries/SD_MMC/examples/SDMMC_time/SDMMC_time.ino +++ b/libraries/SD_MMC/examples/SDMMC_time/SDMMC_time.ino @@ -14,6 +14,7 @@ * Connections for ║ ║ ╔═══╩═║═║═══╗ ║ ║ ║ * full-sized ║ ║ ║ ╔═╝ ║ ║ ║ ║ ║ * SD card ║ ║ ║ ║ ║ ║ ║ ║ ║ + * ESP32-P4 Func EV | 40 39 GND 43 3V3 GND 44 43 42 | SLOT 0 (IO_MUX) * ESP32-S3 DevKit | 21 47 GND 39 3V3 GND 40 41 42 | * ESP32-S3-USB-OTG | 38 37 GND 36 3V3 GND 35 34 33 | * ESP32 | 4 2 GND 14 3V3 GND 15 13 12 | diff --git a/libraries/SD_MMC/examples/SDMMC_time/ci.json b/libraries/SD_MMC/examples/SDMMC_time/ci.json index 35b6e255471..5552b63d32a 100644 --- a/libraries/SD_MMC/examples/SDMMC_time/ci.json +++ b/libraries/SD_MMC/examples/SDMMC_time/ci.json @@ -1,8 +1,9 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false - } + "requires": [ + "CONFIG_SOC_SDMMC_HOST_SUPPORTED=y" + ], + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/SD_MMC/library.properties b/libraries/SD_MMC/library.properties index 9e281aaecda..855390e5057 100644 --- a/libraries/SD_MMC/library.properties +++ b/libraries/SD_MMC/library.properties @@ -1,5 +1,5 @@ name=SD_MMC -version=2.0.0 +version=3.2.0 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 SDMMC File System diff --git a/libraries/SD_MMC/src/SD_MMC.cpp b/libraries/SD_MMC/src/SD_MMC.cpp index 13e5fcf27fc..4665198c4ae 100644 --- a/libraries/SD_MMC/src/SD_MMC.cpp +++ b/libraries/SD_MMC/src/SD_MMC.cpp @@ -32,10 +32,14 @@ #include "ff.h" #include "esp32-hal-periman.h" +#if SOC_SDMMC_IO_POWER_EXTERNAL +#include "sd_pwr_ctrl_by_on_chip_ldo.h" +#endif + using namespace fs; SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) { -#if defined(SOC_SDMMC_USE_GPIO_MATRIX) && defined(BOARD_HAS_SDMMC) +#if defined(SOC_SDMMC_USE_GPIO_MATRIX) && defined(BOARD_HAS_SDMMC) && !defined(CONFIG_IDF_TARGET_ESP32P4) _pin_clk = SDMMC_CLK; _pin_cmd = SDMMC_CMD; _pin_d0 = SDMMC_D0; @@ -45,7 +49,7 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) { _pin_d3 = SDMMC_D3; #endif // BOARD_HAS_1BIT_SDMMC -#elif SOC_SDMMC_USE_IOMUX +#elif defined(SOC_SDMMC_USE_IOMUX) && defined(CONFIG_IDF_TARGET_ESP32) _pin_clk = SDMMC_SLOT1_IOMUX_PIN_NUM_CLK; _pin_cmd = SDMMC_SLOT1_IOMUX_PIN_NUM_CMD; _pin_d0 = SDMMC_SLOT1_IOMUX_PIN_NUM_D0; @@ -54,6 +58,31 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) { _pin_d2 = SDMMC_SLOT1_IOMUX_PIN_NUM_D2; _pin_d3 = SDMMC_SLOT1_IOMUX_PIN_NUM_D3; #endif // BOARD_HAS_1BIT_SDMMC + +// ESP32-P4 can use either IOMUX or GPIO matrix +#elif defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32P4) +#if defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0) + _pin_clk = SDMMC_SLOT0_IOMUX_PIN_NUM_CLK; + _pin_cmd = SDMMC_SLOT0_IOMUX_PIN_NUM_CMD; + _pin_d0 = SDMMC_SLOT0_IOMUX_PIN_NUM_D0; +#ifndef BOARD_HAS_1BIT_SDMMC + _pin_d1 = SDMMC_SLOT0_IOMUX_PIN_NUM_D1; + _pin_d2 = SDMMC_SLOT0_IOMUX_PIN_NUM_D2; + _pin_d3 = SDMMC_SLOT0_IOMUX_PIN_NUM_D3; +#endif // BOARD_HAS_1BIT_SDMMC +#else + _pin_clk = SDMMC_CLK; + _pin_cmd = SDMMC_CMD; + _pin_d0 = SDMMC_D0; +#ifndef BOARD_HAS_1BIT_SDMMC + _pin_d1 = SDMMC_D1; + _pin_d2 = SDMMC_D2; + _pin_d3 = SDMMC_D3; +#endif // BOARD_HAS_1BIT_SDMMC +#endif // BOARD_SDMMC_SLOT_NO +#endif +#if defined(SOC_SDMMC_IO_POWER_EXTERNAL) && defined(BOARD_SDMMC_POWER_CHANNEL) + _power_channel = BOARD_SDMMC_POWER_CHANNEL; #endif } @@ -83,7 +112,7 @@ bool SDMMCFS::setPins(int clk, int cmd, int d0, int d1, int d2, int d3) { d2 = digitalPinToGPIONumber(d2); d3 = digitalPinToGPIONumber(d3); -#ifdef SOC_SDMMC_USE_GPIO_MATRIX +#if defined(SOC_SDMMC_USE_GPIO_MATRIX) && !defined(CONFIG_IDF_TARGET_ESP32P4) // SoC supports SDMMC pin configuration via GPIO matrix. Save the pins for later use in SDMMCFS::begin. _pin_clk = (int8_t)clk; _pin_cmd = (int8_t)cmd; @@ -104,11 +133,42 @@ bool SDMMCFS::setPins(int clk, int cmd, int d0, int d1, int d2, int d3) { return false; } return true; +#elif defined(CONFIG_IDF_TARGET_ESP32P4) +#if defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0) + // ESP32-P4 can use either IOMUX or GPIO matrix + bool pins_ok = + (clk == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_CLK) && (cmd == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_CMD) && (d0 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D0) + && (((d1 == -1) && (d2 == -1) && (d3 == -1)) || ((d1 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D1) && (d2 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D2) && (d3 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D3))); + if (!pins_ok) { + log_e("SDMMCFS: specified pins are not supported when using IOMUX (SDMMC SLOT 0)."); + return false; + } + return true; +#else + _pin_clk = (int8_t)clk; + _pin_cmd = (int8_t)cmd; + _pin_d0 = (int8_t)d0; + _pin_d1 = (int8_t)d1; + _pin_d2 = (int8_t)d2; + _pin_d3 = (int8_t)d3; + return true; +#endif #else #error SoC not supported #endif } +#ifdef SOC_SDMMC_IO_POWER_EXTERNAL +bool SDMMCFS::setPowerChannel(int power_channel) { + if (_card != nullptr) { + log_e("SD_MMC.setPowerChannel must be called before SD_MMC.begin"); + return false; + } + _power_channel = power_channel; + return true; +} +#endif + bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_failed, int sdmmc_frequency, uint8_t maxOpenFiles) { if (_card) { return true; @@ -123,7 +183,9 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_ } //mount sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); -#ifdef SOC_SDMMC_USE_GPIO_MATRIX +#if (defined(SOC_SDMMC_USE_GPIO_MATRIX) && !defined(CONFIG_IDF_TARGET_ESP32P4)) \ + || (defined(CONFIG_IDF_TARGET_ESP32P4) && ((defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 1)) || !defined(BOARD_HAS_SDMMC))) + log_d("pin_cmd: %d, pin_clk: %d, pin_d0: %d, pin_d1: %d, pin_d2: %d, pin_d3: %d", _pin_cmd, _pin_clk, _pin_d0, _pin_d1, _pin_d2, _pin_d3); // SoC supports SDMMC pin configuration via GPIO matrix. // Check that the pins have been set either in the constructor or setPins function. if (_pin_cmd == -1 || _pin_clk == -1 || _pin_d0 == -1 || (!mode1bit && (_pin_d1 == -1 || _pin_d2 == -1 || _pin_d3 == -1))) { @@ -163,7 +225,18 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_ sdmmc_host_t host = SDMMC_HOST_DEFAULT(); host.flags = SDMMC_HOST_FLAG_4BIT; +#if defined(CONFIG_IDF_TARGET_ESP32P4) && defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0) + host.slot = SDMMC_HOST_SLOT_0; + // reconfigure slot_config to remove all pins in order to use IO_MUX + slot_config = { + .cd = SDMMC_SLOT_NO_CD, + .wp = SDMMC_SLOT_NO_WP, + .width = 4, + .flags = 0, + }; +#else host.slot = SDMMC_HOST_SLOT_1; +#endif host.max_freq_khz = sdmmc_frequency; #ifdef BOARD_HAS_1BIT_SDMMC mode1bit = true; @@ -174,8 +247,40 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_ } _mode1bit = mode1bit; +#ifdef SOC_SDMMC_IO_POWER_EXTERNAL + if (_power_channel == -1) { + log_i("On-chip power channel specified, use external power for SDMMC"); + } else { + sd_pwr_ctrl_ldo_config_t ldo_config = { + .ldo_chan_id = _power_channel, + }; + sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL; + + if (sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle) != ESP_OK) { + log_e("Failed to create a new on-chip LDO power control driver"); + return false; + } + host.pwr_ctrl_handle = pwr_ctrl_handle; + } +#endif + +#if defined(BOARD_SDMMC_POWER_PIN) +#ifndef BOARD_SDMMC_POWER_ON_LEVEL +#error "BOARD_SDMMC_POWER_ON_LEVEL not defined, please define it in pins_arduino.h" +#endif + pinMode(BOARD_SDMMC_POWER_PIN, OUTPUT); + digitalWrite(BOARD_SDMMC_POWER_PIN, !BOARD_SDMMC_POWER_ON_LEVEL); + delay(200); + digitalWrite(BOARD_SDMMC_POWER_PIN, BOARD_SDMMC_POWER_ON_LEVEL); + perimanSetPinBusExtraType(BOARD_SDMMC_POWER_PIN, "SDMMC_POWER"); +#endif + esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = format_if_mount_failed, .max_files = maxOpenFiles, .allocation_unit_size = 0, .disk_status_check_enable = false + .format_if_mount_failed = format_if_mount_failed, + .max_files = maxOpenFiles, + .allocation_unit_size = 0, + .disk_status_check_enable = false, + .use_one_fat = false }; esp_err_t ret = esp_vfs_fat_sdmmc_mount(mountpoint, &host, &slot_config, &mount_config, &_card); @@ -236,6 +341,9 @@ void SDMMCFS::end() { perimanClearPinBus(_pin_d2); perimanClearPinBus(_pin_d3); } +#if defined(BOARD_SDMMC_POWER_PIN) + perimanClearPinBus(BOARD_SDMMC_POWER_PIN); +#endif } } diff --git a/libraries/SD_MMC/src/SD_MMC.h b/libraries/SD_MMC/src/SD_MMC.h index a2bc12aed64..b6fe13a0d24 100644 --- a/libraries/SD_MMC/src/SD_MMC.h +++ b/libraries/SD_MMC/src/SD_MMC.h @@ -44,6 +44,9 @@ class SDMMCFS : public FS { int8_t _pin_d1 = -1; int8_t _pin_d2 = -1; int8_t _pin_d3 = -1; +#ifdef SOC_SDMMC_IO_POWER_EXTERNAL + int8_t _power_channel = -1; +#endif uint8_t _pdrv = 0xFF; bool _mode1bit = false; @@ -51,6 +54,9 @@ class SDMMCFS : public FS { SDMMCFS(FSImplPtr impl); bool setPins(int clk, int cmd, int d0); bool setPins(int clk, int cmd, int d0, int d1, int d2, int d3); +#ifdef SOC_SDMMC_IO_POWER_EXTERNAL + bool setPowerChannel(int power_channel); +#endif bool begin( const char *mountpoint = "/sdcard", bool mode1bit = false, bool format_if_mount_failed = false, int sdmmc_frequency = BOARD_MAX_SDMMC_FREQ, uint8_t maxOpenFiles = 5 diff --git a/libraries/SPI/examples/SPI_Multiple_Buses/SPI_Multiple_Buses.ino b/libraries/SPI/examples/SPI_Multiple_Buses/SPI_Multiple_Buses.ino index 672d5fe2b49..06765c64fd2 100644 --- a/libraries/SPI/examples/SPI_Multiple_Buses/SPI_Multiple_Buses.ino +++ b/libraries/SPI/examples/SPI_Multiple_Buses/SPI_Multiple_Buses.ino @@ -39,13 +39,13 @@ #define HSPI_SS 15 #endif -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#if !defined(CONFIG_IDF_TARGET_ESP32) #define VSPI FSPI #endif static const int spiClk = 1000000; // 1 MHz -//uninitialised pointers to SPI objects +//uninitialized pointers to SPI objects SPIClass *vspi = NULL; SPIClass *hspi = NULL; diff --git a/libraries/SPI/examples/SPI_Multiple_Buses/ci.json b/libraries/SPI/examples/SPI_Multiple_Buses/ci.json index 25c42144223..cd27a02724b 100644 --- a/libraries/SPI/examples/SPI_Multiple_Buses/ci.json +++ b/libraries/SPI/examples/SPI_Multiple_Buses/ci.json @@ -1,7 +1,5 @@ { - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_SPI_PERIPH_NUM=[2-9]" + ] } diff --git a/libraries/SPI/library.properties b/libraries/SPI/library.properties index e32675a8828..64db93aceeb 100644 --- a/libraries/SPI/library.properties +++ b/libraries/SPI/library.properties @@ -1,5 +1,5 @@ name=SPI -version=2.0.0 +version=3.2.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables the communication with devices that use the Serial Peripheral Interface (SPI) Bus. For all Arduino boards, BUT Arduino DUE. diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 93c686a0d13..ae207a7ff3c 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -83,7 +83,7 @@ void SPIClass::begin(int8_t sck, int8_t miso, int8_t mosi, int8_t ss) { _miso = (_spi_num == FSPI) ? MISO : -1; _mosi = (_spi_num == FSPI) ? MOSI : -1; _ss = (_spi_num == FSPI) ? SS : -1; -#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 _sck = SCK; _miso = MISO; _mosi = MOSI; @@ -144,6 +144,12 @@ void SPIClass::setHwCs(bool use) { _use_hw_ss = use; } +void SPIClass::setSSInvert(bool invert) { + if (_spi) { + spiSSInvert(_spi, invert); + } +} + void SPIClass::setFrequency(uint32_t freq) { SPI_PARAM_LOCK(); //check if last freq changed diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index adb3d1bc11f..628c2190f50 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -65,6 +65,7 @@ class SPIClass { void end(); void setHwCs(bool use); + void setSSInvert(bool invert); //use before setHwCS for change to be used by setHwCs void setBitOrder(uint8_t bitOrder); void setDataMode(uint8_t dataMode); void setFrequency(uint32_t freq); diff --git a/libraries/SPIFFS/examples/SPIFFS_time/ci.json b/libraries/SPIFFS/examples/SPIFFS_time/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/SPIFFS/examples/SPIFFS_time/ci.json +++ b/libraries/SPIFFS/examples/SPIFFS_time/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/SPIFFS/library.properties b/libraries/SPIFFS/library.properties index a59fbc74c6a..78f77fe9794 100644 --- a/libraries/SPIFFS/library.properties +++ b/libraries/SPIFFS/library.properties @@ -1,5 +1,5 @@ name=SPIFFS -version=2.0.0 +version=3.2.0 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 SPIFFS File System diff --git a/libraries/SPIFFS/src/SPIFFS.cpp b/libraries/SPIFFS/src/SPIFFS.cpp index a77b32990bf..0b2cc0d462d 100644 --- a/libraries/SPIFFS/src/SPIFFS.cpp +++ b/libraries/SPIFFS/src/SPIFFS.cpp @@ -91,9 +91,11 @@ void SPIFFSFS::end() { } bool SPIFFSFS::format() { - disableCore0WDT(); + bool wdt_active = disableCore0WDT(); esp_err_t err = esp_spiffs_format(partitionLabel_); - enableCore0WDT(); + if (wdt_active) { + enableCore0WDT(); + } if (err) { log_e("Formatting SPIFFS failed! Error: %d", err); return false; diff --git a/libraries/SimpleBLE/examples/SimpleBleDevice/ci.json b/libraries/SimpleBLE/examples/SimpleBleDevice/ci.json index a571a89a877..d33a23f332e 100644 --- a/libraries/SimpleBLE/examples/SimpleBleDevice/ci.json +++ b/libraries/SimpleBLE/examples/SimpleBleDevice/ci.json @@ -1,6 +1,6 @@ { - "targets": { - "esp32c3": false, - "esp32s2": false - } + "requires": [ + "CONFIG_BT_ENABLED=y", + "CONFIG_BLUEDROID_ENABLED=y" + ] } diff --git a/libraries/SimpleBLE/library.properties b/libraries/SimpleBLE/library.properties index b2d32944e41..ad5e10d3acb 100644 --- a/libraries/SimpleBLE/library.properties +++ b/libraries/SimpleBLE/library.properties @@ -1,5 +1,5 @@ name=SimpleBLE -version=2.0.0 +version=3.2.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Provides really simple BLE advertizer with just on and off diff --git a/libraries/TFLiteMicro/library.properties b/libraries/TFLiteMicro/library.properties index c4bbca4221a..1e8db045610 100644 --- a/libraries/TFLiteMicro/library.properties +++ b/libraries/TFLiteMicro/library.properties @@ -1,5 +1,5 @@ name=TFLite Micro -version=1.0.0 +version=3.2.0 author=Sanket Wadekar maintainer=Sanket Wadekar sentence=TensorFlow Lite for Microcontrollers diff --git a/libraries/Ticker/library.properties b/libraries/Ticker/library.properties index 91932a699c8..975db96d1ad 100644 --- a/libraries/Ticker/library.properties +++ b/libraries/Ticker/library.properties @@ -1,5 +1,5 @@ name=Ticker -version=2.0.0 +version=3.2.0 author=Bert Melis maintainer=Hristo Gochkov sentence=Allows to call functions with a given interval. diff --git a/libraries/USB/examples/CompositeDevice/ci.json b/libraries/USB/examples/CompositeDevice/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/CompositeDevice/ci.json +++ b/libraries/USB/examples/CompositeDevice/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/ConsumerControl/ci.json b/libraries/USB/examples/ConsumerControl/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/ConsumerControl/ci.json +++ b/libraries/USB/examples/ConsumerControl/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/CustomHIDDevice/ci.json b/libraries/USB/examples/CustomHIDDevice/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/CustomHIDDevice/ci.json +++ b/libraries/USB/examples/CustomHIDDevice/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/FirmwareMSC/ci.json b/libraries/USB/examples/FirmwareMSC/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/FirmwareMSC/ci.json +++ b/libraries/USB/examples/FirmwareMSC/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/Gamepad/ci.json b/libraries/USB/examples/Gamepad/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/Gamepad/ci.json +++ b/libraries/USB/examples/Gamepad/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/HIDVendor/ci.json b/libraries/USB/examples/HIDVendor/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/HIDVendor/ci.json +++ b/libraries/USB/examples/HIDVendor/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/Keyboard/KeyboardLogout/ci.json b/libraries/USB/examples/Keyboard/KeyboardLogout/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/Keyboard/KeyboardLogout/ci.json +++ b/libraries/USB/examples/Keyboard/KeyboardLogout/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/Keyboard/KeyboardMessage/ci.json b/libraries/USB/examples/Keyboard/KeyboardMessage/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/Keyboard/KeyboardMessage/ci.json +++ b/libraries/USB/examples/Keyboard/KeyboardMessage/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/Keyboard/KeyboardReprogram/ci.json b/libraries/USB/examples/Keyboard/KeyboardReprogram/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/Keyboard/KeyboardReprogram/ci.json +++ b/libraries/USB/examples/Keyboard/KeyboardReprogram/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/Keyboard/KeyboardSerial/ci.json b/libraries/USB/examples/Keyboard/KeyboardSerial/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/Keyboard/KeyboardSerial/ci.json +++ b/libraries/USB/examples/Keyboard/KeyboardSerial/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/KeyboardAndMouseControl/ci.json b/libraries/USB/examples/KeyboardAndMouseControl/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/KeyboardAndMouseControl/ci.json +++ b/libraries/USB/examples/KeyboardAndMouseControl/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/MIDI/MidiController/ci.json b/libraries/USB/examples/MIDI/MidiController/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/MIDI/MidiController/ci.json +++ b/libraries/USB/examples/MIDI/MidiController/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/MIDI/MidiInterface/MidiInterface.ino b/libraries/USB/examples/MIDI/MidiInterface/MidiInterface.ino index 7088e9b03f0..e3ad1c4e028 100644 --- a/libraries/USB/examples/MIDI/MidiInterface/MidiInterface.ino +++ b/libraries/USB/examples/MIDI/MidiInterface/MidiInterface.ino @@ -50,7 +50,7 @@ void loop() { } // USB MIDI 1.0 to MIDI Serial 1.0 - midiEventPacket_t midi_packet_in = {0}; + midiEventPacket_t midi_packet_in = {0, 0, 0, 0}; // See Chapter 4: USB-MIDI Event Packets (page 16) of the spec. int8_t cin_to_midix_size[16] = {-1, -1, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1}; diff --git a/libraries/USB/examples/MIDI/MidiInterface/ci.json b/libraries/USB/examples/MIDI/MidiInterface/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/MIDI/MidiInterface/ci.json +++ b/libraries/USB/examples/MIDI/MidiInterface/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/MIDI/MidiMusicBox/ci.json b/libraries/USB/examples/MIDI/MidiMusicBox/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/MIDI/MidiMusicBox/ci.json +++ b/libraries/USB/examples/MIDI/MidiMusicBox/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/MIDI/ReceiveMidi/ReceiveMidi.ino b/libraries/USB/examples/MIDI/ReceiveMidi/ReceiveMidi.ino index 75078d163c8..09a3e2a7b5c 100644 --- a/libraries/USB/examples/MIDI/ReceiveMidi/ReceiveMidi.ino +++ b/libraries/USB/examples/MIDI/ReceiveMidi/ReceiveMidi.ino @@ -28,7 +28,7 @@ void setup() { } void loop() { - midiEventPacket_t midi_packet_in = {0}; + midiEventPacket_t midi_packet_in = {0, 0, 0, 0}; if (MIDI.readPacket(&midi_packet_in)) { printDetails(midi_packet_in); diff --git a/libraries/USB/examples/MIDI/ReceiveMidi/ci.json b/libraries/USB/examples/MIDI/ReceiveMidi/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/MIDI/ReceiveMidi/ci.json +++ b/libraries/USB/examples/MIDI/ReceiveMidi/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/Mouse/ButtonMouseControl/ci.json b/libraries/USB/examples/Mouse/ButtonMouseControl/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/Mouse/ButtonMouseControl/ci.json +++ b/libraries/USB/examples/Mouse/ButtonMouseControl/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/SystemControl/ci.json b/libraries/USB/examples/SystemControl/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/SystemControl/ci.json +++ b/libraries/USB/examples/SystemControl/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/USBMSC/ci.json b/libraries/USB/examples/USBMSC/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/USBMSC/ci.json +++ b/libraries/USB/examples/USBMSC/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/USBSerial/ci.json b/libraries/USB/examples/USBSerial/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/USBSerial/ci.json +++ b/libraries/USB/examples/USBSerial/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/examples/USBVendor/ci.json b/libraries/USB/examples/USBVendor/ci.json index e7d65393dd6..f9ac7d0bec9 100644 --- a/libraries/USB/examples/USBVendor/ci.json +++ b/libraries/USB/examples/USBVendor/ci.json @@ -1,8 +1,5 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_USB_OTG_SUPPORTED=y" + ] } diff --git a/libraries/USB/library.properties b/libraries/USB/library.properties index 2b50f782562..9d47dfc6719 100644 --- a/libraries/USB/library.properties +++ b/libraries/USB/library.properties @@ -1,5 +1,5 @@ name=USB -version=2.0.0 +version=3.2.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=ESP32S2 USB Library diff --git a/libraries/USB/src/USBHID.cpp b/libraries/USB/src/USBHID.cpp index 995700de4c9..1d5d86fb3a3 100644 --- a/libraries/USB/src/USBHID.cpp +++ b/libraries/USB/src/USBHID.cpp @@ -206,7 +206,9 @@ extern "C" uint16_t tusb_hid_load_descriptor(uint8_t *dst, uint8_t *itf) { uint8_t descriptor[TUD_HID_INOUT_DESC_LEN] = { // HID Input & Output descriptor // Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval - TUD_HID_INOUT_DESCRIPTOR(*itf, str_index, tinyusb_interface_protocol, tinyusb_hid_device_descriptor_len, ep_out, (uint8_t)(0x80 | ep_in), 64, 1) + TUD_HID_INOUT_DESCRIPTOR( + *itf, str_index, tinyusb_interface_protocol, tinyusb_hid_device_descriptor_len, ep_out, (uint8_t)(0x80 | ep_in), CFG_TUD_ENDOINT_SIZE, 1 + ) }; *itf += 1; memcpy(dst, descriptor, TUD_HID_INOUT_DESC_LEN); @@ -259,7 +261,7 @@ uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_t // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) { - if (!report_id && !report_type) { + if (!report_id && (!report_type || report_type == HID_REPORT_TYPE_OUTPUT)) { if (!tinyusb_on_set_output(0, buffer, bufsize) && !tinyusb_on_set_output(buffer[0], buffer + 1, bufsize - 1)) { log_d( "instance: %u, report_id: %u, report_type: %s, bufsize: %u", instance, buffer[0], tinyusb_hid_device_report_types[HID_REPORT_TYPE_OUTPUT], bufsize - 1 diff --git a/libraries/USB/src/USBHIDConsumerControl.h b/libraries/USB/src/USBHIDConsumerControl.h index e65e529a77b..7a59c70b6b1 100644 --- a/libraries/USB/src/USBHIDConsumerControl.h +++ b/libraries/USB/src/USBHIDConsumerControl.h @@ -37,10 +37,14 @@ #define CONSUMER_CONTROL_WIRELESS_RADIO_SLIDER_SWITCH 0x00C8 // Media Control -#define CONSUMER_CONTROL_PLAY_PAUSE 0x00CD +#define CONSUMER_CONTROL_RECORD 0x00B2 +#define CONSUMER_CONTROL_FAST_FORWARD 0x00B3 +#define CONSUMER_CONTROL_REWIND 0x00B4 #define CONSUMER_CONTROL_SCAN_NEXT 0x00B5 #define CONSUMER_CONTROL_SCAN_PREVIOUS 0x00B6 #define CONSUMER_CONTROL_STOP 0x00B7 +#define CONSUMER_CONTROL_EJECT 0x00B8 +#define CONSUMER_CONTROL_PLAY_PAUSE 0x00CD #define CONSUMER_CONTROL_VOLUME 0x00E0 #define CONSUMER_CONTROL_MUTE 0x00E2 #define CONSUMER_CONTROL_BASS 0x00E3 diff --git a/libraries/USB/src/USBHIDKeyboard.cpp b/libraries/USB/src/USBHIDKeyboard.cpp index 076a5be3ba3..9f371b2e099 100644 --- a/libraries/USB/src/USBHIDKeyboard.cpp +++ b/libraries/USB/src/USBHIDKeyboard.cpp @@ -24,6 +24,7 @@ #if CONFIG_TINYUSB_HID_ENABLED #include "USBHIDKeyboard.h" +#include "keyboardLayout/KeyboardLayout.h" ESP_EVENT_DEFINE_BASE(ARDUINO_USB_HID_KEYBOARD_EVENTS); esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait); @@ -31,7 +32,7 @@ esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, i static const uint8_t report_descriptor[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(HID_REPORT_ID_KEYBOARD))}; -USBHIDKeyboard::USBHIDKeyboard() : hid(HID_ITF_PROTOCOL_KEYBOARD), shiftKeyReports(true) { +USBHIDKeyboard::USBHIDKeyboard() : hid(HID_ITF_PROTOCOL_KEYBOARD), _asciimap(KeyboardLayout_en_US), shiftKeyReports(false) { static bool initialized = false; if (!initialized) { initialized = true; @@ -45,7 +46,8 @@ uint16_t USBHIDKeyboard::_onGetDescriptor(uint8_t *dst) { return sizeof(report_descriptor); } -void USBHIDKeyboard::begin() { +void USBHIDKeyboard::begin(const uint8_t *layout) { + _asciimap = layout; hid.begin(); } @@ -80,139 +82,6 @@ void USBHIDKeyboard::setShiftKeyReports(bool set) { shiftKeyReports = set; } -#define SHIFT 0x80 -const uint8_t _asciimap[128] = { - 0x00, // NUL - 0x00, // SOH - 0x00, // STX - 0x00, // ETX - 0x00, // EOT - 0x00, // ENQ - 0x00, // ACK - 0x00, // BEL - 0x2a, // BS Backspace - 0x2b, // TAB Tab - 0x28, // LF Enter - 0x00, // VT - 0x00, // FF - 0x00, // CR - 0x00, // SO - 0x00, // SI - 0x00, // DEL - 0x00, // DC1 - 0x00, // DC2 - 0x00, // DC3 - 0x00, // DC4 - 0x00, // NAK - 0x00, // SYN - 0x00, // ETB - 0x00, // CAN - 0x00, // EM - 0x00, // SUB - 0x00, // ESC - 0x00, // FS - 0x00, // GS - 0x00, // RS - 0x00, // US - - 0x2c, // ' ' - 0x1e | SHIFT, // ! - 0x34 | SHIFT, // " - 0x20 | SHIFT, // # - 0x21 | SHIFT, // $ - 0x22 | SHIFT, // % - 0x24 | SHIFT, // & - 0x34, // ' - 0x26 | SHIFT, // ( - 0x27 | SHIFT, // ) - 0x25 | SHIFT, // * - 0x2e | SHIFT, // + - 0x36, // , - 0x2d, // - - 0x37, // . - 0x38, // / - 0x27, // 0 - 0x1e, // 1 - 0x1f, // 2 - 0x20, // 3 - 0x21, // 4 - 0x22, // 5 - 0x23, // 6 - 0x24, // 7 - 0x25, // 8 - 0x26, // 9 - 0x33 | SHIFT, // : - 0x33, // ; - 0x36 | SHIFT, // < - 0x2e, // = - 0x37 | SHIFT, // > - 0x38 | SHIFT, // ? - 0x1f | SHIFT, // @ - 0x04 | SHIFT, // A - 0x05 | SHIFT, // B - 0x06 | SHIFT, // C - 0x07 | SHIFT, // D - 0x08 | SHIFT, // E - 0x09 | SHIFT, // F - 0x0a | SHIFT, // G - 0x0b | SHIFT, // H - 0x0c | SHIFT, // I - 0x0d | SHIFT, // J - 0x0e | SHIFT, // K - 0x0f | SHIFT, // L - 0x10 | SHIFT, // M - 0x11 | SHIFT, // N - 0x12 | SHIFT, // O - 0x13 | SHIFT, // P - 0x14 | SHIFT, // Q - 0x15 | SHIFT, // R - 0x16 | SHIFT, // S - 0x17 | SHIFT, // T - 0x18 | SHIFT, // U - 0x19 | SHIFT, // V - 0x1a | SHIFT, // W - 0x1b | SHIFT, // X - 0x1c | SHIFT, // Y - 0x1d | SHIFT, // Z - 0x2f, // [ - 0x31, // bslash - 0x30, // ] - 0x23 | SHIFT, // ^ - 0x2d | SHIFT, // _ - 0x35, // ` - 0x04, // a - 0x05, // b - 0x06, // c - 0x07, // d - 0x08, // e - 0x09, // f - 0x0a, // g - 0x0b, // h - 0x0c, // i - 0x0d, // j - 0x0e, // k - 0x0f, // l - 0x10, // m - 0x11, // n - 0x12, // o - 0x13, // p - 0x14, // q - 0x15, // r - 0x16, // s - 0x17, // t - 0x18, // u - 0x19, // v - 0x1a, // w - 0x1b, // x - 0x1c, // y - 0x1d, // z - 0x2f | SHIFT, // { - 0x31 | SHIFT, // | - 0x30 | SHIFT, // } - 0x35 | SHIFT, // ~ - 0 // DEL -}; - size_t USBHIDKeyboard::pressRaw(uint8_t k) { uint8_t i; if (k >= 0xE0 && k < 0xE8) { @@ -234,7 +103,7 @@ size_t USBHIDKeyboard::pressRaw(uint8_t k) { return 0; } } - } else { + } else if (_keyReport.modifiers == 0) { //not a modifier and not a key return 0; } @@ -255,11 +124,8 @@ size_t USBHIDKeyboard::releaseRaw(uint8_t k) { _keyReport.keys[i] = 0x00; } } - } else { - //not a modifier and not a key - return 0; } - + // Allowing for the release of a modifier key without a corresponding press sendReport(&_keyReport); return 1; } @@ -274,19 +140,26 @@ size_t USBHIDKeyboard::press(uint8_t k) { } else if (k >= 0x80) { // it's a modifier key _keyReport.modifiers |= (1 << (k - 0x80)); k = 0; - } else { // it's a printing key + } else { // it's a printing key (k is a ASCII 0..127) k = _asciimap[k]; if (!k) { return 0; } - if (k & 0x80) { // it's a capital letter or other character reached with shift + if ((k & SHIFT) == SHIFT) { // it's a capital letter or other character reached with shift // At boot, some PCs need a separate report with the shift key down like a real keyboard. if (shiftKeyReports) { pressRaw(HID_KEY_SHIFT_LEFT); } else { _keyReport.modifiers |= 0x02; // the left shift modifier } - k &= 0x7F; + k &= ~SHIFT; + } + if ((k & ALT_GR) == ALT_GR) { + _keyReport.modifiers |= 0x40; // AltGr = right Alt + k &= ~ALT_GR; + } + if (k == ISO_REPLACEMENT) { + k = ISO_KEY; } } return pressRaw(k); @@ -306,15 +179,22 @@ size_t USBHIDKeyboard::release(uint8_t k) { if (!k) { return 0; } - if (k & 0x80) { // it's a capital letter or other character reached with shift + if ((k & SHIFT) == SHIFT) { // it's a capital letter or other character reached with shift if (shiftKeyReports) { releaseRaw(k & 0x7F); // Release key without shift modifier k = HID_KEY_SHIFT_LEFT; // Below, release shift modifier } else { _keyReport.modifiers &= ~(0x02); // the left shift modifier - k &= 0x7F; + k &= ~SHIFT; } } + if ((k & ALT_GR) == ALT_GR) { + _keyReport.modifiers &= ~(0x40); // AltGr = right Alt + k &= ~ALT_GR; + } + if (k == ISO_REPLACEMENT) { + k = ISO_KEY; + } } return releaseRaw(k); } diff --git a/libraries/USB/src/USBHIDKeyboard.h b/libraries/USB/src/USBHIDKeyboard.h index 5606bb13ff4..d78b7fcc031 100644 --- a/libraries/USB/src/USBHIDKeyboard.h +++ b/libraries/USB/src/USBHIDKeyboard.h @@ -50,20 +50,32 @@ typedef union { uint8_t leds; } arduino_usb_hid_keyboard_event_data_t; +// Supported keyboard layouts +extern const uint8_t KeyboardLayout_de_DE[]; +extern const uint8_t KeyboardLayout_en_US[]; +extern const uint8_t KeyboardLayout_es_ES[]; +extern const uint8_t KeyboardLayout_fr_FR[]; +extern const uint8_t KeyboardLayout_it_IT[]; +extern const uint8_t KeyboardLayout_pt_PT[]; +extern const uint8_t KeyboardLayout_sv_SE[]; +extern const uint8_t KeyboardLayout_da_DK[]; +extern const uint8_t KeyboardLayout_hu_HU[]; +extern const uint8_t KeyboardLayout_pt_BR[]; + #define KEY_LEFT_CTRL 0x80 #define KEY_LEFT_SHIFT 0x81 #define KEY_LEFT_ALT 0x82 #define KEY_LEFT_GUI 0x83 #define KEY_RIGHT_CTRL 0x84 #define KEY_RIGHT_SHIFT 0x85 -#define KEY_RIGHT_ALT 0x86 +#define KEY_RIGHT_ALT 0x86 // AltGr (Right Alt) Key #define KEY_RIGHT_GUI 0x87 #define KEY_UP_ARROW 0xDA #define KEY_DOWN_ARROW 0xD9 #define KEY_LEFT_ARROW 0xD8 #define KEY_RIGHT_ARROW 0xD7 -#define KEY_MENU 0xFE +#define KEY_MENU 0xED // "Keyboard Application" in USB standard #define KEY_SPACE 0x20 #define KEY_BACKSPACE 0xB2 #define KEY_TAB 0xB3 @@ -111,6 +123,24 @@ typedef union { #define LED_COMPOSE 0x08 #define LED_KANA 0x10 +// Numeric keypad +#define KEY_KP_SLASH 0xDC +#define KEY_KP_ASTERISK 0xDD +#define KEY_KP_MINUS 0xDE +#define KEY_KP_PLUS 0xDF +#define KEY_KP_ENTER 0xE0 +#define KEY_KP_1 0xE1 +#define KEY_KP_2 0xE2 +#define KEY_KP_3 0xE3 +#define KEY_KP_4 0xE4 +#define KEY_KP_5 0xE5 +#define KEY_KP_6 0xE6 +#define KEY_KP_7 0xE7 +#define KEY_KP_8 0xE8 +#define KEY_KP_9 0xE9 +#define KEY_KP_0 0xEA +#define KEY_KP_DOT 0xEB + // Low level key report: up to 6 keys and shift, ctrl etc at once typedef struct { uint8_t modifiers; @@ -122,11 +152,12 @@ class USBHIDKeyboard : public USBHIDDevice, public Print { private: USBHID hid; KeyReport _keyReport; + const uint8_t *_asciimap; bool shiftKeyReports; public: USBHIDKeyboard(void); - void begin(void); + void begin(const uint8_t *layout = KeyboardLayout_en_US); void end(void); size_t write(uint8_t k); size_t write(const uint8_t *buffer, size_t size); diff --git a/libraries/USB/src/USBMIDI.cpp b/libraries/USB/src/USBMIDI.cpp index cfc40e7b154..8a9571855e1 100644 --- a/libraries/USB/src/USBMIDI.cpp +++ b/libraries/USB/src/USBMIDI.cpp @@ -24,7 +24,7 @@ extern "C" uint16_t tusb_midi_load_descriptor(uint8_t *dst, uint8_t *itf) { uint8_t ep_out = tinyusb_get_free_out_endpoint(); TU_VERIFY(ep_out != 0); uint8_t descriptor[TUD_MIDI_DESC_LEN] = { - TUD_MIDI_DESCRIPTOR(*itf, str_index, ep_out, (uint8_t)(0x80 | ep_in), 64), + TUD_MIDI_DESCRIPTOR(*itf, str_index, ep_out, (uint8_t)(0x80 | ep_in), CFG_TUD_ENDOINT_SIZE), }; *itf += 2; memcpy(dst, descriptor, TUD_MIDI_DESC_LEN); diff --git a/libraries/USB/src/USBVendor.cpp b/libraries/USB/src/USBVendor.cpp index 293d5866945..70fac5770ae 100644 --- a/libraries/USB/src/USBVendor.cpp +++ b/libraries/USB/src/USBVendor.cpp @@ -24,7 +24,7 @@ esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, i static USBVendor *_Vendor = NULL; static QueueHandle_t rx_queue = NULL; -static uint8_t USB_VENDOR_ENDPOINT_SIZE = 64; +static uint16_t USB_VENDOR_ENDPOINT_SIZE = CFG_TUD_ENDOINT_SIZE; uint16_t tusb_vendor_load_descriptor(uint8_t *dst, uint8_t *itf) { uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB Vendor"); @@ -68,10 +68,13 @@ extern "C" bool tinyusb_vendor_control_request_cb(uint8_t rhport, uint8_t stage, return false; } -USBVendor::USBVendor(uint8_t endpoint_size) : itf(0), cb(NULL) { +USBVendor::USBVendor(uint16_t endpoint_size) : itf(0), cb(NULL) { if (!_Vendor) { _Vendor = this; - if (endpoint_size <= 64) { + if (endpoint_size == 0) { + endpoint_size = CFG_TUD_ENDOINT_SIZE; + } + if (endpoint_size <= CFG_TUD_ENDOINT_SIZE) { USB_VENDOR_ENDPOINT_SIZE = endpoint_size; } tinyusb_enable_interface(USB_INTERFACE_VENDOR, TUD_VENDOR_DESC_LEN, tusb_vendor_load_descriptor); @@ -97,7 +100,7 @@ size_t USBVendor::setRxBufferSize(size_t rx_queue_len) { } void USBVendor::begin() { - setRxBufferSize(256); //default if not preset + setRxBufferSize(512); //default if not preset } void USBVendor::end() { diff --git a/libraries/USB/src/USBVendor.h b/libraries/USB/src/USBVendor.h index e3e22281939..4990e466321 100644 --- a/libraries/USB/src/USBVendor.h +++ b/libraries/USB/src/USBVendor.h @@ -74,7 +74,7 @@ class USBVendor : public Stream { arduino_usb_vendor_control_request_handler_t cb; public: - USBVendor(uint8_t endpoint_size = 64); + USBVendor(uint16_t endpoint_size = 0); void begin(void); void end(void); size_t setRxBufferSize(size_t); diff --git a/libraries/USB/src/keyboardLayout/KeyboardLayout.h b/libraries/USB/src/keyboardLayout/KeyboardLayout.h new file mode 100644 index 00000000000..ee6b6b4e11e --- /dev/null +++ b/libraries/USB/src/keyboardLayout/KeyboardLayout.h @@ -0,0 +1,68 @@ +/* + KeyboardLayout.h + + This file is not part of the public API. It is meant to be included + only in Keyboard.cpp and the keyboard layout files. Layout files map + ASCII character codes to keyboard scan codes (technically, to USB HID + Usage codes), possibly altered by the SHIFT or ALT_GR modifiers. + Non-ASCII characters (anything outside the 7-bit range NUL..DEL) are + not supported. + + == Creating your own layout == + + In order to create your own layout file, copy an existing layout that + is similar to yours, then modify it to use the correct keys. The + layout is an array in ASCII order. Each entry contains a scan code, + possibly modified by "|SHIFT" or "|ALT_GR", as in this excerpt from + the Italian layout: + + 0x35, // bslash + 0x30|ALT_GR, // ] + 0x2e|SHIFT, // ^ + + Do not change the control characters (those before scan code 0x2c, + corresponding to space). Do not attempt to grow the table past DEL. Do + not use both SHIFT and ALT_GR on the same character: this is not + supported. Unsupported characters should have 0x00 as scan code. + + For a keyboard with an ISO physical layout, use the scan codes below: + + +---+---+---+---+---+---+---+---+---+---+---+---+---+-------+ + |35 |1e |1f |20 |21 |22 |23 |24 |25 |26 |27 |2d |2e |BackSp | + +---+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-----+ + | Tab |14 |1a |08 |15 |17 |1c |18 |0c |12 |13 |2f |30 | Ret | + +-----++--++--++--++--++--++--++--++--++--++--++--++--++ | + |CapsL |04 |16 |07 |09 |0a |0b |0d |0e |0f |33 |34 |31 | | + +----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+---+----+ + |Shi.|32 |1d |1b |06 |19 |05 |11 |10 |36 |37 |38 | Shift | + +----+---++--+-+-+---+---+---+---+---+--++---+---++----+----+ + |Ctrl|Win |Alt | |AlGr|Win |Menu|Ctrl| + +----+----+----+------------------------+----+----+----+----+ + + The ANSI layout is identical except that key 0x31 is above (rather + than next to) Return, and there is not key 0x32. + + Give a unique name to the layout array, then declare it in Keyboard.h + with a line of the form: + + extern const uint8_t KeyboardLayout_xx_YY[]; + + == Encoding details == + + All scan codes are less than 0x80, which makes bit 7 available to + signal that a modifier (Shift or AltGr) is needed to generate the + character. With only one exception, keys that are used with modifiers + have scan codes that are less than 0x40. This makes bit 6 available + to signal whether the modifier is Shift or AltGr. The exception is + 0x64, the key next next to Left Shift on the ISO layout (and absent + from the ANSI layout). We handle it by replacing its value by 0x32 in + the layout arrays. +*/ + +#include + +// Modifier keys for _asciimap[] table (not to be used directly) +#define SHIFT 0x80 +#define ALT_GR 0x40 +#define ISO_KEY 0x64 +#define ISO_REPLACEMENT 0x32 diff --git a/libraries/USB/src/keyboardLayout/KeyboardLayout_da_DK.cpp b/libraries/USB/src/keyboardLayout/KeyboardLayout_da_DK.cpp new file mode 100644 index 00000000000..7de2e1f6a43 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/KeyboardLayout_da_DK.cpp @@ -0,0 +1,137 @@ +/* + * Danish keyboard layout. + */ + +#include "KeyboardLayout.h" + +extern const uint8_t KeyboardLayout_da_DK[128] = { + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x1e | SHIFT, // ! + 0x1f | SHIFT, // " + 0x20 | SHIFT, // # + 0x21 | ALT_GR, // $ + 0x22 | SHIFT, // % + 0x23 | SHIFT, // & + 0x31, // ' + 0x25 | SHIFT, // ( + 0x26 | SHIFT, // ) + 0x31 | SHIFT, // * + 0x2d, // + + 0x36, // , + 0x38, // - + 0x37, // . + 0x24 | SHIFT, // / + 0x27, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + 0x37 | SHIFT, // : + 0x36 | SHIFT, // ; + 0x32, // < + 0x27 | SHIFT, // = + 0x32 | SHIFT, // > + 0x2d | SHIFT, // ? + 0x1f | ALT_GR, // @ + 0x04 | SHIFT, // A + 0x05 | SHIFT, // B + 0x06 | SHIFT, // C + 0x07 | SHIFT, // D + 0x08 | SHIFT, // E + 0x09 | SHIFT, // F + 0x0a | SHIFT, // G + 0x0b | SHIFT, // H + 0x0c | SHIFT, // I + 0x0d | SHIFT, // J + 0x0e | SHIFT, // K + 0x0f | SHIFT, // L + 0x10 | SHIFT, // M + 0x11 | SHIFT, // N + 0x12 | SHIFT, // O + 0x13 | SHIFT, // P + 0x14 | SHIFT, // Q + 0x15 | SHIFT, // R + 0x16 | SHIFT, // S + 0x17 | SHIFT, // T + 0x18 | SHIFT, // U + 0x19 | SHIFT, // V + 0x1a | SHIFT, // W + 0x1b | SHIFT, // X + 0x1c | SHIFT, // Y + 0x1d | SHIFT, // Z + 0x25 | ALT_GR, // [ + 0x32 | ALT_GR, // bslash + 0x26 | ALT_GR, // ] + 0x00, // ^ not supported (requires dead key + space) + 0x38 | SHIFT, // _ + 0x00, // ` not supported (requires dead key + space) + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1c, // y + 0x1d, // z + 0x24 | ALT_GR, // { + 0x2e | ALT_GR, // | + 0x27 | ALT_GR, // } + 0x00, // ~ not supported (requires dead key + space) + 0x00 // DEL +}; diff --git a/libraries/USB/src/keyboardLayout/KeyboardLayout_de_DE.cpp b/libraries/USB/src/keyboardLayout/KeyboardLayout_de_DE.cpp new file mode 100644 index 00000000000..0e430164e05 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/KeyboardLayout_de_DE.cpp @@ -0,0 +1,137 @@ +/* + * German keyboard layout. + */ + +#include "KeyboardLayout.h" + +extern const uint8_t KeyboardLayout_de_DE[128] PROGMEM = { + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x1e | SHIFT, // ! + 0x1f | SHIFT, // " + 0x31, // # + 0x21 | SHIFT, // $ + 0x22 | SHIFT, // % + 0x23 | SHIFT, // & + 0x31 | SHIFT, // ' + 0x25 | SHIFT, // ( + 0x26 | SHIFT, // ) + 0x30 | SHIFT, // * + 0x30, // + + 0x36, // , + 0x38, // - + 0x37, // . + 0x24 | SHIFT, // / + 0x27, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + 0x37 | SHIFT, // : + 0x36 | SHIFT, // ; + 0x32, // < + 0x27 | SHIFT, // = + 0x32 | SHIFT, // > + 0x2d | SHIFT, // ? + 0x14 | ALT_GR, // @ + 0x04 | SHIFT, // A + 0x05 | SHIFT, // B + 0x06 | SHIFT, // C + 0x07 | SHIFT, // D + 0x08 | SHIFT, // E + 0x09 | SHIFT, // F + 0x0a | SHIFT, // G + 0x0b | SHIFT, // H + 0x0c | SHIFT, // I + 0x0d | SHIFT, // J + 0x0e | SHIFT, // K + 0x0f | SHIFT, // L + 0x10 | SHIFT, // M + 0x11 | SHIFT, // N + 0x12 | SHIFT, // O + 0x13 | SHIFT, // P + 0x14 | SHIFT, // Q + 0x15 | SHIFT, // R + 0x16 | SHIFT, // S + 0x17 | SHIFT, // T + 0x18 | SHIFT, // U + 0x19 | SHIFT, // V + 0x1a | SHIFT, // W + 0x1b | SHIFT, // X + 0x1d | SHIFT, // Y + 0x1c | SHIFT, // Z + 0x25 | ALT_GR, // [ + 0x2d | ALT_GR, // bslash + 0x26 | ALT_GR, // ] + 0x00, // ^ not supported (requires dead key + space) + 0x38 | SHIFT, // _ + 0x00, // ` not supported (requires dead key + space) + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1d, // y + 0x1c, // z + 0x24 | ALT_GR, // { + 0x32 | ALT_GR, // | + 0x27 | ALT_GR, // } + 0x30 | ALT_GR, // ~ + 0x00 // DEL +}; diff --git a/libraries/USB/src/keyboardLayout/KeyboardLayout_en_US.cpp b/libraries/USB/src/keyboardLayout/KeyboardLayout_en_US.cpp new file mode 100644 index 00000000000..36a961e779f --- /dev/null +++ b/libraries/USB/src/keyboardLayout/KeyboardLayout_en_US.cpp @@ -0,0 +1,137 @@ +/* + * Standard US keyboard layout. + */ + +#include "KeyboardLayout.h" + +extern const uint8_t KeyboardLayout_en_US[128] PROGMEM = { + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x1e | SHIFT, // ! + 0x34 | SHIFT, // " + 0x20 | SHIFT, // # + 0x21 | SHIFT, // $ + 0x22 | SHIFT, // % + 0x24 | SHIFT, // & + 0x34, // ' + 0x26 | SHIFT, // ( + 0x27 | SHIFT, // ) + 0x25 | SHIFT, // * + 0x2e | SHIFT, // + + 0x36, // , + 0x2d, // - + 0x37, // . + 0x38, // / + 0x27, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + 0x33 | SHIFT, // : + 0x33, // ; + 0x36 | SHIFT, // < + 0x2e, // = + 0x37 | SHIFT, // > + 0x38 | SHIFT, // ? + 0x1f | SHIFT, // @ + 0x04 | SHIFT, // A + 0x05 | SHIFT, // B + 0x06 | SHIFT, // C + 0x07 | SHIFT, // D + 0x08 | SHIFT, // E + 0x09 | SHIFT, // F + 0x0a | SHIFT, // G + 0x0b | SHIFT, // H + 0x0c | SHIFT, // I + 0x0d | SHIFT, // J + 0x0e | SHIFT, // K + 0x0f | SHIFT, // L + 0x10 | SHIFT, // M + 0x11 | SHIFT, // N + 0x12 | SHIFT, // O + 0x13 | SHIFT, // P + 0x14 | SHIFT, // Q + 0x15 | SHIFT, // R + 0x16 | SHIFT, // S + 0x17 | SHIFT, // T + 0x18 | SHIFT, // U + 0x19 | SHIFT, // V + 0x1a | SHIFT, // W + 0x1b | SHIFT, // X + 0x1c | SHIFT, // Y + 0x1d | SHIFT, // Z + 0x2f, // [ + 0x31, // bslash + 0x30, // ] + 0x23 | SHIFT, // ^ + 0x2d | SHIFT, // _ + 0x35, // ` + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1c, // y + 0x1d, // z + 0x2f | SHIFT, // { + 0x31 | SHIFT, // | + 0x30 | SHIFT, // } + 0x35 | SHIFT, // ~ + 0x00 // DEL +}; diff --git a/libraries/USB/src/keyboardLayout/KeyboardLayout_es_ES.cpp b/libraries/USB/src/keyboardLayout/KeyboardLayout_es_ES.cpp new file mode 100644 index 00000000000..dac69cb92c3 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/KeyboardLayout_es_ES.cpp @@ -0,0 +1,137 @@ +/* + * Spanish keyboard layout. + */ + +#include "KeyboardLayout.h" + +extern const uint8_t KeyboardLayout_es_ES[128] PROGMEM = { + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x1e | SHIFT, // ! + 0x1f | SHIFT, // " + 0x20 | ALT_GR, // # + 0x21 | SHIFT, // $ + 0x22 | SHIFT, // % + 0x23 | SHIFT, // & + 0x2d, // ' + 0x25 | SHIFT, // ( + 0x26 | SHIFT, // ) + 0x30 | SHIFT, // * + 0x30, // + + 0x36, // , + 0x38, // - + 0x37, // . + 0x24 | SHIFT, // / + 0x27, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + 0x37 | SHIFT, // : + 0x36 | SHIFT, // ; + 0x32, // < + 0x27 | SHIFT, // = + 0x32 | SHIFT, // > + 0x2d | SHIFT, // ? + 0x1f | ALT_GR, // @ + 0x04 | SHIFT, // A + 0x05 | SHIFT, // B + 0x06 | SHIFT, // C + 0x07 | SHIFT, // D + 0x08 | SHIFT, // E + 0x09 | SHIFT, // F + 0x0a | SHIFT, // G + 0x0b | SHIFT, // H + 0x0c | SHIFT, // I + 0x0d | SHIFT, // J + 0x0e | SHIFT, // K + 0x0f | SHIFT, // L + 0x10 | SHIFT, // M + 0x11 | SHIFT, // N + 0x12 | SHIFT, // O + 0x13 | SHIFT, // P + 0x14 | SHIFT, // Q + 0x15 | SHIFT, // R + 0x16 | SHIFT, // S + 0x17 | SHIFT, // T + 0x18 | SHIFT, // U + 0x19 | SHIFT, // V + 0x1a | SHIFT, // W + 0x1b | SHIFT, // X + 0x1c | SHIFT, // Y + 0x1d | SHIFT, // Z + 0x2f | ALT_GR, // [ + 0x35 | ALT_GR, // bslash + 0x30 | ALT_GR, // ] + 0x00, // ^ not supported (requires dead key + space) + 0x38 | SHIFT, // _ + 0x00, // ` not supported (requires dead key + space) + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1c, // y + 0x1d, // z + 0x34 | ALT_GR, // { + 0x1e | ALT_GR, // | + 0x31 | ALT_GR, // } + 0x00, // ~ not supported (requires dead key + space) + 0x00 // DEL +}; diff --git a/libraries/USB/src/keyboardLayout/KeyboardLayout_fr_FR.cpp b/libraries/USB/src/keyboardLayout/KeyboardLayout_fr_FR.cpp new file mode 100644 index 00000000000..8728417d8d8 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/KeyboardLayout_fr_FR.cpp @@ -0,0 +1,137 @@ +/* + * Traditional (not AFNOR) French keyboard layout. + */ + +#include "KeyboardLayout.h" + +extern const uint8_t KeyboardLayout_fr_FR[128] PROGMEM = { + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x38, // ! + 0x20, // " + 0x20 | ALT_GR, // # + 0x30, // $ + 0x34 | SHIFT, // % + 0x1E, // & + 0x21, // ' + 0x22, // ( + 0x2d, // ) + 0x31, // * + 0x2e | SHIFT, // + + 0x10, // , + 0x23, // - + 0x36 | SHIFT, // . + 0x37 | SHIFT, // / + 0x27 | SHIFT, // 0 + 0x1e | SHIFT, // 1 + 0x1f | SHIFT, // 2 + 0x20 | SHIFT, // 3 + 0x21 | SHIFT, // 4 + 0x22 | SHIFT, // 5 + 0x23 | SHIFT, // 6 + 0x24 | SHIFT, // 7 + 0x25 | SHIFT, // 8 + 0x26 | SHIFT, // 9 + 0x37, // : + 0x36, // ; + 0x32, // < + 0x2e, // = + 0x32 | SHIFT, // > + 0x10 | SHIFT, // ? + 0x27 | ALT_GR, // @ + 0x14 | SHIFT, // A + 0x05 | SHIFT, // B + 0x06 | SHIFT, // C + 0x07 | SHIFT, // D + 0x08 | SHIFT, // E + 0x09 | SHIFT, // F + 0x0a | SHIFT, // G + 0x0b | SHIFT, // H + 0x0c | SHIFT, // I + 0x0d | SHIFT, // J + 0x0e | SHIFT, // K + 0x0f | SHIFT, // L + 0x33 | SHIFT, // M + 0x11 | SHIFT, // N + 0x12 | SHIFT, // O + 0x13 | SHIFT, // P + 0x04 | SHIFT, // Q + 0x15 | SHIFT, // R + 0x16 | SHIFT, // S + 0x17 | SHIFT, // T + 0x18 | SHIFT, // U + 0x19 | SHIFT, // V + 0x1d | SHIFT, // W + 0x1b | SHIFT, // X + 0x1c | SHIFT, // Y + 0x1a | SHIFT, // Z + 0x22 | ALT_GR, // [ + 0x25 | ALT_GR, // bslash + 0x2d | ALT_GR, // ] + 0x26 | ALT_GR, // ^ + 0x25, // _ + 0x24 | ALT_GR, // ` + 0x14, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x33, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x04, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1d, // w + 0x1b, // x + 0x1c, // y + 0x1a, // z + 0x21 | ALT_GR, // { + 0x23 | ALT_GR, // | + 0x2e | ALT_GR, // } + 0x1f | ALT_GR, // ~ + 0x00 // DEL +}; diff --git a/libraries/USB/src/keyboardLayout/KeyboardLayout_hu_HU.cpp b/libraries/USB/src/keyboardLayout/KeyboardLayout_hu_HU.cpp new file mode 100644 index 00000000000..ff4344a7a0d --- /dev/null +++ b/libraries/USB/src/keyboardLayout/KeyboardLayout_hu_HU.cpp @@ -0,0 +1,143 @@ +/* + * Standard HU keyboard layout. + */ + +#include "KeyboardLayout.h" + +extern const uint8_t KeyboardLayout_hu_HU[128] PROGMEM = { + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x21 | SHIFT, // ! + 0x1f | SHIFT, // " + 0x1b | ALT_GR, // # + 0x33 | ALT_GR, // $ + 0x22 | SHIFT, // % + 0x06 | ALT_GR, // & + 0x1e | SHIFT, // ' + 0x25 | SHIFT, // ( + 0x26 | SHIFT, // ) + 0x38 | ALT_GR, // * + 0x20 | SHIFT, // + + 0x36, // , + 0x38, // - + 0x37, // . + 0x23 | SHIFT, // / + + 0x35, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + + 0x37 | SHIFT, // : + 0x36 | ALT_GR, // ; + 0x32 | ALT_GR, // < + 0x24 | SHIFT, // = + 0x1d | ALT_GR, // > + 0x36 | SHIFT, // ? + 0x19 | ALT_GR, // @ + + 0x04 | SHIFT, // A + 0x05 | SHIFT, // B + 0x06 | SHIFT, // C + 0x07 | SHIFT, // D + 0x08 | SHIFT, // E + 0x09 | SHIFT, // F + 0x0a | SHIFT, // G + 0x0b | SHIFT, // H + 0x0c | SHIFT, // I + 0x0d | SHIFT, // J + 0x0e | SHIFT, // K + 0x0f | SHIFT, // L + 0x10 | SHIFT, // M + 0x11 | SHIFT, // N + 0x12 | SHIFT, // O + 0x13 | SHIFT, // P + 0x14 | SHIFT, // Q + 0x15 | SHIFT, // R + 0x16 | SHIFT, // S + 0x17 | SHIFT, // T + 0x18 | SHIFT, // U + 0x19 | SHIFT, // V + 0x1a | SHIFT, // W + 0x1b | SHIFT, // X + 0x1d | SHIFT, // Y + 0x1c | SHIFT, // Z + + 0x09 | ALT_GR, // [ + 0x14 | ALT_GR, // bslash + 0x0a | ALT_GR, // ] + 0x20 | ALT_GR, // ^ + 0x38 | SHIFT, // _ + 0x24 | ALT_GR, // ` + + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1d, // y + 0x1c, // z + + 0x05 | ALT_GR, // { + 0x1a | ALT_GR, // | + 0x11 | ALT_GR, // } + 0x1e | ALT_GR, // ~ + 0x00 // DEL +}; diff --git a/libraries/USB/src/keyboardLayout/KeyboardLayout_it_IT.cpp b/libraries/USB/src/keyboardLayout/KeyboardLayout_it_IT.cpp new file mode 100644 index 00000000000..60a46bcd59f --- /dev/null +++ b/libraries/USB/src/keyboardLayout/KeyboardLayout_it_IT.cpp @@ -0,0 +1,137 @@ +/* + * Italian keyboard layout. + */ + +#include "KeyboardLayout.h" + +extern const uint8_t KeyboardLayout_it_IT[128] PROGMEM = { + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x1e | SHIFT, // ! + 0x1f | SHIFT, // " + 0x34 | ALT_GR, // # + 0x21 | SHIFT, // $ + 0x22 | SHIFT, // % + 0x23 | SHIFT, // & + 0x2d, // ' + 0x25 | SHIFT, // ( + 0x26 | SHIFT, // ) + 0x30 | SHIFT, // * + 0x30, // + + 0x36, // , + 0x38, // - + 0x37, // . + 0x24 | SHIFT, // / + 0x27, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + 0x37 | SHIFT, // : + 0x36 | SHIFT, // ; + 0x32, // < + 0x27 | SHIFT, // = + 0x32 | SHIFT, // > + 0x2d | SHIFT, // ? + 0x33 | ALT_GR, // @ + 0x04 | SHIFT, // A + 0x05 | SHIFT, // B + 0x06 | SHIFT, // C + 0x07 | SHIFT, // D + 0x08 | SHIFT, // E + 0x09 | SHIFT, // F + 0x0a | SHIFT, // G + 0x0b | SHIFT, // H + 0x0c | SHIFT, // I + 0x0d | SHIFT, // J + 0x0e | SHIFT, // K + 0x0f | SHIFT, // L + 0x10 | SHIFT, // M + 0x11 | SHIFT, // N + 0x12 | SHIFT, // O + 0x13 | SHIFT, // P + 0x14 | SHIFT, // Q + 0x15 | SHIFT, // R + 0x16 | SHIFT, // S + 0x17 | SHIFT, // T + 0x18 | SHIFT, // U + 0x19 | SHIFT, // V + 0x1a | SHIFT, // W + 0x1b | SHIFT, // X + 0x1c | SHIFT, // Y + 0x1d | SHIFT, // Z + 0x2f | ALT_GR, // [ + 0x35, // bslash + 0x30 | ALT_GR, // ] + 0x2e | SHIFT, // ^ + 0x38 | SHIFT, // _ + 0x00, // ` not in this layout + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1c, // y + 0x1d, // z + 0x00, // { not supported (requires AltGr+Shift) + 0x35 | SHIFT, // | + 0x00, // } not supported (requires AltGr+Shift) + 0x00, // ~ not in this layout + 0x00 // DEL +}; diff --git a/libraries/USB/src/keyboardLayout/KeyboardLayout_pt_BR.cpp b/libraries/USB/src/keyboardLayout/KeyboardLayout_pt_BR.cpp new file mode 100644 index 00000000000..09014a7e04c --- /dev/null +++ b/libraries/USB/src/keyboardLayout/KeyboardLayout_pt_BR.cpp @@ -0,0 +1,141 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-License-Identifier: Apache-2.0 + * + * Keyboard_pt_BR.h + * Portuguese Brazilian keyboard layout. + */ + +#include "KeyboardLayout.h" + +extern const uint8_t KeyboardLayout_pt_BR[128] PROGMEM = { + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x1e | SHIFT, // ! + 0x35 | SHIFT, // " + 0x20 | SHIFT, // # + 0x21 | SHIFT, // $ + 0x22 | SHIFT, // % + 0x24 | SHIFT, // & + 0x35, // ' + 0x26 | SHIFT, // ( + 0x27 | SHIFT, // ) + 0x25 | SHIFT, // * + 0x2e | SHIFT, // + + 0x36, // , + 0x2d, // - + 0x37, // . + 0x14 | ALT_GR, // / R_ALT + q + 0x27, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + 0x38 | SHIFT, // : + 0x38, // ; + 0x36 | SHIFT, // < + 0x2e, // = + 0x37 | SHIFT, // > + 0x1a | ALT_GR, // ? R_ALT + w + 0x1f | SHIFT, // @ + 0x04 | SHIFT, // A + 0x05 | SHIFT, // B + 0x06 | SHIFT, // C + 0x07 | SHIFT, // D + 0x08 | SHIFT, // E + 0x09 | SHIFT, // F + 0x0a | SHIFT, // G + 0x0b | SHIFT, // H + 0x0c | SHIFT, // I + 0x0d | SHIFT, // J + 0x0e | SHIFT, // K + 0x0f | SHIFT, // L + 0x10 | SHIFT, // M + 0x11 | SHIFT, // N + 0x12 | SHIFT, // O + 0x13 | SHIFT, // P + 0x14 | SHIFT, // Q + 0x15 | SHIFT, // R + 0x16 | SHIFT, // S + 0x17 | SHIFT, // T + 0x18 | SHIFT, // U + 0x19 | SHIFT, // V + 0x1a | SHIFT, // W + 0x1b | SHIFT, // X + 0x1c | SHIFT, // Y + 0x1d | SHIFT, // Z + 0x30, // [ + 0x32, // bslash -->ISO Key + 0x31, // ] + 0x34 | SHIFT, // ^ + 0x2d | SHIFT, // _ + 0x2f | SHIFT, // ` + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1c, // y + 0x1d, // z + 0x30 | SHIFT, // { + 0x32 | SHIFT, // | -->ISO Key + 0x31 | SHIFT, // } + 0x34, // ~ + 0x4c // DEL +}; diff --git a/libraries/USB/src/keyboardLayout/KeyboardLayout_pt_PT.cpp b/libraries/USB/src/keyboardLayout/KeyboardLayout_pt_PT.cpp new file mode 100644 index 00000000000..4f0c53d536d --- /dev/null +++ b/libraries/USB/src/keyboardLayout/KeyboardLayout_pt_PT.cpp @@ -0,0 +1,137 @@ +/* + * Portuguese keyboard layout. + */ + +#include "KeyboardLayout.h" + +extern const uint8_t KeyboardLayout_pt_PT[128] PROGMEM = { + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x1e | SHIFT, // ! + 0x1f | SHIFT, // " + 0x20 | SHIFT, // # + 0x21 | SHIFT, // $ + 0x22 | SHIFT, // % + 0x23 | SHIFT, // & + 0x2d, // ' + 0x25 | SHIFT, // ( + 0x26 | SHIFT, // ) + 0x2f | SHIFT, // * + 0x2f, // + + 0x36, // , + 0x38, // - + 0x37, // . + 0x24 | SHIFT, // / + 0x27, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + 0x37 | SHIFT, // : + 0x36 | SHIFT, // ; + 0x32, // < + 0x27 | SHIFT, // = + 0x32 | SHIFT, // > + 0x2d | SHIFT, // ? + 0x1f | ALT_GR, // @ + 0x04 | SHIFT, // A + 0x05 | SHIFT, // B + 0x06 | SHIFT, // C + 0x07 | SHIFT, // D + 0x08 | SHIFT, // E + 0x09 | SHIFT, // F + 0x0a | SHIFT, // G + 0x0b | SHIFT, // H + 0x0c | SHIFT, // I + 0x0d | SHIFT, // J + 0x0e | SHIFT, // K + 0x0f | SHIFT, // L + 0x10 | SHIFT, // M + 0x11 | SHIFT, // N + 0x12 | SHIFT, // O + 0x13 | SHIFT, // P + 0x14 | SHIFT, // Q + 0x15 | SHIFT, // R + 0x16 | SHIFT, // S + 0x17 | SHIFT, // T + 0x18 | SHIFT, // U + 0x19 | SHIFT, // V + 0x1a | SHIFT, // W + 0x1b | SHIFT, // X + 0x1c | SHIFT, // Y + 0x1d | SHIFT, // Z + 0x25 | ALT_GR, // [ + 0x35, // bslash + 0x26 | ALT_GR, // ] + 0x00, // ^ not supported (requires dead key + space) + 0x38 | SHIFT, // _ + 0x00, // ` not supported (requires dead key + space) + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1c, // y + 0x1d, // z + 0x24 | ALT_GR, // { + 0x35 | SHIFT, // | + 0x27 | ALT_GR, // } + 0x00, // ~ not supported (requires dead key + space) + 0x00 // DEL +}; diff --git a/libraries/USB/src/keyboardLayout/KeyboardLayout_sv_SE.cpp b/libraries/USB/src/keyboardLayout/KeyboardLayout_sv_SE.cpp new file mode 100644 index 00000000000..8ef92c1a0e6 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/KeyboardLayout_sv_SE.cpp @@ -0,0 +1,137 @@ +/* + * Swedish keyboard layout. + */ + +#include "KeyboardLayout.h" + +extern const uint8_t KeyboardLayout_sv_SE[128] PROGMEM = { + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x1e | SHIFT, // ! + 0x1f | SHIFT, // " + 0x20 | SHIFT, // # + 0x21 | ALT_GR, // $ + 0x22 | SHIFT, // % + 0x23 | SHIFT, // & + 0x31, // ' + 0x25 | SHIFT, // ( + 0x26 | SHIFT, // ) + 0x31 | SHIFT, // * + 0x2d, // + + 0x36, // , + 0x38, // - + 0x37, // . + 0x24 | SHIFT, // / + 0x27, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + 0x37 | SHIFT, // : + 0x36 | SHIFT, // ; + 0x32, // < + 0x27 | SHIFT, // = + 0x32 | SHIFT, // > + 0x2d | SHIFT, // ? + 0x1f | ALT_GR, // @ + 0x04 | SHIFT, // A + 0x05 | SHIFT, // B + 0x06 | SHIFT, // C + 0x07 | SHIFT, // D + 0x08 | SHIFT, // E + 0x09 | SHIFT, // F + 0x0a | SHIFT, // G + 0x0b | SHIFT, // H + 0x0c | SHIFT, // I + 0x0d | SHIFT, // J + 0x0e | SHIFT, // K + 0x0f | SHIFT, // L + 0x10 | SHIFT, // M + 0x11 | SHIFT, // N + 0x12 | SHIFT, // O + 0x13 | SHIFT, // P + 0x14 | SHIFT, // Q + 0x15 | SHIFT, // R + 0x16 | SHIFT, // S + 0x17 | SHIFT, // T + 0x18 | SHIFT, // U + 0x19 | SHIFT, // V + 0x1a | SHIFT, // W + 0x1b | SHIFT, // X + 0x1c | SHIFT, // Y + 0x1d | SHIFT, // Z + 0x25 | ALT_GR, // [ + 0x2d | ALT_GR, // bslash + 0x26 | ALT_GR, // ] + 0x00, // ^ not supported (requires dead key + space) + 0x38 | SHIFT, // _ + 0x00, // ` not supported (requires dead key + space) + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1c, // y + 0x1d, // z + 0x24 | ALT_GR, // { + 0x32 | ALT_GR, // | + 0x27 | ALT_GR, // } + 0x00, // ~ not supported (requires dead key + space) + 0x00 // DEL +}; diff --git a/libraries/USB/src/keyboardLayout/Keyboard_da_DK.h b/libraries/USB/src/keyboardLayout/Keyboard_da_DK.h new file mode 100644 index 00000000000..8ad1540ac57 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/Keyboard_da_DK.h @@ -0,0 +1,35 @@ +/* + Keyboard_da_DK.h + + Copyright (c) 2021, Peter John + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KEYBOARD_DA_DK_h +#define KEYBOARD_DA_DK_h + +//================================================================================ +//================================================================================ +// Keyboard + +// DA_DK keys +#define KEY_A_RING (0x88 + 0x2f) +#define KEY_SLASHED_O (0x88 + 0x34) +#define KEY_ASH (0x88 + 0x33) +#define KEY_UMLAUT (0x88 + 0x30) +#define KEY_ACUTE_ACC (0x88 + 0x2e) + +#endif diff --git a/libraries/USB/src/keyboardLayout/Keyboard_de_DE.h b/libraries/USB/src/keyboardLayout/Keyboard_de_DE.h new file mode 100644 index 00000000000..8fec4e1b244 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/Keyboard_de_DE.h @@ -0,0 +1,36 @@ +/* + Keyboard_de_DE.h + + Copyright (c) 2022, Edgar Bonet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KEYBOARD_DE_DE_h +#define KEYBOARD_DE_DE_h + +//================================================================================ +//================================================================================ +// Keyboard + +// de_DE keys +#define KEY_CIRCUMFLEX (0x88 + 0x35) +#define KEY_ESZETT (0x88 + 0x2d) +#define KEY_ACUTE (0x88 + 0x2e) +#define KEY_U_UMLAUT (0x88 + 0x2f) +#define KEY_O_UMLAUT (0x88 + 0x33) +#define KEY_A_UMLAUT (0x88 + 0x34) + +#endif diff --git a/libraries/USB/src/keyboardLayout/Keyboard_es_ES.h b/libraries/USB/src/keyboardLayout/Keyboard_es_ES.h new file mode 100644 index 00000000000..25f7c01395b --- /dev/null +++ b/libraries/USB/src/keyboardLayout/Keyboard_es_ES.h @@ -0,0 +1,37 @@ +/* + Keyboard_es_ES.h + + Copyright (c) 2022, Edgar Bonet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KEYBOARD_ES_ES_h +#define KEYBOARD_ES_ES_h + +#include "class/hid/hid.h" +//================================================================================ +//================================================================================ +// Keyboard + +// es_ES keys +#define KEY_MASCULINE_ORDINAL (0x88 + 0x35) +#define KEY_INVERTED_EXCLAMATION (0x88 + 0x2e) +#define KEY_GRAVE (0x88 + 0x2f) +#define KEY_N_TILDE (0x88 + 0x33) +#define KEY_ACUTE (0x88 + 0x34) +#define KEY_C_CEDILLA (0x88 + 0x31) + +#endif diff --git a/libraries/USB/src/keyboardLayout/Keyboard_fr_FR.h b/libraries/USB/src/keyboardLayout/Keyboard_fr_FR.h new file mode 100644 index 00000000000..d5d9fa80402 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/Keyboard_fr_FR.h @@ -0,0 +1,37 @@ +/* + Keyboard_fr_FR.h + + Copyright (c) 2022, Edgar Bonet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KEYBOARD_FR_FR_h +#define KEYBOARD_FR_FR_h + +//================================================================================ +//================================================================================ +// Keyboard + +// fr_FR keys +#define KEY_SUPERSCRIPT_TWO (0x88 + 0x35) +#define KEY_E_ACUTE (0x88 + 0x1f) +#define KEY_E_GRAVE (0x88 + 0x24) +#define KEY_C_CEDILLA (0x88 + 0x26) +#define KEY_A_GRAVE (0x88 + 0x27) +#define KEY_CIRCUMFLEX (0x88 + 0x2f) +#define KEY_U_GRAVE (0x88 + 0x34) + +#endif diff --git a/libraries/USB/src/keyboardLayout/Keyboard_hu_HU.h b/libraries/USB/src/keyboardLayout/Keyboard_hu_HU.h new file mode 100644 index 00000000000..b0214319690 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/Keyboard_hu_HU.h @@ -0,0 +1,43 @@ +/* + Keyboard_hu_HU.h + + Copyright (c) 2023, Barab(0x34)si Rich(0x34)rd + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KEYBOARD_HU_HU_h +#define KEYBOARD_HU_HU_h + +//================================================================================ +//================================================================================ +// Keyboard + +// hu_HU keys +#define KEY_O_ACUTE (0x88 + 0x2e) +#define KEY_O_UMLAUT (0x88 + 0x27) +#define KEY_O_DOUBLE_ACUTE (0x88 + 0x2f) + +#define KEY_U_ACUTE (0x88 + 0x30) +#define KEY_U_UMLAUT (0x88 + 0x2d) +#define KEY_U_DOUBLE_ACUTE (0x88 + 0x31) + +#define KEY_A_ACUTE (0x88 + 0x34) + +#define KEY_E_ACUTE (0x88 + 0x33) + +#define KEY_I_ACUTE (0x88 + 0x32) + +#endif diff --git a/libraries/USB/src/keyboardLayout/Keyboard_it_IT.h b/libraries/USB/src/keyboardLayout/Keyboard_it_IT.h new file mode 100644 index 00000000000..41b52c8bb53 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/Keyboard_it_IT.h @@ -0,0 +1,35 @@ +/* + Keyboard_it_IT.h + + Copyright (c) 2022, Edgar Bonet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KEYBOARD_IT_IT_h +#define KEYBOARD_IT_IT_h + +//================================================================================ +//================================================================================ +// Keyboard + +// it_IT keys +#define KEY_I_GRAVE (0x88 + 0x2e) +#define KEY_E_GRAVE (0x88 + 0x2f) +#define KEY_O_GRAVE (0x88 + 0x33) +#define KEY_A_GRAVE (0x88 + 0x34) +#define KEY_U_GRAVE (0x88 + 0x31) + +#endif diff --git a/libraries/USB/src/keyboardLayout/Keyboard_pt_BR.h b/libraries/USB/src/keyboardLayout/Keyboard_pt_BR.h new file mode 100644 index 00000000000..6b597e56386 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/Keyboard_pt_BR.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-License-Identifier: Apache-2.0 + * + * Keyboard_pt_BR.h + * Portuguese Brazilian keyboard layout. +*/ + +#ifndef KEYBOARD_PT_BR_h +#define KEYBOARD_PT_BR_h + +//================================================================================ +//================================================================================ +// Keyboard + +// pt_BR keys +#define KEY_C_CEDILLA (0x88 + 0x33) +#define KEY_ACUTE (0x88 + 0x2f) +// use the pressRaw() to press the modification key and then press the key you want to modify +#define KEY_MASCULINE_ORDINAL (0x88 + 0x32) // first pressRaw(HID_KEY_ALT_RIGHT), then press(KEY_MASCULINE_ORDINAL) +#define KEY_FEMININE_ORDINAL (0x88 + 0x30) // first pressRaw(HID_KEY_ALT_RIGHT), then press(KEY_FEMININE_ORDINAL) +#define KEY_PARAGRAPH (0x88 + 0x2e) // first pressRaw(HID_KEY_ALT_RIGHT), then press(KEY_PARAGRAPH) +#define KEY_UMLAUT (0x88 + 0x23) // first pressRaw(HID_KEY_SHIFT_RIGHT), then press(KEY_UMLAUT) + +#endif diff --git a/libraries/USB/src/keyboardLayout/Keyboard_pt_PT.h b/libraries/USB/src/keyboardLayout/Keyboard_pt_PT.h new file mode 100644 index 00000000000..c1a2dbfebf6 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/Keyboard_pt_PT.h @@ -0,0 +1,35 @@ +/* + Keyboard_pt_PT.h + + Copyright (c) 2022, Edgar Bonet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KEYBOARD_PT_PT_h +#define KEYBOARD_PT_PT_h + +//================================================================================ +//================================================================================ +// Keyboard + +// pt_PT keys +#define KEY_LEFT_GUILLEMET (0x88 + 0x2e) +#define KEY_ACUTE (0x88 + 0x30) +#define KEY_C_CEDILLA (0x88 + 0x33) +#define KEY_MASCULINE_ORDINAL (0x88 + 0x34) +#define KEY_TILDE (0x88 + 0x31) + +#endif diff --git a/libraries/USB/src/keyboardLayout/Keyboard_sv_SE.h b/libraries/USB/src/keyboardLayout/Keyboard_sv_SE.h new file mode 100644 index 00000000000..1a3e3bc6087 --- /dev/null +++ b/libraries/USB/src/keyboardLayout/Keyboard_sv_SE.h @@ -0,0 +1,35 @@ +/* + Keyboard_sv_SE.h + + Copyright (c) 2021, Peter John + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KEYBOARD_SV_SE_h +#define KEYBOARD_SV_SE_h + +//================================================================================ +//================================================================================ +// Keyboard + +// SV_SE keys +#define KEY_A_RING (0x88 + 0x2f) +#define KEY_A_UMLAUT (0x88 + 0x34) +#define KEY_O_UMLAUT (0x88 + 0x33) +#define KEY_UMLAUT (0x88 + 0x30) +#define KEY_ACUTE_ACC (0x88 + 0x2e) + +#endif diff --git a/libraries/Update/examples/AWS_S3_OTA_Update/AWS_S3_OTA_Update.ino b/libraries/Update/examples/AWS_S3_OTA_Update/AWS_S3_OTA_Update.ino index c51fcf478bf..08c0a5a9ff0 100644 --- a/libraries/Update/examples/AWS_S3_OTA_Update/AWS_S3_OTA_Update.ino +++ b/libraries/Update/examples/AWS_S3_OTA_Update/AWS_S3_OTA_Update.ino @@ -178,11 +178,11 @@ void execOTA() { // Understand the partitions and // space availability Serial.println("Not enough space to begin OTA"); - client.flush(); + client.clear(); } } else { Serial.println("There was no content in the response"); - client.flush(); + client.clear(); } } diff --git a/libraries/Update/examples/AWS_S3_OTA_Update/ci.json b/libraries/Update/examples/AWS_S3_OTA_Update/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/Update/examples/AWS_S3_OTA_Update/ci.json +++ b/libraries/Update/examples/AWS_S3_OTA_Update/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/Update/examples/HTTPS_OTA_Update/ci.json b/libraries/Update/examples/HTTPS_OTA_Update/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/Update/examples/HTTPS_OTA_Update/ci.json +++ b/libraries/Update/examples/HTTPS_OTA_Update/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/Update/examples/HTTP_Client_AES_OTA_Update/ci.json b/libraries/Update/examples/HTTP_Client_AES_OTA_Update/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/Update/examples/HTTP_Client_AES_OTA_Update/ci.json +++ b/libraries/Update/examples/HTTP_Client_AES_OTA_Update/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/Update/examples/HTTP_Server_AES_OTA_Update/ci.json b/libraries/Update/examples/HTTP_Server_AES_OTA_Update/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/Update/examples/HTTP_Server_AES_OTA_Update/ci.json +++ b/libraries/Update/examples/HTTP_Server_AES_OTA_Update/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/Update/examples/OTAWebUpdater/ci.json b/libraries/Update/examples/OTAWebUpdater/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/Update/examples/OTAWebUpdater/ci.json +++ b/libraries/Update/examples/OTAWebUpdater/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/Update/library.properties b/libraries/Update/library.properties index ccfccb36952..c3ee8f7e506 100644 --- a/libraries/Update/library.properties +++ b/libraries/Update/library.properties @@ -1,5 +1,5 @@ name=Update -version=2.0.0 +version=3.2.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=ESP32 Sketch Update Library diff --git a/libraries/Update/src/Update.h b/libraries/Update/src/Update.h index 7ae5e980751..9a4d3e02489 100644 --- a/libraries/Update/src/Update.h +++ b/libraries/Update/src/Update.h @@ -63,6 +63,7 @@ class UpdateClass { */ bool begin(size_t size = UPDATE_SIZE_UNKNOWN, int command = U_FLASH, int ledPin = -1, uint8_t ledOn = LOW, const char *label = NULL); +#ifndef UPDATE_NOCRYPT /* Setup decryption configuration Crypt Key is 32bytes(256bits) block of data, use the same key as used to encrypt image file @@ -71,6 +72,7 @@ class UpdateClass { Crypt Mode, used to select if image files should be decrypted or not */ bool setupCrypt(const uint8_t *cryptKey = 0, size_t cryptAddress = 0, uint8_t cryptConfig = 0xf, int cryptMode = U_AES_DECRYPT_AUTO); +#endif /* UPDATE_NOCRYPT */ /* Writes a buffer to the flash and increments the address @@ -99,6 +101,7 @@ class UpdateClass { */ bool end(bool evenIfRemaining = false); +#ifndef UPDATE_NOCRYPT /* sets AES256 key(32 bytes) used for decrypting image file */ @@ -122,6 +125,7 @@ class UpdateClass { void setCryptConfig(const uint8_t cryptConfig) { _cryptCfg = cryptConfig & 0x0f; } +#endif /* UPDATE_NOCRYPT */ /* Aborts the running update @@ -137,8 +141,15 @@ class UpdateClass { /* sets the expected MD5 for the firmware (hexString) + If calc_post_decryption is true, the update library will calculate the MD5 after the decryption, if false the calculation occurs before the decryption */ - bool setMD5(const char *expected_md5); + bool setMD5( + const char *expected_md5 +#ifndef UPDATE_NOCRYPT + , + bool calc_post_decryption = true +#endif /* #ifdef UPDATE_NOCRYPT */ + ); /* returns the MD5 String of the successfully ended firmware @@ -235,8 +246,10 @@ class UpdateClass { private: void _reset(); void _abort(uint8_t err); +#ifndef UPDATE_NOCRYPT void _cryptKeyTweak(size_t cryptAddress, uint8_t *tweaked_key); bool _decryptBuffer(); +#endif /* UPDATE_NOCRYPT */ bool _writeBuffer(); bool _verifyHeader(uint8_t data); bool _verifyEnd(); @@ -244,8 +257,10 @@ class UpdateClass { bool _chkDataInBlock(const uint8_t *data, size_t len) const; // check if block contains any data or is empty uint8_t _error; +#ifndef UPDATE_NOCRYPT uint8_t *_cryptKey; uint8_t *_cryptBuffer; +#endif /* UPDATE_NOCRYPT */ uint8_t *_buffer; uint8_t *_skipBuffer; size_t _bufferLen; @@ -257,14 +272,19 @@ class UpdateClass { const esp_partition_t *_partition; String _target_md5; +#ifndef UPDATE_NOCRYPT + bool _target_md5_decrypted = true; +#endif /* UPDATE_NOCRYPT */ MD5Builder _md5; int _ledPin; uint8_t _ledOn; +#ifndef UPDATE_NOCRYPT uint8_t _cryptMode; size_t _cryptAddress; uint8_t _cryptCfg; +#endif /* UPDATE_NOCRYPT */ }; #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_UPDATE) diff --git a/libraries/Update/src/Updater.cpp b/libraries/Update/src/Updater.cpp index f5f6992db5a..3b0c517431d 100644 --- a/libraries/Update/src/Updater.cpp +++ b/libraries/Update/src/Updater.cpp @@ -9,7 +9,9 @@ #include "spi_flash_mmap.h" #include "esp_ota_ops.h" #include "esp_image_format.h" +#ifndef UPDATE_NOCRYPT #include "mbedtls/aes.h" +#endif /* UPDATE_NOCRYPT */ static const char *_err2str(uint8_t _error) { if (_error == UPDATE_ERROR_OK) { @@ -38,8 +40,10 @@ static const char *_err2str(uint8_t _error) { return ("Bad Argument"); } else if (_error == UPDATE_ERROR_ABORT) { return ("Aborted"); +#ifndef UPDATE_NOCRYPT } else if (_error == UPDATE_ERROR_DECRYPT) { return ("Decryption error"); +#endif /* UPDATE_NOCRYPT */ } return ("UNKNOWN"); } @@ -67,8 +71,17 @@ bool UpdateClass::_enablePartition(const esp_partition_t *partition) { } UpdateClass::UpdateClass() - : _error(0), _cryptKey(0), _cryptBuffer(0), _buffer(0), _skipBuffer(0), _bufferLen(0), _size(0), _progress_callback(NULL), _progress(0), _paroffset(0), - _command(U_FLASH), _partition(NULL), _cryptMode(U_AES_DECRYPT_AUTO), _cryptAddress(0), _cryptCfg(0xf) {} + : _error(0), +#ifndef UPDATE_NOCRYPT + _cryptKey(0), _cryptBuffer(0), +#endif /* UPDATE_NOCRYPT */ + _buffer(0), _skipBuffer(0), _bufferLen(0), _size(0), _progress_callback(NULL), _progress(0), _paroffset(0), _command(U_FLASH), _partition(NULL) +#ifndef UPDATE_NOCRYPT + , + _cryptMode(U_AES_DECRYPT_AUTO), _cryptAddress(0), _cryptCfg(0xf) +#endif /* UPDATE_NOCRYPT */ +{ +} UpdateClass &UpdateClass::onProgress(THandlerFunction_Progress fn) { _progress_callback = fn; @@ -83,7 +96,9 @@ void UpdateClass::_reset() { delete[] _skipBuffer; } +#ifndef UPDATE_NOCRYPT _cryptBuffer = nullptr; +#endif /* UPDATE_NOCRYPT */ _buffer = nullptr; _skipBuffer = nullptr; _bufferLen = 0; @@ -175,6 +190,7 @@ bool UpdateClass::begin(size_t size, int command, int ledPin, uint8_t ledOn, con return true; } +#ifndef UPDATE_NOCRYPT bool UpdateClass::setupCrypt(const uint8_t *cryptKey, size_t cryptAddress, uint8_t cryptConfig, int cryptMode) { if (setCryptKey(cryptKey)) { if (setCryptMode(cryptMode)) { @@ -216,6 +232,7 @@ bool UpdateClass::setCryptMode(const int cryptMode) { } return true; } +#endif /* UPDATE_NOCRYPT */ void UpdateClass::_abort(uint8_t err) { _reset(); @@ -226,6 +243,7 @@ void UpdateClass::abort() { _abort(UPDATE_ERROR_ABORT); } +#ifndef UPDATE_NOCRYPT void UpdateClass::_cryptKeyTweak(size_t cryptAddress, uint8_t *tweaked_key) { memcpy(tweaked_key, _cryptKey, ENCRYPTED_KEY_SIZE); if (_cryptCfg == 0) { @@ -338,8 +356,10 @@ bool UpdateClass::_decryptBuffer() { } return true; } +#endif /* UPDATE_NOCRYPT */ bool UpdateClass::_writeBuffer() { +#ifndef UPDATE_NOCRYPT //first bytes of loading image, check to see if loading image needs decrypting if (!_progress) { _cryptMode &= U_AES_DECRYPT_MODE_MASK; @@ -348,6 +368,11 @@ bool UpdateClass::_writeBuffer() { log_d("Decrypting OTA Image"); } } + + if (!_target_md5_decrypted) { + _md5.add(_buffer, _bufferLen); + } + //check if data in buffer needs decrypting if (_cryptMode & U_AES_IMAGE_DECRYPTING_BIT) { if (!_decryptBuffer()) { @@ -355,6 +380,7 @@ bool UpdateClass::_writeBuffer() { return false; } } +#endif /* UPDATE_NOCRYPT */ //first bytes of new firmware uint8_t skip = 0; if (!_progress && _command == U_FLASH) { @@ -393,7 +419,7 @@ bool UpdateClass::_writeBuffer() { } } - // try to skip empty blocks on unecrypted partitions + // try to skip empty blocks on unencrypted partitions if ((_partition->encrypted || _chkDataInBlock(_buffer + skip / sizeof(uint32_t), _bufferLen - skip)) && !ESP.partitionWrite(_partition, _progress + skip, (uint32_t *)_buffer + skip / sizeof(uint32_t), _bufferLen - skip)) { _abort(UPDATE_ERROR_WRITE); @@ -404,7 +430,13 @@ bool UpdateClass::_writeBuffer() { if (!_progress && _command == U_FLASH) { _buffer[0] = ESP_IMAGE_HEADER_MAGIC; } - _md5.add(_buffer, _bufferLen); +#ifndef UPDATE_NOCRYPT + if (_target_md5_decrypted) { +#endif /* UPDATE_NOCRYPT */ + _md5.add(_buffer, _bufferLen); +#ifndef UPDATE_NOCRYPT + } +#endif /* UPDATE_NOCRYPT */ _progress += _bufferLen; _bufferLen = 0; if (_progress_callback) { @@ -446,12 +478,21 @@ bool UpdateClass::_verifyEnd() { return false; } -bool UpdateClass::setMD5(const char *expected_md5) { +bool UpdateClass::setMD5( + const char *expected_md5 +#ifndef UPDATE_NOCRYPT + , + bool calc_post_decryption +#endif /* UPDATE_NOCRYPT */ +) { if (strlen(expected_md5) != 32) { return false; } _target_md5 = expected_md5; _target_md5.toLowerCase(); +#ifndef UPDATE_NOCRYPT + _target_md5_decrypted = calc_post_decryption; +#endif /* UPDATE_NOCRYPT */ return true; } @@ -524,10 +565,16 @@ size_t UpdateClass::writeStream(Stream &data) { return 0; } - if (!_verifyHeader(data.peek())) { - _reset(); - return 0; +#ifndef UPDATE_NOCRYPT + if (_command == U_FLASH && !_cryptMode) { +#endif /* UPDATE_NOCRYPT */ + if (!_verifyHeader(data.peek())) { + _reset(); + return 0; + } +#ifndef UPDATE_NOCRYPT } +#endif /* UPDATE_NOCRYPT */ if (_ledPin != -1) { pinMode(_ledPin, OUTPUT); diff --git a/libraries/WebServer/examples/AdvancedWebServer/ci.json b/libraries/WebServer/examples/AdvancedWebServer/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/AdvancedWebServer/ci.json +++ b/libraries/WebServer/examples/AdvancedWebServer/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/FSBrowser/ci.json b/libraries/WebServer/examples/FSBrowser/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/FSBrowser/ci.json +++ b/libraries/WebServer/examples/FSBrowser/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/Filters/Filters.ino b/libraries/WebServer/examples/Filters/Filters.ino new file mode 100644 index 00000000000..8974e55d322 --- /dev/null +++ b/libraries/WebServer/examples/Filters/Filters.ino @@ -0,0 +1,110 @@ +#include +#include +#include +#include + +// Your STA WiFi Credentials +// ( This is the AP your ESP will connect to ) +const char *ssid = "........"; +const char *password = "........"; + +// Your AP WiFi Credentials +// ( This is the AP your ESP will broadcast ) +const char *ap_ssid = "ESP32_Demo"; +const char *ap_password = ""; + +WebServer server(80); + +const int led = 13; + +// ON_STA_FILTER - Only accept requests coming from STA interface +bool ON_STA_FILTER(WebServer &server) { + return WiFi.STA.hasIP() && WiFi.STA.localIP() == server.client().localIP(); +} + +// ON_AP_FILTER - Only accept requests coming from AP interface +bool ON_AP_FILTER(WebServer &server) { + return WiFi.AP.hasIP() && WiFi.AP.localIP() == server.client().localIP(); +} + +void handleNotFound() { + digitalWrite(led, 1); + String message = "File Not Found\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + for (uint8_t i = 0; i < server.args(); i++) { + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + } + server.send(404, "text/plain", message); + digitalWrite(led, 0); +} + +void setup(void) { + pinMode(led, OUTPUT); + digitalWrite(led, 0); + Serial.begin(115200); + WiFi.mode(WIFI_AP_STA); + // Connect to STA + WiFi.begin(ssid, password); + // Start AP + WiFi.softAP(ap_ssid, ap_password); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + if (MDNS.begin("esp32")) { + Serial.println("MDNS responder started"); + } + + // This route will be accessible by STA clients only + server + .on( + "/", + [&]() { + digitalWrite(led, 1); + server.send(200, "text/plain", "Hi!, This route is accessible for STA clients only"); + digitalWrite(led, 0); + } + ) + .setFilter(ON_STA_FILTER); + + // This route will be accessible by AP clients only + server + .on( + "/", + [&]() { + digitalWrite(led, 1); + server.send(200, "text/plain", "Hi!, This route is accessible for AP clients only"); + digitalWrite(led, 0); + } + ) + .setFilter(ON_AP_FILTER); + + server.on("/inline", []() { + server.send(200, "text/plain", "this works as well"); + }); + + server.onNotFound(handleNotFound); + + server.begin(); + Serial.println("HTTP server started"); +} + +void loop(void) { + server.handleClient(); + delay(2); //allow the cpu to switch to other tasks +} diff --git a/libraries/WebServer/examples/Filters/ci.json b/libraries/WebServer/examples/Filters/ci.json new file mode 100644 index 00000000000..618e46bd244 --- /dev/null +++ b/libraries/WebServer/examples/Filters/ci.json @@ -0,0 +1,6 @@ +{ + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] +} diff --git a/libraries/WebServer/examples/HelloServer/ci.json b/libraries/WebServer/examples/HelloServer/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/HelloServer/ci.json +++ b/libraries/WebServer/examples/HelloServer/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/HttpAdvancedAuth/ci.json b/libraries/WebServer/examples/HttpAdvancedAuth/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/HttpAdvancedAuth/ci.json +++ b/libraries/WebServer/examples/HttpAdvancedAuth/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/HttpAuthCallback/HttpAuthCallback.ino b/libraries/WebServer/examples/HttpAuthCallback/HttpAuthCallback.ino index f164429cae9..0d3bca1a720 100644 --- a/libraries/WebServer/examples/HttpAuthCallback/HttpAuthCallback.ino +++ b/libraries/WebServer/examples/HttpAuthCallback/HttpAuthCallback.ino @@ -29,9 +29,7 @@ String *credentialsHandler(HTTPAuthMethod mode, String username, String params[] void setup() { Serial.begin(115200); - while (!Serial) { - delay(10); - } + WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); if (WiFi.waitForConnectResult() != WL_CONNECTED) { diff --git a/libraries/WebServer/examples/HttpAuthCallback/ci.json b/libraries/WebServer/examples/HttpAuthCallback/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/HttpAuthCallback/ci.json +++ b/libraries/WebServer/examples/HttpAuthCallback/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/HttpAuthCallbackInline/HttpAuthCallbackInline.ino b/libraries/WebServer/examples/HttpAuthCallbackInline/HttpAuthCallbackInline.ino index 48cbaa93dac..bcf78a9ce65 100644 --- a/libraries/WebServer/examples/HttpAuthCallbackInline/HttpAuthCallbackInline.ino +++ b/libraries/WebServer/examples/HttpAuthCallbackInline/HttpAuthCallbackInline.ino @@ -9,17 +9,15 @@ const char *password = "........"; WebServer server(80); typedef struct credentials_t { - char *username; - char *password; + const char *username; + const char *password; } credentials_t; credentials_t passwdfile[] = {{"admin", "esp32"}, {"fred", "41234123"}, {"charlie", "sdfsd"}, {"alice", "vambdnkuhj"}, {"bob", "svcdbjhws12"}, {NULL, NULL}}; void setup() { Serial.begin(115200); - while (!Serial) { - delay(10); - } + WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); if (WiFi.waitForConnectResult() != WL_CONNECTED) { diff --git a/libraries/WebServer/examples/HttpAuthCallbackInline/ci.json b/libraries/WebServer/examples/HttpAuthCallbackInline/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/HttpAuthCallbackInline/ci.json +++ b/libraries/WebServer/examples/HttpAuthCallbackInline/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/HttpBasicAuth/ci.json b/libraries/WebServer/examples/HttpBasicAuth/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/HttpBasicAuth/ci.json +++ b/libraries/WebServer/examples/HttpBasicAuth/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/HttpBasicAuthSHA1/HttpBasicAuthSHA1.ino b/libraries/WebServer/examples/HttpBasicAuthSHA1/HttpBasicAuthSHA1.ino index aff5da272d4..643a05380e9 100644 --- a/libraries/WebServer/examples/HttpBasicAuthSHA1/HttpBasicAuthSHA1.ino +++ b/libraries/WebServer/examples/HttpBasicAuthSHA1/HttpBasicAuthSHA1.ino @@ -31,9 +31,7 @@ const char *www_password_base64 = "jLEk+MJ3wW7Asu4AVp/RUaCONCs="; void setup() { Serial.begin(115200); - while (!Serial) { - delay(10); - } + WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); if (WiFi.waitForConnectResult() != WL_CONNECTED) { diff --git a/libraries/WebServer/examples/HttpBasicAuthSHA1/ci.json b/libraries/WebServer/examples/HttpBasicAuthSHA1/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/HttpBasicAuthSHA1/ci.json +++ b/libraries/WebServer/examples/HttpBasicAuthSHA1/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/HttpBasicAuthSHA1orBearerToken/HttpBasicAuthSHA1orBearerToken.ino b/libraries/WebServer/examples/HttpBasicAuthSHA1orBearerToken/HttpBasicAuthSHA1orBearerToken.ino index 968741114fb..89933a4ddb2 100644 --- a/libraries/WebServer/examples/HttpBasicAuthSHA1orBearerToken/HttpBasicAuthSHA1orBearerToken.ino +++ b/libraries/WebServer/examples/HttpBasicAuthSHA1orBearerToken/HttpBasicAuthSHA1orBearerToken.ino @@ -78,9 +78,7 @@ String *check_bearer_or_auth(HTTPAuthMethod mode, String authReq, String params[ void setup() { Serial.begin(115200); - while (!Serial) { - delay(10); - } + WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); if (WiFi.waitForConnectResult() != WL_CONNECTED) { diff --git a/libraries/WebServer/examples/HttpBasicAuthSHA1orBearerToken/ci.json b/libraries/WebServer/examples/HttpBasicAuthSHA1orBearerToken/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/HttpBasicAuthSHA1orBearerToken/ci.json +++ b/libraries/WebServer/examples/HttpBasicAuthSHA1orBearerToken/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/Middleware/Middleware.ino b/libraries/WebServer/examples/Middleware/Middleware.ino new file mode 100644 index 00000000000..9d957341c2d --- /dev/null +++ b/libraries/WebServer/examples/Middleware/Middleware.ino @@ -0,0 +1,186 @@ +/** + * Basic example of using Middlewares with WebServer + * + * Middleware are common request/response processing functions that can be applied globally to all incoming requests or to specific handlers. + * They allow for a common processing thus saving memory and space to avoid duplicating code or states on multiple handlers. + * + * Once the example is flashed (with the correct WiFi credentials), you can test the following scenarios with the listed curl commands: + * - CORS Middleware: answers to OPTIONS requests with the specified CORS headers and also add CORS headers to the response when the request has the Origin header + * - Logging Middleware: logs the request and response to an output in a curl-like format + * - Authentication Middleware: test the authentication with Digest Auth + * + * You can also add your own Middleware by extending the Middleware class and implementing the run method. + * When implementing a Middleware, you can decide when to call the next Middleware in the chain by calling next(). + * + * Middleware are execute in order of addition, the ones attached to the server will be executed first. + */ +#include +#include +#include + +// Your AP WiFi Credentials +// ( This is the AP your ESP will broadcast ) +const char *ap_ssid = "ESP32_Demo"; +const char *ap_password = ""; + +WebServer server(80); + +LoggingMiddleware logger; +CorsMiddleware cors; +AuthenticationMiddleware auth; + +void setup(void) { + Serial.begin(115200); + WiFi.softAP(ap_ssid, ap_password); + + Serial.print("IP address: "); + Serial.println(WiFi.AP.localIP()); + + // curl-like output example: + // + // > curl -v -X OPTIONS -H "origin: http://192.168.4.1" http://192.168.4.1/ + // + // Connection from 192.168.4.2:51683 + // > OPTIONS / HTTP/1.1 + // > Host: 192.168.4.1 + // > User-Agent: curl/8.10.0 + // > Accept: */* + // > origin: http://192.168.4.1 + // > + // * Processed in 5 ms + // < HTTP/1.HTTP/1.1 200 OK + // < Content-Type: text/html + // < Access-Control-Allow-Origin: http://192.168.4.1 + // < Access-Control-Allow-Methods: POST,GET,OPTIONS,DELETE + // < Access-Control-Allow-Headers: X-Custom-Header + // < Access-Control-Allow-Credentials: false + // < Access-Control-Max-Age: 600 + // < Content-Length: 0 + // < Connection: close + // < + logger.setOutput(Serial); + + cors.setOrigin("http://192.168.4.1"); + cors.setMethods("POST,GET,OPTIONS,DELETE"); + cors.setHeaders("X-Custom-Header"); + cors.setAllowCredentials(false); + cors.setMaxAge(600); + + auth.setUsername("admin"); + auth.setPassword("admin"); + auth.setRealm("My Super App"); + auth.setAuthMethod(DIGEST_AUTH); + auth.setAuthFailureMessage("Authentication Failed"); + + server.addMiddleware(&logger); + server.addMiddleware(&cors); + + // Not authenticated + // + // Test CORS preflight request with: + // > curl -v -X OPTIONS -H "origin: http://192.168.4.1" http://192.168.4.1/ + // + // Test cross-domain request with: + // > curl -v -X GET -H "origin: http://192.168.4.1" http://192.168.4.1/ + // + server.on("/", []() { + server.send(200, "text/plain", "Home"); + }); + + // Authenticated + // + // > curl -v -X GET -H "origin: http://192.168.4.1" http://192.168.4.1/protected + // + // Outputs: + // + // * Connection from 192.168.4.2:51750 + // > GET /protected HTTP/1.1 + // > Host: 192.168.4.1 + // > User-Agent: curl/8.10.0 + // > Accept: */* + // > origin: http://192.168.4.1 + // > + // * Processed in 7 ms + // < HTTP/1.HTTP/1.1 401 Unauthorized + // < Content-Type: text/html + // < Access-Control-Allow-Origin: http://192.168.4.1 + // < Access-Control-Allow-Methods: POST,GET,OPTIONS,DELETE + // < Access-Control-Allow-Headers: X-Custom-Header + // < Access-Control-Allow-Credentials: false + // < Access-Control-Max-Age: 600 + // < WWW-Authenticate: Digest realm="My Super App", qop="auth", nonce="ac388a64184e3e102aae6fff1c9e8d76", opaque="e7d158f2b54d25328142d118ff0f932d" + // < Content-Length: 21 + // < Connection: close + // < + // + // > curl -v -X GET -H "origin: http://192.168.4.1" --digest -u admin:admin http://192.168.4.1/protected + // + // Outputs: + // + // * Connection from 192.168.4.2:53662 + // > GET /protected HTTP/1.1 + // > Authorization: Digest username="admin", realm="My Super App", nonce="db9e6824eb2a13bc7b2bf8f3c43db896", uri="/protected", cnonce="NTliZDZiNTcwODM2MzAyY2JjMDBmZGJmNzFiY2ZmNzk=", nc=00000001, qop=auth, response="6ebd145ba0d3496a4a73f5ae79ff5264", opaque="23d739c22810282ff820538cba98bda4" + // > Host: 192.168.4.1 + // > User-Agent: curl/8.10.0 + // > Accept: */* + // > origin: http://192.168.4.1 + // > + // Request handling... + // * Processed in 7 ms + // < HTTP/1.HTTP/1.1 200 OK + // < Content-Type: text/plain + // < Access-Control-Allow-Origin: http://192.168.4.1 + // < Access-Control-Allow-Methods: POST,GET,OPTIONS,DELETE + // < Access-Control-Allow-Headers: X-Custom-Header + // < Access-Control-Allow-Credentials: false + // < Access-Control-Max-Age: 600 + // < Content-Length: 9 + // < Connection: close + // < + server + .on( + "/protected", + []() { + Serial.println("Request handling..."); + server.send(200, "text/plain", "Protected"); + } + ) + .addMiddleware(&auth); + + // Not found is also handled by global middleware + // + // curl -v -X GET -H "origin: http://192.168.4.1" http://192.168.4.1/inexsting + // + // Outputs: + // + // * Connection from 192.168.4.2:53683 + // > GET /inexsting HTTP/1.1 + // > Host: 192.168.4.1 + // > User-Agent: curl/8.10.0 + // > Accept: */* + // > origin: http://192.168.4.1 + // > + // * Processed in 16 ms + // < HTTP/1.HTTP/1.1 404 Not Found + // < Content-Type: text/plain + // < Access-Control-Allow-Origin: http://192.168.4.1 + // < Access-Control-Allow-Methods: POST,GET,OPTIONS,DELETE + // < Access-Control-Allow-Headers: X-Custom-Header + // < Access-Control-Allow-Credentials: false + // < Access-Control-Max-Age: 600 + // < Content-Length: 14 + // < Connection: close + // < + server.onNotFound([]() { + server.send(404, "text/plain", "Page not found"); + }); + + server.collectAllHeaders(); + server.begin(); + Serial.println("HTTP server started"); +} + +void loop(void) { + server.handleClient(); + delay(2); //allow the cpu to switch to other tasks +} diff --git a/libraries/WebServer/examples/Middleware/ci.json b/libraries/WebServer/examples/Middleware/ci.json new file mode 100644 index 00000000000..36babb82730 --- /dev/null +++ b/libraries/WebServer/examples/Middleware/ci.json @@ -0,0 +1,5 @@ +{ + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] +} diff --git a/libraries/WebServer/examples/MultiHomedServers/MultiHomedServers.ino b/libraries/WebServer/examples/MultiHomedServers/MultiHomedServers.ino index cc9f15dbd5e..300a651e3b1 100644 --- a/libraries/WebServer/examples/MultiHomedServers/MultiHomedServers.ino +++ b/libraries/WebServer/examples/MultiHomedServers/MultiHomedServers.ino @@ -66,9 +66,7 @@ void setup(void) { pinMode(led, OUTPUT); digitalWrite(led, 0); Serial.begin(115200); - while (!Serial) { - delay(100); - } + Serial.println("Multi-homed Servers example starting"); delay(1000); WiFi.mode(WIFI_STA); diff --git a/libraries/WebServer/examples/MultiHomedServers/README.md b/libraries/WebServer/examples/MultiHomedServers/README.md index bf5f7dfd18a..04b96dfbd53 100644 --- a/libraries/WebServer/examples/MultiHomedServers/README.md +++ b/libraries/WebServer/examples/MultiHomedServers/README.md @@ -2,7 +2,7 @@ This example tests support for multi-homed servers, i.e. a distinct web servers on distinct IP interface. -It only tests the case n=2 because on a basic ESP32 device, we only have two IP interfaces, namely the WiFi station interfaces and the WiFi soft AP interface. +It only tests the case n=2 because on a basic ESP32 device, we only have two IP interfaces, namely the Wi-Fi station interfaces and the Wi-Fi soft AP interface. For this to work, the WebServer and the NetworkServer classes must correctly handle the case where an IP address is passed to their relevant constructor. It also requires WebServer to work with multiple, simultaneous instances. @@ -55,7 +55,7 @@ Currently, this example supports the following targets. ## How to Use Example -Change the SSID and password in the example to your WiFi and flash the example. +Change the SSID and password in the example to your Wi-Fi and flash the example. Open a serial terminal and the example will write the exact addresses with used IP addresses you can use to test the servers. * How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide). @@ -67,10 +67,6 @@ To get more information about the Espressif boards see [Espressif Development Ki * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file. - ## Example Log Output ``` diff --git a/libraries/WebServer/examples/MultiHomedServers/ci.json b/libraries/WebServer/examples/MultiHomedServers/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/MultiHomedServers/ci.json +++ b/libraries/WebServer/examples/MultiHomedServers/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/PathArgServer/ci.json b/libraries/WebServer/examples/PathArgServer/ci.json index d8b3664bc65..cbdd28f773d 100644 --- a/libraries/WebServer/examples/PathArgServer/ci.json +++ b/libraries/WebServer/examples/PathArgServer/ci.json @@ -1,5 +1,7 @@ { - "targets": { - "esp32h2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/SDWebServer/ci.json b/libraries/WebServer/examples/SDWebServer/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/SDWebServer/ci.json +++ b/libraries/WebServer/examples/SDWebServer/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/SimpleAuthentification/ci.json b/libraries/WebServer/examples/SimpleAuthentification/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/SimpleAuthentification/ci.json +++ b/libraries/WebServer/examples/SimpleAuthentification/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/UploadHugeFile/UploadHugeFile.ino b/libraries/WebServer/examples/UploadHugeFile/UploadHugeFile.ino index 030ac09d129..54c94ed61d8 100644 --- a/libraries/WebServer/examples/UploadHugeFile/UploadHugeFile.ino +++ b/libraries/WebServer/examples/UploadHugeFile/UploadHugeFile.ino @@ -1,5 +1,4 @@ #include -#include #include #include #include diff --git a/libraries/WebServer/examples/UploadHugeFile/ci.json b/libraries/WebServer/examples/UploadHugeFile/ci.json index d8b3664bc65..cbdd28f773d 100644 --- a/libraries/WebServer/examples/UploadHugeFile/ci.json +++ b/libraries/WebServer/examples/UploadHugeFile/ci.json @@ -1,5 +1,7 @@ { - "targets": { - "esp32h2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/WebServer/README.md b/libraries/WebServer/examples/WebServer/README.md index 2af4e379433..b316682845f 100644 --- a/libraries/WebServer/examples/WebServer/README.md +++ b/libraries/WebServer/examples/WebServer/README.md @@ -4,11 +4,11 @@ This example shows different techniques on how to use and extend the WebServer f It is a small project in it's own and has some files to use on the web server to show how to use simple REST based services. -This example requires some space for a filesystem and runs fine boards with 4 MByte flash using the following options: +This example requires some space for a filesystem and runs fine on supported SoCs with 4 MByte or more flash by selecting the proper partition table: + +* For using SPIFFS(LittleFS): `Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)` +* For using FATFS: `Default 4MB with ffat (1.2MB APP/1.5MB FATFS)` -* Board: ESP32 Dev Module -* Partition Scheme: Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) - but LittleFS will be used in the partition (not SPIFFS) It features @@ -28,15 +28,15 @@ It features Currently, this example supports the following targets. -| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | -| ----------------- | ----- | -------- | -------- | -| | yes | yes | yes | +| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 | ESP32-C3 | ESP32-C6 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | +| | yes | yes | yes | yes | yes | ## Use the Example How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide). -* In the file `secrets.h` you can add the home WiFi network name ans password. +* In the file `secrets.h` you can add the home Wi-Fi network name ans password. * Compile and upload to the device. * Have a look into the monitoring output. * Open or using a browser. @@ -56,9 +56,9 @@ It offers plug-in capabilities by registering specific functionalities that will In the setup() function in the webserver.ino sketch file the following steps are implemented to make the webserver available on the local network. -* Create a webserver listening to port 80 for http requests. +* Create a webserver listening to port 80 for HTTP requests. * Initialize the access to the filesystem in the free flash memory. -* Connect to the local WiFi network. Here is only a straight-forward implementation hard-coding network name and passphrase. You may consider to use something like the WiFiManager library in real applications. +* Connect to the local Wi-Fi network. Here is only a straight-forward implementation hard-coding network name and passphrase. You may consider to use something like the WiFiManager library in real applications. * Register the device in DNS using a known hostname. * Registering several plug-ins (see below). * Starting the web server. @@ -200,6 +200,7 @@ This class has to implements several functions and works in a more detailed way: * The `canUpload()`and `upload()` methods work similar while the `upload()` method is called multiple times to create, append data and close the new file. + ## File upload By opening you can easily upload files by dragging them over the drop area. @@ -238,6 +239,7 @@ You can see on the Serial output that one filesystem write error is reported. Please be patient and wait for the upload ending even when writing to the filesystem is disabled it maybe take more than a minute. + ## Registering a special handler for "file not found" Any other incoming request that was not handled by the registered plug-ins above can be detected by registering @@ -253,6 +255,7 @@ Any other incoming request that was not handled by the registered plug-ins above This allows sending back an "friendly" result for the browser. Here a simple html page is created from a static string. You can easily change the html code in the file `builtinfiles.h`. + ## customizations You may like to change the hostname and the timezone in the lines: @@ -262,10 +265,18 @@ You may like to change the hostname and the timezone in the lines: > #define TIMEZONE "CET-1CEST,M3.5.0,M10.5.0/3" > ``` + ## Troubleshooting Have a look in the Serial output for some additional runtime information. + +## Changes + +* 2024-08-02 -- Fixing for board implementation 3.0.4 ff. +* 2024-08-02 -- Support for FAT + + ## Contribute To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) @@ -274,11 +285,13 @@ If you have any **feedback** or **issue** to report on this example/library, ple 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 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) * ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) +* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) * ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) * Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/WebServer/examples/WebServer/WebServer.ino b/libraries/WebServer/examples/WebServer/WebServer.ino index 5757c09cbae..809a95ce1f3 100644 --- a/libraries/WebServer/examples/WebServer/WebServer.ino +++ b/libraries/WebServer/examples/WebServer/WebServer.ino @@ -18,14 +18,15 @@ // // Please use the following Arduino IDE configuration // -// * Board: ESP32 Dev Module -// * Partition Scheme: Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +// * Board: "ESP32 Dev Module" or other board with ESP32 +// * Partition Scheme: "Default 4MB with spiffs" or any other scheme with spiffs or FAT // but LittleFS will be used in the partition (not SPIFFS) // * other setting as applicable // // Changelog: // 21.07.2021 creation, first version // 08.01.2023 ESP32 version with ETag +// 02.08.2024 support LitteFS and FAT file systems (on large Flash chips) #include #include @@ -33,8 +34,11 @@ #include "secrets.h" // add WLAN Credentials in here. +#include "esp_partition.h" // to check existing data partitions in Flash memory + #include // File System for Web Server Files -#include // This file system is used. +#include // Use LittleFSThis file system is used. +#include // or.. FAT // mark parameters not used in example #define UNUSED __attribute__((unused)) @@ -51,6 +55,9 @@ // need a WebServer for http access on port 80. WebServer server(80); +// The file system in use... +fs::FS *fsys = nullptr; + // The text of builtin files are in this header file #include "builtinfiles.h" @@ -65,7 +72,7 @@ void handleRedirect() { TRACE("Redirect...\n"); String url = "/index.htm"; - if (!LittleFS.exists(url)) { + if (!fsys->exists(url)) { url = "/$upload.htm"; } @@ -76,7 +83,7 @@ void handleRedirect() { // This function is called when the WebServer was requested to list all existing files in the filesystem. // a JSON array with file information is returned. void handleListFiles() { - File dir = LittleFS.open("/", "r"); + File dir = fsys->open("/", "r"); String result; result += "[\n"; @@ -107,8 +114,15 @@ void handleSysInfo() { result += " \"Chip Revision\": " + String(ESP.getChipRevision()) + ",\n"; result += " \"flashSize\": " + String(ESP.getFlashChipSize()) + ",\n"; result += " \"freeHeap\": " + String(ESP.getFreeHeap()) + ",\n"; - result += " \"fsTotalBytes\": " + String(LittleFS.totalBytes()) + ",\n"; - result += " \"fsUsedBytes\": " + String(LittleFS.usedBytes()) + ",\n"; + + if (fsys == (fs::FS *)&FFat) { + result += " \"fsTotalBytes\": " + String(FFat.totalBytes()) + ",\n"; + result += " \"fsUsedBytes\": " + String(FFat.usedBytes()) + ",\n"; + } else { + result += " \"fsTotalBytes\": " + String(LittleFS.totalBytes()) + ",\n"; + result += " \"fsUsedBytes\": " + String(LittleFS.usedBytes()) + ",\n"; + } + result += "}"; server.sendHeader("Cache-Control", "no-cache"); @@ -132,31 +146,29 @@ public: // @param requestMethod method of the http request line. // @param requestUri request resource from the http request line. // @return true when method can be handled. - bool canHandle(HTTPMethod requestMethod, String UNUSED uri) override { + bool canHandle(WebServer &server, HTTPMethod requestMethod, const String &uri) override { return ((requestMethod == HTTP_POST) || (requestMethod == HTTP_DELETE)); } // canHandle() - bool canUpload(String uri) override { + bool canUpload(WebServer &server, const String &uri) override { // only allow upload on root fs level. return (uri == "/"); } // canUpload() - bool handle(WebServer &server, HTTPMethod requestMethod, String requestUri) override { + bool handle(WebServer &server, HTTPMethod requestMethod, const String &requestUri) override { // ensure that filename starts with '/' String fName = requestUri; if (!fName.startsWith("/")) { fName = "/" + fName; } - TRACE("handle %s\n", fName.c_str()); - if (requestMethod == HTTP_POST) { // all done in upload. no other forms. } else if (requestMethod == HTTP_DELETE) { - if (LittleFS.exists(fName)) { + if (fsys->exists(fName)) { TRACE("DELETE %s\n", fName.c_str()); - LittleFS.remove(fName); + fsys->remove(fName); } } // if @@ -165,7 +177,7 @@ public: } // handle() // uploading process - void upload(WebServer UNUSED &server, String UNUSED _requestUri, HTTPUpload &upload) override { + void upload(WebServer UNUSED &server, const String &requestUri, HTTPUpload &upload) override { // ensure that filename starts with '/' static size_t uploadSize; @@ -178,10 +190,10 @@ public: } TRACE("start uploading file %s...\n", fName.c_str()); - if (LittleFS.exists(fName)) { - LittleFS.remove(fName); + if (fsys->exists(fName)) { + fsys->remove(fName); } // if - _fsUploadFile = LittleFS.open(fName, "w"); + _fsUploadFile = fsys->open(fName, "w"); uploadSize = 0; } else if (upload.status == UPLOAD_FILE_WRITE) { @@ -198,7 +210,7 @@ public: if (!fName.startsWith("/")) { fName = "/" + fName; } - LittleFS.remove(fName); + fsys->remove(fName); } uploadSize += upload.currentSize; // TRACE("free:: %d of %d\n", LittleFS.usedBytes(), LittleFS.totalBytes()); @@ -207,7 +219,7 @@ public: } // if } else if (upload.status == UPLOAD_FILE_END) { - TRACE("finished.\n"); + TRACE("upload done.\n"); // Close the file if (_fsUploadFile) { _fsUploadFile.close(); @@ -231,14 +243,49 @@ void setup(void) { TRACE("Starting WebServer example...\n"); + // ----- check partitions for finding the filesystem type ----- + esp_partition_iterator_t i; + + i = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, nullptr); + if (i) { + TRACE("FAT partition found."); + fsys = &FFat; + + } else { + i = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, nullptr); + if (i) { + TRACE("SPIFFS partition found."); + fsys = &LittleFS; + + } else { + TRACE("no partition found."); + } + } + esp_partition_iterator_release(i); + + // mount and format as needed TRACE("Mounting the filesystem...\n"); - if (!LittleFS.begin()) { + if (!fsys) { + TRACE("need to change the board configuration to include a partition for files.\n"); + delay(30000); + + } else if ((fsys == (fs::FS *)&FFat) && (!FFat.begin())) { + TRACE("could not mount the filesystem...\n"); + delay(2000); + TRACE("formatting FAT...\n"); + FFat.format(); + delay(2000); + TRACE("restarting...\n"); + delay(2000); + ESP.restart(); + + } else if ((fsys == (fs::FS *)&LittleFS) && (!LittleFS.begin())) { TRACE("could not mount the filesystem...\n"); delay(2000); - TRACE("formatting...\n"); + TRACE("formatting LittleFS...\n"); LittleFS.format(); delay(2000); - TRACE("restart.\n"); + TRACE("restarting...\n"); delay(2000); ESP.restart(); } @@ -286,7 +333,7 @@ void setup(void) { // UPLOAD and DELETE of files in the file system using a request handler. server.addHandler(new FileServerHandler()); - // // enable CORS header in webserver results + // enable CORS header in webserver results server.enableCORS(true); // enable ETAG header in webserver results (used by serveStatic handler) @@ -306,7 +353,7 @@ void setup(void) { #endif // serve all static files - server.serveStatic("/", LittleFS, "/"); + server.serveStatic("/", *fsys, "/"); TRACE("Register default (not found) answer...\n"); diff --git a/libraries/WebServer/examples/WebServer/ci.json b/libraries/WebServer/examples/WebServer/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/WebServer/ci.json +++ b/libraries/WebServer/examples/WebServer/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/examples/WebUpdate/ci.json b/libraries/WebServer/examples/WebUpdate/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WebServer/examples/WebUpdate/ci.json +++ b/libraries/WebServer/examples/WebUpdate/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WebServer/library.properties b/libraries/WebServer/library.properties index 1942ca42da7..2a9ff530d57 100644 --- a/libraries/WebServer/library.properties +++ b/libraries/WebServer/library.properties @@ -1,5 +1,5 @@ name=WebServer -version=2.0.0 +version=3.2.0 author=Ivan Grokhotkov maintainer=Ivan Grokhtkov sentence=Simple web server library diff --git a/libraries/WebServer/src/Middlewares.h b/libraries/WebServer/src/Middlewares.h new file mode 100644 index 00000000000..04fab52790b --- /dev/null +++ b/libraries/WebServer/src/Middlewares.h @@ -0,0 +1,66 @@ +#ifndef MIDDLEWARES_H +#define MIDDLEWARES_H + +#include +#include + +#include + +// curl-like logging middleware +class LoggingMiddleware : public Middleware { +public: + void setOutput(Print &output); + + bool run(WebServer &server, Middleware::Callback next) override; + +private: + Print *_out = nullptr; +}; + +class CorsMiddleware : public Middleware { +public: + CorsMiddleware &setOrigin(const char *origin); + CorsMiddleware &setMethods(const char *methods); + CorsMiddleware &setHeaders(const char *headers); + CorsMiddleware &setAllowCredentials(bool credentials); + CorsMiddleware &setMaxAge(uint32_t seconds); + + void addCORSHeaders(WebServer &server); + + bool run(WebServer &server, Middleware::Callback next) override; + +private: + String _origin = F("*"); + String _methods = F("*"); + String _headers = F("*"); + bool _credentials = true; + uint32_t _maxAge = 86400; +}; + +class AuthenticationMiddleware : public Middleware { +public: + AuthenticationMiddleware &setUsername(const char *username); + AuthenticationMiddleware &setPassword(const char *password); + AuthenticationMiddleware &setPasswordHash(const char *sha1AsBase64orHex); + AuthenticationMiddleware &setCallback(WebServer::THandlerFunctionAuthCheck fn); + + AuthenticationMiddleware &setRealm(const char *realm); + AuthenticationMiddleware &setAuthMethod(HTTPAuthMethod method); + AuthenticationMiddleware &setAuthFailureMessage(const char *message); + + bool isAllowed(WebServer &server) const; + + bool run(WebServer &server, Middleware::Callback next) override; + +private: + String _username; + String _password; + bool _hash = false; + WebServer::THandlerFunctionAuthCheck _callback; + + const char *_realm = nullptr; + HTTPAuthMethod _method = BASIC_AUTH; + String _authFailMsg; +}; + +#endif diff --git a/libraries/WebServer/src/Parsing.cpp b/libraries/WebServer/src/Parsing.cpp index 3d3e7d1c55a..3030317eeea 100644 --- a/libraries/WebServer/src/Parsing.cpp +++ b/libraries/WebServer/src/Parsing.cpp @@ -78,8 +78,14 @@ bool WebServer::_parseRequest(NetworkClient &client) { String req = client.readStringUntil('\r'); client.readStringUntil('\n'); //reset header value - for (int i = 0; i < _headerKeysCount; ++i) { - _currentHeaders[i].value = String(); + if (_collectAllHeaders) { + // clear previous headers + collectAllHeaders(); + } else { + // clear previous headers + for (RequestArgument *header = _currentHeaders; header; header = header->next) { + header->value = String(); + } } // First line of HTTP request looks like "GET /path HTTP/1.1" @@ -124,7 +130,7 @@ bool WebServer::_parseRequest(NetworkClient &client) { //attach handler RequestHandler *handler; for (handler = _firstHandler; handler; handler = handler->next()) { - if (handler->canHandle(_currentMethod, _currentUri)) { + if (handler->canHandle(*this, _currentMethod, _currentUri)) { break; } } @@ -154,9 +160,6 @@ bool WebServer::_parseRequest(NetworkClient &client) { headerValue.trim(); _collectHeader(headerName.c_str(), headerValue.c_str()); - log_v("headerName: %s", headerName.c_str()); - log_v("headerValue: %s", headerValue.c_str()); - if (headerName.equalsIgnoreCase(FPSTR(Content_Type))) { using namespace mime; if (headerValue.startsWith(FPSTR(mimeTable[txt].mimeType))) { @@ -176,7 +179,7 @@ bool WebServer::_parseRequest(NetworkClient &client) { } } - if (!isForm && _currentHandler && _currentHandler->canRaw(_currentUri)) { + if (!isForm && _currentHandler && _currentHandler->canRaw(*this, _currentUri)) { log_v("Parse raw"); _currentRaw.reset(new HTTPRaw()); _currentRaw->status = RAW_START; @@ -187,7 +190,8 @@ bool WebServer::_parseRequest(NetworkClient &client) { _currentRaw->status = RAW_WRITE; while (_currentRaw->totalSize < _clientContentLength) { - _currentRaw->currentSize = client.readBytes(_currentRaw->buf, HTTP_RAW_BUFLEN); + size_t read_len = std::min(_clientContentLength - _currentRaw->totalSize, (size_t)HTTP_RAW_BUFLEN); + _currentRaw->currentSize = client.readBytes(_currentRaw->buf, read_len); _currentRaw->totalSize += _currentRaw->currentSize; if (_currentRaw->currentSize == 0) { _currentRaw->status = RAW_ABORTED; @@ -253,16 +257,13 @@ bool WebServer::_parseRequest(NetworkClient &client) { headerValue = req.substring(headerDiv + 2); _collectHeader(headerName.c_str(), headerValue.c_str()); - log_v("headerName: %s", headerName.c_str()); - log_v("headerValue: %s", headerValue.c_str()); - if (headerName.equalsIgnoreCase("Host")) { _hostHeader = headerValue; } } _parseArguments(searchStr); } - client.flush(); + client.clear(); log_v("Request: %s", url.c_str()); log_v(" Arguments: %s", searchStr.c_str()); @@ -271,16 +272,33 @@ bool WebServer::_parseRequest(NetworkClient &client) { } bool WebServer::_collectHeader(const char *headerName, const char *headerValue) { - for (int i = 0; i < _headerKeysCount; i++) { - if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) { - _currentHeaders[i].value = headerValue; + RequestArgument *last = nullptr; + for (RequestArgument *header = _currentHeaders; header; header = header->next) { + if (header->next == nullptr) { + last = header; + } + if (header->key.equalsIgnoreCase(headerName)) { + header->value = headerValue; + log_v("header collected: %s: %s", headerName, headerValue); return true; } } + assert(last); + if (_collectAllHeaders) { + last->next = new RequestArgument(); + last->next->key = headerName; + last->next->value = headerValue; + _headerKeysCount++; + log_v("header collected: %s: %s", headerName, headerValue); + return true; + } + + log_v("header skipped: %s: %s", headerName, headerValue); + return false; } -void WebServer::_parseArguments(String data) { +void WebServer::_parseArguments(const String &data) { log_v("args: %s", data.c_str()); if (_currentArgs) { delete[] _currentArgs; @@ -334,7 +352,7 @@ void WebServer::_parseArguments(String data) { void WebServer::_uploadWriteByte(uint8_t b) { if (_currentUpload->currentSize == HTTP_UPLOAD_BUFLEN) { - if (_currentHandler && _currentHandler->canUpload(_currentUri)) { + if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) { _currentHandler->upload(*this, _currentUri, *_currentUpload); } _currentUpload->totalSize += _currentUpload->currentSize; @@ -347,17 +365,47 @@ int WebServer::_uploadReadByte(NetworkClient &client) { int res = client.read(); if (res < 0) { - while (!client.available() && client.connected()) { - delay(2); - } + // keep trying until you either read a valid byte or timeout + const unsigned long startMillis = millis(); + const long timeoutIntervalMillis = client.getTimeout(); + bool timedOut = false; + for (;;) { + if (!client.connected()) { + return -1; + } + // loosely modeled after blinkWithoutDelay pattern + while (!timedOut && !client.available() && client.connected()) { + delay(2); + timedOut = (millis() - startMillis) >= timeoutIntervalMillis; + } - res = client.read(); + res = client.read(); + if (res >= 0) { + return res; // exit on a valid read + } + // NOTE: it is possible to get here and have all of the following + // assertions hold true + // + // -- client.available() > 0 + // -- client.connected == true + // -- res == -1 + // + // a simple retry strategy overcomes this which is to say the + // assertion is not permanent, but the reason that this works + // is elusive, and possibly indicative of a more subtle underlying + // issue + + timedOut = (millis() - startMillis) >= timeoutIntervalMillis; + if (timedOut) { + return res; // exit on a timeout + } + } } return res; } -bool WebServer::_parseForm(NetworkClient &client, String boundary, uint32_t len) { +bool WebServer::_parseForm(NetworkClient &client, const String &boundary, uint32_t len) { (void)len; log_v("Parse Form: Boundary: %s Length: %d", boundary.c_str(), len); String line; @@ -449,7 +497,7 @@ bool WebServer::_parseForm(NetworkClient &client, String boundary, uint32_t len) _currentUpload->totalSize = 0; _currentUpload->currentSize = 0; log_v("Start File: %s Type: %s", _currentUpload->filename.c_str(), _currentUpload->type.c_str()); - if (_currentHandler && _currentHandler->canUpload(_currentUri)) { + if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) { _currentHandler->upload(*this, _currentUri, *_currentUpload); } _currentUpload->status = UPLOAD_FILE_WRITE; @@ -488,12 +536,12 @@ bool WebServer::_parseForm(NetworkClient &client, String boundary, uint32_t len) } } // Found the boundary string, finish processing this file upload - if (_currentHandler && _currentHandler->canUpload(_currentUri)) { + if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) { _currentHandler->upload(*this, _currentUri, *_currentUpload); } _currentUpload->totalSize += _currentUpload->currentSize; _currentUpload->status = UPLOAD_FILE_END; - if (_currentHandler && _currentHandler->canUpload(_currentUri)) { + if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) { _currentHandler->upload(*this, _currentUri, *_currentUpload); } log_v("End File: %s Type: %s Size: %d", _currentUpload->filename.c_str(), _currentUpload->type.c_str(), (int)_currentUpload->totalSize); @@ -567,7 +615,7 @@ String WebServer::urlDecode(const String &text) { bool WebServer::_parseFormUploadAborted() { _currentUpload->status = UPLOAD_FILE_ABORTED; - if (_currentHandler && _currentHandler->canUpload(_currentUri)) { + if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) { _currentHandler->upload(*this, _currentUri, *_currentUpload); } return false; diff --git a/libraries/WebServer/src/WebServer.cpp b/libraries/WebServer/src/WebServer.cpp index 83c22b7e493..652a86f587f 100644 --- a/libraries/WebServer/src/WebServer.cpp +++ b/libraries/WebServer/src/WebServer.cpp @@ -41,31 +41,28 @@ static const char WWW_Authenticate[] = "WWW-Authenticate"; static const char Content_Length[] = "Content-Length"; static const char ETAG_HEADER[] = "If-None-Match"; -WebServer::WebServer(IPAddress addr, int port) - : _corsEnabled(false), _server(addr, port), _currentMethod(HTTP_ANY), _currentVersion(0), _currentStatus(HC_NONE), _statusChange(0), _nullDelay(true), - _currentHandler(nullptr), _firstHandler(nullptr), _lastHandler(nullptr), _currentArgCount(0), _currentArgs(nullptr), _postArgsLen(0), _postArgs(nullptr), - _headerKeysCount(0), _currentHeaders(nullptr), _contentLength(0), _clientContentLength(0), _chunked(false) { +WebServer::WebServer(IPAddress addr, int port) : _server(addr, port) { log_v("WebServer::Webserver(addr=%s, port=%d)", addr.toString().c_str(), port); } -WebServer::WebServer(int port) - : _corsEnabled(false), _server(port), _currentMethod(HTTP_ANY), _currentVersion(0), _currentStatus(HC_NONE), _statusChange(0), _nullDelay(true), - _currentHandler(nullptr), _firstHandler(nullptr), _lastHandler(nullptr), _currentArgCount(0), _currentArgs(nullptr), _postArgsLen(0), _postArgs(nullptr), - _headerKeysCount(0), _currentHeaders(nullptr), _contentLength(0), _clientContentLength(0), _chunked(false) { +WebServer::WebServer(int port) : _server(port) { log_v("WebServer::Webserver(port=%d)", port); } WebServer::~WebServer() { _server.close(); - if (_currentHeaders) { - delete[] _currentHeaders; - } + + _clearRequestHeaders(); + _clearResponseHeaders(); + delete _chain; + RequestHandler *handler = _firstHandler; while (handler) { RequestHandler *next = handler->next(); delete handler; handler = next; } + _firstHandler = nullptr; } void WebServer::begin() { @@ -268,6 +265,7 @@ bool WebServer::authenticate(THandlerFunctionAuthCheck fn) { String *ret = fn(OTHER_AUTH, authReq, {}); if (ret) { log_v("Authentication Success"); + delete ret; return true; } } @@ -306,16 +304,18 @@ void WebServer::requestAuthentication(HTTPAuthMethod mode, const char *realm, co send(401, String(FPSTR(mimeTable[html].mimeType)), authFailMsg); } -void WebServer::on(const Uri &uri, WebServer::THandlerFunction handler) { - on(uri, HTTP_ANY, handler); +RequestHandler &WebServer::on(const Uri &uri, WebServer::THandlerFunction handler) { + return on(uri, HTTP_ANY, handler); } -void WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn) { - on(uri, method, fn, _fileUploadHandler); +RequestHandler &WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn) { + return on(uri, method, fn, _fileUploadHandler); } -void WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn) { - _addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method)); +RequestHandler &WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn) { + FunctionRequestHandler *handler = new FunctionRequestHandler(fn, ufn, uri, method); + _addRequestHandler(handler); + return *handler; } bool WebServer::removeRoute(const char *uri) { @@ -331,15 +331,28 @@ bool WebServer::removeRoute(const String &uri) { } bool WebServer::removeRoute(const String &uri, HTTPMethod method) { - // Loop through all request handlers and see if there is a match + bool anyHandlerRemoved = false; RequestHandler *handler = _firstHandler; + RequestHandler *previousHandler = nullptr; + while (handler) { if (handler->canHandle(method, uri)) { - return _removeRequestHandler(handler); + if (_removeRequestHandler(handler)) { + anyHandlerRemoved = true; + // Move to the next handler + if (previousHandler) { + handler = previousHandler->next(); + } else { + handler = _firstHandler; + } + continue; + } } + previousHandler = handler; handler = handler->next(); } - return false; + + return anyHandlerRemoved; } void WebServer::addHandler(RequestHandler *handler) { @@ -417,12 +430,20 @@ void WebServer::handleClient() { case HC_WAIT_READ: // Wait for data from client to become available if (_currentClient.available()) { + _currentClient.setTimeout(HTTP_MAX_SEND_WAIT); /* / 1000 removed, WifiClient setTimeout changed to ms */ if (_parseRequest(_currentClient)) { - // because HTTP_MAX_SEND_WAIT is expressed in milliseconds, - // it must be divided by 1000 - _currentClient.setTimeout(HTTP_MAX_SEND_WAIT); /* / 1000 removed, WifiClient setTimeout changed to ms */ _contentLength = CONTENT_LENGTH_NOT_SET; - _handleRequest(); + _responseCode = 0; + _clearResponseHeaders(); + + // Run server-level middlewares + if (_chain) { + _chain->runChain(*this, [this]() { + return _handleRequest(); + }); + } else { + _handleRequest(); + } if (_currentClient.isSSE()) { _currentStatus = HC_WAIT_CLOSE; @@ -481,16 +502,22 @@ void WebServer::stop() { } void WebServer::sendHeader(const String &name, const String &value, bool first) { - String headerLine = name; - headerLine += F(": "); - headerLine += value; - headerLine += "\r\n"; + RequestArgument *header = new RequestArgument(); + header->key = name; + header->value = value; - if (first) { - _responseHeaders = headerLine + _responseHeaders; + if (!_responseHeaders || first) { + header->next = _responseHeaders; + _responseHeaders = header; } else { - _responseHeaders += headerLine; + RequestArgument *last = _responseHeaders; + while (last->next) { + last = last->next; + } + last->next = header; } + + _responseHeaderCount++; } void WebServer::setContentLength(const size_t contentLength) { @@ -515,11 +542,14 @@ void WebServer::enableETag(bool enable, ETagFunction fn) { } void WebServer::_prepareHeader(String &response, int code, const char *content_type, size_t contentLength) { - response = String(F("HTTP/1.")) + String(_currentVersion) + ' '; - response += String(code); - response += ' '; - response += _responseCodeToString(code); - response += "\r\n"; + _responseCode = code; + + response.concat(version()); + response.concat(' '); + response.concat(String(code)); + response.concat(' '); + response.concat(responseCodeToString(code)); + response.concat(F("\r\n")); using namespace mime; if (!content_type) { @@ -544,9 +574,14 @@ void WebServer::_prepareHeader(String &response, int code, const char *content_t } sendHeader(String(F("Connection")), String(F("close"))); - response += _responseHeaders; - response += "\r\n"; - _responseHeaders = ""; + for (RequestArgument *header = _responseHeaders; header; header = header->next) { + response.concat(header->key); + response.concat(F(": ")); + response.concat(header->value); + response.concat(F("\r\n")); + } + + response.concat(F("\r\n")); } void WebServer::send(int code, const char *content_type, const String &content) { @@ -554,9 +589,6 @@ void WebServer::send(int code, const char *content_type, const String &content) // Can we assume the following? //if(code == 200 && content.length() == 0 && _contentLength == CONTENT_LENGTH_NOT_SET) // _contentLength = CONTENT_LENGTH_UNKNOWN; - if (content.length() == 0) { - log_w("content length is zero"); - } _prepareHeader(header, code, content_type, content.length()); _currentClientWrite(header.c_str(), header.length()); if (content.length()) { @@ -660,14 +692,14 @@ void WebServer::_streamFileCore(const size_t fileSize, const String &fileName, c send(code, contentType, ""); } -String WebServer::pathArg(unsigned int i) { +String WebServer::pathArg(unsigned int i) const { if (_currentHandler != nullptr) { return _currentHandler->pathArg(i); } return ""; } -String WebServer::arg(String name) { +String WebServer::arg(const String &name) const { for (int j = 0; j < _postArgsLen; ++j) { if (_postArgs[j].key == name) { return _postArgs[j].value; @@ -681,25 +713,25 @@ String WebServer::arg(String name) { return ""; } -String WebServer::arg(int i) { +String WebServer::arg(int i) const { if (i < _currentArgCount) { return _currentArgs[i].value; } return ""; } -String WebServer::argName(int i) { +String WebServer::argName(int i) const { if (i < _currentArgCount) { return _currentArgs[i].key; } return ""; } -int WebServer::args() { +int WebServer::args() const { return _currentArgCount; } -bool WebServer::hasArg(String name) { +bool WebServer::hasArg(const String &name) const { for (int j = 0; j < _postArgsLen; ++j) { if (_postArgs[j].key == name) { return true; @@ -713,56 +745,55 @@ bool WebServer::hasArg(String name) { return false; } -String WebServer::header(String name) { - for (int i = 0; i < _headerKeysCount; ++i) { - if (_currentHeaders[i].key.equalsIgnoreCase(name)) { - return _currentHeaders[i].value; +String WebServer::header(const String &name) const { + for (RequestArgument *current = _currentHeaders; current; current = current->next) { + if (current->key.equalsIgnoreCase(name)) { + return current->value; } } return ""; } void WebServer::collectHeaders(const char *headerKeys[], const size_t headerKeysCount) { - _headerKeysCount = headerKeysCount + 2; - if (_currentHeaders) { - delete[] _currentHeaders; - } - _currentHeaders = new RequestArgument[_headerKeysCount]; - _currentHeaders[0].key = FPSTR(AUTHORIZATION_HEADER); - _currentHeaders[1].key = FPSTR(ETAG_HEADER); + collectAllHeaders(); + _collectAllHeaders = false; + + _headerKeysCount += headerKeysCount; + + RequestArgument *last = _currentHeaders->next; + for (int i = 2; i < _headerKeysCount; i++) { - _currentHeaders[i].key = headerKeys[i - 2]; + last->next = new RequestArgument(); + last->next->key = headerKeys[i - 2]; + last = last->next; } } -String WebServer::header(int i) { - if (i < _headerKeysCount) { - return _currentHeaders[i].value; +String WebServer::header(int i) const { + RequestArgument *current = _currentHeaders; + while (current && i--) { + current = current->next; } - return ""; + return current ? current->value : emptyString; } -String WebServer::headerName(int i) { - if (i < _headerKeysCount) { - return _currentHeaders[i].key; +String WebServer::headerName(int i) const { + RequestArgument *current = _currentHeaders; + while (current && i--) { + current = current->next; } - return ""; + return current ? current->key : emptyString; } -int WebServer::headers() { +int WebServer::headers() const { return _headerKeysCount; } -bool WebServer::hasHeader(String name) { - for (int i = 0; i < _headerKeysCount; ++i) { - if ((_currentHeaders[i].key.equalsIgnoreCase(name)) && (_currentHeaders[i].value.length() > 0)) { - return true; - } - } - return false; +bool WebServer::hasHeader(const String &name) const { + return header(name).length() > 0; } -String WebServer::hostHeader() { +String WebServer::hostHeader() const { return _hostHeader; } @@ -774,16 +805,17 @@ void WebServer::onNotFound(THandlerFunction fn) { _notFoundHandler = fn; } -void WebServer::_handleRequest() { +bool WebServer::_handleRequest() { bool handled = false; - if (!_currentHandler) { - log_e("request handler not found"); - } else { - handled = _currentHandler->handle(*this, _currentMethod, _currentUri); + if (_currentHandler) { + handled = _currentHandler->process(*this, _currentMethod, _currentUri); if (!handled) { log_e("request handler failed to handle request"); } } + // DO NOT LOG if _currentHandler == null !! + // This is is valid use case to handle any other requests + // Also, this is just causing log flooding if (!handled && _notFoundHandler) { _notFoundHandler(); handled = true; @@ -797,6 +829,7 @@ void WebServer::_handleRequest() { _finalizeResponse(); } _currentUri = ""; + return handled; } void WebServer::_finalizeResponse() { @@ -805,7 +838,7 @@ void WebServer::_finalizeResponse() { } } -String WebServer::_responseCodeToString(int code) { +String WebServer::responseCodeToString(int code) { switch (code) { case 100: return F("Continue"); case 101: return F("Switching Protocols"); @@ -850,3 +883,108 @@ String WebServer::_responseCodeToString(int code) { default: return F(""); } } + +void WebServer::_clearResponseHeaders() { + _responseHeaderCount = 0; + RequestArgument *current = _responseHeaders; + while (current) { + RequestArgument *next = current->next; + delete current; + current = next; + } + _responseHeaders = nullptr; +} + +void WebServer::_clearRequestHeaders() { + _headerKeysCount = 0; + RequestArgument *current = _currentHeaders; + while (current) { + RequestArgument *next = current->next; + delete current; + current = next; + } + _currentHeaders = nullptr; +} + +void WebServer::collectAllHeaders() { + _clearRequestHeaders(); + + _currentHeaders = new RequestArgument(); + _currentHeaders->key = FPSTR(AUTHORIZATION_HEADER); + + _currentHeaders->next = new RequestArgument(); + _currentHeaders->next->key = FPSTR(ETAG_HEADER); + + _headerKeysCount = 2; + _collectAllHeaders = true; +} + +const String &WebServer::responseHeader(String name) const { + for (RequestArgument *current = _responseHeaders; current; current = current->next) { + if (current->key.equalsIgnoreCase(name)) { + return current->value; + } + } + return emptyString; +} + +const String &WebServer::responseHeader(int i) const { + RequestArgument *current = _responseHeaders; + while (current && i--) { + current = current->next; + } + return current ? current->value : emptyString; +} + +const String &WebServer::responseHeaderName(int i) const { + RequestArgument *current = _responseHeaders; + while (current && i--) { + current = current->next; + } + return current ? current->key : emptyString; +} + +bool WebServer::hasResponseHeader(const String &name) const { + return header(name).length() > 0; +} + +int WebServer::clientContentLength() const { + return _clientContentLength; +} + +const String WebServer::version() const { + String v; + v.reserve(8); + v.concat(F("HTTP/1.")); + v.concat(_currentVersion); + return v; +} +int WebServer::responseCode() const { + return _responseCode; +} +int WebServer::responseHeaders() const { + return _responseHeaderCount; +} + +WebServer &WebServer::addMiddleware(Middleware *middleware) { + if (!_chain) { + _chain = new MiddlewareChain(); + } + _chain->addMiddleware(middleware); + return *this; +} + +WebServer &WebServer::addMiddleware(Middleware::Function fn) { + if (!_chain) { + _chain = new MiddlewareChain(); + } + _chain->addMiddleware(fn); + return *this; +} + +WebServer &WebServer::removeMiddleware(Middleware *middleware) { + if (_chain) { + _chain->removeMiddleware(middleware); + } + return *this; +} diff --git a/libraries/WebServer/src/WebServer.h b/libraries/WebServer/src/WebServer.h index f69c08f22b6..8daf12c5c30 100644 --- a/libraries/WebServer/src/WebServer.h +++ b/libraries/WebServer/src/WebServer.h @@ -66,7 +66,7 @@ enum HTTPAuthMethod { #define HTTP_MAX_DATA_WAIT 5000 //ms to wait for the client to send the request #define HTTP_MAX_POST_WAIT 5000 //ms to wait for POST data to arrive #define HTTP_MAX_SEND_WAIT 5000 //ms to wait for data chunk to be ACKed -#define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection +#define HTTP_MAX_CLOSE_WAIT 5000 //ms to wait for the client to close the connection #define HTTP_MAX_BASIC_AUTH_LEN 256 // maximum length of a basic Auth base64 encoded username:password string #define CONTENT_LENGTH_UNKNOWN ((size_t) - 1) @@ -88,10 +88,11 @@ typedef struct { HTTPRawStatus status; size_t totalSize; // content size size_t currentSize; // size of data currently in buf - uint8_t buf[HTTP_UPLOAD_BUFLEN]; + uint8_t buf[HTTP_RAW_BUFLEN]; void *data; // additional data } HTTPRaw; +#include "middleware/Middleware.h" #include "detail/RequestHandler.h" namespace fs { @@ -144,9 +145,10 @@ class WebServer { void requestAuthentication(HTTPAuthMethod mode = BASIC_AUTH, const char *realm = NULL, const String &authFailMsg = String("")); typedef std::function THandlerFunction; - void on(const Uri &uri, THandlerFunction fn); - void on(const Uri &uri, HTTPMethod method, THandlerFunction fn); - void on(const Uri &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn); //ufn handles file uploads + typedef std::function FilterFunction; + RequestHandler &on(const Uri &uri, THandlerFunction fn); + RequestHandler &on(const Uri &uri, HTTPMethod method, THandlerFunction fn); + RequestHandler &on(const Uri &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn); //ufn handles file uploads bool removeRoute(const char *uri); bool removeRoute(const char *uri, HTTPMethod method); bool removeRoute(const String &uri); @@ -157,10 +159,14 @@ class WebServer { void onNotFound(THandlerFunction fn); //called when handler is not assigned void onFileUpload(THandlerFunction ufn); //handle file uploads - String uri() { + WebServer &addMiddleware(Middleware *middleware); + WebServer &addMiddleware(Middleware::Function fn); + WebServer &removeMiddleware(Middleware *middleware); + + String uri() const { return _currentUri; } - HTTPMethod method() { + HTTPMethod method() const { return _currentMethod; } virtual NetworkClient &client() { @@ -173,24 +179,30 @@ class WebServer { return *_currentRaw; } - String pathArg(unsigned int i); // get request path argument by number - String arg(String name); // get request argument value by name - String arg(int i); // get request argument value by number - String argName(int i); // get request argument name by number - int args(); // get arguments count - bool hasArg(String name); // check if argument exists + String pathArg(unsigned int i) const; // get request path argument by number + String arg(const String &name) const; // get request argument value by name + String arg(int i) const; // get request argument value by number + String argName(int i) const; // get request argument name by number + int args() const; // get arguments count + bool hasArg(const String &name) const; // check if argument exists void collectHeaders(const char *headerKeys[], const size_t headerKeysCount); // set the request headers to collect - String header(String name); // get request header value by name - String header(int i); // get request header value by number - String headerName(int i); // get request header name by number - int headers(); // get header count - bool hasHeader(String name); // check if header exists - - int clientContentLength() { - return _clientContentLength; - } // return "content-length" of incoming HTTP header from "_currentClient" - - String hostHeader(); // get request host header if available or empty String if not + void collectAllHeaders(); // collect all request headers + String header(const String &name) const; // get request header value by name + String header(int i) const; // get request header value by number + String headerName(int i) const; // get request header name by number + int headers() const; // get header count + bool hasHeader(const String &name) const; // check if header exists + + int clientContentLength() const; // return "content-length" of incoming HTTP header from "_currentClient" + const String version() const; // get the HTTP version string + String hostHeader() const; // get request host header if available or empty String if not + + int responseCode() const; // get the HTTP response code set + int responseHeaders() const; // get the HTTP response headers count + const String &responseHeader(String name) const; // get the HTTP response header value by name + const String &responseHeader(int i) const; // get the HTTP response header value by number + const String &responseHeaderName(int i) const; // get the HTTP response header name by number + bool hasResponseHeader(const String &name) const; // check if response header exists // send response to the client // code - HTTP response code, can be 200 or 404 @@ -227,6 +239,8 @@ class WebServer { bool _eTagEnabled = false; ETagFunction _eTagFunction = nullptr; + static String responseCodeToString(int code); + protected: virtual size_t _currentClientWrite(const char *b, size_t l) { return _currentClient.write(b, l); @@ -236,12 +250,11 @@ class WebServer { } void _addRequestHandler(RequestHandler *handler); bool _removeRequestHandler(RequestHandler *handler); - void _handleRequest(); + bool _handleRequest(); void _finalizeResponse(); bool _parseRequest(NetworkClient &client); - void _parseArguments(String data); - static String _responseCodeToString(int code); - bool _parseForm(NetworkClient &client, String boundary, uint32_t len); + void _parseArguments(const String &data); + bool _parseForm(NetworkClient &client, const String &boundary, uint32_t len); bool _parseFormUploadAborted(); void _uploadWriteByte(uint8_t b); int _uploadReadByte(NetworkClient &client); @@ -254,48 +267,57 @@ class WebServer { // for extracting Auth parameters String _extractParam(String &authReq, const String ¶m, const char delimit = '"'); + void _clearResponseHeaders(); + void _clearRequestHeaders(); + struct RequestArgument { String key; String value; + RequestArgument *next; }; - boolean _corsEnabled; + boolean _corsEnabled = false; NetworkServer _server; NetworkClient _currentClient; - HTTPMethod _currentMethod; + HTTPMethod _currentMethod = HTTP_ANY; String _currentUri; - uint8_t _currentVersion; - HTTPClientStatus _currentStatus; - unsigned long _statusChange; - boolean _nullDelay; - - RequestHandler *_currentHandler; - RequestHandler *_firstHandler; - RequestHandler *_lastHandler; - THandlerFunction _notFoundHandler; - THandlerFunction _fileUploadHandler; - - int _currentArgCount; - RequestArgument *_currentArgs; - int _postArgsLen; - RequestArgument *_postArgs; + uint8_t _currentVersion = 0; + HTTPClientStatus _currentStatus = HC_NONE; + unsigned long _statusChange = 0; + boolean _nullDelay = true; + + RequestHandler *_currentHandler = nullptr; + RequestHandler *_firstHandler = nullptr; + RequestHandler *_lastHandler = nullptr; + THandlerFunction _notFoundHandler = nullptr; + THandlerFunction _fileUploadHandler = nullptr; + + int _currentArgCount = 0; + RequestArgument *_currentArgs = nullptr; + int _postArgsLen = 0; + RequestArgument *_postArgs = nullptr; std::unique_ptr _currentUpload; std::unique_ptr _currentRaw; - int _headerKeysCount; - RequestArgument *_currentHeaders; - size_t _contentLength; - int _clientContentLength; // "Content-Length" from header of incoming POST or GET request - String _responseHeaders; + int _headerKeysCount = 0; + RequestArgument *_currentHeaders = nullptr; + size_t _contentLength = 0; + int _clientContentLength = 0; // "Content-Length" from header of incoming POST or GET request + RequestArgument *_responseHeaders = nullptr; String _hostHeader; - bool _chunked; + bool _chunked = false; String _snonce; // Store noance and opaque for future comparison String _sopaque; String _srealm; // Store the Auth realm between Calls + + int _responseHeaderCount = 0; + int _responseCode = 0; + bool _collectAllHeaders = false; + MiddlewareChain *_chain = nullptr; }; #endif //ESP8266WEBSERVER_H diff --git a/libraries/WebServer/src/detail/RequestHandler.h b/libraries/WebServer/src/detail/RequestHandler.h index 4ef4b1d0075..75e11c94ba8 100644 --- a/libraries/WebServer/src/detail/RequestHandler.h +++ b/libraries/WebServer/src/detail/RequestHandler.h @@ -6,37 +6,70 @@ class RequestHandler { public: - virtual ~RequestHandler() {} - virtual bool canHandle(HTTPMethod method, String uri) { + virtual ~RequestHandler() { + delete _chain; + } + + /* + note: old handler API for backward compatibility + */ + + virtual bool canHandle(HTTPMethod method, const String &uri) { (void)method; (void)uri; return false; } - virtual bool canUpload(String uri) { + virtual bool canUpload(const String &uri) { (void)uri; return false; } - virtual bool canRaw(String uri) { + virtual bool canRaw(const String &uri) { (void)uri; return false; } - virtual bool handle(WebServer &server, HTTPMethod requestMethod, String requestUri) { + + /* + note: new handler API with support for filters etc. + */ + + virtual bool canHandle(WebServer &server, HTTPMethod method, const String &uri) { + (void)server; + (void)method; + (void)uri; + return false; + } + virtual bool canUpload(WebServer &server, const String &uri) { + (void)server; + (void)uri; + return false; + } + virtual bool canRaw(WebServer &server, const String &uri) { + (void)server; + (void)uri; + return false; + } + virtual bool handle(WebServer &server, HTTPMethod requestMethod, const String &requestUri) { (void)server; (void)requestMethod; (void)requestUri; return false; } - virtual void upload(WebServer &server, String requestUri, HTTPUpload &upload) { + virtual void upload(WebServer &server, const String &requestUri, HTTPUpload &upload) { (void)server; (void)requestUri; (void)upload; } - virtual void raw(WebServer &server, String requestUri, HTTPRaw &raw) { + virtual void raw(WebServer &server, const String &requestUri, HTTPRaw &raw) { (void)server; (void)requestUri; (void)raw; } + virtual RequestHandler &setFilter(std::function filter) { + (void)filter; + return *this; + } + RequestHandler *next() { return _next; } @@ -44,8 +77,14 @@ class RequestHandler { _next = r; } + RequestHandler &addMiddleware(Middleware *middleware); + RequestHandler &addMiddleware(Middleware::Function fn); + RequestHandler &removeMiddleware(Middleware *middleware); + bool process(WebServer &server, HTTPMethod requestMethod, String requestUri); + private: RequestHandler *_next = nullptr; + MiddlewareChain *_chain = nullptr; protected: std::vector pathArgs; diff --git a/libraries/WebServer/src/detail/RequestHandlersImpl.h b/libraries/WebServer/src/detail/RequestHandlersImpl.h index d24d36fd9d4..3750b594ab2 100644 --- a/libraries/WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/WebServer/src/detail/RequestHandlersImpl.h @@ -10,6 +10,39 @@ using namespace mime; +RequestHandler &RequestHandler::addMiddleware(Middleware *middleware) { + if (!_chain) { + _chain = new MiddlewareChain(); + } + _chain->addMiddleware(middleware); + return *this; +} + +RequestHandler &RequestHandler::addMiddleware(Middleware::Function fn) { + if (!_chain) { + _chain = new MiddlewareChain(); + } + _chain->addMiddleware(fn); + return *this; +} + +RequestHandler &RequestHandler::removeMiddleware(Middleware *middleware) { + if (_chain) { + _chain->removeMiddleware(middleware); + } + return *this; +} + +bool RequestHandler::process(WebServer &server, HTTPMethod requestMethod, String requestUri) { + if (_chain) { + return _chain->runChain(server, [this, &server, &requestMethod, &requestUri]() { + return handle(server, requestMethod, requestUri); + }); + } else { + return handle(server, requestMethod, requestUri); + } +} + class FunctionRequestHandler : public RequestHandler { public: FunctionRequestHandler(WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn, const Uri &uri, HTTPMethod method) @@ -21,7 +54,7 @@ class FunctionRequestHandler : public RequestHandler { delete _uri; } - bool canHandle(HTTPMethod requestMethod, String requestUri) override { + bool canHandle(HTTPMethod requestMethod, const String &requestUri) override { if (_method != HTTP_ANY && _method != requestMethod) { return false; } @@ -29,14 +62,15 @@ class FunctionRequestHandler : public RequestHandler { return _uri->canHandle(requestUri, pathArgs); } - bool canUpload(String requestUri) override { + bool canUpload(const String &requestUri) override { if (!_ufn || !canHandle(HTTP_POST, requestUri)) { return false; } return true; } - bool canRaw(String requestUri) override { + + bool canRaw(const String &requestUri) override { if (!_ufn || _method == HTTP_GET) { return false; } @@ -44,9 +78,32 @@ class FunctionRequestHandler : public RequestHandler { return true; } - bool handle(WebServer &server, HTTPMethod requestMethod, String requestUri) override { - (void)server; - if (!canHandle(requestMethod, requestUri)) { + bool canHandle(WebServer &server, HTTPMethod requestMethod, const String &requestUri) override { + if (_method != HTTP_ANY && _method != requestMethod) { + return false; + } + + return _uri->canHandle(requestUri, pathArgs) && (_filter != NULL ? _filter(server) : true); + } + + bool canUpload(WebServer &server, const String &requestUri) override { + if (!_ufn || !canHandle(server, HTTP_POST, requestUri)) { + return false; + } + + return true; + } + + bool canRaw(WebServer &server, const String &requestUri) override { + if (!_ufn || _method == HTTP_GET || (_filter != NULL ? _filter(server) == false : false)) { + return false; + } + + return true; + } + + bool handle(WebServer &server, HTTPMethod requestMethod, const String &requestUri) override { + if (!canHandle(server, requestMethod, requestUri)) { return false; } @@ -54,25 +111,31 @@ class FunctionRequestHandler : public RequestHandler { return true; } - void upload(WebServer &server, String requestUri, HTTPUpload &upload) override { - (void)server; + void upload(WebServer &server, const String &requestUri, HTTPUpload &upload) override { (void)upload; - if (canUpload(requestUri)) { + if (canUpload(server, requestUri)) { _ufn(); } } - void raw(WebServer &server, String requestUri, HTTPRaw &raw) override { - (void)server; + void raw(WebServer &server, const String &requestUri, HTTPRaw &raw) override { (void)raw; - if (canRaw(requestUri)) { + if (canRaw(server, requestUri)) { _ufn(); } } + FunctionRequestHandler &setFilter(WebServer::FilterFunction filter) { + _filter = filter; + return *this; + } + protected: WebServer::THandlerFunction _fn; WebServer::THandlerFunction _ufn; + // _filter should return 'true' when the request should be handled + // and 'false' when the request should be ignored + WebServer::FilterFunction _filter; Uri *_uri; HTTPMethod _method; }; @@ -88,7 +151,7 @@ class StaticRequestHandler : public RequestHandler { _baseUriLength = _uri.length(); } - bool canHandle(HTTPMethod requestMethod, String requestUri) override { + bool canHandle(HTTPMethod requestMethod, const String &requestUri) override { if (requestMethod != HTTP_GET) { return false; } @@ -100,21 +163,36 @@ class StaticRequestHandler : public RequestHandler { return true; } - bool handle(WebServer &server, HTTPMethod requestMethod, String requestUri) override { - if (!canHandle(requestMethod, requestUri)) { + bool canHandle(WebServer &server, HTTPMethod requestMethod, const String &requestUri) override { + if (requestMethod != HTTP_GET) { + return false; + } + + if ((_isFile && requestUri != _uri) || !requestUri.startsWith(_uri)) { + return false; + } + + if (_filter != NULL ? _filter(server) == false : false) { + return false; + } + + return true; + } + + bool handle(WebServer &server, HTTPMethod requestMethod, const String &requestUri) override { + if (!canHandle(server, requestMethod, requestUri)) { return false; } log_v("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str()); String path(_path); - String eTagCode; if (!_isFile) { // Base URI doesn't point to a file. // If a directory is requested, look for index file. if (requestUri.endsWith("/")) { - requestUri += "index.htm"; + return handle(server, requestMethod, String(requestUri + "index.htm")); } // Append whatever follows this URI in request to get the file path. @@ -138,6 +216,8 @@ class StaticRequestHandler : public RequestHandler { return false; } + String eTagCode; + if (server._eTagEnabled) { if (server._eTagFunction) { eTagCode = (server._eTagFunction)(_fs, path); @@ -197,7 +277,15 @@ class StaticRequestHandler : public RequestHandler { return (result); } // calcETag + StaticRequestHandler &setFilter(WebServer::FilterFunction filter) { + _filter = filter; + return *this; + } + protected: + // _filter should return 'true' when the request should be handled + // and 'false' when the request should be ignored + WebServer::FilterFunction _filter; FS _fs; String _uri; String _path; diff --git a/libraries/WebServer/src/middleware/AuthenticationMiddleware.cpp b/libraries/WebServer/src/middleware/AuthenticationMiddleware.cpp new file mode 100644 index 00000000000..cab25ba4e50 --- /dev/null +++ b/libraries/WebServer/src/middleware/AuthenticationMiddleware.cpp @@ -0,0 +1,82 @@ +#include "Middlewares.h" + +AuthenticationMiddleware &AuthenticationMiddleware::setUsername(const char *username) { + _username = username; + _callback = nullptr; + return *this; +} + +AuthenticationMiddleware &AuthenticationMiddleware::setPassword(const char *password) { + _password = password; + _hash = false; + _callback = nullptr; + return *this; +} + +AuthenticationMiddleware &AuthenticationMiddleware::setPasswordHash(const char *sha1AsBase64orHex) { + _password = sha1AsBase64orHex; + _hash = true; + _callback = nullptr; + return *this; +} + +AuthenticationMiddleware &AuthenticationMiddleware::setCallback(WebServer::THandlerFunctionAuthCheck fn) { + assert(fn); + _callback = fn; + _hash = false; + _username = emptyString; + _password = emptyString; + return *this; +} + +AuthenticationMiddleware &AuthenticationMiddleware::setRealm(const char *realm) { + _realm = realm; + return *this; +} + +AuthenticationMiddleware &AuthenticationMiddleware::setAuthMethod(HTTPAuthMethod method) { + _method = method; + return *this; +} + +AuthenticationMiddleware &AuthenticationMiddleware::setAuthFailureMessage(const char *message) { + _authFailMsg = message; + return *this; +} + +bool AuthenticationMiddleware::isAllowed(WebServer &server) const { + if (_callback) { + return server.authenticate(_callback); + } + + if (!_username.isEmpty() && !_password.isEmpty()) { + if (_hash) { + return server.authenticateBasicSHA1(_username.c_str(), _password.c_str()); + } else { + return server.authenticate(_username.c_str(), _password.c_str()); + } + } + + return true; +} + +bool AuthenticationMiddleware::run(WebServer &server, Middleware::Callback next) { + bool authenticationRequired = false; + + if (_callback) { + authenticationRequired = !server.authenticate(_callback); + } else if (!_username.isEmpty() && !_password.isEmpty()) { + if (_hash) { + authenticationRequired = !server.authenticateBasicSHA1(_username.c_str(), _password.c_str()); + } else { + authenticationRequired = !server.authenticate(_username.c_str(), _password.c_str()); + } + } + + if (authenticationRequired) { + server.requestAuthentication(_method, _realm, _authFailMsg); + return true; + } else { + return next(); + } +} diff --git a/libraries/WebServer/src/middleware/CorsMiddleware.cpp b/libraries/WebServer/src/middleware/CorsMiddleware.cpp new file mode 100644 index 00000000000..a52ccd59f23 --- /dev/null +++ b/libraries/WebServer/src/middleware/CorsMiddleware.cpp @@ -0,0 +1,47 @@ +#include "Middlewares.h" + +CorsMiddleware &CorsMiddleware::setOrigin(const char *origin) { + _origin = origin; + return *this; +} + +CorsMiddleware &CorsMiddleware::setMethods(const char *methods) { + _methods = methods; + return *this; +} + +CorsMiddleware &CorsMiddleware::setHeaders(const char *headers) { + _headers = headers; + return *this; +} + +CorsMiddleware &CorsMiddleware::setAllowCredentials(bool credentials) { + _credentials = credentials; + return *this; +} + +CorsMiddleware &CorsMiddleware::setMaxAge(uint32_t seconds) { + _maxAge = seconds; + return *this; +} + +void CorsMiddleware::addCORSHeaders(WebServer &server) { + server.sendHeader(F("Access-Control-Allow-Origin"), _origin.c_str()); + server.sendHeader(F("Access-Control-Allow-Methods"), _methods.c_str()); + server.sendHeader(F("Access-Control-Allow-Headers"), _headers.c_str()); + server.sendHeader(F("Access-Control-Allow-Credentials"), _credentials ? F("true") : F("false")); + server.sendHeader(F("Access-Control-Max-Age"), String(_maxAge).c_str()); +} + +bool CorsMiddleware::run(WebServer &server, Middleware::Callback next) { + // Origin header ? => CORS handling + if (server.hasHeader(F("Origin"))) { + addCORSHeaders(server); + // check if this is a preflight request => handle it and return + if (server.method() == HTTP_OPTIONS) { + server.send(200); + return true; + } + } + return next(); +} diff --git a/libraries/WebServer/src/middleware/LoggingMiddleware.cpp b/libraries/WebServer/src/middleware/LoggingMiddleware.cpp new file mode 100644 index 00000000000..e1f6d708c2e --- /dev/null +++ b/libraries/WebServer/src/middleware/LoggingMiddleware.cpp @@ -0,0 +1,74 @@ +#include "Middlewares.h" + +void LoggingMiddleware::setOutput(Print &output) { + _out = &output; +} + +bool LoggingMiddleware::run(WebServer &server, Middleware::Callback next) { + if (_out == nullptr) { + return next(); + } + + _out->print(F("* Connection from ")); + _out->print(server.client().remoteIP().toString()); + _out->print(F(":")); + _out->println(server.client().remotePort()); + + _out->print(F("> ")); + const HTTPMethod method = server.method(); + if (method == HTTP_ANY) { + _out->print(F("HTTP_ANY")); + } else { + _out->print(http_method_str(method)); + } + _out->print(F(" ")); + _out->print(server.uri()); + _out->print(F(" ")); + _out->println(server.version()); + + int n = server.headers(); + for (int i = 0; i < n; i++) { + String v = server.header(i); + if (!v.isEmpty()) { + // because these 2 are always there, eventually empty: "Authorization", "If-None-Match" + _out->print(F("> ")); + _out->print(server.headerName(i)); + _out->print(F(": ")); + _out->println(server.header(i)); + } + } + + _out->println(F(">")); + + uint32_t elapsed = millis(); + const bool ret = next(); + elapsed = millis() - elapsed; + + if (ret) { + _out->print(F("* Processed in ")); + _out->print(elapsed); + _out->println(F(" ms")); + _out->print(F("< ")); + _out->print(F("HTTP/1.")); + _out->print(server.version()); + _out->print(F(" ")); + _out->print(server.responseCode()); + _out->print(F(" ")); + _out->println(WebServer::responseCodeToString(server.responseCode())); + + n = server.responseHeaders(); + for (int i = 0; i < n; i++) { + _out->print(F("< ")); + _out->print(server.responseHeaderName(i)); + _out->print(F(": ")); + _out->println(server.responseHeader(i)); + } + + _out->println(F("<")); + + } else { + _out->println(F("* Not processed!")); + } + + return ret; +} diff --git a/libraries/WebServer/src/middleware/Middleware.h b/libraries/WebServer/src/middleware/Middleware.h new file mode 100644 index 00000000000..080f5be0aba --- /dev/null +++ b/libraries/WebServer/src/middleware/Middleware.h @@ -0,0 +1,54 @@ +#ifndef MIDDLEWARE_H +#define MIDDLEWARE_H + +#include +#include + +class MiddlewareChain; +class WebServer; + +class Middleware { +public: + typedef std::function Callback; + typedef std::function Function; + + virtual ~Middleware() {} + + virtual bool run(WebServer &server, Callback next) { + return next(); + }; + +private: + friend MiddlewareChain; + Middleware *_next = nullptr; + bool _freeOnRemoval = false; +}; + +class MiddlewareFunction : public Middleware { +public: + MiddlewareFunction(Middleware::Function fn) : _fn(fn) {} + + bool run(WebServer &server, Middleware::Callback next) override { + return _fn(server, next); + } + +private: + Middleware::Function _fn; +}; + +class MiddlewareChain { +public: + ~MiddlewareChain(); + + void addMiddleware(Middleware::Function fn); + void addMiddleware(Middleware *middleware); + bool removeMiddleware(Middleware *middleware); + + bool runChain(WebServer &server, Middleware::Callback finalizer); + +private: + Middleware *_root = nullptr; + Middleware *_current = nullptr; +}; + +#endif diff --git a/libraries/WebServer/src/middleware/MiddlewareChain.cpp b/libraries/WebServer/src/middleware/MiddlewareChain.cpp new file mode 100644 index 00000000000..56b3066caea --- /dev/null +++ b/libraries/WebServer/src/middleware/MiddlewareChain.cpp @@ -0,0 +1,73 @@ +#include "Middleware.h" + +MiddlewareChain::~MiddlewareChain() { + Middleware *current = _root; + while (current) { + Middleware *next = current->_next; + if (current->_freeOnRemoval) { + delete current; + } + current = next; + } + _root = nullptr; +} + +void MiddlewareChain::addMiddleware(Middleware::Function fn) { + MiddlewareFunction *middleware = new MiddlewareFunction(fn); + middleware->_freeOnRemoval = true; + addMiddleware(middleware); +} + +void MiddlewareChain::addMiddleware(Middleware *middleware) { + if (!_root) { + _root = middleware; + return; + } + Middleware *current = _root; + while (current->_next) { + current = current->_next; + } + current->_next = middleware; +} + +bool MiddlewareChain::removeMiddleware(Middleware *middleware) { + if (!_root) { + return false; + } + if (_root == middleware) { + _root = _root->_next; + if (middleware->_freeOnRemoval) { + delete middleware; + } + return true; + } + Middleware *current = _root; + while (current->_next) { + if (current->_next == middleware) { + current->_next = current->_next->_next; + if (middleware->_freeOnRemoval) { + delete middleware; + } + return true; + } + current = current->_next; + } + return false; +} + +bool MiddlewareChain::runChain(WebServer &server, Middleware::Callback finalizer) { + if (!_root) { + return finalizer(); + } + _current = _root; + Middleware::Callback next; + next = [this, &server, &next, finalizer]() { + if (!_current) { + return finalizer(); + } + Middleware *that = _current; + _current = _current->_next; + return that->run(server, next); + }; + return next(); +} diff --git a/libraries/WiFi/examples/FTM/FTM_Initiator/README.md b/libraries/WiFi/examples/FTM/FTM_Initiator/README.md index 3558f75d372..b9c7f8d438d 100644 --- a/libraries/WiFi/examples/FTM/FTM_Initiator/README.md +++ b/libraries/WiFi/examples/FTM/FTM_Initiator/README.md @@ -55,10 +55,6 @@ To get more information about the Espressif boards see [Espressif Development Ki * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or setting the `upload_port` option on the `platformio.ini` file. - ## Log Output Expected log output: diff --git a/libraries/WiFi/examples/FTM/FTM_Initiator/ci.json b/libraries/WiFi/examples/FTM/FTM_Initiator/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/FTM/FTM_Initiator/ci.json +++ b/libraries/WiFi/examples/FTM/FTM_Initiator/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/FTM/FTM_Responder/README.md b/libraries/WiFi/examples/FTM/FTM_Responder/README.md index feede0867f3..fdcf1ab921b 100644 --- a/libraries/WiFi/examples/FTM/FTM_Responder/README.md +++ b/libraries/WiFi/examples/FTM/FTM_Responder/README.md @@ -48,10 +48,6 @@ To get more information about the Espressif boards see [Espressif Development Ki * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or setting the `upload_port` option on the `platformio.ini` file. - ## Log Output Expected log output: diff --git a/libraries/WiFi/examples/FTM/FTM_Responder/ci.json b/libraries/WiFi/examples/FTM/FTM_Responder/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/FTM/FTM_Responder/ci.json +++ b/libraries/WiFi/examples/FTM/FTM_Responder/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/SimpleWiFiServer/ci.json b/libraries/WiFi/examples/SimpleWiFiServer/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/SimpleWiFiServer/ci.json +++ b/libraries/WiFi/examples/SimpleWiFiServer/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WPS/WPS.ino b/libraries/WiFi/examples/WPS/WPS.ino index 194aac0119d..aacdd14ddab 100644 --- a/libraries/WiFi/examples/WPS/WPS.ino +++ b/libraries/WiFi/examples/WPS/WPS.ino @@ -14,41 +14,47 @@ Author: Pranav Cherukupalli */ +#include "sdkconfig.h" +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +#error "WPS is only supported in SoCs with native Wi-Fi support" +#endif + #include "WiFi.h" #include "esp_wps.h" /* Change the definition of the WPS mode from WPS_TYPE_PBC to WPS_TYPE_PIN in the case that you are using pin type -WPS +WPS (pin is 00000000) */ -#define ESP_WPS_MODE WPS_TYPE_PBC -#define ESP_MANUFACTURER "ESPRESSIF" -#define ESP_MODEL_NUMBER "ESP32" -#define ESP_MODEL_NAME "ESPRESSIF IOT" -#define ESP_DEVICE_NAME "ESP STATION" - -static esp_wps_config_t config; +#define ESP_WPS_MODE WPS_TYPE_PBC -void wpsInitConfig() { +void wpsStart() { + esp_wps_config_t config; + memset(&config, 0, sizeof(esp_wps_config_t)); + //Same as config = WPS_CONFIG_INIT_DEFAULT(ESP_WPS_MODE); config.wps_type = ESP_WPS_MODE; - strcpy(config.factory_info.manufacturer, ESP_MANUFACTURER); - strcpy(config.factory_info.model_number, ESP_MODEL_NUMBER); - strcpy(config.factory_info.model_name, ESP_MODEL_NAME); - strcpy(config.factory_info.device_name, ESP_DEVICE_NAME); -} + strcpy(config.factory_info.manufacturer, "ESPRESSIF"); + strcpy(config.factory_info.model_number, CONFIG_IDF_TARGET); + strcpy(config.factory_info.model_name, "ESPRESSIF IOT"); + strcpy(config.factory_info.device_name, "ESP DEVICE"); + strcpy(config.pin, "00000000"); + esp_err_t err = esp_wifi_wps_enable(&config); + if (err != ESP_OK) { + Serial.printf("WPS Enable Failed: 0x%x: %s\n", err, esp_err_to_name(err)); + return; + } -void wpsStart() { - if (esp_wifi_wps_enable(&config)) { - Serial.println("WPS Enable Failed"); - } else if (esp_wifi_wps_start(0)) { - Serial.println("WPS Start Failed"); + err = esp_wifi_wps_start(0); + if (err != ESP_OK) { + Serial.printf("WPS Start Failed: 0x%x: %s\n", err, esp_err_to_name(err)); } } void wpsStop() { - if (esp_wifi_wps_disable()) { - Serial.println("WPS Disable Failed"); + esp_err_t err = esp_wifi_wps_disable(); + if (err != ESP_OK) { + Serial.printf("WPS Disable Failed: 0x%x: %s\n", err, esp_err_to_name(err)); } } @@ -102,7 +108,6 @@ void setup() { WiFi.onEvent(WiFiEvent); // Will call WiFiEvent() from another thread. WiFi.mode(WIFI_MODE_STA); Serial.println("Starting WPS"); - wpsInitConfig(); wpsStart(); } diff --git a/libraries/WiFi/examples/WPS/ci.json b/libraries/WiFi/examples/WPS/ci.json index d8b3664bc65..36babb82730 100644 --- a/libraries/WiFi/examples/WPS/ci.json +++ b/libraries/WiFi/examples/WPS/ci.json @@ -1,5 +1,5 @@ { - "targets": { - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiAccessPoint/ci.json b/libraries/WiFi/examples/WiFiAccessPoint/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiAccessPoint/ci.json +++ b/libraries/WiFi/examples/WiFiAccessPoint/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiBlueToothSwitch/ci.json b/libraries/WiFi/examples/WiFiBlueToothSwitch/ci.json index 521ae8f5ff1..f27dd13c83e 100644 --- a/libraries/WiFi/examples/WiFiBlueToothSwitch/ci.json +++ b/libraries/WiFi/examples/WiFiBlueToothSwitch/ci.json @@ -1,6 +1,9 @@ { - "targets": { - "esp32h2": false, - "esp32s2": false - } + "requires": [ + "CONFIG_BT_ENABLED=y" + ], + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiClient/README.md b/libraries/WiFi/examples/WiFiClient/README.md index b85ec43e691..9d3698a543a 100644 --- a/libraries/WiFi/examples/WiFiClient/README.md +++ b/libraries/WiFi/examples/WiFiClient/README.md @@ -4,7 +4,7 @@ This example demonstrates reading and writing data from and to a web service whi # Supported Targets -Currently, this example supports all SoC with WiFi. +Currently, this example supports all SoC with Wi-Fi. | Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | @@ -18,7 +18,7 @@ Please note that this public channel can be accessed by anyone and it is possibl ### Configure the Project -Change `SSID` and `password` to connect to your WiFi. +Change `SSID` and `password` to connect to your Wi-Fi. Default values will allow you to use this example without any changes. If you want to use your own channel and you don't have one already follow these steps: * Create an account on [thingspeak.com](https://www.thingspeak.com). @@ -61,10 +61,6 @@ To get more information about the Espressif boards see [Espressif Development Ki * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file. - ## Example Log Output The initial output which is common for all examples can be ignored: @@ -79,7 +75,7 @@ load:0x403cc710,len:0x918 load:0x403ce710,len:0x24e4 entry 0x403cc710 ``` -Follows the setup output where connection to your WiFi happens: +Follows the setup output where connection to your Wi-Fi happens: ``` ****************************************************** Connecting to your-ssid @@ -139,7 +135,7 @@ After this the write+read log repeat every 10 seconds. ***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** -* **WiFi not connected:** Check the SSID and password and also that the signal has sufficient strength. +* **Wi-Fi not connected:** Check the SSID and password and also that the signal has sufficient strength. * **400 Bad Request:** Check the writeApiKey. * **404 Not Found:** Check the channel ID. * **No data on chart / reading NULL:** Data must be sent as an integer, without commas. diff --git a/libraries/WiFi/examples/WiFiClient/WiFiClient.ino b/libraries/WiFi/examples/WiFiClient/WiFiClient.ino index e91ead028de..b4c88244c26 100644 --- a/libraries/WiFi/examples/WiFiClient/WiFiClient.ino +++ b/libraries/WiFi/examples/WiFiClient/WiFiClient.ino @@ -34,9 +34,6 @@ int fieldNumber = 1; // Field number which will be read out void setup() { Serial.begin(115200); - while (!Serial) { - delay(100); - } // We start by connecting to a WiFi network diff --git a/libraries/WiFi/examples/WiFiClient/ci.json b/libraries/WiFi/examples/WiFiClient/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiClient/ci.json +++ b/libraries/WiFi/examples/WiFiClient/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiClientBasic/ci.json b/libraries/WiFi/examples/WiFiClientBasic/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiClientBasic/ci.json +++ b/libraries/WiFi/examples/WiFiClientBasic/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiClientConnect/README.md b/libraries/WiFi/examples/WiFiClientConnect/README.md index c18950f0458..939d44c5b76 100644 --- a/libraries/WiFi/examples/WiFiClientConnect/README.md +++ b/libraries/WiFi/examples/WiFiClientConnect/README.md @@ -1,6 +1,6 @@ # NetworkClientConnect Example -This example demonstrates how to connect to the WiFi and manage the status and disconnection from STA. +This example demonstrates how to connect to the Wi-Fi and manage the status and disconnection from STA. # Supported Targets @@ -18,10 +18,6 @@ Currently, this example supports the following targets. * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or set the `upload_port`` option on the `platformio.ini` file. - ## Example/Log Output ``` diff --git a/libraries/WiFi/examples/WiFiClientConnect/ci.json b/libraries/WiFi/examples/WiFiClientConnect/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiClientConnect/ci.json +++ b/libraries/WiFi/examples/WiFiClientConnect/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiClientEnterprise/README.md b/libraries/WiFi/examples/WiFiClientEnterprise/README.md index fefc37f0205..20d38b88d34 100644 --- a/libraries/WiFi/examples/WiFiClientEnterprise/README.md +++ b/libraries/WiFi/examples/WiFiClientEnterprise/README.md @@ -1,5 +1,5 @@ # ESP32-Eduroam -* Eduroam wifi connection with university login identity +* Eduroam Wi-Fi connection with university login identity * Working under Eduroam networks worldwide * Methods: PEAP + MsCHAPv2 @@ -15,6 +15,7 @@ * Board will auto reconnect to Eduroam if it lost connection # Tested locations + |University|Board|Method|Result| |-------------|-------------| -----|------| |Technical University in Košice (Slovakia)|ESP32 Devkit v1|PEAP + MsCHAPv2|Working| @@ -29,13 +30,14 @@ |Universidade Federal de Santa Catarina (Brazil)|xxx|EAP-TTLS + MsCHAPv2|Working| |University of Central Florida (Orlando, Florida)|ESP32 Built-in OLED – Heltec WiFi Kit 32|PEAP + MsCHAPv2|Working| |Université de Montpellier (France)|NodeMCU-32S|PEAP + MsCHAPv2|Working| + # Common errors - Switch to Debug mode for Serial monitor prints |Error|Appearance|Solution| |-------------|-------------|-------------| -|wifi: Set status to INIT|Frequent|Hold EN button for few seconds| +|Wi-Fi: Set status to INIT|Frequent|Hold EN button for few seconds| |HANDSHAKE_TIMEOUT|Rare|Bug was found under Zeroshell RADIUS authentization - Unsuccessful connection| -|AUTH_EXPIRE|Common|In the case of weak wifi network signal, this error is quite common, bring your device closer to AP| +|AUTH_EXPIRE|Common|In the case of weak Wi-Fi network signal, this error is quite common, bring your device closer to AP| |ASSOC_EXPIRE|Rare|-| # Successful connection example ![alt text](https://i.nahraj.to/f/24Kc.png) diff --git a/libraries/WiFi/examples/WiFiClientEnterprise/WiFiClientEnterprise.ino b/libraries/WiFi/examples/WiFiClientEnterprise/WiFiClientEnterprise.ino index 75b7a4dcc06..198f97e2805 100644 --- a/libraries/WiFi/examples/WiFiClientEnterprise/WiFiClientEnterprise.ino +++ b/libraries/WiFi/examples/WiFiClientEnterprise/WiFiClientEnterprise.ino @@ -1,3 +1,8 @@ +#include "sdkconfig.h" +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +#error "WPA-Enterprise is only supported in SoCs with native Wi-Fi support" +#endif + #include //Wifi library #define EAP_IDENTITY "login" //if connecting from another corporation, use identity@organization.domain in Eduroam #define EAP_USERNAME "login" //oftentimes just a repeat of the identity diff --git a/libraries/WiFi/examples/WiFiClientEnterprise/ci.json b/libraries/WiFi/examples/WiFiClientEnterprise/ci.json index d8b3664bc65..36babb82730 100644 --- a/libraries/WiFi/examples/WiFiClientEnterprise/ci.json +++ b/libraries/WiFi/examples/WiFiClientEnterprise/ci.json @@ -1,5 +1,5 @@ { - "targets": { - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiClientEvents/ci.json b/libraries/WiFi/examples/WiFiClientEvents/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiClientEvents/ci.json +++ b/libraries/WiFi/examples/WiFiClientEvents/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiClientStaticIP/ci.json b/libraries/WiFi/examples/WiFiClientStaticIP/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiClientStaticIP/ci.json +++ b/libraries/WiFi/examples/WiFiClientStaticIP/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiExtender/WiFiExtender.ino b/libraries/WiFi/examples/WiFiExtender/WiFiExtender.ino new file mode 100644 index 00000000000..c7f95c1b416 --- /dev/null +++ b/libraries/WiFi/examples/WiFiExtender/WiFiExtender.ino @@ -0,0 +1,68 @@ +#include + +#define STA_SSID "YOUR-SSID" +#define STA_PASS "YOUR-PASS" + +#define AP_SSID "ESP32-WIFI-EXTENDER" +#define AP_PASS "password" + +IPAddress ap_ip(192, 168, 4, 1); +IPAddress ap_mask(255, 255, 255, 0); +IPAddress ap_leaseStart(192, 168, 4, 2); +IPAddress ap_dns(8, 8, 4, 4); + +void setup() { + Serial.begin(115200); + Serial.setDebugOutput(true); + Network.onEvent(onEvent); + + WiFi.AP.begin(); + WiFi.AP.config(ap_ip, ap_ip, ap_mask, ap_leaseStart, ap_dns); + WiFi.AP.create(AP_SSID, AP_PASS); + if (!WiFi.AP.waitStatusBits(ESP_NETIF_STARTED_BIT, 1000)) { + Serial.println("Failed to start AP!"); + return; + } + + WiFi.begin(STA_SSID, STA_PASS); +} + +void loop() { + delay(20000); +} + +void onEvent(arduino_event_id_t event, arduino_event_info_t info) { + switch (event) { + case ARDUINO_EVENT_WIFI_STA_START: Serial.println("STA Started"); break; + case ARDUINO_EVENT_WIFI_STA_CONNECTED: Serial.println("STA Connected"); break; + case ARDUINO_EVENT_WIFI_STA_GOT_IP: + Serial.println("STA Got IP"); + Serial.println(WiFi.STA); + WiFi.AP.enableNAPT(true); + break; + case ARDUINO_EVENT_WIFI_STA_LOST_IP: + Serial.println("STA Lost IP"); + WiFi.AP.enableNAPT(false); + break; + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: + Serial.println("STA Disconnected"); + WiFi.AP.enableNAPT(false); + break; + case ARDUINO_EVENT_WIFI_STA_STOP: Serial.println("STA Stopped"); break; + + case ARDUINO_EVENT_WIFI_AP_START: + Serial.println("AP Started"); + Serial.println(WiFi.AP); + break; + case ARDUINO_EVENT_WIFI_AP_STACONNECTED: Serial.println("AP STA Connected"); break; + case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: Serial.println("AP STA Disconnected"); break; + case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED: + Serial.print("AP STA IP Assigned: "); + Serial.println(IPAddress(info.wifi_ap_staipassigned.ip.addr)); + break; + case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED: Serial.println("AP Probe Request Received"); break; + case ARDUINO_EVENT_WIFI_AP_STOP: Serial.println("AP Stopped"); break; + + default: break; + } +} diff --git a/libraries/WiFi/examples/WiFiExtender/ci.json b/libraries/WiFi/examples/WiFiExtender/ci.json new file mode 100644 index 00000000000..618e46bd244 --- /dev/null +++ b/libraries/WiFi/examples/WiFiExtender/ci.json @@ -0,0 +1,6 @@ +{ + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] +} diff --git a/libraries/WiFi/examples/WiFiIPv6/ci.json b/libraries/WiFi/examples/WiFiIPv6/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiIPv6/ci.json +++ b/libraries/WiFi/examples/WiFiIPv6/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiMulti/ci.json b/libraries/WiFi/examples/WiFiMulti/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiMulti/ci.json +++ b/libraries/WiFi/examples/WiFiMulti/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiMultiAdvanced/ci.json b/libraries/WiFi/examples/WiFiMultiAdvanced/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiMultiAdvanced/ci.json +++ b/libraries/WiFi/examples/WiFiMultiAdvanced/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiScan/README.md b/libraries/WiFi/examples/WiFiScan/README.md index 04dc8e90b32..f1268f21b5c 100644 --- a/libraries/WiFi/examples/WiFiScan/README.md +++ b/libraries/WiFi/examples/WiFiScan/README.md @@ -1,10 +1,10 @@ # WiFiScan Example -This example demonstrates how to use the WiFi library to scan available WiFi networks and print the results. +This example demonstrates how to use the Wi-Fi library to scan available Wi-Fi networks and print the results. ## Supported Targets -Currently this example supports the following targets. +Currently, this example supports the following targets. | Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | ESP32-C6 | | ----------------- | ----- | -------- | -------- | -------- | -------- | @@ -18,10 +18,6 @@ Currently this example supports the following targets. * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or setting the `upload_port` option on the `platformio.ini` file. - ## Example/Log Output ``` @@ -45,7 +41,7 @@ Nr | SSID | RSSI | CH | Encryption * **Programming Fail:** If the programming/flash procedure fails, try to reduce the serial connection speed. * **COM port not detected:** Check the USB cable connection and the USB to Serial driver installation. -If the error persist, you can ask help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). ## Contribute diff --git a/libraries/WiFi/examples/WiFiScan/ci.json b/libraries/WiFi/examples/WiFiScan/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiScan/ci.json +++ b/libraries/WiFi/examples/WiFiScan/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiScanAsync/README.md b/libraries/WiFi/examples/WiFiScanAsync/README.md index f8aeb759d2c..26120aaa31c 100644 --- a/libraries/WiFi/examples/WiFiScanAsync/README.md +++ b/libraries/WiFi/examples/WiFiScanAsync/README.md @@ -1,10 +1,10 @@ # WiFiScanAsync Example -This example demonstrates how to use the WiFi library to scan available WiFi networks in asynchronous mode and print the results. +This example demonstrates how to use the Wi-Fi library to scan available Wi-Fi networks in asynchronous mode and print the results. ## Supported Targets -Currently this example supports the following targets. +Currently, this example supports the following targets. | Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | ESP32-C6 | | ----------------- | ----- | -------- | -------- | -------- | -------- | @@ -18,10 +18,6 @@ Currently this example supports the following targets. * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or setting the `upload_port` option on the `platformio.ini` file. - ## Example/Log Output ``` @@ -55,7 +51,7 @@ Nr | SSID | RSSI | CH | Encryption * **Programming Fail:** If the programming/flash procedure fails, try to reduce the serial connection speed. * **COM port not detected:** Check the USB cable connection and the USB to Serial driver installation. -If the error persist, you can ask help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). ## Contribute diff --git a/libraries/WiFi/examples/WiFiScanAsync/ci.json b/libraries/WiFi/examples/WiFiScanAsync/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiScanAsync/ci.json +++ b/libraries/WiFi/examples/WiFiScanAsync/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiScanDualAntenna/README.md b/libraries/WiFi/examples/WiFiScanDualAntenna/README.md index f33a25b5370..9a6611149d0 100644 --- a/libraries/WiFi/examples/WiFiScanDualAntenna/README.md +++ b/libraries/WiFi/examples/WiFiScanDualAntenna/README.md @@ -1,6 +1,6 @@ # WiFiScan Example -This example demonstrates how to use the WiFi library to scan available WiFi networks and print the results. +This example demonstrates how to use the Wi-Fi library to scan available Wi-Fi networks and print the results. This example shows the basic functionality of the dual antenna capability. @@ -17,10 +17,6 @@ This example is compatible with the ESP32-WROOM-DA. * Before Compile/Verify, select the correct board: `Tools -> Board`. * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. -#### Using Platform IO - -* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file. - ## Example/Log Output ``` diff --git a/libraries/WiFi/examples/WiFiScanDualAntenna/ci.json b/libraries/WiFi/examples/WiFiScanDualAntenna/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiScanDualAntenna/ci.json +++ b/libraries/WiFi/examples/WiFiScanDualAntenna/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiScanTime/README.md b/libraries/WiFi/examples/WiFiScanTime/README.md new file mode 100644 index 00000000000..7be0e05d4fe --- /dev/null +++ b/libraries/WiFi/examples/WiFiScanTime/README.md @@ -0,0 +1,61 @@ +# WiFiScanTime Example + +This example demonstrates how to use the Wi-Fi library to scan available Wi-Fi networks with custom scan timing and print the results. + +## Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | ESP32-C6 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | + +## How to Use Example + +* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide). + +#### Using Arduino IDE + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. + +## Example/Log Output + +``` +Setup done +Scan start +Scan done, elapsed time: 4960 ms +17 networks found +Nr | SSID | RSSI | CH | Encryption + 1 | IoTNetwork | -62 | 1 | WPA2 + 2 | WiFiSSID | -62 | 1 | WPA2-EAP + 3 | B3A7992 | -63 | 6 | WPA+WPA2 + 4 | WiFi | -63 | 6 | WPA3 + 5 | IoTNetwork2 | -64 | 11 | WPA2+WPA3 +... +``` + +## Troubleshooting + +***Important: Be sure you're using a good quality USB cable and you have enough power source for your project.*** + +* **Programming Fail:** If the programming/flash procedure fails, try to reduce the serial connection speed. +* **COM port not detected:** Check the USB cable connection 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 the Troubleshooting and to check if the same issue was already created by someone else. + +## Resources + +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) +* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) +* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/WiFi/examples/WiFiScanTime/WiFiScanTime.ino b/libraries/WiFi/examples/WiFiScanTime/WiFiScanTime.ino new file mode 100644 index 00000000000..93dba7905ae --- /dev/null +++ b/libraries/WiFi/examples/WiFiScanTime/WiFiScanTime.ino @@ -0,0 +1,92 @@ +/* + * This sketch demonstrates how to scan WiFi networks with custom scanning time. + * The API is based on the Arduino WiFi Shield library, but has significant changes as newer WiFi functions are supported. + * E.g. the return value of `encryptionType()` different because more modern encryption is supported. + */ + +/* + * WiFi scan timing parameters explained: + * + * min=0, max=0: scan dwells on each channel for 120 ms. + * min>0, max=0: scan dwells on each channel for 120 ms. + * min=0, max>0: scan dwells on each channel for max ms. + * min>0, max>0: the minimum time the scan dwells on each channel is min ms. If no AP is found during this time frame, the scan switches to the next channel. Otherwise, the scan dwells on the channel for max ms. + */ + +#include "WiFi.h" + +void wifiScan(uint16_t min_time, uint16_t max_time) { + Serial.println("Scan start"); + + // Set the minimum time per channel for active scanning. + WiFi.setScanActiveMinTime(min_time); + + // Capture the start time of the scan. + uint32_t start = millis(); + + // WiFi.scanNetworks will return the number of networks found. + // Scan networks with those options: Synchrone mode, show hidden networks, active scan, max scan time per channel. + int n = WiFi.scanNetworks(false, true, false, max_time); + Serial.printf("Scan done, elapsed time: %lu ms\n", millis() - start); + if (n == 0) { + Serial.println("no networks found"); + } else { + Serial.print(n); + Serial.println(" networks found"); + Serial.println("Nr | SSID | RSSI | CH | Encryption"); + for (int i = 0; i < n; ++i) { + // Print SSID and RSSI for each network found + Serial.printf("%2d", i + 1); + Serial.print(" | "); + Serial.printf("%-32.32s", WiFi.SSID(i).c_str()); + Serial.print(" | "); + Serial.printf("%4ld", WiFi.RSSI(i)); + Serial.print(" | "); + Serial.printf("%2ld", WiFi.channel(i)); + Serial.print(" | "); + switch (WiFi.encryptionType(i)) { + case WIFI_AUTH_OPEN: Serial.print("open"); break; + case WIFI_AUTH_WEP: Serial.print("WEP"); break; + case WIFI_AUTH_WPA_PSK: Serial.print("WPA"); break; + case WIFI_AUTH_WPA2_PSK: Serial.print("WPA2"); break; + case WIFI_AUTH_WPA_WPA2_PSK: Serial.print("WPA+WPA2"); break; + case WIFI_AUTH_WPA2_ENTERPRISE: Serial.print("WPA2-EAP"); break; + case WIFI_AUTH_WPA3_PSK: Serial.print("WPA3"); break; + case WIFI_AUTH_WPA2_WPA3_PSK: Serial.print("WPA2+WPA3"); break; + case WIFI_AUTH_WAPI_PSK: Serial.print("WAPI"); break; + default: Serial.print("unknown"); + } + Serial.println(); + delay(10); + } + } + Serial.println(""); + + // Delete the scan result to free memory for code below. + WiFi.scanDelete(); + + // Wait a bit before scanning again + delay(2000); +} + +void setup() { + Serial.begin(115200); + + // Set WiFi to station mode and disconnect from an AP if it was previously connected. + WiFi.mode(WIFI_STA); + WiFi.disconnect(); + delay(100); + + // Scan WiFi networks with a minimum time of 100 ms per channel and a maximum time of 300 ms per channel (default values). + wifiScan(100, 300); + + // Scan WiFi networks with a minimum time of 100 ms per channel and a maximum time of 1500 ms per channel. + wifiScan(100, 1500); + + // Scan WiFi networks with a minimum time of 0 ms per channel and a maximum time of 1500 ms per channel. + wifiScan(0, 1500); +} + +void loop() { + // Nothing to do here +} diff --git a/libraries/WiFi/examples/WiFiScanTime/ci.json b/libraries/WiFi/examples/WiFiScanTime/ci.json new file mode 100644 index 00000000000..618e46bd244 --- /dev/null +++ b/libraries/WiFi/examples/WiFiScanTime/ci.json @@ -0,0 +1,6 @@ +{ + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] +} diff --git a/libraries/WiFi/examples/WiFiSmartConfig/WiFiSmartConfig.ino b/libraries/WiFi/examples/WiFiSmartConfig/WiFiSmartConfig.ino index 6d372bb1098..724355c6a37 100644 --- a/libraries/WiFi/examples/WiFiSmartConfig/WiFiSmartConfig.ino +++ b/libraries/WiFi/examples/WiFiSmartConfig/WiFiSmartConfig.ino @@ -1,3 +1,8 @@ +#include "sdkconfig.h" +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +#error "SmartConfig is only supported in SoCs with native Wi-Fi support" +#endif + #include "WiFi.h" void setup() { diff --git a/libraries/WiFi/examples/WiFiSmartConfig/ci.json b/libraries/WiFi/examples/WiFiSmartConfig/ci.json index d8b3664bc65..36babb82730 100644 --- a/libraries/WiFi/examples/WiFiSmartConfig/ci.json +++ b/libraries/WiFi/examples/WiFiSmartConfig/ci.json @@ -1,5 +1,5 @@ { - "targets": { - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiTelnetToSerial/ci.json b/libraries/WiFi/examples/WiFiTelnetToSerial/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiTelnetToSerial/ci.json +++ b/libraries/WiFi/examples/WiFiTelnetToSerial/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/examples/WiFiUDPClient/ci.json b/libraries/WiFi/examples/WiFiUDPClient/ci.json index d8b3664bc65..618e46bd244 100644 --- a/libraries/WiFi/examples/WiFiUDPClient/ci.json +++ b/libraries/WiFi/examples/WiFiUDPClient/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] } diff --git a/libraries/WiFi/library.properties b/libraries/WiFi/library.properties index cf1976aded9..03112c2fcc6 100644 --- a/libraries/WiFi/library.properties +++ b/libraries/WiFi/library.properties @@ -1,5 +1,5 @@ name=WiFi -version=2.0.0 +version=3.2.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables network connection (local and Internet) using the ESP32 built-in WiFi. diff --git a/libraries/WiFi/src/AP.cpp b/libraries/WiFi/src/AP.cpp index db61c2f0ff1..0e7839764ea 100644 --- a/libraries/WiFi/src/AP.cpp +++ b/libraries/WiFi/src/AP.cpp @@ -7,7 +7,7 @@ #include "WiFi.h" #include "WiFiGeneric.h" #include "WiFiAP.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include #include #include @@ -87,6 +87,7 @@ static void _onApArduinoEvent(arduino_event_t *ev) { } log_v("Arduino AP Event: %d - %s", ev->event_id, Network.eventName(ev->event_id)); if (ev->event_id == ARDUINO_EVENT_WIFI_AP_START) { +#if CONFIG_LWIP_IPV6 if (_ap_network_if->getStatusBits() & ESP_NETIF_WANT_IP6_BIT) { esp_err_t err = esp_netif_create_ip6_linklocal(_ap_network_if->netif()); if (err != ESP_OK) { @@ -95,6 +96,7 @@ static void _onApArduinoEvent(arduino_event_t *ev) { log_v("Enabled IPv6 Link Local on %s", _ap_network_if->desc()); } } +#endif } } @@ -146,7 +148,7 @@ void APClass::_onApEvent(int32_t event_id, void *event_data) { } } -APClass::APClass() { +APClass::APClass() : _wifi_ap_event_handle(0) { _ap_network_if = this; } @@ -161,7 +163,7 @@ bool APClass::onEnable() { return false; } if (_esp_netif == NULL) { - Network.onSysEvent(_onApArduinoEvent); + _wifi_ap_event_handle = Network.onSysEvent(_onApArduinoEvent); _esp_netif = get_esp_interface_netif(ESP_IF_WIFI_AP); /* attach to receive events */ initNetif(ESP_NETIF_ID_AP); @@ -170,7 +172,8 @@ bool APClass::onEnable() { } bool APClass::onDisable() { - Network.removeEvent(_onApArduinoEvent); + Network.removeEvent(_wifi_ap_event_handle); + _wifi_ap_event_handle = 0; // we just set _esp_netif to NULL here, so destroyNetif() does not try to destroy it. // That would be done by WiFi.enableAP(false) if STA is not enabled, or when it gets disabled _esp_netif = NULL; @@ -187,6 +190,10 @@ bool APClass::begin() { log_e("AP enable failed!"); return false; } + if (!waitStatusBits(ESP_NETIF_STARTED_BIT, 1000)) { + log_e("Failed to start AP!"); + return false; + } return true; } diff --git a/libraries/WiFi/src/STA.cpp b/libraries/WiFi/src/STA.cpp index dacb0cae2d4..84258589b28 100644 --- a/libraries/WiFi/src/STA.cpp +++ b/libraries/WiFi/src/STA.cpp @@ -6,7 +6,7 @@ #include "WiFi.h" #include "WiFiGeneric.h" #include "WiFiSTA.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include #include #include @@ -118,6 +118,7 @@ static void _onStaArduinoEvent(arduino_event_t *ev) { _sta_network_if->_setStatus(WL_STOPPED); } else if (ev->event_id == ARDUINO_EVENT_WIFI_STA_CONNECTED) { _sta_network_if->_setStatus(WL_IDLE_STATUS); +#if CONFIG_LWIP_IPV6 if (_sta_network_if->getStatusBits() & ESP_NETIF_WANT_IP6_BIT) { esp_err_t err = esp_netif_create_ip6_linklocal(_sta_network_if->netif()); if (err != ESP_OK) { @@ -126,6 +127,7 @@ static void _onStaArduinoEvent(arduino_event_t *ev) { log_v("Enabled IPv6 Link Local on %s", _sta_network_if->desc()); } } +#endif } else if (ev->event_id == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) { uint8_t reason = ev->event_info.wifi_sta_disconnected.reason; // Reason 0 causes crash, use reason 1 (UNSPECIFIED) instead @@ -226,7 +228,8 @@ void STAClass::_onStaEvent(int32_t event_id, void *event_data) { } STAClass::STAClass() - : _minSecurity(WIFI_AUTH_WPA2_PSK), _scanMethod(WIFI_FAST_SCAN), _sortMethod(WIFI_CONNECT_AP_BY_SIGNAL), _autoReconnect(true), _status(WL_STOPPED) { + : _minSecurity(WIFI_AUTH_WPA2_PSK), _scanMethod(WIFI_FAST_SCAN), _sortMethod(WIFI_CONNECT_AP_BY_SIGNAL), _autoReconnect(true), _status(WL_STOPPED), + _wifi_sta_event_handle(0) { _sta_network_if = this; } @@ -274,14 +277,15 @@ bool STAClass::onEnable() { return false; } /* attach to receive events */ - Network.onSysEvent(_onStaArduinoEvent); + _wifi_sta_event_handle = Network.onSysEvent(_onStaArduinoEvent); initNetif(ESP_NETIF_ID_STA); } return true; } bool STAClass::onDisable() { - Network.removeEvent(_onStaArduinoEvent); + Network.removeEvent(_wifi_sta_event_handle); + _wifi_sta_event_handle = 0; // we just set _esp_netif to NULL here, so destroyNetif() does not try to destroy it. // That would be done by WiFi.enableSTA(false) if AP is not enabled, or when it gets disabled _esp_netif = NULL; @@ -298,6 +302,10 @@ bool STAClass::begin(bool tryConnect) { log_e("STA enable failed!"); return false; } + if (!waitStatusBits(ESP_NETIF_STARTED_BIT, 1000)) { + log_e("Failed to start STA!"); + return false; + } if (tryConnect) { return connect(); } @@ -415,6 +423,7 @@ bool STAClass::connect(const char *ssid, const char *passphrase, int32_t channel return true; } +#if CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT /** * Start Wifi connection with a WPA2 Enterprise AP * if passphrase is set the most secure supported mode will be automatically selected @@ -513,6 +522,7 @@ bool STAClass::connect( return connect(wpa2_ssid, NULL, channel, bssid, tryConnect); //connect to wifi } +#endif /* CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT */ bool STAClass::disconnect(bool eraseap, unsigned long timeout) { if (eraseap) { diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index a854cb0ceb7..7fb0ed16459 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -22,7 +22,7 @@ */ #include "WiFi.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED extern "C" { #include diff --git a/libraries/WiFi/src/WiFi.h b/libraries/WiFi/src/WiFi.h index a823dabd864..ea2efd97697 100644 --- a/libraries/WiFi/src/WiFi.h +++ b/libraries/WiFi/src/WiFi.h @@ -22,7 +22,8 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#include "sdkconfig.h" +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include diff --git a/libraries/WiFi/src/WiFiAP.cpp b/libraries/WiFi/src/WiFiAP.cpp index fac84dc8512..bb15ff44625 100644 --- a/libraries/WiFi/src/WiFiAP.cpp +++ b/libraries/WiFi/src/WiFiAP.cpp @@ -25,7 +25,7 @@ #include "WiFi.h" #include "WiFiGeneric.h" #include "WiFiAP.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include #include @@ -177,6 +177,7 @@ bool WiFiAPClass::softAPsetHostname(const char *hostname) { return AP.setHostname(hostname); } +#if CONFIG_LWIP_IPV6 /** * Enable IPv6 on the softAP interface. * @return true on success @@ -193,5 +194,5 @@ bool WiFiAPClass::softAPenableIPv6(bool enable) { IPAddress WiFiAPClass::softAPlinkLocalIPv6() { return AP.linkLocalIPv6(); } - +#endif #endif /* SOC_WIFI_SUPPORTED */ diff --git a/libraries/WiFi/src/WiFiAP.h b/libraries/WiFi/src/WiFiAP.h index 9acd124c27e..540ec87f44f 100644 --- a/libraries/WiFi/src/WiFiAP.h +++ b/libraries/WiFi/src/WiFiAP.h @@ -23,7 +23,8 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#include "sdkconfig.h" +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "esp_wifi_types.h" #include "WiFiType.h" @@ -59,6 +60,8 @@ class APClass : public NetworkInterface { void _onApEvent(int32_t event_id, void *event_data); protected: + network_event_handle_t _wifi_ap_event_handle; + size_t printDriverInfo(Print &out) const; friend class WiFiGenericClass; @@ -100,8 +103,10 @@ class WiFiAPClass { IPAddress softAPSubnetMask(); uint8_t softAPSubnetCIDR(); +#if CONFIG_LWIP_IPV6 bool softAPenableIPv6(bool enable = true); IPAddress softAPlinkLocalIPv6(); +#endif const char *softAPgetHostname(); bool softAPsetHostname(const char *hostname); diff --git a/libraries/WiFi/src/WiFiClient.h b/libraries/WiFi/src/WiFiClient.h index 30729e27923..4add805ca09 100644 --- a/libraries/WiFi/src/WiFiClient.h +++ b/libraries/WiFi/src/WiFiClient.h @@ -1,3 +1,3 @@ #pragma once #include "NetworkClient.h" -#define WiFiClient NetworkClient +typedef NetworkClient WiFiClient; diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index 1903a5c9c41..3faf34fef34 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -24,7 +24,7 @@ #include "WiFi.h" #include "WiFiGeneric.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED extern "C" { #include @@ -39,6 +39,9 @@ extern "C" { #include #include #include +#if SOC_WIFI_SUPPORTED +#include +#endif #include "lwip/ip_addr.h" #include "lwip/opt.h" #include "lwip/err.h" @@ -102,6 +105,7 @@ static void _arduino_event_cb(void *arg, esp_event_base_t event_base, int32_t ev arduino_event.event_id = ARDUINO_EVENT_WIFI_FTM_REPORT; memcpy(&arduino_event.event_info.wifi_ftm_report, event_data, sizeof(wifi_event_ftm_report_t)); +#if !CONFIG_ESP_WIFI_REMOTE_ENABLED /* * SMART CONFIG * */ @@ -123,39 +127,42 @@ static void _arduino_event_cb(void *arg, esp_event_base_t event_base, int32_t ev log_v("SC Send Ack Done"); arduino_event.event_id = ARDUINO_EVENT_SC_SEND_ACK_DONE; +#if CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI /* * Provisioning * */ - } else if (event_base == WIFI_PROV_EVENT && event_id == WIFI_PROV_INIT) { + } else if (event_base == NETWORK_PROV_EVENT && event_id == NETWORK_PROV_INIT) { log_v("Provisioning Initialized!"); arduino_event.event_id = ARDUINO_EVENT_PROV_INIT; - } else if (event_base == WIFI_PROV_EVENT && event_id == WIFI_PROV_DEINIT) { + } else if (event_base == NETWORK_PROV_EVENT && event_id == NETWORK_PROV_DEINIT) { log_v("Provisioning Uninitialized!"); arduino_event.event_id = ARDUINO_EVENT_PROV_DEINIT; - } else if (event_base == WIFI_PROV_EVENT && event_id == WIFI_PROV_START) { + } else if (event_base == NETWORK_PROV_EVENT && event_id == NETWORK_PROV_START) { log_v("Provisioning Start!"); arduino_event.event_id = ARDUINO_EVENT_PROV_START; - } else if (event_base == WIFI_PROV_EVENT && event_id == WIFI_PROV_END) { + } else if (event_base == NETWORK_PROV_EVENT && event_id == NETWORK_PROV_END) { log_v("Provisioning End!"); - wifi_prov_mgr_deinit(); + network_prov_mgr_deinit(); arduino_event.event_id = ARDUINO_EVENT_PROV_END; - } else if (event_base == WIFI_PROV_EVENT && event_id == WIFI_PROV_CRED_RECV) { + } else if (event_base == NETWORK_PROV_EVENT && event_id == NETWORK_PROV_WIFI_CRED_RECV) { #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE wifi_sta_config_t *event = (wifi_sta_config_t *)event_data; log_v("Provisioned Credentials: SSID: %s, Password: %s", (const char *)event->ssid, (const char *)event->password); #endif arduino_event.event_id = ARDUINO_EVENT_PROV_CRED_RECV; memcpy(&arduino_event.event_info.prov_cred_recv, event_data, sizeof(wifi_sta_config_t)); - } else if (event_base == WIFI_PROV_EVENT && event_id == WIFI_PROV_CRED_FAIL) { + } else if (event_base == NETWORK_PROV_EVENT && event_id == NETWORK_PROV_WIFI_CRED_FAIL) { #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR - wifi_prov_sta_fail_reason_t *reason = (wifi_prov_sta_fail_reason_t *)event_data; - log_e("Provisioning Failed: Reason : %s", (*reason == WIFI_PROV_STA_AUTH_ERROR) ? "Authentication Failed" : "AP Not Found"); + network_prov_wifi_sta_fail_reason_t *reason = (network_prov_wifi_sta_fail_reason_t *)event_data; + log_e("Provisioning Failed: Reason : %s", (*reason == NETWORK_PROV_WIFI_STA_AUTH_ERROR) ? "Authentication Failed" : "AP Not Found"); #endif arduino_event.event_id = ARDUINO_EVENT_PROV_CRED_FAIL; - memcpy(&arduino_event.event_info.prov_fail_reason, event_data, sizeof(wifi_prov_sta_fail_reason_t)); - } else if (event_base == WIFI_PROV_EVENT && event_id == WIFI_PROV_CRED_SUCCESS) { + memcpy(&arduino_event.event_info.prov_fail_reason, event_data, sizeof(network_prov_wifi_sta_fail_reason_t)); + } else if (event_base == NETWORK_PROV_EVENT && event_id == NETWORK_PROV_WIFI_CRED_SUCCESS) { log_v("Provisioning Success!"); arduino_event.event_id = ARDUINO_EVENT_PROV_CRED_SUCCESS; +#endif +#endif } if (arduino_event.event_id < ARDUINO_EVENT_MAX) { @@ -169,15 +176,19 @@ static bool initWiFiEvents() { return false; } +#if !CONFIG_ESP_WIFI_REMOTE_ENABLED if (esp_event_handler_instance_register(SC_EVENT, ESP_EVENT_ANY_ID, &_arduino_event_cb, NULL, NULL)) { log_e("event_handler_instance_register for SC_EVENT Failed!"); return false; } - if (esp_event_handler_instance_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &_arduino_event_cb, NULL, NULL)) { - log_e("event_handler_instance_register for WIFI_PROV_EVENT Failed!"); +#if CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + if (esp_event_handler_instance_register(NETWORK_PROV_EVENT, ESP_EVENT_ANY_ID, &_arduino_event_cb, NULL, NULL)) { + log_e("event_handler_instance_register for NETWORK_PROV_EVENT Failed!"); return false; } +#endif +#endif return true; } @@ -188,15 +199,19 @@ static bool deinitWiFiEvents() { return false; } +#if !CONFIG_ESP_WIFI_REMOTE_ENABLED if (esp_event_handler_unregister(SC_EVENT, ESP_EVENT_ANY_ID, &_arduino_event_cb)) { log_e("esp_event_handler_unregister for SC_EVENT Failed!"); return false; } - if (esp_event_handler_unregister(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &_arduino_event_cb)) { - log_e("esp_event_handler_unregister for WIFI_PROV_EVENT Failed!"); +#if CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + if (esp_event_handler_unregister(NETWORK_PROV_EVENT, ESP_EVENT_ANY_ID, &_arduino_event_cb)) { + log_e("esp_event_handler_unregister for NETWORK_PROV_EVENT Failed!"); return false; } +#endif +#endif return true; } @@ -224,9 +239,57 @@ void WiFiGenericClass::useStaticBuffers(bool bufferMode) { extern "C" void phy_bbpll_en_usb(bool en); #endif +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +extern "C" { +//#include "esp_hosted.h" +#include "esp_hosted_transport_config.h" +extern esp_err_t esp_hosted_init(); +extern esp_err_t esp_hosted_deinit(); +}; +static bool hosted_initialized = false; + +static bool wifiHostedInit() { + if (!hosted_initialized) { + hosted_initialized = true; + struct esp_hosted_sdio_config conf = INIT_DEFAULT_HOST_SDIO_CONFIG(); + conf.pin_clk.pin = CONFIG_ESP_SDIO_PIN_CLK; + conf.pin_cmd.pin = CONFIG_ESP_SDIO_PIN_CMD; + conf.pin_d0.pin = CONFIG_ESP_SDIO_PIN_D0; + conf.pin_d1.pin = CONFIG_ESP_SDIO_PIN_D1; + conf.pin_d2.pin = CONFIG_ESP_SDIO_PIN_D2; + conf.pin_d3.pin = CONFIG_ESP_SDIO_PIN_D3; + //conf.pin_rst.pin = CONFIG_ESP_SDIO_GPIO_RESET_SLAVE; + // esp_hosted_sdio_set_config() will fail on second attempt but here temporarily to not cause exception on reinit + if (esp_hosted_sdio_set_config(&conf) != ESP_OK || esp_hosted_init() != ESP_OK) { + log_e("esp_hosted_init failed!"); + hosted_initialized = false; + return false; + } + log_v("ESP-HOSTED initialized!"); + } + // Attach pins to PeriMan here + // Slave chip model is CONFIG_IDF_SLAVE_TARGET + // CONFIG_ESP_SDIO_PIN_CMD + // CONFIG_ESP_SDIO_PIN_CLK + // CONFIG_ESP_SDIO_PIN_D0 + // CONFIG_ESP_SDIO_PIN_D1 + // CONFIG_ESP_SDIO_PIN_D2 + // CONFIG_ESP_SDIO_PIN_D3 + // CONFIG_ESP_SDIO_GPIO_RESET_SLAVE + + return true; +} +#endif + bool wifiLowLevelInit(bool persistent) { if (!lowLevelInitDone) { lowLevelInitDone = true; +#if CONFIG_ESP_WIFI_REMOTE_ENABLED + if (!wifiHostedInit()) { + lowLevelInitDone = false; + return lowLevelInitDone; + } +#endif if (!Network.begin()) { lowLevelInitDone = false; return lowLevelInitDone; @@ -245,7 +308,7 @@ bool wifiLowLevelInit(bool persistent) { esp_err_t err = esp_wifi_init(&cfg); if (err) { - log_e("esp_wifi_init %d", err); + log_e("esp_wifi_init 0x%x: %s", err, esp_err_to_name(err)); lowLevelInitDone = false; return lowLevelInitDone; } @@ -290,6 +353,13 @@ static bool wifiLowLevelDeinit() { arduino_event_t arduino_event; arduino_event.event_id = ARDUINO_EVENT_WIFI_OFF; Network.postEvent(&arduino_event); +#if CONFIG_ESP_WIFI_REMOTE_ENABLED + if (hosted_initialized && esp_hosted_deinit() == ESP_OK) { + hosted_initialized = false; + log_v("ESP-HOSTED uninitialized!"); + // detach SDIO pins from PeriMan + } +#endif } } return !lowLevelInitDone; @@ -305,7 +375,7 @@ static bool espWiFiStart() { esp_err_t err = esp_wifi_start(); if (err != ESP_OK) { _esp_wifi_started = false; - log_e("esp_wifi_start %d", err); + log_e("esp_wifi_start 0x%x: %s", err, esp_err_to_name(err)); return _esp_wifi_started; } return _esp_wifi_started; @@ -319,7 +389,7 @@ static bool espWiFiStop() { _esp_wifi_started = false; err = esp_wifi_stop(); if (err) { - log_e("Could not stop WiFi! %d", err); + log_e("Could not stop WiFi! 0x%x: %s", err, esp_err_to_name(err)); _esp_wifi_started = true; return false; } @@ -369,6 +439,7 @@ void WiFiGenericClass::_eventCallback(arduino_event_t *event) { // log_d("Arduino Event: %d - %s", event->event_id, WiFi.eventName(event->event_id)); if (event->event_id == ARDUINO_EVENT_WIFI_SCAN_DONE) { WiFiScanClass::_scanDone(); +#if !CONFIG_ESP_WIFI_REMOTE_ENABLED } else if (event->event_id == ARDUINO_EVENT_SC_GOT_SSID_PSWD) { WiFi.begin( (const char *)event->event_info.sc_got_ssid_pswd.ssid, (const char *)event->event_info.sc_got_ssid_pswd.password, 0, @@ -377,6 +448,7 @@ void WiFiGenericClass::_eventCallback(arduino_event_t *event) { } else if (event->event_id == ARDUINO_EVENT_SC_SEND_ACK_DONE) { esp_smartconfig_stop(); WiFiSTAClass::_smartConfigDone = true; +#endif } } @@ -406,7 +478,7 @@ int WiFiGenericClass::setChannel(uint8_t primary, wifi_second_chan_t secondary) ret = esp_wifi_get_country(&country); if (ret != ESP_OK) { - log_e("Failed to get country info"); + log_e("Failed to get country info 0x%x: %s", ret, esp_err_to_name(ret)); return ret; } @@ -420,7 +492,7 @@ int WiFiGenericClass::setChannel(uint8_t primary, wifi_second_chan_t secondary) ret = esp_wifi_set_channel(primary, secondary); if (ret != ESP_OK) { - log_e("Failed to set channel"); + log_e("Failed to set channel 0x%x: %s", ret, esp_err_to_name(ret)); return ret; } @@ -490,13 +562,13 @@ bool WiFiGenericClass::mode(wifi_mode_t m) { if (((m & WIFI_MODE_STA) != 0) && ((cm & WIFI_MODE_STA) == 0)) { err = esp_netif_set_hostname(esp_netifs[ESP_IF_WIFI_STA], NetworkManager::getHostname()); if (err) { - log_e("Could not set hostname! %d", err); + log_e("Could not set hostname! 0x%x: %s", err, esp_err_to_name(err)); return false; } } err = esp_wifi_set_mode(m); if (err) { - log_e("Could not set mode! %d", err); + log_e("Could not set mode! 0x%x: %s", err, esp_err_to_name(err)); return false; } @@ -513,17 +585,44 @@ bool WiFiGenericClass::mode(wifi_mode_t m) { if (m & WIFI_MODE_STA) { err = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); if (err != ESP_OK) { - log_e("Could not enable long range on STA! %d", err); + log_e("Could not enable long range on STA! 0x%x: %s", err, esp_err_to_name(err)); return false; } } if (m & WIFI_MODE_AP) { err = esp_wifi_set_protocol(WIFI_IF_AP, WIFI_PROTOCOL_LR); if (err != ESP_OK) { - log_e("Could not enable long range on AP! %d", err); + log_e("Could not enable long range on AP! 0x%x: %s", err, esp_err_to_name(err)); return false; } } + } else { +#if CONFIG_SOC_WIFI_HE_SUPPORT +#define WIFI_PROTOCOL_DEFAULT (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX) +#else +#define WIFI_PROTOCOL_DEFAULT (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N) +#endif + uint32_t current_protocol = 0; + if (m & WIFI_MODE_STA) { + err = esp_wifi_get_protocol(WIFI_IF_STA, (uint8_t *)¤t_protocol); + if (err == ESP_OK && current_protocol == WIFI_PROTOCOL_LR) { + log_v("Disabling long range on STA"); + err = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_DEFAULT); + if (err != ESP_OK) { + log_e("Could not disable long range on STA! 0x%x: %s", err, esp_err_to_name(err)); + } + } + } + if (m & WIFI_MODE_AP) { + err = esp_wifi_get_protocol(WIFI_IF_AP, (uint8_t *)¤t_protocol); + if (err == ESP_OK && current_protocol == WIFI_PROTOCOL_LR) { + log_v("Disabling long range on AP"); + err = esp_wifi_set_protocol(WIFI_IF_AP, WIFI_PROTOCOL_DEFAULT); + if (err != ESP_OK) { + log_e("Could not disable long range on AP! 0x%x: %s", err, esp_err_to_name(err)); + } + } + } } if (!espWiFiStart()) { return false; @@ -611,8 +710,9 @@ bool WiFiGenericClass::setSleep(wifi_ps_type_t sleepType) { if (sleepType != _sleepEnabled) { _sleepEnabled = sleepType; if (WiFi.STA.started()) { - if (esp_wifi_set_ps(_sleepEnabled) != ESP_OK) { - log_e("esp_wifi_set_ps failed!"); + esp_err_t err = esp_wifi_set_ps(_sleepEnabled); + if (err != ESP_OK) { + log_e("esp_wifi_set_ps failed!: 0x%x: %s", err, esp_err_to_name(err)); return false; } } @@ -639,7 +739,11 @@ bool WiFiGenericClass::setTxPower(wifi_power_t power) { log_w("Neither AP or STA has been started"); return false; } - return esp_wifi_set_max_tx_power(power) == ESP_OK; + esp_err_t err = esp_wifi_set_max_tx_power(power); + if (err != ESP_OK) { + log_e("Failed to set TX Power: 0x%x: %s", err, esp_err_to_name(err)); + } + return err == ESP_OK; } wifi_power_t WiFiGenericClass::getTxPower() { @@ -648,7 +752,9 @@ wifi_power_t WiFiGenericClass::getTxPower() { log_w("Neither AP or STA has been started"); return WIFI_POWER_19_5dBm; } - if (esp_wifi_get_max_tx_power(&power)) { + esp_err_t err = esp_wifi_get_max_tx_power(&power); + if (err != ESP_OK) { + log_e("Failed to get TX Power: 0x%x: %s", err, esp_err_to_name(err)); return WIFI_POWER_19_5dBm; } return (wifi_power_t)power; @@ -670,8 +776,9 @@ bool WiFiGenericClass::initiateFTM(uint8_t frm_count, uint16_t burst_period, uin memcpy(ftmi_cfg.resp_mac, mac, 6); } // Request FTM session with the Responder - if (ESP_OK != esp_wifi_ftm_initiate_session(&ftmi_cfg)) { - log_e("Failed to initiate FTM session"); + esp_err_t err = esp_wifi_ftm_initiate_session(&ftmi_cfg); + if (ESP_OK != err) { + log_e("Failed to initiate FTM session: 0x%x: %s", err, esp_err_to_name(err)); return false; } return true; @@ -686,11 +793,13 @@ bool WiFiGenericClass::initiateFTM(uint8_t frm_count, uint16_t burst_period, uin * @return true on success */ bool WiFiGenericClass::setDualAntennaConfig(uint8_t gpio_ant1, uint8_t gpio_ant2, wifi_rx_ant_t rx_mode, wifi_tx_ant_t tx_mode) { +#if !CONFIG_ESP_WIFI_REMOTE_ENABLED - wifi_ant_gpio_config_t wifi_ant_io; + esp_phy_ant_gpio_config_t wifi_ant_io; - if (ESP_OK != esp_wifi_get_ant_gpio(&wifi_ant_io)) { - log_e("Failed to get antenna configuration"); + esp_err_t err = esp_phy_get_ant_gpio(&wifi_ant_io); + if (ESP_OK != err) { + log_e("Failed to get antenna configuration: 0x%x: %s", err, esp_err_to_name(err)); return false; } @@ -699,60 +808,62 @@ bool WiFiGenericClass::setDualAntennaConfig(uint8_t gpio_ant1, uint8_t gpio_ant2 wifi_ant_io.gpio_cfg[1].gpio_num = gpio_ant2; wifi_ant_io.gpio_cfg[1].gpio_select = 1; - if (ESP_OK != esp_wifi_set_ant_gpio(&wifi_ant_io)) { - log_e("Failed to set antenna GPIO configuration"); + err = esp_phy_set_ant_gpio(&wifi_ant_io); + if (ESP_OK != err) { + log_e("Failed to set antenna GPIO configuration: 0x%x: %s", err, esp_err_to_name(err)); return false; } // Set antenna default configuration - wifi_ant_config_t ant_config = { - .rx_ant_mode = WIFI_ANT_MODE_AUTO, - .rx_ant_default = WIFI_ANT_MAX, // Ignored in AUTO mode - .tx_ant_mode = WIFI_ANT_MODE_AUTO, + esp_phy_ant_config_t ant_config = { + .rx_ant_mode = ESP_PHY_ANT_MODE_AUTO, + .rx_ant_default = ESP_PHY_ANT_MAX, // Ignored in AUTO mode + .tx_ant_mode = ESP_PHY_ANT_MODE_AUTO, .enabled_ant0 = 1, .enabled_ant1 = 2, }; switch (rx_mode) { - case WIFI_RX_ANT0: ant_config.rx_ant_mode = WIFI_ANT_MODE_ANT0; break; - case WIFI_RX_ANT1: ant_config.rx_ant_mode = WIFI_ANT_MODE_ANT1; break; + case WIFI_RX_ANT0: ant_config.rx_ant_mode = ESP_PHY_ANT_MODE_ANT0; break; + case WIFI_RX_ANT1: ant_config.rx_ant_mode = ESP_PHY_ANT_MODE_ANT1; break; case WIFI_RX_ANT_AUTO: log_i("TX Antenna will be automatically selected"); - ant_config.rx_ant_default = WIFI_ANT_ANT0; - ant_config.rx_ant_mode = WIFI_ANT_MODE_AUTO; + ant_config.rx_ant_default = ESP_PHY_ANT_ANT0; + ant_config.rx_ant_mode = ESP_PHY_ANT_MODE_AUTO; // Force TX for AUTO if RX is AUTO - ant_config.tx_ant_mode = WIFI_ANT_MODE_AUTO; + ant_config.tx_ant_mode = ESP_PHY_ANT_MODE_AUTO; goto set_ant; break; default: log_e("Invalid default antenna! Falling back to AUTO"); - ant_config.rx_ant_mode = WIFI_ANT_MODE_AUTO; + ant_config.rx_ant_mode = ESP_PHY_ANT_MODE_AUTO; break; } switch (tx_mode) { - case WIFI_TX_ANT0: ant_config.tx_ant_mode = WIFI_ANT_MODE_ANT0; break; - case WIFI_TX_ANT1: ant_config.tx_ant_mode = WIFI_ANT_MODE_ANT1; break; + case WIFI_TX_ANT0: ant_config.tx_ant_mode = ESP_PHY_ANT_MODE_ANT0; break; + case WIFI_TX_ANT1: ant_config.tx_ant_mode = ESP_PHY_ANT_MODE_ANT1; break; case WIFI_TX_ANT_AUTO: log_i("RX Antenna will be automatically selected"); - ant_config.rx_ant_default = WIFI_ANT_ANT0; - ant_config.tx_ant_mode = WIFI_ANT_MODE_AUTO; + ant_config.rx_ant_default = ESP_PHY_ANT_ANT0; + ant_config.tx_ant_mode = ESP_PHY_ANT_MODE_AUTO; // Force RX for AUTO if RX is AUTO - ant_config.rx_ant_mode = WIFI_ANT_MODE_AUTO; + ant_config.rx_ant_mode = ESP_PHY_ANT_MODE_AUTO; break; default: log_e("Invalid default antenna! Falling back to AUTO"); - ant_config.rx_ant_default = WIFI_ANT_ANT0; - ant_config.tx_ant_mode = WIFI_ANT_MODE_AUTO; + ant_config.rx_ant_default = ESP_PHY_ANT_ANT0; + ant_config.tx_ant_mode = ESP_PHY_ANT_MODE_AUTO; break; } set_ant: - if (ESP_OK != esp_wifi_set_ant(&ant_config)) { - log_e("Failed to set antenna configuration"); + err = esp_phy_set_ant(&ant_config); + if (ESP_OK != err) { + log_e("Failed to set antenna configuration: 0x%x: %s", err, esp_err_to_name(err)); return false; } - +#endif return true; } diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index 6ed74dfed84..ed216229ed4 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -23,7 +23,8 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#include "sdkconfig.h" +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "esp_err.h" #include "esp_event.h" @@ -32,8 +33,12 @@ #include "IPAddress.h" #include "esp_smartconfig.h" #include "esp_netif_types.h" +#if CONFIG_ETH_ENABLED #include "esp_eth_driver.h" -#include "wifi_provisioning/manager.h" +#endif +#if CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#include "network_provisioning/manager.h" +#endif #include "lwip/ip_addr.h" #include "Network.h" @@ -44,6 +49,9 @@ #define wifi_event_id_t network_event_handle_t typedef enum { + WIFI_POWER_21dBm = 84, // 21dBm + WIFI_POWER_20_5dBm = 82, // 20.5dBm + WIFI_POWER_20dBm = 80, // 20dBm WIFI_POWER_19_5dBm = 78, // 19.5dBm WIFI_POWER_19dBm = 76, // 19dBm WIFI_POWER_18_5dBm = 74, // 18.5dBm diff --git a/libraries/WiFi/src/WiFiMulti.cpp b/libraries/WiFi/src/WiFiMulti.cpp index a438919f792..c99bef5ac90 100644 --- a/libraries/WiFi/src/WiFiMulti.cpp +++ b/libraries/WiFi/src/WiFiMulti.cpp @@ -24,7 +24,7 @@ */ #include "WiFiMulti.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include #include #include @@ -251,9 +251,11 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout, bool scanHidden) { bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb ); +#if CONFIG_LWIP_IPV6 if (ipv6_support == true) { WiFi.enableIPv6(); } +#endif WiFi.disconnect(); delay(10); WiFi.begin(bestNetwork.ssid, (_bAllowOpenAP && bestNetworkSec == WIFI_AUTH_OPEN) ? NULL : bestNetwork.passphrase, bestChannel, bestBSSID); @@ -318,9 +320,11 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout, bool scanHidden) { return status; } +#if CONFIG_LWIP_IPV6 void WiFiMulti::enableIPv6(bool state) { ipv6_support = state; } +#endif void WiFiMulti::markAsFailed(int32_t i) { APlist[i].hasFailed = true; diff --git a/libraries/WiFi/src/WiFiMulti.h b/libraries/WiFi/src/WiFiMulti.h index 1e11ff13f51..d818f77899f 100644 --- a/libraries/WiFi/src/WiFiMulti.h +++ b/libraries/WiFi/src/WiFiMulti.h @@ -26,7 +26,8 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#include "sdkconfig.h" +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "WiFi.h" #include @@ -46,7 +47,9 @@ class WiFiMulti { bool addAP(const char *ssid, const char *passphrase = NULL); uint8_t run(uint32_t connectTimeout = 5000, bool scanHidden = false); +#if CONFIG_LWIP_IPV6 void enableIPv6(bool state); +#endif // Force (default: true) to only keep connected or to connect to an AP from the provided WiFiMulti list. // When bStrict is false, it will keep the last/current connected AP even if not in the WiFiMulti List. diff --git a/libraries/WiFi/src/WiFiSTA.cpp b/libraries/WiFi/src/WiFiSTA.cpp index 1c1ce42c12f..b956e35ba26 100644 --- a/libraries/WiFi/src/WiFiSTA.cpp +++ b/libraries/WiFi/src/WiFiSTA.cpp @@ -25,7 +25,7 @@ #include "WiFi.h" #include "WiFiGeneric.h" #include "WiFiSTA.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include #include @@ -63,6 +63,7 @@ wl_status_t WiFiSTAClass::status() { return STA.status(); } +#if CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT wl_status_t WiFiSTAClass::begin( const char *wpa2_ssid, wpa2_auth_method_t method, const char *wpa2_identity, const char *wpa2_username, const char *wpa2_password, const char *ca_pem, const char *client_crt, const char *client_key, int ttls_phase2_type, int32_t channel, const uint8_t *bssid, bool connect @@ -77,6 +78,7 @@ wl_status_t WiFiSTAClass::begin( return STA.status(); } +#endif /* CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT */ wl_status_t WiFiSTAClass::begin(const char *ssid, const char *passphrase, int32_t channel, const uint8_t *bssid, bool connect) { if (!STA.begin()) { @@ -215,7 +217,7 @@ bool WiFiSTAClass::bandwidth(wifi_bandwidth_t bandwidth) { * @return true if STA is connected to an AP */ bool WiFiSTAClass::isConnected() { - return STA.connected(); + return STA.connected() && STA.hasIP(); } /** @@ -386,6 +388,7 @@ int8_t WiFiSTAClass::RSSI(void) { return STA.RSSI(); } +#if CONFIG_LWIP_IPV6 /** * Enable IPv6 on the station interface. * Should be called before WiFi.begin() @@ -411,6 +414,7 @@ IPAddress WiFiSTAClass::linkLocalIPv6() { IPAddress WiFiSTAClass::globalIPv6() { return STA.globalIPv6(); } +#endif bool WiFiSTAClass::_smartConfigStarted = false; bool WiFiSTAClass::_smartConfigDone = false; diff --git a/libraries/WiFi/src/WiFiSTA.h b/libraries/WiFi/src/WiFiSTA.h index 2c046c4c4b9..6063eae7968 100644 --- a/libraries/WiFi/src/WiFiSTA.h +++ b/libraries/WiFi/src/WiFiSTA.h @@ -23,7 +23,8 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#include "sdkconfig.h" +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "WiFiType.h" #include "WiFiGeneric.h" @@ -53,11 +54,13 @@ class STAClass : public NetworkInterface { bool connect(); bool connect(const char *ssid, const char *passphrase = NULL, int32_t channel = 0, const uint8_t *bssid = NULL, bool connect = true); +#if CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT bool connect( const char *wpa2_ssid, wpa2_auth_method_t method, const char *wpa2_identity = NULL, const char *wpa2_username = NULL, const char *wpa2_password = NULL, const char *ca_pem = NULL, const char *client_crt = NULL, const char *client_key = NULL, int ttls_phase2_type = -1, int32_t channel = 0, const uint8_t *bssid = 0, bool connect = true ); +#endif /* CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT */ bool disconnect(bool eraseap = false, unsigned long timeout = 0); bool reconnect(); bool erase(); @@ -92,6 +95,7 @@ class STAClass : public NetworkInterface { wifi_sort_method_t _sortMethod; bool _autoReconnect; wl_status_t _status; + network_event_handle_t _wifi_sta_event_handle; size_t printDriverInfo(Print &out) const; @@ -108,6 +112,7 @@ class WiFiSTAClass { public: STAClass STA; +#if CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT wl_status_t begin( const char *wpa2_ssid, wpa2_auth_method_t method, const char *wpa2_identity = NULL, const char *wpa2_username = NULL, const char *wpa2_password = NULL, const char *ca_pem = NULL, const char *client_crt = NULL, const char *client_key = NULL, int ttls_phase2_type = -1, int32_t channel = 0, @@ -123,6 +128,8 @@ class WiFiSTAClass { ttls_phase2_type, channel, bssid, connect ); } +#endif /* CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT */ + wl_status_t begin(const char *ssid, const char *passphrase = NULL, int32_t channel = 0, const uint8_t *bssid = NULL, bool connect = true); wl_status_t begin(const String &ssid, const String &passphrase = (const char *)NULL, int32_t channel = 0, const uint8_t *bssid = NULL, bool connect = true) { return begin(ssid.c_str(), passphrase.c_str(), channel, bssid, connect); @@ -179,9 +186,11 @@ class WiFiSTAClass { IPAddress networkID(); uint8_t subnetCIDR(); +#if CONFIG_LWIP_IPV6 bool enableIPv6(bool en = true); IPAddress linkLocalIPv6(); IPAddress globalIPv6(); +#endif // ---------------------------------------------------------------------------------------------- // ---------------------------------------- Smart Config ---------------------------------------- diff --git a/libraries/WiFi/src/WiFiScan.cpp b/libraries/WiFi/src/WiFiScan.cpp index 70d3fb31cef..086b875fcb2 100644 --- a/libraries/WiFi/src/WiFiScan.cpp +++ b/libraries/WiFi/src/WiFiScan.cpp @@ -25,7 +25,7 @@ #include "WiFi.h" #include "WiFiGeneric.h" #include "WiFiScan.h" -#if SOC_WIFI_SUPPORTED +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED extern "C" { #include @@ -46,12 +46,18 @@ bool WiFiScanClass::_scanAsync = false; uint32_t WiFiScanClass::_scanStarted = 0; uint32_t WiFiScanClass::_scanTimeout = 60000; uint16_t WiFiScanClass::_scanCount = 0; -void *WiFiScanClass::_scanResult = 0; +uint32_t WiFiScanClass::_scanActiveMinTime = 100; + +void *WiFiScanClass::_scanResult = nullptr; void WiFiScanClass::setScanTimeout(uint32_t ms) { WiFiScanClass::_scanTimeout = ms; } +void WiFiScanClass::setScanActiveMinTime(uint32_t ms) { + WiFiScanClass::_scanActiveMinTime = ms; +} + /** * Start scan WiFi networks available * @param async run in async mode @@ -71,6 +77,7 @@ int16_t scanDelete(); wifi_scan_config_t config; + memset(&config, 0, sizeof(wifi_scan_config_t)); config.ssid = (uint8_t *)ssid; config.bssid = (uint8_t *)bssid; config.channel = channel; @@ -80,14 +87,11 @@ int16_t config.scan_time.passive = max_ms_per_chan; } else { config.scan_type = WIFI_SCAN_TYPE_ACTIVE; - config.scan_time.active.min = 100; + config.scan_time.active.min = _scanActiveMinTime; config.scan_time.active.max = max_ms_per_chan; } if (esp_wifi_scan_start(&config, false) == ESP_OK) { _scanStarted = millis(); - if (!_scanStarted) { //Prevent 0 from millis overflow - ++_scanStarted; - } WiFiGenericClass::clearStatusBits(WIFI_SCAN_DONE_BIT); WiFiGenericClass::setStatusBits(WIFI_SCANNING_BIT); @@ -110,13 +114,21 @@ int16_t */ void WiFiScanClass::_scanDone() { esp_wifi_scan_get_ap_num(&(WiFiScanClass::_scanCount)); + if (WiFiScanClass::_scanResult) { + free(WiFiScanClass::_scanResult); + WiFiScanClass::_scanResult = NULL; + } + if (WiFiScanClass::_scanCount) { - WiFiScanClass::_scanResult = new wifi_ap_record_t[WiFiScanClass::_scanCount]; - if (!WiFiScanClass::_scanResult || esp_wifi_scan_get_ap_records(&(WiFiScanClass::_scanCount), (wifi_ap_record_t *)_scanResult) != ESP_OK) { + WiFiScanClass::_scanResult = calloc(WiFiScanClass::_scanCount, sizeof(wifi_ap_record_t)); + if (!WiFiScanClass::_scanResult) { + WiFiScanClass::_scanCount = 0; + } else if (esp_wifi_scan_get_ap_records(&(WiFiScanClass::_scanCount), (wifi_ap_record_t *)_scanResult) != ESP_OK) { + free(WiFiScanClass::_scanResult); + WiFiScanClass::_scanResult = NULL; WiFiScanClass::_scanCount = 0; } } - WiFiScanClass::_scanStarted = 0; //Reset after a scan is completed for normal behavior WiFiGenericClass::setStatusBits(WIFI_SCAN_DONE_BIT); WiFiGenericClass::clearStatusBits(WIFI_SCANNING_BIT); } @@ -145,15 +157,13 @@ int16_t WiFiScanClass::scanComplete() { } if (WiFiGenericClass::getStatusBits() & WIFI_SCANNING_BIT) { + // Check if the delay expired, return WIFI_SCAN_FAILED in this case + if ((millis() - WiFiScanClass::_scanStarted) > WiFiScanClass::_scanTimeout) { + WiFiGenericClass::clearStatusBits(WIFI_SCANNING_BIT); + return WIFI_SCAN_FAILED; + } return WIFI_SCAN_RUNNING; } - // last one to avoid time affecting Async mode - if (WiFiScanClass::_scanStarted - && (millis() - WiFiScanClass::_scanStarted) - > WiFiScanClass::_scanTimeout) { //Check is scan was started and if the delay expired, return WIFI_SCAN_FAILED in this case - WiFiGenericClass::clearStatusBits(WIFI_SCANNING_BIT); - return WIFI_SCAN_FAILED; - } return WIFI_SCAN_FAILED; } @@ -163,11 +173,12 @@ int16_t WiFiScanClass::scanComplete() { */ void WiFiScanClass::scanDelete() { WiFiGenericClass::clearStatusBits(WIFI_SCAN_DONE_BIT); + WiFiGenericClass::clearStatusBits(WIFI_SCANNING_BIT); if (WiFiScanClass::_scanResult) { - delete[] reinterpret_cast(WiFiScanClass::_scanResult); - WiFiScanClass::_scanResult = 0; - WiFiScanClass::_scanCount = 0; + free(WiFiScanClass::_scanResult); + WiFiScanClass::_scanResult = NULL; } + WiFiScanClass::_scanCount = 0; } /** diff --git a/libraries/WiFi/src/WiFiScan.h b/libraries/WiFi/src/WiFiScan.h index 5e09a93351c..7afd26bb76a 100644 --- a/libraries/WiFi/src/WiFiScan.h +++ b/libraries/WiFi/src/WiFiScan.h @@ -23,7 +23,8 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#include "sdkconfig.h" +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "WiFiType.h" #include "WiFiGeneric.h" @@ -32,6 +33,7 @@ class WiFiScanClass { public: void setScanTimeout(uint32_t ms); + void setScanActiveMinTime(uint32_t ms); int16_t scanNetworks( bool async = false, bool show_hidden = false, bool passive = false, uint32_t max_ms_per_chan = 300, uint8_t channel = 0, const char *ssid = nullptr, @@ -62,6 +64,7 @@ class WiFiScanClass { static uint32_t _scanStarted; static uint32_t _scanTimeout; static uint16_t _scanCount; + static uint32_t _scanActiveMinTime; static void *_scanResult; diff --git a/libraries/WiFi/src/WiFiServer.h b/libraries/WiFi/src/WiFiServer.h index 39d984486cf..850bd98d9c8 100644 --- a/libraries/WiFi/src/WiFiServer.h +++ b/libraries/WiFi/src/WiFiServer.h @@ -1,3 +1,3 @@ #pragma once #include "NetworkServer.h" -#define WiFiServer NetworkServer +typedef NetworkServer WiFiServer; diff --git a/libraries/WiFi/src/WiFiType.h b/libraries/WiFi/src/WiFiType.h index 1d721d33963..29af9ce2252 100644 --- a/libraries/WiFi/src/WiFiType.h +++ b/libraries/WiFi/src/WiFiType.h @@ -22,7 +22,8 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#include "sdkconfig.h" +#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED #include "esp_wifi_types.h" diff --git a/libraries/WiFi/src/WiFiUdp.h b/libraries/WiFi/src/WiFiUdp.h index b0b11570fa6..420d29b634b 100644 --- a/libraries/WiFi/src/WiFiUdp.h +++ b/libraries/WiFi/src/WiFiUdp.h @@ -1,3 +1,3 @@ #pragma once #include "NetworkUdp.h" -#define WiFiUDP NetworkUDP +typedef NetworkUDP WiFiUDP; diff --git a/libraries/WiFiProv/examples/WiFiProv/README.md b/libraries/WiFiProv/examples/WiFiProv/README.md index b0eb9654a6e..690c27606d0 100644 --- a/libraries/WiFiProv/examples/WiFiProv/README.md +++ b/libraries/WiFiProv/examples/WiFiProv/README.md @@ -8,12 +8,16 @@ This example allows Arduino users to choose either BLE or SOFTAP as the mode of ## APIs introduced for provisioning + ### WiFi.onEvent() + This API can be used to register a function to be called from another -thread for WiFi Events and Provisioning Events. +thread for Wi-Fi Events and Provisioning Events. + ### WiFi.beginProvision() + ``` WiFi.beginProvision(void (*scheme_cb)(), wifi_prov_scheme_event_handler_t scheme_event_handler, wifi_prov_security_t security, char *pop, char *service_name, char *service_key, uint8_t *uuid); @@ -50,7 +54,7 @@ WiFi.beginProvision(void (*scheme_cb)(), wifi_prov_scheme_event_handler_t scheme { 0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02 } ``` -- `reset_provisioned`: Resets previously provisioned data before initializing. Using this prevents problem when the device automatically connects to previously connected WiFi and therefore cannot be found. +- `reset_provisioned`: Resets previously provisioned data before initializing. Using this prevents problem when the device automatically connects to previously connected Wi-Fi and therefore cannot be found. **NOTE:** If none of the parameters are specified in `beginProvision`, default provisioning takes place using SoftAP with the following settings: - `scheme = WIFI_PROV_SCHEME_SOFTAP` @@ -65,7 +69,7 @@ WiFi.beginProvision(void (*scheme_cb)(), wifi_prov_scheme_event_handler_t scheme ## Flashing This sketch takes up a lot of space for the app and may not be able to flash with default setting on some chips. If you see Error like this: "Sketch too big" -In Arduino IDE go to: Tools > Partition scheme > chose anything that has more than 1.4MB APP for example `No OTA (2MB APP/2MB SPIFFS)` +In Arduino IDE go to: Tools > Partition scheme > chose anything that has more than 1.4 MB APP for example `No OTA (2MB APP/2MB SPIFFS)` ## Log Output - To enable debugging: Go to Tools -> Core Debug Level -> Info. diff --git a/libraries/WiFiProv/examples/WiFiProv/WiFiProv.ino b/libraries/WiFiProv/examples/WiFiProv/WiFiProv.ino index 5401c0cf286..76025d75770 100644 --- a/libraries/WiFiProv/examples/WiFiProv/WiFiProv.ino +++ b/libraries/WiFiProv/examples/WiFiProv/WiFiProv.ino @@ -8,6 +8,11 @@ Note: This sketch takes up a lot of space for the app and may not be able to fla - for example "No OTA (2MB APP/2MB SPIFFS)" */ +#include "sdkconfig.h" +#if CONFIG_ESP_WIFI_REMOTE_ENABLED +#error "WiFiProv is only supported in SoCs with native Wi-Fi support" +#endif + #include "WiFiProv.h" #include "WiFi.h" @@ -38,7 +43,7 @@ void SysProvEvent(arduino_event_t *sys_event) { case ARDUINO_EVENT_PROV_CRED_FAIL: { Serial.println("\nProvisioning failed!\nPlease reset to factory and retry provisioning\n"); - if (sys_event->event_info.prov_fail_reason == WIFI_PROV_STA_AUTH_ERROR) { + if (sys_event->event_info.prov_fail_reason == NETWORK_PROV_WIFI_STA_AUTH_ERROR) { Serial.println("\nWi-Fi AP password incorrect"); } else { Serial.println("\nWi-Fi AP not found....Add API \" nvs_flash_erase() \" before beginProvision()"); @@ -53,6 +58,7 @@ void SysProvEvent(arduino_event_t *sys_event) { void setup() { Serial.begin(115200); + WiFi.begin(); // no SSID/PWD - get it from the Provisioning APP or from NVS (last successful connection) WiFi.onEvent(SysProvEvent); // BLE Provisioning using the ESP SoftAP Prov works fine for any BLE SoC, including ESP32, ESP32S3 and ESP32C3. @@ -61,13 +67,13 @@ void setup() { // Sample uuid that user can pass during provisioning using BLE uint8_t uuid[16] = {0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02}; WiFiProv.beginProvision( - WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name, service_key, uuid, reset_provisioned + NETWORK_PROV_SCHEME_BLE, NETWORK_PROV_SCHEME_HANDLER_FREE_BLE, NETWORK_PROV_SECURITY_1, pop, service_name, service_key, uuid, reset_provisioned ); log_d("ble qr"); WiFiProv.printQR(service_name, pop, "ble"); #else Serial.println("Begin Provisioning using Soft AP"); - WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name, service_key); + WiFiProv.beginProvision(NETWORK_PROV_SCHEME_SOFTAP, NETWORK_PROV_SCHEME_HANDLER_NONE, NETWORK_PROV_SECURITY_1, pop, service_name, service_key); log_d("wifi qr"); WiFiProv.printQR(service_name, pop, "softap"); #endif diff --git a/libraries/WiFiProv/examples/WiFiProv/ci.json b/libraries/WiFiProv/examples/WiFiProv/ci.json index d8b3664bc65..04eb62b977a 100644 --- a/libraries/WiFiProv/examples/WiFiProv/ci.json +++ b/libraries/WiFiProv/examples/WiFiProv/ci.json @@ -1,5 +1,6 @@ { - "targets": { - "esp32h2": false - } + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] } diff --git a/libraries/WiFiProv/library.properties b/libraries/WiFiProv/library.properties index 8053d038ced..13a63c50bb1 100644 --- a/libraries/WiFiProv/library.properties +++ b/libraries/WiFiProv/library.properties @@ -1,5 +1,5 @@ name=WiFiProv -version=2.0.0 +version=3.2.0 author=Switi Mhaiske maintainer=Hristo Gochkov sentence=Enables provisioning. diff --git a/libraries/WiFiProv/src/WiFiProv.cpp b/libraries/WiFiProv/src/WiFiProv.cpp index 37084e6568b..31337196b5f 100644 --- a/libraries/WiFiProv/src/WiFiProv.cpp +++ b/libraries/WiFiProv/src/WiFiProv.cpp @@ -18,7 +18,8 @@ */ #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#include "sdkconfig.h" +#if SOC_WIFI_SUPPORTED && CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI #include #include @@ -34,10 +35,10 @@ #include #if CONFIG_BLUEDROID_ENABLED -#include "wifi_provisioning/scheme_ble.h" +#include "network_provisioning/scheme_ble.h" #endif -#include -#include +#include +#include #undef IPADDR_NONE #include "WiFiProv.h" #if CONFIG_IDF_TARGET_ESP32 @@ -61,7 +62,7 @@ static void get_device_service_name(prov_scheme_t prov_scheme, char *service_nam return; } #if CONFIG_IDF_TARGET_ESP32 && defined(CONFIG_BLUEDROID_ENABLED) - if (prov_scheme == WIFI_PROV_SCHEME_BLE) { + if (prov_scheme == NETWORK_PROV_SCHEME_BLE) { snprintf(service_name, max, "%s%02X%02X%02X", SERV_NAME_PREFIX_PROV, eth_mac[3], eth_mac[4], eth_mac[5]); } else { #endif @@ -71,37 +72,35 @@ static void get_device_service_name(prov_scheme_t prov_scheme, char *service_nam #endif } -void WiFiProvClass ::beginProvision( - prov_scheme_t prov_scheme, scheme_handler_t scheme_handler, wifi_prov_security_t security, const char *pop, const char *service_name, const char *service_key, - uint8_t *uuid, bool reset_provisioned -) { - bool provisioned = false; - static char service_name_temp[32]; - - wifi_prov_mgr_config_t config; +void WiFiProvClass ::initProvision(prov_scheme_t prov_scheme, scheme_handler_t scheme_handler, bool reset_provisioned) { + if (this->provInitDone) { + log_i("provInit was already done!"); + return; + } + network_prov_mgr_config_t config; #if CONFIG_BLUEDROID_ENABLED - if (prov_scheme == WIFI_PROV_SCHEME_BLE) { - config.scheme = wifi_prov_scheme_ble; + if (prov_scheme == NETWORK_PROV_SCHEME_BLE) { + config.scheme = network_prov_scheme_ble; } else { #endif - config.scheme = wifi_prov_scheme_softap; + config.scheme = network_prov_scheme_softap; #if CONFIG_BLUEDROID_ENABLED } - if (scheme_handler == WIFI_PROV_SCHEME_HANDLER_NONE) { + if (scheme_handler == NETWORK_PROV_SCHEME_HANDLER_NONE) { #endif - wifi_prov_event_handler_t scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; - memcpy(&config.scheme_event_handler, &scheme_event_handler, sizeof(wifi_prov_event_handler_t)); + network_prov_event_handler_t scheme_event_handler = NETWORK_PROV_EVENT_HANDLER_NONE; + memcpy(&config.scheme_event_handler, &scheme_event_handler, sizeof(network_prov_event_handler_t)); #if CONFIG_BLUEDROID_ENABLED - } else if (scheme_handler == WIFI_PROV_SCHEME_HANDLER_FREE_BTDM) { - wifi_prov_event_handler_t scheme_event_handler = WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM; - memcpy(&config.scheme_event_handler, &scheme_event_handler, sizeof(wifi_prov_event_handler_t)); - } else if (scheme_handler == WIFI_PROV_SCHEME_HANDLER_FREE_BT) { - wifi_prov_event_handler_t scheme_event_handler = WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BT; - memcpy(&config.scheme_event_handler, &scheme_event_handler, sizeof(wifi_prov_event_handler_t)); - } else if (scheme_handler == WIFI_PROV_SCHEME_HANDLER_FREE_BLE) { - wifi_prov_event_handler_t scheme_event_handler = WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BLE; - memcpy(&config.scheme_event_handler, &scheme_event_handler, sizeof(wifi_prov_event_handler_t)); + } else if (scheme_handler == NETWORK_PROV_SCHEME_HANDLER_FREE_BTDM) { + network_prov_event_handler_t scheme_event_handler = NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM; + memcpy(&config.scheme_event_handler, &scheme_event_handler, sizeof(network_prov_event_handler_t)); + } else if (scheme_handler == NETWORK_PROV_SCHEME_HANDLER_FREE_BT) { + network_prov_event_handler_t scheme_event_handler = NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BT; + memcpy(&config.scheme_event_handler, &scheme_event_handler, sizeof(network_prov_event_handler_t)); + } else if (scheme_handler == NETWORK_PROV_SCHEME_HANDLER_FREE_BLE) { + network_prov_event_handler_t scheme_event_handler = NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BLE; + memcpy(&config.scheme_event_handler, &scheme_event_handler, sizeof(network_prov_event_handler_t)); } else { log_e("Unknown scheme handler!"); return; @@ -109,27 +108,38 @@ void WiFiProvClass ::beginProvision( #endif config.app_event_handler.event_cb = NULL; config.app_event_handler.user_data = NULL; - wifiLowLevelInit(true); - if (wifi_prov_mgr_init(config) != ESP_OK) { - log_e("wifi_prov_mgr_init failed!"); + WiFi.STA.begin(false); + if (network_prov_mgr_init(config) != ESP_OK) { + log_e("network_prov_mgr_init failed!"); return; } if (reset_provisioned) { log_i("Resetting provisioned data."); - wifi_prov_mgr_reset_provisioning(); - } else if (wifi_prov_mgr_is_provisioned(&provisioned) != ESP_OK) { - log_e("wifi_prov_mgr_is_provisioned failed!"); - wifi_prov_mgr_deinit(); + network_prov_mgr_reset_wifi_provisioning(); + } else if (network_prov_mgr_is_wifi_provisioned(&(this->provisioned)) != ESP_OK) { + log_e("network_prov_mgr_is_wifi_provisioned failed!"); + network_prov_mgr_deinit(); return; } + this->provInitDone = true; +} + +void WiFiProvClass ::beginProvision( + prov_scheme_t prov_scheme, scheme_handler_t scheme_handler, network_prov_security_t security, const char *pop, const char *service_name, + const char *service_key, uint8_t *uuid, bool reset_provisioned +) { + if (!this->provInitDone) { + WiFiProvClass ::initProvision(prov_scheme, scheme_handler, reset_provisioned); + } + static char service_name_temp[32]; if (provisioned == false) { #if CONFIG_BLUEDROID_ENABLED - if (prov_scheme == WIFI_PROV_SCHEME_BLE) { + if (prov_scheme == NETWORK_PROV_SCHEME_BLE) { service_key = NULL; if (uuid == NULL) { uuid = (uint8_t *)custom_service_uuid; } - wifi_prov_scheme_ble_set_service_uuid(uuid); + network_prov_scheme_ble_set_service_uuid(uuid); } #endif @@ -139,7 +149,7 @@ void WiFiProvClass ::beginProvision( } #if CONFIG_BLUEDROID_ENABLED - if (prov_scheme == WIFI_PROV_SCHEME_BLE) { + if (prov_scheme == NETWORK_PROV_SCHEME_BLE) { log_i("Starting AP using BLE. service_name : %s, pop : %s", service_name, pop); } else { #endif @@ -151,8 +161,8 @@ void WiFiProvClass ::beginProvision( #if CONFIG_BLUEDROID_ENABLED } #endif - if (wifi_prov_mgr_start_provisioning(security, pop, service_name, service_key) != ESP_OK) { - log_e("wifi_prov_mgr_start_provisioning failed!"); + if (network_prov_mgr_start_provisioning(security, pop, service_name, service_key) != ESP_OK) { + log_e("network_prov_mgr_start_provisioning failed!"); return; } } else { @@ -163,13 +173,80 @@ void WiFiProvClass ::beginProvision( log_i("Attempting connect to AP: %s\n", conf.sta.ssid); #endif esp_wifi_start(); - wifi_prov_mgr_deinit(); + network_prov_mgr_deinit(); WiFi.begin(); } } +void WiFiProvClass::endProvision() { + network_prov_mgr_stop_provisioning(); +} + +bool WiFiProvClass::disableAutoStop(uint32_t cleanup_delay) { + esp_err_t err = network_prov_mgr_disable_auto_stop(cleanup_delay); + if (err != ESP_OK) { + log_e("disable_auto_stop failed!"); + } + return err == ESP_OK; +} + // Copied from IDF example -void WiFiProvClass ::printQR(const char *name, const char *pop, const char *transport) { + +#if __has_include("qrcode.h") +static const char *lt[] = { + /* 0 */ " ", + /* 1 */ "\u2580 ", + /* 2 */ " \u2580", + /* 3 */ "\u2580\u2580", + /* 4 */ "\u2584 ", + /* 5 */ "\u2588 ", + /* 6 */ "\u2584\u2580", + /* 7 */ "\u2588\u2580", + /* 8 */ " \u2584", + /* 9 */ "\u2580\u2584", + /* 10 */ " \u2588", + /* 11 */ "\u2580\u2588", + /* 12 */ "\u2584\u2584", + /* 13 */ "\u2588\u2584", + /* 14 */ "\u2584\u2588", + /* 15 */ "\u2588\u2588", +}; + +static Print *qr_out = NULL; + +static void _qrcode_print_console(esp_qrcode_handle_t qrcode) { + int size = esp_qrcode_get_size(qrcode); + int border = 2; + unsigned char num = 0; + + if (qr_out == NULL) { + return; + } + + for (int y = -border; y < size + border; y += 2) { + for (int x = -border; x < size + border; x += 2) { + num = 0; + if (esp_qrcode_get_module(qrcode, x, y)) { + num |= 1 << 0; + } + if ((x < size + border) && esp_qrcode_get_module(qrcode, x + 1, y)) { + num |= 1 << 1; + } + if ((y < size + border) && esp_qrcode_get_module(qrcode, x, y + 1)) { + num |= 1 << 2; + } + if ((x < size + border) && (y < size + border) && esp_qrcode_get_module(qrcode, x + 1, y + 1)) { + num |= 1 << 3; + } + qr_out->print(lt[num]); + } + qr_out->print("\n"); + } + qr_out->print("\n"); +} +#endif + +void WiFiProvClass::printQR(const char *name, const char *pop, const char *transport, Print &out) { if (!name || !transport) { log_w("Cannot generate QR code payload. Data missing."); return; @@ -191,12 +268,15 @@ void WiFiProvClass ::printQR(const char *name, const char *pop, const char *tran ); } #if __has_include("qrcode.h") - log_i("Scan this QR code from the provisioning application for Provisioning."); esp_qrcode_config_t cfg = ESP_QRCODE_CONFIG_DEFAULT(); + cfg.display_func = _qrcode_print_console; + out.printf("Scan this QR code from the provisioning application for Provisioning.\n"); + qr_out = &out; esp_qrcode_generate(&cfg, payload); + qr_out = NULL; + out.printf("If QR code is not visible, copy paste the below URL in a browser.\nhttps://rainmaker.espressif.com/qrcode.html?data=%s\n", payload); #else - log_i("If QR code is not visible, copy paste the below URL in a browser.\n%s?data=%s", "https://espressif.github.io/esp-jumpstart/qrcode.html", payload); - log_i("If you are using Arduino as IDF component, install ESP Rainmaker:\nhttps://github.com/espressif/esp-rainmaker"); + out.println("If you are using Arduino as IDF component, install ESP Rainmaker:\nhttps://github.com/espressif/esp-rainmaker"); #endif } diff --git a/libraries/WiFiProv/src/WiFiProv.h b/libraries/WiFiProv/src/WiFiProv.h index 57794742fc9..b660f8cf064 100644 --- a/libraries/WiFiProv/src/WiFiProv.h +++ b/libraries/WiFiProv/src/WiFiProv.h @@ -20,38 +20,49 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_WIFI_SUPPORTED +#include "sdkconfig.h" +#if SOC_WIFI_SUPPORTED && CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI #include "WiFi.h" -#include "wifi_provisioning/manager.h" +#include "HardwareSerial.h" +#include "network_provisioning/manager.h" //Select the scheme using which you want to provision typedef enum { - WIFI_PROV_SCHEME_SOFTAP, + NETWORK_PROV_SCHEME_SOFTAP, #if CONFIG_BLUEDROID_ENABLED - WIFI_PROV_SCHEME_BLE, + NETWORK_PROV_SCHEME_BLE, #endif - WIFI_PROV_SCHEME_MAX + NETWORK_PROV_SCHEME_MAX } prov_scheme_t; typedef enum { - WIFI_PROV_SCHEME_HANDLER_NONE, + NETWORK_PROV_SCHEME_HANDLER_NONE, #if CONFIG_BLUEDROID_ENABLED - WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, - WIFI_PROV_SCHEME_HANDLER_FREE_BLE, - WIFI_PROV_SCHEME_HANDLER_FREE_BT, + NETWORK_PROV_SCHEME_HANDLER_FREE_BTDM, + NETWORK_PROV_SCHEME_HANDLER_FREE_BLE, + NETWORK_PROV_SCHEME_HANDLER_FREE_BT, #endif - WIFI_PROV_SCHEME_HANDLER_MAX + NETWORK_PROV_SCHEME_HANDLER_MAX } scheme_handler_t; //Provisioning class class WiFiProvClass { +private: + bool provInitDone = false; + bool provisioned = false; + public: + void initProvision( + prov_scheme_t prov_scheme = NETWORK_PROV_SCHEME_SOFTAP, scheme_handler_t scheme_handler = NETWORK_PROV_SCHEME_HANDLER_NONE, bool reset_provisioned = false + ); void beginProvision( - prov_scheme_t prov_scheme = WIFI_PROV_SCHEME_SOFTAP, scheme_handler_t scheme_handler = WIFI_PROV_SCHEME_HANDLER_NONE, - wifi_prov_security_t security = WIFI_PROV_SECURITY_1, const char *pop = "abcd1234", const char *service_name = NULL, const char *service_key = NULL, + prov_scheme_t prov_scheme = NETWORK_PROV_SCHEME_SOFTAP, scheme_handler_t scheme_handler = NETWORK_PROV_SCHEME_HANDLER_NONE, + network_prov_security_t security = NETWORK_PROV_SECURITY_1, const char *pop = "abcd1234", const char *service_name = NULL, const char *service_key = NULL, uint8_t *uuid = NULL, bool reset_provisioned = false ); - void printQR(const char *name, const char *pop, const char *transport); + void endProvision(); + bool disableAutoStop(uint32_t cleanup_delay); + void printQR(const char *name, const char *pop, const char *transport, Print &out = Serial); }; extern WiFiProvClass WiFiProv; diff --git a/libraries/Wire/examples/WireMaster/ci.json b/libraries/Wire/examples/WireMaster/ci.json new file mode 100644 index 00000000000..1844adfc786 --- /dev/null +++ b/libraries/Wire/examples/WireMaster/ci.json @@ -0,0 +1,5 @@ +{ + "requires": [ + "CONFIG_SOC_I2C_SUPPORTED=y" + ] +} diff --git a/libraries/Wire/examples/WireScan/ci.json b/libraries/Wire/examples/WireScan/ci.json new file mode 100644 index 00000000000..1844adfc786 --- /dev/null +++ b/libraries/Wire/examples/WireScan/ci.json @@ -0,0 +1,5 @@ +{ + "requires": [ + "CONFIG_SOC_I2C_SUPPORTED=y" + ] +} diff --git a/libraries/Wire/examples/WireSlave/ci.json b/libraries/Wire/examples/WireSlave/ci.json index 46e0dfffebb..3c877975d62 100644 --- a/libraries/Wire/examples/WireSlave/ci.json +++ b/libraries/Wire/examples/WireSlave/ci.json @@ -1,5 +1,5 @@ { - "targets": { - "esp32c2": false - } + "requires": [ + "CONFIG_SOC_I2C_SUPPORT_SLAVE=y" + ] } diff --git a/libraries/Wire/library.properties b/libraries/Wire/library.properties index 79fddb63065..655f4bd3194 100644 --- a/libraries/Wire/library.properties +++ b/libraries/Wire/library.properties @@ -1,5 +1,5 @@ name=Wire -version=2.0.0 +version=3.2.0 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. For esp8266 boards. diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index 047795f949a..f8d9496389f 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -462,10 +462,11 @@ uint8_t TwoWire::endTransmission(bool sendStop) { nonStop = true; } switch (err) { - case ESP_OK: return 0; - case ESP_FAIL: return 2; - case ESP_ERR_TIMEOUT: return 5; - default: break; + case ESP_OK: return 0; + case ESP_FAIL: return 2; + case ESP_ERR_NOT_FOUND: return 2; + case ESP_ERR_TIMEOUT: return 5; + default: break; } return 4; } @@ -646,6 +647,16 @@ void TwoWire::onRequestService(uint8_t num, void *arg) { #endif /* SOC_I2C_SUPPORT_SLAVE */ TwoWire Wire = TwoWire(0); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0) +#if SOC_I2C_NUM > 1 TwoWire Wire1 = TwoWire(1); +#elif SOC_I2C_NUM > 2 +TwoWire Wire2 = TwoWire(2); +#endif /* SOC_I2C_NUM */ +#else +#if SOC_HP_I2C_NUM > 1 +TwoWire Wire1 = TwoWire(1); +#endif /* SOC_HP_I2C_NUM */ +#endif #endif /* SOC_I2C_SUPPORTED */ diff --git a/libraries/Wire/src/Wire.h b/libraries/Wire/src/Wire.h index fcf94313d52..0deab7d4a57 100644 --- a/libraries/Wire/src/Wire.h +++ b/libraries/Wire/src/Wire.h @@ -28,6 +28,7 @@ #include "soc/soc_caps.h" #if SOC_I2C_SUPPORTED +#include "esp_idf_version.h" #include #include @@ -144,7 +145,17 @@ class TwoWire : public HardwareI2C { }; extern TwoWire Wire; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0) +#if SOC_I2C_NUM > 1 extern TwoWire Wire1; +#elif SOC_I2C_NUM > 2 +extern TwoWire Wire2; +#endif /* SOC_I2C_NUM */ +#else +#if SOC_HP_I2C_NUM > 1 +extern TwoWire Wire1; +#endif /* SOC_HP_I2C_NUM */ +#endif #endif /* SOC_I2C_SUPPORTED */ #endif /* TwoWire_h */ diff --git a/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/README.md b/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/README.md new file mode 100644 index 00000000000..d62941755c7 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/README.md @@ -0,0 +1,72 @@ +# Arduino-ESP32 Zigbee Analog Input Output Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) analog input/output device. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Analog Sensor Functions + + * After this board first starts up, it would be configured locally to report an analog input on change or every 30 seconds. + * By clicking the button (BOOT) on this board, this board will immediately send a report of the current measured value to the network. + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +Set the ADC GPIO by changing the `analogPin` variable. By default, it's the pin `A0`. +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (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 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example 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`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***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/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino b/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino new file mode 100644 index 00000000000..e31407cc8be --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino @@ -0,0 +1,119 @@ +// Copyright 2025 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 Zigbee analog input / output device. + * + * The example demonstrates how to use Zigbee library to create a end device analog device. + * + * 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/) + * Modified by Pat Clay + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +/* Zigbee analog device configuration */ +#define ANALOG_DEVICE_ENDPOINT_NUMBER 1 + +uint8_t analogPin = A0; +uint8_t button = BOOT_PIN; + +ZigbeeAnalog zbAnalogDevice = ZigbeeAnalog(ANALOG_DEVICE_ENDPOINT_NUMBER); + +void onAnalogOutputChange(float analog_output) { + Serial.printf("Received analog output change: %.1f\r\n", analog_output); +} + +void setup() { + Serial.begin(115200); + Serial.println("Starting..."); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Set analog resolution to 10 bits + analogReadResolution(10); + + // Optional: set Zigbee device name and model + zbAnalogDevice.setManufacturerAndModel("Espressif", "ZigbeeAnalogDevice"); + + // Add analog clusters to Zigbee Analog according your needs + zbAnalogDevice.addAnalogInput(); + zbAnalogDevice.addAnalogOutput(); + + // If analog output cluster is added, set callback function for analog output change + zbAnalogDevice.onAnalogOutputChange(onAnalogOutputChange); + + // Add endpoints to Zigbee Core + Zigbee.addEndpoint(&zbAnalogDevice); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println("Connected"); + + // Optional: Add reporting for analog input + zbAnalogDevice.setAnalogInputReporting(0, 30, 10); // report every 30 seconds if value changes by 10 +} + +void loop() { + static uint32_t timeCounter = 0; + + // Read ADC value and update the analog value every 2s + if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s + float analog = (float)analogRead(analogPin); + Serial.printf("Updating analog input to %.1f\r\n", analog); + zbAnalogDevice.setAnalogInput(analog); + + // Analog input supports reporting + zbAnalogDevice.reportAnalogInput(); + } + + // Checking button for factory reset and reporting + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/ci.json b/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/README.md new file mode 100644 index 00000000000..88c8bf04a65 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/README.md @@ -0,0 +1,72 @@ +# Arduino-ESP32 Carbon dioxide (CO2) Sensor Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) simple sensor device type with carbon dioxide measuring. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Pressure + Flow Sensor Functions + + * After this board first starts up, it would be configured locally to report the carbon dioxide on every 30 seconds. + * By clicking the button (BOOT) on this board, this board will immediately send a report of the current measured carbon dioxide to the network. + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +In this example, the internal temperature sensor is used to demonstrate reading of the carbon dioxide sensors. +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (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 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example 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`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***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/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/Zigbee_CarbonDioxide_Sensor.ino b/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/Zigbee_CarbonDioxide_Sensor.ino new file mode 100644 index 00000000000..47b9a05493f --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/Zigbee_CarbonDioxide_Sensor.ino @@ -0,0 +1,106 @@ +// 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 Zigbee carbon dioxide sensor. + * + * The example demonstrates how to use Zigbee library to create a end device carbon dioxide sensor. + * + * 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 "Zigbee.h" + +/* Zigbee carbon dioxide sensor configuration */ +#define CARBON_DIOXIDE_SENSOR_ENDPOINT_NUMBER 10 +uint8_t button = BOOT_PIN; + +ZigbeeCarbonDioxideSensor zbCarbonDioxideSensor = ZigbeeCarbonDioxideSensor(CARBON_DIOXIDE_SENSOR_ENDPOINT_NUMBER); + +void setup() { + Serial.begin(115200); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Optional: set Zigbee device name and model + zbCarbonDioxideSensor.setManufacturerAndModel("Espressif", "ZigbeeCarbonDioxideSensor"); + + // Set minimum and maximum carbon dioxide measurement value in ppm + zbCarbonDioxideSensor.setMinMaxValue(0, 1500); + + // Add endpoints to Zigbee Core + Zigbee.addEndpoint(&zbCarbonDioxideSensor); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // Set reporting interval for carbon dioxide measurement to be done every 30 seconds, must be called after Zigbee.begin() + // min_interval and max_interval in seconds, delta (carbon dioxide change in ppm) + // if min = 1 and max = 0, reporting is sent only when carbon dioxide changes by delta + // if min = 0 and max = 10, reporting is sent every 10 seconds or when carbon dioxide changes by delta + // if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of delta change + zbCarbonDioxideSensor.setReporting(0, 30, 0); +} + +void loop() { + static uint32_t timeCounter = 0; + // Read carbon dioxide sensor every 2s + if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s + // Read sensor value - here is chip temperature used + 300 as a dummy value for demonstration + uint16_t carbon_dioxide_value = 300 + (uint16_t)temperatureRead(); + Serial.printf("Updating carbon dioxide sensor value to %d ppm\r\n", carbon_dioxide_value); + zbCarbonDioxideSensor.setCarbonDioxide(carbon_dioxide_value); + } + + // Checking button for factory reset and reporting + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + zbCarbonDioxideSensor.report(); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md new file mode 100644 index 00000000000..4da23c8c7d2 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md @@ -0,0 +1,68 @@ +# Arduino-ESP32 Zigbee Color Dimmable Light Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) color dimmable 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_Color_Dimmer_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_Color_Dimmable_Light example + +### Configure the Project + +Set the LED GPIO by changing the `LED_PIN` definition. By default, the LED_PIN is `RGB_BUILTIN`. + +#### 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example 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`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***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/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino new file mode 100644 index 00000000000..e84720d4863 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino @@ -0,0 +1,122 @@ +// 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 Zigbee Color Dimmable light bulb. + * + * The example demonstrates how to use Zigbee library to create an end device with + * color dimmable light end point. + * 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 "Zigbee.h" + +/* Zigbee color dimmable light configuration */ +#define ZIGBEE_RGB_LIGHT_ENDPOINT 10 +uint8_t led = RGB_BUILTIN; +uint8_t button = BOOT_PIN; + +ZigbeeColorDimmableLight zbColorLight = ZigbeeColorDimmableLight(ZIGBEE_RGB_LIGHT_ENDPOINT); + +/********************* RGB LED functions **************************/ +void setRGBLight(bool state, uint8_t red, uint8_t green, uint8_t blue, uint8_t level) { + if (!state) { + rgbLedWrite(led, 0, 0, 0); + return; + } + float brightness = (float)level / 255; + rgbLedWrite(led, red * brightness, green * brightness, blue * brightness); +} + +// Create a task on identify call to handle the identify function +void identify(uint16_t time) { + static uint8_t blink = 1; + log_d("Identify called for %d seconds", time); + if (time == 0) { + // If identify time is 0, stop blinking and restore light as it was used for identify + zbColorLight.restoreLight(); + return; + } + rgbLedWrite(led, 255 * blink, 255 * blink, 255 * blink); + blink = !blink; +} + +/********************* Arduino functions **************************/ +void setup() { + Serial.begin(115200); + + // Init RMT and leave light OFF + rgbLedWrite(led, 0, 0, 0); + + // Init button for factory reset + pinMode(button, INPUT_PULLUP); + + // Set callback function for light change + zbColorLight.onLightChange(setRGBLight); + + // Optional: Set callback function for device identify + zbColorLight.onIdentify(identify); + + // Optional: Set Zigbee device name and model + zbColorLight.setManufacturerAndModel("Espressif", "ZBColorLightBulb"); + + // Add endpoint to Zigbee Core + Serial.println("Adding ZigbeeLight endpoint to Zigbee Core"); + Zigbee.addEndpoint(&zbColorLight); + + // When all EPs are registered, start Zigbee in End Device mode + 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) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + // Increase blightness by 50 every time the button is pressed + zbColorLight.setLightLevel(zbColorLight.getLightLevel() + 50); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md new file mode 100644 index 00000000000..8dd63a78c5e --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md @@ -0,0 +1,68 @@ +# Arduino-ESP32 Zigbee Color Dimmer Switch Example + +This example shows how to configure Zigbee Coordinator and use it as a Home Automation (HA) color dimmer 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_Color_Dimmable_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_Color_Dimmable_Light example. + +### Configure the Project + +Set the Button Switch GPIO by changing the `GPIO_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 verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with the example `Zigbee_Color_Dimmable_Light` 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`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***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/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino new file mode 100644 index 00000000000..a313f3c0594 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino @@ -0,0 +1,147 @@ +// 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 Zigbee color dimmer switch. + * + * The example demonstrates how to use Zigbee library to control a RGB light bulb. + * The RGB light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator (Switch). + * To turn on/off the light, push the button on the switch. + * To change the color or level of the light, send serial commands to the switch. + * + * By setting the switch to allow multiple binding, so it can bind to multiple lights. + * Also every 30 seconds, all bound lights are printed to the serial console. + * + * 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 "Zigbee.h" + +/* Zigbee color dimmer switch configuration */ +#define SWITCH_ENDPOINT_NUMBER 5 +uint8_t button = BOOT_PIN; + +/* Zigbee switch */ +ZigbeeColorDimmerSwitch zbSwitch = ZigbeeColorDimmerSwitch(SWITCH_ENDPOINT_NUMBER); + +/********************* Arduino functions **************************/ +void setup() { + Serial.begin(115200); + + //Init button switch + pinMode(button, INPUT_PULLUP); + + //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 + Zigbee.addEndpoint(&zbSwitch); + + //Open network for 180 seconds after boot + Zigbee.setRebootOpenNetwork(180); + + //When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode + 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.bound()) { + Serial.printf("."); + delay(500); + } + Serial.println(); +} + +void loop() { + // Handle button switch in loop() + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + while (digitalRead(button) == LOW) { + delay(50); + } + // Toggle light + zbSwitch.lightToggle(); + } + // Handle serial input to control color and level of the light + if (Serial.available()) { + String command = Serial.readString(); + + if (command == "on") { + zbSwitch.lightOn(); + } else if (command == "off") { + zbSwitch.lightOff(); + } else if (command == "toggle") { + zbSwitch.lightToggle(); + } else if (command == "red") { + zbSwitch.setLightColor(255, 0, 0); + } else if (command == "green") { + zbSwitch.setLightColor(0, 255, 0); + } else if (command == "blue") { + zbSwitch.setLightColor(0, 0, 255); + } else if (command == "white") { + zbSwitch.setLightColor(255, 255, 255); + } else if (command == "color") { + //wait for color value + Serial.println("Enter red value (0-255):"); + while (!Serial.available()) { + delay(100); + } + int red = Serial.parseInt(); + Serial.println("Enter green value (0-255):"); + while (!Serial.available()) { + delay(100); + } + int green = Serial.parseInt(); + Serial.println("Enter blue value (0-255):"); + while (!Serial.available()) { + delay(100); + } + int blue = Serial.parseInt(); + zbSwitch.setLightColor(red, green, blue); + } else if (command == "level") { + //wait for level value + Serial.println("Enter level value (0-255):"); + while (!Serial.available()) { + delay(100); + } + int level = Serial.parseInt(); + zbSwitch.setLightLevel(level); + } else { + Serial.println("Unknown command"); + } + } + + // print the bound devices (lights) every 30 seconds + static uint32_t last_print = 0; + if (millis() - last_print > 30000) { + last_print = millis(); + zbSwitch.printBoundDevices(Serial); + } +} diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json new file mode 100644 index 00000000000..15d6190e4ae --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json @@ -0,0 +1,6 @@ +{ + "fqbn_append": "PartitionScheme=zigbee_zczr,ZigbeeMode=zczr", + "requires": [ + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Contact_Switch/README.md b/libraries/Zigbee/examples/Zigbee_Contact_Switch/README.md new file mode 100644 index 00000000000..a5a32358a7c --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Contact_Switch/README.md @@ -0,0 +1,58 @@ +# Arduino-ESP32 Zigbee Contact Switch Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) contact switch (IAS Zone), +that can be used for example as window/door sensor having 2 states - closed/open. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). +Set the Sensor GPIO by changing the `sensor_pin` variable. + +#### 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash of the End device before flashing the example to the board. + +***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/libraries/Zigbee/examples/Zigbee_Contact_Switch/Zigbee_Contact_Switch.ino b/libraries/Zigbee/examples/Zigbee_Contact_Switch/Zigbee_Contact_Switch.ino new file mode 100644 index 00000000000..ce9eedb683d --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Contact_Switch/Zigbee_Contact_Switch.ino @@ -0,0 +1,100 @@ +// 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 Zigbee contact switch (IAS Zone). + * + * The example demonstrates how to use Zigbee library to create a end device contact switch. + * The contact switch is a Zigbee end device, which is reporting data to the Zigbee network. + * + * 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 "Zigbee.h" + +/* Zigbee contact sensor configuration */ +#define CONTACT_SWITCH_ENDPOINT_NUMBER 10 +uint8_t button = BOOT_PIN; +uint8_t sensor_pin = 4; + +ZigbeeContactSwitch zbContactSwitch = ZigbeeContactSwitch(CONTACT_SWITCH_ENDPOINT_NUMBER); + +void setup() { + Serial.begin(115200); + + // Init button + switch + pinMode(button, INPUT_PULLUP); + pinMode(sensor_pin, INPUT_PULLUP); + + // Optional: set Zigbee device name and model + zbContactSwitch.setManufacturerAndModel("Espressif", "ZigbeeContactSwitch"); + + // Add endpoint to Zigbee Core + Zigbee.addEndpoint(&zbContactSwitch); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); +} + +void loop() { + // Checking pin for contact change + static bool contact = false; + if (digitalRead(sensor_pin) == HIGH && !contact) { + // Update contact sensor value + zbContactSwitch.setOpen(); + contact = true; + } else if (digitalRead(sensor_pin) == LOW && contact) { + zbContactSwitch.setClosed(); + contact = false; + } + + // Checking button for factory reset + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Contact_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_Contact_Switch/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Contact_Switch/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Dimmable_Light/README.md b/libraries/Zigbee/examples/Zigbee_Dimmable_Light/README.md new file mode 100644 index 00000000000..e5bf51b660c --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Dimmable_Light/README.md @@ -0,0 +1,68 @@ +# Arduino-ESP32 Zigbee Dimmable Light Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) dimmable light. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* A USB cable for power supply and programming +* Board (ESP32-H2 or ESP32-C6) as Zigbee end device and upload the Zigbee_Dimmable_Light example +* Zigbee network / coordinator (Other board with switch examples or Zigbee2mqtt or ZigbeeHomeAssistant like application) + +### Configure the Project + +Set the LED GPIO by changing the `LED_PIN` definition. By default, the LED_PIN is `RGB_BUILTIN`. + +#### 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example 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`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***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/libraries/Zigbee/examples/Zigbee_Dimmable_Light/Zigbee_Dimmable_Light.ino b/libraries/Zigbee/examples/Zigbee_Dimmable_Light/Zigbee_Dimmable_Light.ino new file mode 100644 index 00000000000..c77a7e742d1 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Dimmable_Light/Zigbee_Dimmable_Light.ino @@ -0,0 +1,121 @@ +// 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 Zigbee Dimmable light bulb. + * + * The example demonstrates how to use Zigbee library to create an end device with + * dimmable light end point. + * 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 [FaBjE](https://github.com/FaBjE) based on examples 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 "Zigbee.h" + +/* Zigbee dimmable light configuration */ +#define ZIGBEE_LIGHT_ENDPOINT 10 +uint8_t led = RGB_BUILTIN; +uint8_t button = BOOT_PIN; + +ZigbeeDimmableLight zbDimmableLight = ZigbeeDimmableLight(ZIGBEE_LIGHT_ENDPOINT); + +/********************* RGB LED functions **************************/ +void setLight(bool state, uint8_t level) { + if (!state) { + rgbLedWrite(led, 0, 0, 0); + return; + } + rgbLedWrite(led, level, level, level); +} + +// Create a task on identify call to handle the identify function +void identify(uint16_t time) { + static uint8_t blink = 1; + log_d("Identify called for %d seconds", time); + if (time == 0) { + // If identify time is 0, stop blinking and restore light as it was used for identify + zbDimmableLight.restoreLight(); + return; + } + rgbLedWrite(led, 255 * blink, 255 * blink, 255 * blink); + blink = !blink; +} + +/********************* Arduino functions **************************/ +void setup() { + Serial.begin(115200); + + // Init RMT and leave light OFF + rgbLedWrite(led, 0, 0, 0); + + // Init button for factory reset + pinMode(button, INPUT_PULLUP); + + // Set callback function for light change + zbDimmableLight.onLightChange(setLight); + + // Optional: Set callback function for device identify + zbDimmableLight.onIdentify(identify); + + // Optional: Set Zigbee device name and model + zbDimmableLight.setManufacturerAndModel("Espressif", "ZBLightBulb"); + + // Add endpoint to Zigbee Core + Serial.println("Adding ZigbeeLight endpoint to Zigbee Core"); + Zigbee.addEndpoint(&zbDimmableLight); + + // When all EPs are registered, start Zigbee in End Device mode + 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) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + // Increase blightness by 50 every time the button is pressed + zbDimmableLight.setLightLevel(zbDimmableLight.getLightLevel() + 50); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Dimmable_Light/ci.json b/libraries/Zigbee/examples/Zigbee_Dimmable_Light/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Dimmable_Light/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Gateway/README.md b/libraries/Zigbee/examples/Zigbee_Gateway/README.md new file mode 100644 index 00000000000..4156538ccd9 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Gateway/README.md @@ -0,0 +1,64 @@ +# Arduino-ESP32 Zigbee Gateway Example + +This example shows how to configure Zigbee Gateway device, running on SoCs without native IEEE 802.15.4. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 | ESP32-C3 | +| ----------------- | ----- | -------- | -------- | -------- | + +## Hardware Required + +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee Radio Co-processor loaded with [ot_rcp example](https://github.com/espressif/esp-idf/tree/master/examples/openthread/ot_rcp). +* A USB cable for power supply and programming. +* Choose another board from supported targets as Zigbee coordinator/router and upload the Zigbee_Gateway example. + +### Configure the Project + +Set the RCP connection (UART) by changing the `GATEWAY_RCP_UART_PORT`, `GATEWAY_RCP_RX_PIN` and `GATEWAY_RCP_TX_PIN` definition. + +#### 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 verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***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/libraries/Zigbee/examples/Zigbee_Gateway/Zigbee_Gateway.ino b/libraries/Zigbee/examples/Zigbee_Gateway/Zigbee_Gateway.ino new file mode 100644 index 00000000000..402227b9a3d --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Gateway/Zigbee_Gateway.ino @@ -0,0 +1,130 @@ +// Copyright 2025 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 Gateway functionality. + * + * The example demonstrates how to use Zigbee library on ESP32s to create a Zigbee Gateway, updating the time from NTP server. + * The Gateway is able to communicate with Zigbee end devices and send/receive data to/from them. + * The Gateway is also able to communicate with the cloud or other devices over Wi-Fi / BLE. + * + * Proper Zigbee mode must be selected in Tools->Zigbee mode->Zigbee ZCZR (coordinator/router) + * and also the correct partition scheme must be selected in Tools->Partition Scheme->Zigbee ZCZR + * + * 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 "Zigbee.h" +#include +#include "time.h" +#include "esp_sntp.h" + +/* Zigbee gateway configuration */ +#define GATEWAY_ENDPOINT_NUMBER 1 +#define GATEWAY_RCP_UART_PORT UART_NUM_1 // UART 0 is used for Serial communication +#define GATEWAY_RCP_RX_PIN 4 +#define GATEWAY_RCP_TX_PIN 5 + +ZigbeeGateway zbGateway = ZigbeeGateway(GATEWAY_ENDPOINT_NUMBER); + +/* Wi-Fi credentials */ +const char *ssid = "your-ssid"; +const char *password = "your-password"; + +/* NTP server configuration */ +const char *ntpServer1 = "pool.ntp.org"; +const char *ntpServer2 = "time.nist.gov"; +const long gmtOffset_sec = 3600; +const int daylightOffset_sec = 3600; +const char *time_zone = "CET-1CEST,M3.5.0,M10.5.0/3"; // TimeZone rule for Europe/Rome including daylight adjustment rules (optional) + +/* Time structure */ +struct tm timeinfo; + +/********************* Arduino functions **************************/ +void setup() { + Serial.begin(115200); + + // Initialize Wi-Fi and connect to AP + WiFi.begin(ssid, password); + esp_sntp_servermode_dhcp(1); // (optional) + + Serial.print("Connecting to WiFi"); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println("WiFi connected"); + + // Initialize Zigbee and Begin Zigbee stack + // Optional: set Zigbee device name and model + zbGateway.setManufacturerAndModel("Espressif", "ZigbeeGateway"); + zbGateway.addTimeCluster(timeinfo, gmtOffset_sec); + + // Add endpoint to Zigbee Core + Serial.println("Adding Zigbee Gateway endpoint"); + Zigbee.addEndpoint(&zbGateway); + + // Optional: Open network for 180 seconds after boot + Zigbee.setRebootOpenNetwork(180); + + // Set custom radio configuration for RCP communication + esp_zb_radio_config_t radio_config = ZIGBEE_DEFAULT_UART_RCP_RADIO_CONFIG(); + radio_config.radio_uart_config.port = GATEWAY_RCP_UART_PORT; + radio_config.radio_uart_config.rx_pin = (gpio_num_t)GATEWAY_RCP_RX_PIN; + radio_config.radio_uart_config.tx_pin = (gpio_num_t)GATEWAY_RCP_TX_PIN; + + Zigbee.setRadioConfig(radio_config); + + // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR or ZIGBEE_ROUTER mode + if (!Zigbee.begin(ZIGBEE_COORDINATOR)) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } + + // set notification call-back function + sntp_set_time_sync_notification_cb(timeavailable); + sntp_set_sync_interval(30000); // sync every 30 seconds + + // config time zone and NTP servers + configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2); +} + +void loop() { + // Nothing to do here in this example +} + +void printLocalTime() { + if (!getLocalTime(&timeinfo)) { + Serial.println("No time available (yet)"); + return; + } + Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); + zbGateway.setTime(timeinfo); + Serial.println("Time updated in Zigbee Gateway"); +} + +// Callback function (gets called when time adjusts via NTP) +void timeavailable(struct timeval *t) { + Serial.println("Got time adjustment from NTP!"); + printLocalTime(); +} diff --git a/libraries/Zigbee/examples/Zigbee_Gateway/ci.json b/libraries/Zigbee/examples/Zigbee_Gateway/ci.json new file mode 100644 index 00000000000..23e1c59d1da --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Gateway/ci.json @@ -0,0 +1,10 @@ +{ + "fqbn_append": "PartitionScheme=zigbee_zczr_8MB,ZigbeeMode=zczr", + "requires": [ + "CONFIG_ZB_ENABLED=y" + ], + "targets": { + "esp32c6": false, + "esp32h2": false + } +} diff --git a/libraries/Zigbee/examples/Zigbee_Illuminance_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Illuminance_Sensor/README.md new file mode 100644 index 00000000000..fe723696d5a --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Illuminance_Sensor/README.md @@ -0,0 +1,78 @@ +# Arduino-ESP32 Zigbee Illuminance Sensor Example + +This example demonstrates how to use the Zigbee library to create an end device illuminance sensor and use it as a Home Automation (HA) extended illuminance sensor. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Illuminance Sensor Functions + +1. Initialize a Zigbee illuminance sensor. +2. Measure illuminance value. +3. Report the measured value to the Zigbee network. + +## Hardware Required + +* ESP32-H2 or ESP32-C6 development board +* A USB cable for power supply and programming +* Some kind of light sensor, such as a photoresistor + +### Configure the Project + +In this example the raw analog value of a light sensor is used to calculate illuminance. +Alter the calculation according to your use case and calibrate it to receive correct lux values. +Set the illuminance sensor GPIO by changing the `illuminance_sensor_pin` variable to the pin to the pin to which your sensor is connected. +Set the button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (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 End device Zigbee mode: `Tools -> Zigbee mode: Zigbee ED (end device)` +* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` +* Enable USB CDC to be able to use the serial monitor: `Tools -> USB CDC On Boot: Enabled` +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example 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`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***Important: Make sure that you are using a good quality USB cable with data lines 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/libraries/Zigbee/examples/Zigbee_Illuminance_Sensor/Zigbee_Illuminance_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Illuminance_Sensor/Zigbee_Illuminance_Sensor.ino new file mode 100644 index 00000000000..bbb2cba569f --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Illuminance_Sensor/Zigbee_Illuminance_Sensor.ino @@ -0,0 +1,141 @@ +// Copyright 2025 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 Zigbee illuminance sensor. + * + * The example demonstrates how to use Zigbee library to create a end device illuminance sensor. + * The illuminance sensor 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 MikaFromTheRoof (https://github.com/MikaFromTheRoof) + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +#define ZIGBEE_ILLUMINANCE_SENSOR_ENDPOINT 9 +uint8_t button = BOOT_PIN; +uint8_t illuminance_sensor_pin = 6; // Insert the analog pin to which the sensor (e.g. photoresistor) is connected + +ZigbeeIlluminanceSensor zbIlluminanceSensor = ZigbeeIlluminanceSensor(ZIGBEE_ILLUMINANCE_SENSOR_ENDPOINT); + +/********************* Illuminance sensor **************************/ +static void illuminance_sensor_value_update(void *arg) { + for (;;) { + // read the raw analog value from the sensor + int lsens_analog_raw = analogRead(illuminance_sensor_pin); + Serial.printf("[Illuminance Sensor] raw analog value: %d\r\n", lsens_analog_raw); + + // conversion into zigbee raw illuminance value (typically between 0 in darkness and 50000 in direct sunlight) + // depends on the value range of the raw analog sensor values and will need calibration for correct lux values + // for demonstration purpose map the 12-bit ADC value (0-4095) to Zigbee illuminance range (0-50000) + int lsens_illuminance_raw = map(lsens_analog_raw, 0, 4095, 0, 50000); + Serial.printf("[Illuminance Sensor] raw illuminance value: %d\r\n", lsens_illuminance_raw); + + // according to zigbee documentation the formular 10^(lsens_illuminance_raw/10000)-1 can be used to calculate lux value from raw illuminance value + // Note: Zigbee2MQTT seems to be using the formular 10^(lsens_illuminance_raw/10000) instead (without -1) + int lsens_illuminance_lux = round(pow(10, (lsens_illuminance_raw / 10000.0)) - 1); + Serial.printf("[Illuminance Sensor] lux value: %d lux\r\n", lsens_illuminance_lux); + + // Update illuminance in illuminance sensor EP + zbIlluminanceSensor.setIlluminance(lsens_illuminance_raw); // use raw illuminance here! + + delay(1000); // reduce delay (in ms), if you want your device to react more quickly to changes in illuminance + } +} + +/********************* Arduino functions **************************/ +void setup() { + Serial.begin(115200); + + // Optional: configure analog input + analogSetAttenuation(ADC_11db); // set analog to digital converter (ADC) attenuation to 11 dB (up to ~3.3V input) + analogReadResolution(12); // set analog read resolution to 12 bits (value range from 0 to 4095), 12 is default + + // Init button for factory reset + pinMode(button, INPUT_PULLUP); + + // Optional: Set Zigbee device name and model + zbIlluminanceSensor.setManufacturerAndModel("Espressif", "ZigbeeIlluminanceSensor"); + + // Optional: Set power source (choose between ZB_POWER_SOURCE_MAINS and ZB_POWER_SOURCE_BATTERY), defaults to unknown + zbIlluminanceSensor.setPowerSource(ZB_POWER_SOURCE_MAINS); + + // Set minimum and maximum for raw illuminance value (0 min and 50000 max equals to 0 lux - 100,000 lux) + zbIlluminanceSensor.setMinMaxValue(0, 50000); + + // Optional: Set tolerance for raw illuminance value + zbIlluminanceSensor.setTolerance(1); + + // Add endpoint to Zigbee Core + Serial.println("Adding Zigbee illuminance sensor endpoint to Zigbee Core"); + Zigbee.addEndpoint(&zbIlluminanceSensor); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // Start illuminance sensor reading task + xTaskCreate(illuminance_sensor_value_update, "illuminance_sensor_update", 2048, NULL, 10, NULL); + + // Set reporting schedule for illuminance value measurement in seconds, must be called after Zigbee.begin() + // min_interval and max_interval in seconds, delta + // if min = 1 and max = 0, delta = 1000, reporting is sent when raw illuminance value changes by 1000, but at most once per second + // if min = 0 and max = 10, delta = 1000, reporting is sent every 10 seconds or if raw illuminance value changes by 1000 + // if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of illuminance change + // Note: On pairing with Zigbee Home Automation or Zigbee2MQTT the reporting schedule will most likely be overwritten with their default settings + zbIlluminanceSensor.setReporting(1, 0, 1000); +} + +/********************* Main loop **************************/ +void loop() { + // Checking button for factory reset + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3 secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s"); + delay(1000); + Zigbee.factoryReset(); + } + } + // force report of illuminance when button is pressed + zbIlluminanceSensor.report(); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Illuminance_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Illuminance_Sensor/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Illuminance_Sensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_OTA_Client/README.md b/libraries/Zigbee/examples/Zigbee_OTA_Client/README.md new file mode 100644 index 00000000000..143ff946f28 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_OTA_Client/README.md @@ -0,0 +1,68 @@ +# Arduino-ESP32 Zigbee OTA Client + on/off light Example + +This example shows how to configure the Zigbee end device with OTA Client 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 + +* A USB cable for power supply and programming + +### Configure the Project + +Set the LED GPIO by changing the `LED_PIN` definition. By default, the LED_PIN is `RGB_BUILTIN`. +By default, the `rgbLedWrite` 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example 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`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + + +***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/libraries/Zigbee/examples/Zigbee_OTA_Client/Zigbee_OTA_Client.ino b/libraries/Zigbee/examples/Zigbee_OTA_Client/Zigbee_OTA_Client.ino new file mode 100644 index 00000000000..29d114014b4 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_OTA_Client/Zigbee_OTA_Client.ino @@ -0,0 +1,112 @@ +// 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 OTA support on light bulb. + * + * The example demonstrates how to use Zigbee library to create a end device light bulb with OTA support. + * 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 "Zigbee.h" + +/* Zigbee light bulb configuration */ +#define ZIGBEE_LIGHT_ENDPOINT 1 +uint8_t led = RGB_BUILTIN; +uint8_t button = BOOT_PIN; + +/* Zigbee OTA configuration */ +#define OTA_UPGRADE_RUNNING_FILE_VERSION 0x01010100 // Increment this value when the running image is updated +#define OTA_UPGRADE_DOWNLOADED_FILE_VERSION 0x01010101 // Increment this value when the downloaded image is updated +#define OTA_UPGRADE_HW_VERSION 0x0101 // The hardware version, this can be used to differentiate between different hardware versions + +ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT); + +/********************* RGB LED functions **************************/ +void setLED(bool 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, OUTPUT); + digitalWrite(led, LOW); + + // Init button for factory reset + pinMode(button, INPUT_PULLUP); + + // Optional: set Zigbee device name and model + zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb"); + + // Set callback function for light change + zbLight.onLightChange(setLED); + + // Add OTA client to the light bulb + zbLight.addOTAClient(OTA_UPGRADE_RUNNING_FILE_VERSION, OTA_UPGRADE_DOWNLOADED_FILE_VERSION, OTA_UPGRADE_HW_VERSION); + + // Add 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 + 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(); + + // Start Zigbee OTA client query, first request is within a minute and the next requests are sent every hour automatically + zbLight.requestOTAUpdate(); +} + +void loop() { + // Checking button for factory reset + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + 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); +} diff --git a/libraries/Zigbee/examples/Zigbee_OTA_Client/ci.json b/libraries/Zigbee/examples/Zigbee_OTA_Client/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_OTA_Client/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/README.md new file mode 100644 index 00000000000..0c5dcd013f2 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/README.md @@ -0,0 +1,57 @@ +# Arduino-ESP32 Zigbee Occupancy Sensor Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) occupancy sensor (PIR). + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). +Set the Sensor GPIO by changing the `sensor_pin` variable. + +#### 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash of the End device before flashing the example to the board. + +***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/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/Zigbee_Occupancy_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/Zigbee_Occupancy_Sensor.ino new file mode 100644 index 00000000000..46afdf3d273 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/Zigbee_Occupancy_Sensor.ino @@ -0,0 +1,103 @@ +// 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 Zigbee occupancy sensor. + * + * The example demonstrates how to use Zigbee library to create a end device occupancy sensor. + * The occupancy sensor is a Zigbee end device, which is reporting data to the Zigbee network. + * Tested with PIR sensor HC-SR501 connected to GPIO4. + * + * 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 "Zigbee.h" + +/* Zigbee occupancy sensor configuration */ +#define OCCUPANCY_SENSOR_ENDPOINT_NUMBER 10 +uint8_t button = BOOT_PIN; +uint8_t sensor_pin = 4; + +ZigbeeOccupancySensor zbOccupancySensor = ZigbeeOccupancySensor(OCCUPANCY_SENSOR_ENDPOINT_NUMBER); + +void setup() { + Serial.begin(115200); + + // Init button + PIR sensor + pinMode(button, INPUT_PULLUP); + pinMode(sensor_pin, INPUT); + + // Optional: set Zigbee device name and model + zbOccupancySensor.setManufacturerAndModel("Espressif", "ZigbeeOccupancyPIRSensor"); + + // Add endpoint to Zigbee Core + Zigbee.addEndpoint(&zbOccupancySensor); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); +} + +void loop() { + // Checking PIR sensor for occupancy change + static bool occupancy = false; + if (digitalRead(sensor_pin) == HIGH && !occupancy) { + // Update occupancy sensor value + zbOccupancySensor.setOccupancy(true); + zbOccupancySensor.report(); + occupancy = true; + } else if (digitalRead(sensor_pin) == LOW && occupancy) { + zbOccupancySensor.setOccupancy(false); + zbOccupancySensor.report(); + occupancy = false; + } + + // Checking button for factory reset + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/README.md b/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md similarity index 59% rename from libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/README.md rename to libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md index cccc97aec98..e74c7505ddb 100644 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/README.md +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md @@ -1,8 +1,6 @@ -# Arduino-ESP32 Zigbee Light Bulb Example +# 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 bulb. - -**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_light.** +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) on/off light. # Supported Targets @@ -13,14 +11,14 @@ Currently, this example supports the following targets. ## Hardware Required -* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with Zigbee_Light_switch example) +* 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 (loaded with Zigbee_Light_bulb example) +* 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. +By default, the `rgbLedWrite` function is used to control the LED. You can change it to digitalWrite to control a simple LED. #### Using Arduino IDE @@ -30,17 +28,22 @@ To get more information about the Espressif boards see [Espressif Development Ki * 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. ## 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. +If the End device flashed with this example 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 sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. -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*** @@ -60,14 +63,8 @@ Before creating a new issue, be sure to try Troubleshooting and check if the sam ## Resources -The ESP Zigbee SDK provides more examples: -* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) -* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) - * Official ESP32 Forum: [Link](https://esp32.com) * Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) -* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) -* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) -* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +* 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/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino new file mode 100644 index 00000000000..6db8bd7b022 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino @@ -0,0 +1,101 @@ +// 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 "Zigbee.h" + +/* 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, 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, OUTPUT); + digitalWrite(led, LOW); + + // Init button for factory reset + pinMode(button, INPUT_PULLUP); + + //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 + 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 + 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) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + 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); +} diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json b/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/README.md b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md similarity index 57% rename from libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/README.md rename to libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md index 81f9354a6a0..b70f57d6e89 100644 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/README.md +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md @@ -1,9 +1,7 @@ -# Arduino-ESP32 Zigbee Light Switch Example +# 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. -**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_switch.** - # Supported Targets Currently, this example supports the following targets. @@ -13,34 +11,37 @@ Currently, this example supports the following targets. ## Hardware Required -* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee end device (loaded with Zigbee_Light_bulb example). +* 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 (loaded with Zigbee_Light_switch example). +* 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, the LED_PIN is `GPIO_NUM_9`. +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)`. +* 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`. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. ## 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. +If the End device flashed with the example `Zigbee_On_Off_Light` 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. +* In the `Zigbee_On_Off_Light` example sketch call `Zigbee.factoryReset();`. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: -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. +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. ***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** @@ -60,14 +61,8 @@ Before creating a new issue, be sure to try Troubleshooting and check if the sam ## Resources -The ESP Zigbee SDK provides more examples: -* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) -* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) - * Official ESP32 Forum: [Link](https://esp32.com) * Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) -* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) -* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) -* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +* 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/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino new file mode 100644 index 00000000000..0721371ce0e --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino @@ -0,0 +1,198 @@ +// 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 "Zigbee.h" + +/* Zigbee switch configuration */ +#define SWITCH_ENDPOINT_NUMBER 5 + +#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 { + 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}}; + +ZigbeeSwitch zbSwitch = ZigbeeSwitch(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 + Serial.println("Toggling 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 + Serial.println("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) { + 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 + 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.bound()) { + Serial.printf("."); + delay(500); + } + + // Optional: List all bound devices and read manufacturer and model name + std::list boundLights = zbSwitch.getBoundDevices(); + for (const auto &device : boundLights) { + 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\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] + ); + char *manufacturer = zbSwitch.readManufacturer(device->endpoint, device->short_addr, device->ieee_addr); + char *model = zbSwitch.readModel(device->endpoint, device->short_addr, device->ieee_addr); + if (manufacturer != nullptr) { + Serial.printf("Light manufacturer: %s\r\n", manufacturer); + } + if (model != nullptr) { + Serial.printf("Light model: %s\r\n", model); + } + } + + 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(Serial); + } +} diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json new file mode 100644 index 00000000000..15d6190e4ae --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json @@ -0,0 +1,6 @@ +{ + "fqbn_append": "PartitionScheme=zigbee_zczr,ZigbeeMode=zczr", + "requires": [ + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_PM25_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_PM25_Sensor/README.md new file mode 100644 index 00000000000..51bf11459b7 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_PM25_Sensor/README.md @@ -0,0 +1,72 @@ +# Arduino-ESP32 PM2.5 Sensor + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) simple sensor device type with particulate matter (PM2.5) measuring + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Pressure + Flow Sensor Functions + + * After this board first starts up, it would be configured locally to report the PM2.5 on every 30 seconds. + * By clicking the button (BOOT) on this board, this board will immediately send a report of the current PM2.5 to the network. + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +In this example, the internal temperature sensor is used to demonstrate reading of the PM2.5 sensors. +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (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 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example 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`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***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/libraries/Zigbee/examples/Zigbee_PM25_Sensor/Zigbee_PM25_Sensor.ino b/libraries/Zigbee/examples/Zigbee_PM25_Sensor/Zigbee_PM25_Sensor.ino new file mode 100644 index 00000000000..a98d697f700 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_PM25_Sensor/Zigbee_PM25_Sensor.ino @@ -0,0 +1,109 @@ +// 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 Zigbee PM2.5 sensor. + * + * The example demonstrates how to use Zigbee library to create a end device PM2.5 sensor. + * + * 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 "Zigbee.h" + +/* Zigbee PM2.5 sensor configuration */ +#define PM2_5_SENSOR_ENDPOINT_NUMBER 1 +uint8_t button = BOOT_PIN; + +ZigbeePM25Sensor zbPM25Sensor = ZigbeePM25Sensor(PM2_5_SENSOR_ENDPOINT_NUMBER); + +void setup() { + Serial.begin(115200); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Optional: set Zigbee device name and model + zbPM25Sensor.setManufacturerAndModel("Espressif", "ZigbeePM25Sensor"); + + // Set minimum and maximum PM2.5 measurement value in µg/m³ + zbPM25Sensor.setMinMaxValue(0, 350); + + // Set tolerance for PM2.5 measurement in µg/m³ + zbPM25Sensor.setTolerance(0.1); + + // Add endpoints to Zigbee Core + Zigbee.addEndpoint(&zbPM25Sensor); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // Set reporting interval for PM2.5 measurement to be done every 30 seconds, must be called after Zigbee.begin() + // min_interval and max_interval in seconds, delta (PM2.5 change in µg/m³) + // if min = 1 and max = 0, reporting is sent only when PM2.5 changes by delta + // if min = 0 and max = 10, reporting is sent every 10 seconds or when PM2.5 changes by delta + // if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of delta change + zbPM25Sensor.setReporting(0, 30, 0); +} + +void loop() { + static uint32_t timeCounter = 0; + // Read PM2.5 sensor every 2s + if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s + // Read sensor value - here is chip temperature used + 50 as a dummy value for demonstration + float pm25_value = 50.5 + temperatureRead(); + Serial.printf("Updating PM2.5 sensor value to %0.1f µg/m³\r\n", pm25_value); + zbPM25Sensor.setPM25(pm25_value); + } + + // Checking button for factory reset and reporting + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + zbPM25Sensor.report(); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_PM25_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_PM25_Sensor/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_PM25_Sensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/README.md new file mode 100644 index 00000000000..964c7503027 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/README.md @@ -0,0 +1,72 @@ +# Arduino-ESP32 Zigbee Pressure + Flow Sensor Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) simple sensor device type with pressure and flow measuring. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Pressure + Flow Sensor Functions + + * After this board first starts up, it would be configured locally to report the pressure and flow on change or every 30 seconds. + * By clicking the button (BOOT) on this board, this board will immediately send a report of the current measured flow and pressure to the network. + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +In this example, the internal temperature sensor is used to demonstrate reading of the flow and pressure sensors. +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (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 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example 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`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***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/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/Zigbee_Pressure_Flow_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/Zigbee_Pressure_Flow_Sensor.ino new file mode 100644 index 00000000000..a652a22c493 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/Zigbee_Pressure_Flow_Sensor.ino @@ -0,0 +1,128 @@ +// 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 Zigbee temperature sensor. + * + * The example demonstrates how to use Zigbee library to create a end device temperature sensor. + * The temperature sensor 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 "Zigbee.h" + +/* Zigbee flow + pressure sensor configuration */ +#define FLOW_SENSOR_ENDPOINT_NUMBER 10 +#define PRESSURE_SENSOR_ENDPOINT_NUMBER 11 + +uint8_t button = BOOT_PIN; + +ZigbeeFlowSensor zbFlowSensor = ZigbeeFlowSensor(FLOW_SENSOR_ENDPOINT_NUMBER); +ZigbeePressureSensor zbPressureSensor = ZigbeePressureSensor(PRESSURE_SENSOR_ENDPOINT_NUMBER); + +void setup() { + Serial.begin(115200); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Optional: set Zigbee device name and model + zbFlowSensor.setManufacturerAndModel("Espressif", "ZigbeeFlowSensor"); + + // Set minimum and maximum flow measurement value in 0,1 m3/h + zbFlowSensor.setMinMaxValue(0.0, 100.0); + + // Optional: Set tolerance for flow measurement in 0,1 m3/h + zbFlowSensor.setTolerance(1.0); + + // Optional: set Zigbee device name and model + zbPressureSensor.setManufacturerAndModel("Espressif", "ZigbeePressureSensor"); + + // Set minimum and maximum pressure measurement value in hPa + zbPressureSensor.setMinMaxValue(0, 10000); + + // Optional: Set tolerance for pressure measurement in hPa + zbPressureSensor.setTolerance(1); + + // Add endpoints to Zigbee Core + Zigbee.addEndpoint(&zbFlowSensor); + Zigbee.addEndpoint(&zbPressureSensor); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // Set reporting interval for flow and pressure measurement in seconds, must be called after Zigbee.begin() + // min_interval and max_interval in seconds, delta (pressure change in hPa, flow change in 0,1 m3/h) + // if min = 1 and max = 0, reporting is sent only when temperature changes by delta + // if min = 0 and max = 10, reporting is sent every 10 seconds or temperature changes by delta + // if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of delta change + zbFlowSensor.setReporting(0, 30, 1.0); + zbPressureSensor.setReporting(0, 30, 1); +} + +void loop() { + static uint32_t timeCounter = 0; + + // Read flow and pressure sensors every 2s + if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s + float flow_value = temperatureRead(); + uint16_t pressure_value = (uint16_t)temperatureRead() * 100; //*100 for demonstration so the value is in 1000-3000hPa + Serial.printf("Updating flow sensor value to %.2f m3/h\r\n", flow_value); + zbFlowSensor.setFlow(flow_value); + Serial.printf("Updating pressure sensor value to %d hPa\r\n", pressure_value); + zbPressureSensor.setPressure(pressure_value); + } + + // Checking button for factory reset and reporting + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + zbFlowSensor.report(); + zbPressureSensor.report(); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Range_Extender/README.md b/libraries/Zigbee/examples/Zigbee_Range_Extender/README.md new file mode 100644 index 00000000000..198dd85b6ee --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Range_Extender/README.md @@ -0,0 +1,68 @@ +# Arduino-ESP32 Zigbee Range Extender (Router) Example + +This example shows how to configure the Zigbee Router device and use it as a Home Automation (HA) network range extender. + +To see if the communication with your Zigbee network works, use the Serial monitor and watch for output there. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* A USB cable for power supply and programming +* Board (ESP32-H2 or ESP32-C6) as Zigbee router device and upload the Zigbee_Range_Extender example +* Zigbee network / coordinator (Other board with switch examples or Zigbee2mqtt or ZigbeeHomeAssistant like application) + +### Configure the Project + +#### 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/Router device Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator/router)` +* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` (select correct size) +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the Router device flashed with this example is not connecting to the coordinator, erase the flash of the Router 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`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***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/libraries/Zigbee/examples/Zigbee_Range_Extender/Zigbee_Range_Extender.ino b/libraries/Zigbee/examples/Zigbee_Range_Extender/Zigbee_Range_Extender.ino new file mode 100644 index 00000000000..a1ba90fbaf6 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Range_Extender/Zigbee_Range_Extender.ino @@ -0,0 +1,120 @@ +// Copyright 2025 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 Range Extender (router). + * + * The example demonstrates how to use Zigbee library to create a Zigbee network ragbe extender (router). + * + * 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/router mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +/* Zigbee light bulb configuration */ +#define USE_CUSTOM_ZIGBEE_CONFIG 1 +#define ZIGBEE_EXTENDER_ENDPOINT 1 + +#ifndef LED_BUILTIN +#define LED_BUILTIN 4 +#endif + +uint8_t led = LED_BUILTIN; +uint8_t button = BOOT_PIN; + +ZigbeeRangeExtender zbExtender = ZigbeeRangeExtender(ZIGBEE_EXTENDER_ENDPOINT); + +/************************** Identify ******************************/ +// Create a task on identify call to handle the identify function +void identify(uint16_t time) { + static uint8_t blink = 1; + log_d("Identify called for %d seconds", time); + if (time == 0) { + digitalWrite(led, LOW); + return; + } + digitalWrite(led, blink); + blink = !blink; +} + +/********************* 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, OUTPUT); + digitalWrite(led, LOW); + + // Init button for factory reset + pinMode(button, INPUT_PULLUP); + + // Optional: Set callback function for device identify + zbExtender.onIdentify(identify); + + // Optional: Set Zigbee device name and model + zbExtender.setManufacturerAndModel("Espressif", "ZigbeeRangeExtender"); + + // Add endpoint to Zigbee Core + Serial.println("Adding Zigbee Extender endpoint to Zigbee Core"); + Zigbee.addEndpoint(&zbExtender); + +#if USE_CUSTOM_ZIGBEE_CONFIG + // Optional: Create a custom Zigbee configuration for Zigbee Extender + esp_zb_cfg_t zigbeeConfig = ZIGBEE_DEFAULT_ROUTER_CONFIG(); + zigbeeConfig.nwk_cfg.zczr_cfg.max_children = 20; // 10 is default + + // When all EPs are registered, start Zigbee with custom config + if (!Zigbee.begin(&zigbeeConfig)) { +#else + // When all EPs are registered, start Zigbee as ROUTER device + if (!Zigbee.begin(ZIGBEE_ROUTER)) { +#endif + 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) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + } +} diff --git a/libraries/Zigbee/examples/Zigbee_Range_Extender/ci.json b/libraries/Zigbee/examples/Zigbee_Range_Extender/ci.json new file mode 100644 index 00000000000..15d6190e4ae --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Range_Extender/ci.json @@ -0,0 +1,6 @@ +{ + "fqbn_append": "PartitionScheme=zigbee_zczr,ZigbeeMode=zczr", + "requires": [ + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md b/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md new file mode 100644 index 00000000000..0b2b2f94695 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md @@ -0,0 +1,71 @@ +# Arduino-ESP32 Zigbee Networks Scan Example + +This example shows how to scan Zigbee Networks. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Example Output + + Setup done + Loop running... + Loop running... + Loop running... + Loop running... + + Scan done + 2 networks found: + Nr | PAN ID | CH | Permit Joining | Router Capacity | End Device Capacity | Extended PAN ID + 1 | 0xe6f0 | 14 | Yes | Yes | Yes | f0:f5:bd:ff:fe:02:3f:24 + 2 | 0xa9bb | 24 | No | Yes | Yes | 60:55:f9:00:00:f7:52:d0 + +## Hardware Required + +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with `Zigbee_Thermostat` example) +* A USB cable for power supply and programming +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device (loaded with `Zigbee_Temperature_Sensor` example) + +### Configure the Project + +In this example, the internal temperature sensor task is reading the chip temperature. +Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, it's the `GPIO_NUM_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 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +***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/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino b/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino new file mode 100644 index 00000000000..eab6ecfd76e --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino @@ -0,0 +1,109 @@ +// 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 Zigbee Network Scanning. + * + * The example demonstrates how to use ESP Zigbee stack to scan for Zigbee networks. + * + * Any Zigbee mode can be selected in Tools->Zigbee mode + * with proper Zigbee partition scheme 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/) + */ + +#if !defined(ZIGBEE_MODE_ED) && !defined(ZIGBEE_MODE_ZCZR) +#error "Zigbee device mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +#ifdef ZIGBEE_MODE_ZCZR +zigbee_role_t role = ZIGBEE_ROUTER; // or can be ZIGBEE_COORDINATOR, but it won't scan itself +#else +zigbee_role_t role = ZIGBEE_END_DEVICE; +#endif + +void printScannedNetworks(uint16_t networksFound) { + if (networksFound == 0) { + Serial.println("No networks found"); + } else { + zigbee_scan_result_t *scan_result = Zigbee.getScanResult(); + Serial.println("\nScan done"); + Serial.print(networksFound); + Serial.println(" networks found:"); + Serial.println("Nr | PAN ID | CH | Permit Joining | Router Capacity | End Device Capacity | Extended PAN ID"); + for (int i = 0; i < networksFound; ++i) { + // Print all available info for each network found + Serial.printf("%2d", i + 1); + Serial.print(" | "); + Serial.printf("0x%04hx", scan_result[i].short_pan_id); + Serial.print(" | "); + Serial.printf("%2d", scan_result[i].logic_channel); + Serial.print(" | "); + Serial.printf("%-14.14s", scan_result[i].permit_joining ? "Yes" : "No"); + Serial.print(" | "); + Serial.printf("%-15.15s", scan_result[i].router_capacity ? "Yes" : "No"); + Serial.print(" | "); + Serial.printf("%-19.19s", scan_result[i].end_device_capacity ? "Yes" : "No"); + Serial.print(" | "); + Serial.printf( + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", scan_result[i].extended_pan_id[7], scan_result[i].extended_pan_id[6], scan_result[i].extended_pan_id[5], + scan_result[i].extended_pan_id[4], scan_result[i].extended_pan_id[3], scan_result[i].extended_pan_id[2], scan_result[i].extended_pan_id[1], + scan_result[i].extended_pan_id[0] + ); + Serial.println(); + delay(10); + } + Serial.println(""); + // Delete the scan result to free memory for code below. + Zigbee.scanDelete(); + } +} + +void setup() { + Serial.begin(115200); + + // Initialize Zigbee stack without any EPs just for scanning + if (!Zigbee.begin(role)) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } + + Serial.println("Setup done, starting Zigbee network scan..."); + // Start Zigbee Network Scan with default parameters (all channels, scan time 5) + Zigbee.scanNetworks(); +} + +void loop() { + // check Zigbee Network Scan process + int16_t ZigbeeScanStatus = Zigbee.scanComplete(); + if (ZigbeeScanStatus < 0) { // it is busy scanning or got an error + if (ZigbeeScanStatus == ZB_SCAN_FAILED) { + Serial.println("Zigbee scan has failed. Starting again."); + Zigbee.scanNetworks(); + } + // other option is status ZB_SCAN_RUNNING - just wait. + } else { // Found Zero or more Wireless Networks + printScannedNetworks(ZigbeeScanStatus); + Zigbee.scanNetworks(); // start over... + } + + // Loop can do something else... + delay(500); + Serial.println("Loop running..."); +} diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json b/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/README.md b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/README.md new file mode 100644 index 00000000000..afaa12c0bfa --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/README.md @@ -0,0 +1,75 @@ +# Arduino-ESP32 Zigbee Temperature and Humidity Sensor Sleepy Device Example + +This example demonstrates how to use the Zigbee library to create an end device temperature/humidity sensor and use it as a Home Automation (HA) extended temperature sensor. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Temperature Sensor Functions + +1. Initialize a Zigbee temperature and humidity sensor. +2. Measure temperature and humidity values. +3. Report the measured values to the Zigbee network. +4. Put the device to sleep to save power. + +## Hardware Required + +* ESP32-H2 or ESP32-C6 development board +* A USB cable for power supply and programming + +### Configure the Project + +In this example, to demonstrate the functionality the chip temperature is used and reported as temperature and humidity. +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (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 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example 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`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***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/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino new file mode 100644 index 00000000000..e9d08d32175 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino @@ -0,0 +1,147 @@ +// 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 Zigbee temperature and humidity sensor Sleepy device. + * + * The example demonstrates how to use Zigbee library to create an end device temperature and humidity sensor. + * The sensor is a Zigbee end device, which is reporting data to the Zigbee network. + * + * 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 "Zigbee.h" + +/* Zigbee temperature + humidity sensor configuration */ +#define TEMP_SENSOR_ENDPOINT_NUMBER 10 + +#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */ +#define TIME_TO_SLEEP 55 /* Sleep for 55s will + 5s delay for establishing connection => data reported every 1 minute */ + +uint8_t button = BOOT_PIN; + +ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER); + +/************************ Temp sensor *****************************/ +void meausureAndSleep() { + // Measure temperature sensor value + float temperature = temperatureRead(); + + // Use temperature value as humidity value to demonstrate both temperature and humidity + float humidity = temperature; + + // Update temperature and humidity values in Temperature sensor EP + zbTempSensor.setTemperature(temperature); + zbTempSensor.setHumidity(humidity); + + // Report temperature and humidity values + zbTempSensor.report(); + Serial.printf("Reported temperature: %.2f°C, Humidity: %.2f%%\r\n", temperature, humidity); + + // Add small delay to allow the data to be sent before going to sleep + delay(100); + + // Put device to deep sleep + Serial.println("Going to sleep now"); + esp_deep_sleep_start(); +} + +/********************* Arduino functions **************************/ +void setup() { + Serial.begin(115200); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Configure the wake up source and set to wake up every 5 seconds + esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); + + // Optional: set Zigbee device name and model + zbTempSensor.setManufacturerAndModel("Espressif", "SleepyZigbeeTempSensor"); + + // Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement) + zbTempSensor.setMinMaxValue(10, 50); + + // Set tolerance for temperature measurement in °C (lowest possible value is 0.01°C) + zbTempSensor.setTolerance(1); + + // Set power source to battery, battery percentage and battery voltage (now 100% and 3.5V for demonstration) + // The value can be also updated by calling zbTempSensor.setBatteryPercentage(percentage) or zbTempSensor.setBatteryVoltage(voltage) anytime after Zigbee.begin() + zbTempSensor.setPowerSource(ZB_POWER_SOURCE_BATTERY, 100, 35); + + // Add humidity cluster to the temperature sensor device with min, max and tolerance values + zbTempSensor.addHumiditySensor(0, 100, 1); + + // Add endpoint to Zigbee Core + Zigbee.addEndpoint(&zbTempSensor); + + // Create a custom Zigbee configuration for End Device with keep alive 10s to avoid interference with reporting data + esp_zb_cfg_t zigbeeConfig = ZIGBEE_DEFAULT_ED_CONFIG(); + zigbeeConfig.nwk_cfg.zed_cfg.keep_alive = 10000; + + // For battery powered devices, it can be better to set timeout for Zigbee Begin to lower value to save battery + // If the timeout has been reached, the network channel mask will be reset and the device will try to connect again after reset (scanning all channels) + Zigbee.setTimeout(10000); // Set timeout for Zigbee Begin to 10s (default is 30s) + + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin(&zigbeeConfig, false)) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); // If Zigbee failed to start, reboot the device and try again + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); + Serial.println("Successfully connected to Zigbee network"); + + // Delay approx 1s (may be adjusted) to allow establishing proper connection with coordinator, needed for sleepy devices + delay(1000); +} + +void loop() { + // Checking button for factory reset + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 10000) { + // If key pressed for more than 10secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + // Optional set reset in factoryReset to false, to not restart device after erasing nvram, but set it to endless sleep manually instead + Zigbee.factoryReset(false); + Serial.println("Going to endless sleep, press RESET button or power off/on the device to wake up"); + esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER); + esp_deep_sleep_start(); + } + } + } + + // Call the function to measure temperature and put the device to sleep + meausureAndSleep(); +} diff --git a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/ci.json b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md similarity index 59% rename from libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/README.md rename to libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md index c7c2489970c..577bd7c8058 100644 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/README.md +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md @@ -2,8 +2,6 @@ This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) temperature sensor. -**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_temperature_sensor.** - # Supported Targets Currently, this example supports the following targets. @@ -14,23 +12,23 @@ Currently, this example supports the following targets. ## Temperature Sensor Functions Note: - * This board means the board (e.g. ESP32-H2) loaded with `Zigbee_Temperature_Sensor` example. - * The remote board means the board (e.g. ESP32-H2) loaded with `Zigbee_Thermostat` example. + * This board means the board (e.g. ESP32-H2 / C6) loaded with `Zigbee_Temperature_Sensor` example. + * The remote board means the board (e.g. ESP32-H2 / C6) loaded with `Zigbee_Thermostat` example. Functions: * After this board first starts up, it would be configured locally to report the temperature on 1 degree change and no periodic reporting to the remote board. - * By clicking the switch button (BOOT) on this board, this board will immediately send a report of the current measured temperature to the remote board. + * By clicking the button (BOOT) on this board, this board will immediately send a report of the current measured temperature to the remote board. ## Hardware Required * One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with `Zigbee_Thermostat` example) * A USB cable for power supply and programming -* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device (loaded with `Zigbee_Temperature_Sensor` example) +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device and upload the `Zigbee_Temperature_Sensor` example ### Configure the Project In this example, the internal temperature sensor task is reading the chip temperature. -Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, it's the `GPIO_NUM_9` (BOOT button on ESP32-C6 and ESP32-H2). +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). #### Using Arduino IDE @@ -40,17 +38,21 @@ To get more information about the Espressif boards see [Espressif Development Ki * 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. ## 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. +If the End device flashed with this example 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 sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: -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. +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. ***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** @@ -70,14 +72,8 @@ Before creating a new issue, be sure to try Troubleshooting and check if the sam ## Resources -The ESP Zigbee SDK provides more examples: -* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) -* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) - * Official ESP32 Forum: [Link](https://esp32.com) * Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) -* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) -* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) -* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +* 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/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino new file mode 100644 index 00000000000..ad007abbbaa --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino @@ -0,0 +1,138 @@ +// 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 Zigbee temperature sensor. + * + * The example demonstrates how to use Zigbee library to create a end device temperature sensor. + * The temperature sensor 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 "Zigbee.h" + +/* Zigbee temperature sensor configuration */ +#define TEMP_SENSOR_ENDPOINT_NUMBER 10 +uint8_t button = BOOT_PIN; + +// Optional Time cluster variables +struct tm timeinfo; +struct tm *localTime; +int32_t timezone; + +ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER); + +/************************ Temp sensor *****************************/ +static void temp_sensor_value_update(void *arg) { + for (;;) { + // Read temperature sensor value + float tsens_value = temperatureRead(); + Serial.printf("Updated temperature sensor value to %.2f°C\r\n", tsens_value); + // Update temperature value in Temperature sensor EP + zbTempSensor.setTemperature(tsens_value); + delay(1000); + } +} + +/********************* Arduino functions **************************/ +void setup() { + Serial.begin(115200); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Optional: set Zigbee device name and model + zbTempSensor.setManufacturerAndModel("Espressif", "ZigbeeTempSensor"); + + // Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement) + zbTempSensor.setMinMaxValue(10, 50); + + // Optional: Set tolerance for temperature measurement in °C (lowest possible value is 0.01°C) + zbTempSensor.setTolerance(1); + + // Optional: Time cluster configuration (default params, as this device will revieve time from coordinator) + zbTempSensor.addTimeCluster(); + + // Add endpoint to Zigbee Core + Zigbee.addEndpoint(&zbTempSensor); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // Optional: If time cluster is added, time can be read from the coordinator + timeinfo = zbTempSensor.getTime(); + timezone = zbTempSensor.getTimezone(); + + Serial.println("UTC time:"); + Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); + + time_t local = mktime(&timeinfo) + timezone; + localTime = localtime(&local); + + Serial.println("Local time with timezone:"); + Serial.println(localTime, "%A, %B %d %Y %H:%M:%S"); + + // Start Temperature sensor reading task + xTaskCreate(temp_sensor_value_update, "temp_sensor_update", 2048, NULL, 10, NULL); + + // Set reporting interval for temperature measurement in seconds, must be called after Zigbee.begin() + // min_interval and max_interval in seconds, delta (temp change in 0,1 °C) + // if min = 1 and max = 0, reporting is sent only when temperature changes by delta + // if min = 0 and max = 10, reporting is sent every 10 seconds or temperature changes by delta + // if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of temperature change + zbTempSensor.setReporting(1, 0, 1); +} + +void loop() { + // Checking button for factory reset + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + zbTempSensor.reportTemperature(); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/README.md b/libraries/Zigbee/examples/Zigbee_Thermostat/README.md similarity index 64% rename from libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/README.md rename to libraries/Zigbee/examples/Zigbee_Thermostat/README.md index dc2a70782f8..e61173f6f4d 100644 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/README.md +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/README.md @@ -18,7 +18,7 @@ Note: * The remote board means the board (e.g. ESP32-H2) loaded with `Zigbee_Temperature_Sensor` example. Functions: - * By clicking the switch button (BOOT) on this board, this board will read temperature value, temperature measurement range and temperature tolerance from the remote board. Also, this board will configure the remote board to report the measured temperature value every 10 seconds or every 2 degree changes. + * By clicking the button (BOOT) on this board, this board will read temperature value, temperature measurement range and temperature tolerance from the remote board. Also, this board will configure the remote board to report the measured temperature value every 10 seconds or every 2 degree changes. ## Hardware Required @@ -28,17 +28,17 @@ Functions: ### Configure the Project -Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, it's the `GPIO_NUM_9` (BOOT button on ESP32-C6 and ESP32-H2). +Set the Button GPIO by changing the `BUTTON_PIN` 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)`. +* 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`. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. ## Troubleshooting @@ -46,10 +46,13 @@ If the End device flashed with the example `Zigbee_Temperature_Sensor` is not co 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_Temperature_Sensor` example sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. +* In the `Zigbee_Temperature_Sensor` example sketch call `Zigbee.factoryReset();`. -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. +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. ***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** @@ -69,14 +72,8 @@ Before creating a new issue, be sure to try Troubleshooting and check if the sam ## Resources -The ESP Zigbee SDK provides more examples: -* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) -* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) - * Official ESP32 Forum: [Link](https://esp32.com) * Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) -* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) -* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) -* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +* 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/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino new file mode 100644 index 00000000000..7cdf45ef711 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino @@ -0,0 +1,134 @@ +// 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 thermostat. + * + * The example demonstrates how to use Zigbee library to get data from temperature + * sensor end device and act as an thermostat. + * The temperature sensor is a Zigbee end device, which is controlled by a Zigbee coordinator (thermostat). + * + * 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 "Zigbee.h" + +/* Zigbee thermostat configuration */ +#define THERMOSTAT_ENDPOINT_NUMBER 5 +uint8_t button = BOOT_PIN; + +ZigbeeThermostat zbThermostat = ZigbeeThermostat(THERMOSTAT_ENDPOINT_NUMBER); + +// Save temperature sensor data +float sensor_temp; +float sensor_max_temp; +float sensor_min_temp; +float sensor_tolerance; + +struct tm timeinfo = {}; // Time structure for Time cluster + +/****************** Temperature sensor handling *******************/ +void recieveSensorTemp(float temperature) { + Serial.printf("Temperature sensor value: %.2f°C\n", temperature); + sensor_temp = temperature; +} + +void recieveSensorConfig(float min_temp, float max_temp, float tolerance) { + Serial.printf("Temperature sensor settings: min %.2f°C, max %.2f°C, tolerance %.2f°C\n", min_temp, max_temp, tolerance); + sensor_min_temp = min_temp; + sensor_max_temp = max_temp; + sensor_tolerance = tolerance; +} +/********************* Arduino functions **************************/ +void setup() { + Serial.begin(115200); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Set callback functions for temperature and configuration receive + zbThermostat.onTempRecieve(recieveSensorTemp); + zbThermostat.onConfigRecieve(recieveSensorConfig); + + //Optional: set Zigbee device name and model + zbThermostat.setManufacturerAndModel("Espressif", "ZigbeeThermostat"); + + //Optional Time cluster configuration + //example time January 13, 2025 13:30:30 CET + timeinfo.tm_year = 2025 - 1900; // = 2025 + timeinfo.tm_mon = 0; // January + timeinfo.tm_mday = 13; // 13th + timeinfo.tm_hour = 12; // 12 hours - 1 hour (CET) + timeinfo.tm_min = 30; // 30 minutes + timeinfo.tm_sec = 30; // 30 seconds + timeinfo.tm_isdst = -1; + + // Set time and gmt offset (timezone in seconds -> CET = +3600 seconds) + zbThermostat.addTimeCluster(timeinfo, 3600); + + //Add endpoint to Zigbee Core + Zigbee.addEndpoint(&zbThermostat); + + //Open network for 180 seconds after boot + Zigbee.setRebootOpenNetwork(180); + + // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode + if (!Zigbee.begin(ZIGBEE_COORDINATOR)) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } + + Serial.println("Waiting for Temperature sensor to bound to the thermostat"); + while (!zbThermostat.bound()) { + Serial.printf("."); + delay(500); + } + + Serial.println(); + + // Get temperature sensor configuration + zbThermostat.getSensorSettings(); +} + +void loop() { + // Handle button switch in loop() + if (digitalRead(button) == LOW) { // Push button pressed + + // Key debounce handling + while (digitalRead(button) == LOW) { + delay(50); + } + + // Set reporting interval for temperature sensor + zbThermostat.setTemperatureReporting(0, 10, 2); + } + + // Print temperature sensor data each 10 seconds + static uint32_t last_print = 0; + if (millis() - last_print > 10000) { + last_print = millis(); + int temp_percent = (int)((sensor_temp - sensor_min_temp) / (sensor_max_temp - sensor_min_temp) * 100); + Serial.printf("Loop temperature info: %.2f°C (%d %%)\n", sensor_temp, temp_percent); + } +} diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json b/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json new file mode 100644 index 00000000000..15d6190e4ae --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json @@ -0,0 +1,6 @@ +{ + "fqbn_append": "PartitionScheme=zigbee_zczr,ZigbeeMode=zczr", + "requires": [ + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Vibration_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Vibration_Sensor/README.md new file mode 100644 index 00000000000..b0e5b5f09e8 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Vibration_Sensor/README.md @@ -0,0 +1,58 @@ +# Arduino-ESP32 Zigbee Vibration Sensor Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) vibration sensor (IAS Zone), +that can be used for example as a security device which is sensing a vibrations. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). +Set the Sensor GPIO by changing the `sensor_pin` variable. + +#### 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. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash of the End device before flashing the example to the board. + +***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/libraries/Zigbee/examples/Zigbee_Vibration_Sensor/Zigbee_Vibration_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Vibration_Sensor/Zigbee_Vibration_Sensor.ino new file mode 100644 index 00000000000..d9ac7b6e241 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Vibration_Sensor/Zigbee_Vibration_Sensor.ino @@ -0,0 +1,104 @@ +// 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 Zigbee vibration sensor (IAS Zone). + * + * The example demonstrates how to use Zigbee library to create a end device vibration sensor. + * The vibration sensor is a Zigbee end device, which is reporting data to the Zigbee network. + * + * 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 "Zigbee.h" + +/* Zigbee vibration sensor configuration */ +#define VIBRATION_SENSOR_ENDPOINT_NUMBER 10 +uint8_t button = BOOT_PIN; +uint8_t sensor_pin = 4; + +ZigbeeVibrationSensor zbVibrationSensor = ZigbeeVibrationSensor(VIBRATION_SENSOR_ENDPOINT_NUMBER); + +void setup() { + Serial.begin(115200); + + // Init button + sensor + pinMode(button, INPUT_PULLUP); + pinMode(sensor_pin, INPUT); + + // Optional: set Zigbee device name and model + zbVibrationSensor.setManufacturerAndModel("Espressif", "ZigbeeVibrationSensor"); + + // Add endpoint to Zigbee Core + Zigbee.addEndpoint(&zbVibrationSensor); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); +} + +void loop() { + // Checking pin for contact change + static bool sensed = false; + if (digitalRead(sensor_pin) == HIGH && !sensed) { + // Update contact sensor value + zbVibrationSensor.setVibration(true); + sensed = true; + //if sensed, wait 2 seconds before next sensing + delay(2000); + } else if (digitalRead(sensor_pin) == LOW && sensed) { + zbVibrationSensor.setVibration(false); + sensed = false; + //if not sensed, wait 0,5 seconds before next sensing + delay(500); + } + + // Checking button for factory reset + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Vibration_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Vibration_Sensor/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Vibration_Sensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Wind_Speed_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Wind_Speed_Sensor/README.md new file mode 100644 index 00000000000..826c7666e6b --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Wind_Speed_Sensor/README.md @@ -0,0 +1,60 @@ +# Zigbee Wind Speed Sensor Integration with HomeAssistant ZHA + +This guide provides a workaround for integrating a Zigbee Wind Speed Sensor with HomeAssistant using the ZHA integration. Since the wind speed cluster is not natively supported, we will use the ZHA Toolkit from HACS to read the wind speed attribute and store it in a helper variable. +## Alternative Option: Creating a Custom Quirk + +For advanced users, a more robust solution is to create a custom quirk for your Zigbee Wind Speed Sensor. This approach involves writing a custom device handler that directly supports the wind speed cluster, providing a more seamless integration with HomeAssistant. + +Creating a custom quirk can be complex and requires familiarity with Python and the Zigbee protocol. However, it offers greater flexibility and control over your device's behavior. + +For more information and guidance on creating custom quirks, visit the [ZHA Device Handlers repository](https://github.com/zigpy/zha-device-handlers/). + +## Prerequisites + +- HomeAssistant installed and running +- Zigbee Wind Speed Sensor paired with HomeAssistant ZHA +- HACS (Home Assistant Community Store) installed. For more information, visit [HACS](https://hacs.xyz) + +## Steps + +### 1. Install ZHA Toolkit + +1. Open HomeAssistant. +2. Navigate to HACS > Integrations. +3. Search for "ZHA Toolkit - Service for advanced Zigbee Usage" and install it. For more information, visit the [ZHA Toolkit repository](https://github.com/mdeweerd/zha-toolkit). +4. Restart HomeAssistant to apply changes. + +### 2. Create a Helper Variable + +1. Go to Configuration -> Devices & Services -> Helpers. +2. Click on "Add Helper" and select "Number". +3. Name the helper (e.g., `wind_speed`), set the minimum and maximum values, and save it. + +### 3. Create an Automation + +1. Go to Configuration > Automations & Scenes. +2. Click on "Add Automation" and choose "Start with an empty automation". +3. Set a name for the automation (e.g., `Read Wind Speed`). +4. Add a trigger: + - Trigger Type: Time Pattern + - Every: 30 seconds +5. Add an action (Then do): + - Action Type: ZHA Toolkit: Read Attribute + - Setup the action: + ```yaml + action: zha_toolkit.attr_read + metadata: {} + data: + ieee: f0:f5:bd:ff:fe:0e:61:30 #set device IEEE address + endpoint: 10 #set windspeed device endpoint + cluster: 1035 #use this windspeed cluster + attribute: 0 #read measurement value + state_id: input_number.wind_speed #save to created helper variable + state_value_template: value/100 #use correct value format (convert u16 to float) + ``` +6. Save the automation. + +## Conclusion + +By following these steps, you can successfully integrate your Zigbee Wind Speed Sensor with HomeAssistant using the ZHA integration and ZHA Toolkit. The wind speed readings will be updated every 30 seconds and stored in the helper variable for use in your HomeAssistant setup. +The helper variable `wind_speed` is now an entity in HomeAssistant. You can use this entity to display the wind speed on your dashboard or in other automations. diff --git a/libraries/Zigbee/examples/Zigbee_Wind_Speed_Sensor/Zigbee_Wind_Speed_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Wind_Speed_Sensor/Zigbee_Wind_Speed_Sensor.ino new file mode 100644 index 00000000000..1c24df9a091 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Wind_Speed_Sensor/Zigbee_Wind_Speed_Sensor.ino @@ -0,0 +1,119 @@ +// 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 Zigbee windspeed sensor. + * + * The example demonstrates how to use Zigbee library to create a end device wind speed sensor. + * The wind speed sensor 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 coordinator mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +#define BUTTON_PIN 9 //Boot button for C6/H2 +#define WIND_SPEED_SENSOR_ENDPOINT_NUMBER 10 + +ZigbeeWindSpeedSensor zbWindSpeedSensor = ZigbeeWindSpeedSensor(WIND_SPEED_SENSOR_ENDPOINT_NUMBER); + +/************************ WindSpeed sensor *****************************/ +static void windspeed_sensor_value_update(void *arg) { + for (;;) { + // Read wind speed sensor value (simulated now by temperature sensor) + float windspeed = temperatureRead(); + log_v("Wind speed sensor value: %.2fm/s", windspeed); + // Update windspeed value in Windspeed sensor EP + zbWindSpeedSensor.setWindSpeed(windspeed); + delay(1000); + } +} + +/********************* Arduino functions **************************/ +void setup() { + Serial.begin(115200); + while (!Serial) { + delay(10); + } + + // Init button switch + pinMode(BUTTON_PIN, INPUT); + + // Optional: set Zigbee device name and model + zbWindSpeedSensor.setManufacturerAndModel("Espressif", "ZigbeeWindSpeedSensor"); + + // Set minimum and maximum windspeed measurement value in m/s + zbWindSpeedSensor.setMinMaxValue(0, 50); + + // Set tolerance for windspeed measurement in m/s (lowest possible value is 0.01 m/s) + zbWindSpeedSensor.setTolerance(1); + + // Add endpoint to Zigbee Core + Zigbee.addEndpoint(&zbWindSpeedSensor); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // Start Wind speed sensor reading task + xTaskCreate(windspeed_sensor_value_update, "wind_speed_sensor_update", 2048, NULL, 10, NULL); + + // Set reporting interval for windspeed measurement in seconds, must be called after Zigbee.begin() + // min_interval and max_interval in seconds, delta (WindSpeed change in m/s) + // if min = 1 and max = 0, reporting is sent only when windspeed changes by delta + // if min = 0 and max = 10, reporting is sent every 10 seconds or windspeed changes by delta + // if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of windspeed change + zbWindSpeedSensor.setReporting(1, 0, 1); +} + +void loop() { + // 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 key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + zbWindSpeedSensor.reportWindSpeed(); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Wind_Speed_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Wind_Speed_Sensor/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Wind_Speed_Sensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Window_Covering/README.md b/libraries/Zigbee/examples/Zigbee_Window_Covering/README.md new file mode 100644 index 00000000000..469560a0e0c --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Window_Covering/README.md @@ -0,0 +1,69 @@ +# Arduino-ESP32 Window Covering Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) window covering device. + +To see if the communication with your Zigbee network works, use the Serial monitor and watch for output there. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* A USB cable for power supply and programming +* Board (ESP32-H2 or ESP32-C6) as Zigbee end device and upload the Zigbee_Window_Covering example +* Zigbee network / coordinator (Other board with switch examples or Zigbee2mqtt or ZigbeeHomeAssistant like application) + +### Configure the Project + +#### 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 Tools / USB CDC On Boot: "Enabled" +* 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 verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example 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`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***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/libraries/Zigbee/examples/Zigbee_Window_Covering/Zigbee_Window_Covering.ino b/libraries/Zigbee/examples/Zigbee_Window_Covering/Zigbee_Window_Covering.ino new file mode 100644 index 00000000000..c7f9cf84f74 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Window_Covering/Zigbee_Window_Covering.ino @@ -0,0 +1,198 @@ +// Copyright 2025 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 Zigbee Window Covering. + * + * The example demonstrates how to use Zigbee library to create a end device window covering device. + * The window covering is a Zigbee end device, which is moving the blinds (lift+tilt) and reporting + * its current position to the Zigbee network. + * + * Use setCoveringType() to set the type of covering (blind, shade, etc.). + * + * The example also demonstrates how to use the button to manually control the lift position. + * + * 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 hennikul and 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/ZigbeeWindowCovering.h" + +#define ZIGBEE_COVERING_ENDPOINT 10 +#define BUTTON_PIN 9 // ESP32-C6/H2 Boot button + +#define MAX_LIFT 200 // centimeters from open position (0-900) +#define MIN_LIFT 0 + +#define MAX_TILT 40 // centimeters from open position (0-900) +#define MIN_TILT 0 + +uint16_t currentLift = MAX_LIFT; +uint8_t currentLiftPercentage = 100; + +uint16_t currentTilt = MAX_TILT; +uint8_t currentTiltPercentage = 100; + +ZigbeeWindowCovering zbCovering = ZigbeeWindowCovering(ZIGBEE_COVERING_ENDPOINT); + +void setup() { + Serial.begin(115200); + + // Init button for factory reset + pinMode(BUTTON_PIN, INPUT_PULLUP); + + // Optional: set Zigbee device name and model + zbCovering.setManufacturerAndModel("Espressif", "WindowBlinds"); + + // Set proper covering type, it defines which attributes are available + zbCovering.setCoveringType(BLIND_LIFT_AND_TILT); + + // Set configuration: operational, online, not commands_reversed, lift / tilt closed_loop, lift / tilt encoder_controlled + zbCovering.setConfigStatus(true, true, false, true, true, true, true); + + // Set mode: not motor_reversed, calibration_mode, not maintenance_mode, not leds_on + zbCovering.setMode(false, true, false, false); + + // Set limits of motion + zbCovering.setLimits(MIN_LIFT, MAX_LIFT, MIN_TILT, MAX_TILT); + + // Set callback function for open, close, filt and tilt change, stop + zbCovering.onOpen(fullOpen); + zbCovering.onClose(fullClose); + zbCovering.onGoToLiftPercentage(goToLiftPercentage); + zbCovering.onGoToTiltPercentage(goToTiltPercentage); + zbCovering.onStop(stopMotor); + + // Add endpoint to Zigbee Core + Serial.println("Adding ZigbeeWindowCovering endpoint to Zigbee Core"); + Zigbee.addEndpoint(&zbCovering); + + // When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE + Serial.println("Calling 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(); + + // Set initial position + zbCovering.setLiftPercentage(currentLiftPercentage); + zbCovering.setTiltPercentage(currentTiltPercentage); +} + +void loop() { + // 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 key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.printf("Resetting Zigbee to factory settings, reboot.\n"); + Zigbee.factoryReset(); + delay(30000); + } + } + // Manual lift control simulation by pressing button + manualControl(); + } + delay(500); +} + +void fullOpen() { + /* This is where you would trigger your motor to go to full open state, currentLift should + be updated until full open has been reached in order to provide feedback to controller of actual position + The stop can be always called, so the movement can be stopped at any time */ + + // Our cover updates instantly! + currentLift = MAX_LIFT; + currentLiftPercentage = 100; + Serial.println("Opening cover"); + // Update the current position + zbCovering.setLiftPercentage(currentLiftPercentage); +} + +void fullClose() { + /* This is where you would trigger your motor to go to full close state, currentLift should + be updated until full close has been reached in order to provide feedback to controller of actual position + The stop can be always called, so the movement can be stopped at any time */ + + // Our cover updates instantly! + currentLift = MIN_LIFT; + currentLiftPercentage = 0; + Serial.println("Closing cover"); + // Update the current position + zbCovering.setLiftPercentage(currentLiftPercentage); +} + +void goToLiftPercentage(uint8_t liftPercentage) { + /* This is where you would trigger your motor to go towards liftPercentage, currentLift should + be updated until liftPercentage has been reached in order to provide feedback to controller */ + + // Our simulated cover updates instantly! + currentLift = (liftPercentage * MAX_LIFT) / 100; + currentLiftPercentage = liftPercentage; + Serial.printf("New requested lift from Zigbee: %d (%d)\n", currentLift, liftPercentage); + + // Update the current position + zbCovering.setLiftPercentage(currentLiftPercentage); //or setLiftPosition() +} + +void goToTiltPercentage(uint8_t tiltPercentage) { + /* This is where you would trigger your motor to go towards tiltPercentage, currentTilt should + be updated until tiltPercentage has been reached in order to provide feedback to controller */ + + // Our simulated cover updates instantly! + currentTilt = (tiltPercentage * MAX_TILT) / 100; + currentTiltPercentage = tiltPercentage; + Serial.printf("New requested tilt from Zigbee: %d (%d)\n", currentTilt, tiltPercentage); + + // Update the current position + zbCovering.setTiltPercentage(currentTiltPercentage); //or setTiltPosition() +} + +void stopMotor() { + // Motor can be stopped while moving cover toward current target, when stopped the actual position should be updated + Serial.println("Stopping motor"); + // Update the current position of both lift and tilt + zbCovering.setLiftPercentage(currentLiftPercentage); + zbCovering.setTiltPercentage(currentTiltPercentage); +} + +void manualControl() { + // Simulate lift percentage move by increasing it by 20% each time + currentLiftPercentage += 20; + if (currentLiftPercentage > 100) { + currentLiftPercentage = 0; + } + zbCovering.setLiftPercentage(currentLiftPercentage); + // Also setLiftPosition() can be used to set the exact position instead of percentage +} diff --git a/libraries/Zigbee/examples/Zigbee_Window_Covering/ci.json b/libraries/Zigbee/examples/Zigbee_Window_Covering/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Window_Covering/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/keywords.txt b/libraries/Zigbee/keywords.txt new file mode 100644 index 00000000000..586d2bdc677 --- /dev/null +++ b/libraries/Zigbee/keywords.txt @@ -0,0 +1,193 @@ +####################################### +# Syntax Coloring Map For Zigbee +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +# Base Classes +ZigbeeCore KEYWORD1 +Zigbee KEYWORD1 +ZigbeeEP KEYWORD1 + +# Endpoint Classes +ZigbeeLight KEYWORD1 +ZigbeeSwitch KEYWORD1 +ZigbeeColorDimmableLight KEYWORD1 +ZigbeeColorDimmerSwitch KEYWORD1 +ZigbeeTempSensor KEYWORD1 +ZigbeeThermostat KEYWORD1 +ZigbeeFlowSensor KEYWORD1 +ZigbeePressureSensor KEYWORD1 +ZigbeeOccupancySensor KEYWORD1 +ZigbeeAnalog KEYWORD1 +ZigbeeCarbonDioxideSensor KEYWORD1 +ZigbeeContactSwitch KEYWORD1 +ZigbeeDoorWindowHandle KEYWORD1 +ZigbeeGateway KEYWORD1 +ZigbeeRangeExtender KEYWORD1 +ZigbeeVibrationSensor KEYWORD1 +ZigbeeWindowCovering KEYWORD1 +ZigbeeIlluminanceSensor KEYWORD1 + +# Other +zigbee_role_t KEYWORD1 +zbstring_t KEYWORD1 +zb_device_params_t KEYWORD1 +zigbee_scan_result_t KEYWORD1 +zb_power_source_t KEYWORD1 +ZigbeeWindowCoveringType KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +# ZigbeeCore +begin KEYWORD2 +started KEYWORD2 +connected KEYWORD2 +getRole KEYWORD2 +addEndpoint KEYWORD2 +setRadioConfig KEYWORD2 +getRadioConfig KEYWORD2 +setHostConfig KEYWORD2 +getHostConfig KEYWORD2 +setPrimaryChannelMask KEYWORD2 +setScanDuration KEYWORD2 +getScanDuration KEYWORD2 +setRebootOpenNetwork KEYWORD2 +openNetwork KEYWORD2 +scanNetworks KEYWORD2 +scanComplete KEYWORD2 +getScanResult KEYWORD2 +scanDelete KEYWORD2 +factoryReset KEYWORD2 + +# Common ZigbeeEP +setEpConfig KEYWORD2 +setVersion KEYWORD2 +getEndpoint KEYWORD2 +printBoundDevices KEYWORD2 +getBoundDevices KEYWORD2 +bound KEYWORD2 +allowMultipleBinding KEYWORD2 +setManufacturerAndModel KEYWORD2 +setPowerSource KEYWORD2 +setBatteryPercentage KEYWORD2 +reportBatteryPercentage KEYWORD2 +readManufacturer KEYWORD2 +readModel KEYWORD2 +onIdentify KEYWORD2 + +# ZigbeeLight + ZigbeeColorDimmableLight +onLightChange KEYWORD2 +restoreLight KEYWORD2 +setLight KEYWORD2 +setLightState KEYWORD2 +setLightLevel KEYWORD2 +setLightColor KEYWORD2 +getLightState KEYWORD2 +getLightLevel KEYWORD2 +getLightRed KEYWORD2 +getLightGreen KEYWORD2 +getLightBlue KEYWORD2 + +# ZigbeeSwitch + ZigbeeColorDimmerSwitch +lightToggle KEYWORD2 +lightOn KEYWORD2 +lightOff KEYWORD2 +lightOffWithEffect KEYWORD2 +lightOnWithTimedOff KEYWORD2 +lightOnWithSceneRecall KEYWORD2 +setLightLevel KEYWORD2 +setLightColor KEYWORD2 + +# ZigbeeThermostat +onTempRecieve KEYWORD2 +onConfigRecieve KEYWORD2 +getTemperature KEYWORD2 +getSensorSettings KEYWORD2 +setTemperatureReporting KEYWORD2 + +# Common Zigbee Sensor +setMinMaxValue KEYWORD2 +setTolerance KEYWORD2 +setReporting KEYWORD2 +report KEYWORD2 + +# ZigbeeTempSensor + humidity +setTemperature KEYWORD2 +reportTemperature KEYWORD2 +addHumiditySensor KEYWORD2 +setHumidity KEYWORD2 +setHumidityReporting KEYWORD2 +reportHumidity KEYWORD2 + +# ZigbeeIlluminanceSensor +setIlluminance KEYWORD2 + +# ZigbeeFlowSensor +setFlow KEYWORD2 + +# ZigbeePressureSensor +setPressure KEYWORD2 + +# ZigbeeOccupancySensor +setOccupancy KEYWORD2 +setSensorType KEYWORD2 + +# ZigbeeCarbonDioxideSensor +setCarbonDioxide KEYWORD2 + +# ZigbeeAnalog +addAnalogValue KEYWORD2 +addAnalogInput KEYWORD2 +addAnalogOutput KEYWORD2 +onAnalogOutputChange KEYWORD2 +setAnalogValue KEYWORD2 +setAnalogInput KEYWORD2 +reportAnalogInput KEYWORD2 +setAnalogInputReporting KEYWORD2 + +# ZigbeeCarbonDioxideSensor +setCarbonDioxide KEYWORD2 + +# ZigbeeContactSwitch + ZigbeeDoorWindowHandle +setIASClientEndpoint KEYWORD2 +setClosed KEYWORD2 +setOpen KEYWORD2 +setTilted KEYWORD2 + +# ZigbeeVibrationSensor +setVibration KEYWORD2 + +ZigbeeWindowCovering +onOpen KEYWORD2 +onClose KEYWORD2 +onGoToLiftPercentage KEYWORD2 +onGoToTiltPercentage KEYWORD2 +onStop KEYWORD2 +setLiftPosition KEYWORD2 +setLiftPercentage KEYWORD2 +setTiltPosition KEYWORD2 +setTiltPercentage KEYWORD2 +setCoveringType KEYWORD2 +setConfigStatus KEYWORD2 +setMode KEYWORD2 +setLimits KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +ZIGBEE_COORDINATOR LITERAL1 +ZIGBEE_ROUTER LITERAL1 +ZIGBEE_END_DEVICE LITERAL1 +ZIGBEE_DEFAULT_ED_CONFIG LITERAL1 +ZIGBEE_DEFAULT_ROUTER_CONFIG LITERAL1 +ZIGBEE_DEFAULT_COORDINATOR_CONFIG LITERAL1 +ZIGBEE_DEFAULT_RADIO_CONFIG LITERAL1 +ZIGBEE_DEFAULT_UART_RCP_RADIO_CONFIG LITERAL1 +ZIGBEE_DEFAULT_HOST_CONFIG LITERAL1 +ZB_ARRAY_LENTH LITERAL1 diff --git a/libraries/Zigbee/library.properties b/libraries/Zigbee/library.properties new file mode 100644 index 00000000000..9a558d70216 --- /dev/null +++ b/libraries/Zigbee/library.properties @@ -0,0 +1,9 @@ +name=Zigbee +version=3.2.0 +author=P-R-O-C-H-Y +maintainer=Jan Procházka +sentence=Enables zigbee connection with the ESP32 +paragraph=With this library you can create zigbee end devices, routers, coordinators and connect them to the zigbee network. +category=Communication +url= +architectures=esp32 diff --git a/libraries/Zigbee/src/Zigbee.h b/libraries/Zigbee/src/Zigbee.h new file mode 100644 index 00000000000..7f44d7813af --- /dev/null +++ b/libraries/Zigbee/src/Zigbee.h @@ -0,0 +1,35 @@ +// Zigbee library header file for includes of all Zigbee library headers. + +#pragma once + +// Core +#include "ZigbeeCore.h" +#include "ZigbeeEP.h" + +// Endpoints +//// Switches +#include "ep/ZigbeeColorDimmerSwitch.h" +#include "ep/ZigbeeSwitch.h" +//// Lights +#include "ep/ZigbeeColorDimmableLight.h" +#include "ep/ZigbeeDimmableLight.h" +#include "ep/ZigbeeLight.h" +//// Controllers +#include "ep/ZigbeeThermostat.h" +//// Sensors +#include "ep/ZigbeeAnalog.h" +#include "ep/ZigbeeCarbonDioxideSensor.h" +#include "ep/ZigbeeContactSwitch.h" +#include "ep/ZigbeeDoorWindowHandle.h" +#include "ep/ZigbeeFlowSensor.h" +#include "ep/ZigbeeIlluminanceSensor.h" +#include "ep/ZigbeeOccupancySensor.h" +#include "ep/ZigbeePM25Sensor.h" +#include "ep/ZigbeePressureSensor.h" +#include "ep/ZigbeeTempSensor.h" +#include "ep/ZigbeeVibrationSensor.h" +#include "ep/ZigbeeWindSpeedSensor.h" +#include "ep/ZigbeeWindowCovering.h" +//// Other +#include "ep/ZigbeeGateway.h" +#include "ep/ZigbeeRangeExtender.h" diff --git a/libraries/Zigbee/src/ZigbeeCore.cpp b/libraries/Zigbee/src/ZigbeeCore.cpp new file mode 100644 index 00000000000..b93542159a6 --- /dev/null +++ b/libraries/Zigbee/src/ZigbeeCore.cpp @@ -0,0 +1,577 @@ +/* Zigbee Core Functions */ + +#include "ZigbeeCore.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeHandlers.cpp" +#include "Arduino.h" + +#ifdef __cplusplus +extern "C" { +#endif +#include "zboss_api.h" +extern zb_ret_t zb_nvram_write_dataset(zb_nvram_dataset_types_t t); // rejoin scanning workaround +extern void zb_set_ed_node_descriptor(bool power_src, bool rx_on_when_idle, bool alloc_addr); // sleepy device power mode workaround +#ifdef __cplusplus +} +#endif + +static bool edBatteryPowered = false; + +ZigbeeCore::ZigbeeCore() { + _radio_config.radio_mode = ZB_RADIO_MODE_NATIVE; // Use the native 15.4 radio + _host_config.host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE; // Disable host connection + _zb_ep_list = esp_zb_ep_list_create(); + _primary_channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK; + _open_network = 0; + _scan_status = ZB_SCAN_FAILED; + _begin_timeout = ZB_BEGIN_TIMEOUT_DEFAULT; + _started = false; + _connected = false; + _scan_duration = 3; // default scan duration + _rx_on_when_idle = true; + if (!lock) { + lock = xSemaphoreCreateBinary(); + if (lock == NULL) { + log_e("Semaphore creation failed"); + } + } +} + +//forward declaration +static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message); + +bool ZigbeeCore::begin(esp_zb_cfg_t *role_cfg, bool erase_nvs) { + if (!zigbeeInit(role_cfg, erase_nvs)) { + log_e("ZigbeeCore begin failed"); + return false; + } + _role = (zigbee_role_t)role_cfg->esp_zb_role; + if (xSemaphoreTake(lock, _begin_timeout) != pdTRUE) { + log_e("ZigbeeCore begin failed or timeout"); + if (_role != ZIGBEE_COORDINATOR) { // Only End Device and Router can rejoin + resetNVRAMChannelMask(); + } + } + return started(); +} + +bool ZigbeeCore::begin(zigbee_role_t role, bool erase_nvs) { + bool status = true; + switch (role) { + case ZIGBEE_COORDINATOR: + { + _role = ZIGBEE_COORDINATOR; + esp_zb_cfg_t zb_nwk_cfg = ZIGBEE_DEFAULT_COORDINATOR_CONFIG(); + status = zigbeeInit(&zb_nwk_cfg, erase_nvs); + break; + } + case ZIGBEE_ROUTER: + { + _role = ZIGBEE_ROUTER; + esp_zb_cfg_t zb_nwk_cfg = ZIGBEE_DEFAULT_ROUTER_CONFIG(); + status = zigbeeInit(&zb_nwk_cfg, erase_nvs); + break; + } + case ZIGBEE_END_DEVICE: + { + _role = ZIGBEE_END_DEVICE; + esp_zb_cfg_t zb_nwk_cfg = ZIGBEE_DEFAULT_ED_CONFIG(); + status = zigbeeInit(&zb_nwk_cfg, erase_nvs); + break; + } + default: log_e("Invalid Zigbee Role"); return false; + } + if (!status || xSemaphoreTake(lock, _begin_timeout) != pdTRUE) { + log_e("ZigbeeCore begin failed or timeout"); + if (_role != ZIGBEE_COORDINATOR) { // Only End Device and Router can rejoin + resetNVRAMChannelMask(); + } + } + return started(); +} + +bool ZigbeeCore::addEndpoint(ZigbeeEP *ep) { + ep_objects.push_back(ep); + + log_d("Endpoint: %d, Device ID: 0x%04x", ep->_endpoint, ep->_device_id); + //Register clusters and ep_list to the ZigbeeCore class's ep_list + if (ep->_ep_config.endpoint == 0 || ep->_cluster_list == nullptr) { + log_e("Endpoint config or Cluster list is not initialized, EP not added to ZigbeeCore's EP list"); + return false; + } + esp_err_t ret = ESP_OK; + if (ep->_device_id == ESP_ZB_HA_HOME_GATEWAY_DEVICE_ID) { + ret = esp_zb_ep_list_add_gateway_ep(_zb_ep_list, ep->_cluster_list, ep->_ep_config); + } else { + ret = esp_zb_ep_list_add_ep(_zb_ep_list, ep->_cluster_list, ep->_ep_config); + } + if (ret != ESP_OK) { + log_e("Failed to add endpoint: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +static void esp_zb_task(void *pvParameters) { + esp_zb_bdb_set_scan_duration(Zigbee.getScanDuration()); + + /* initialize Zigbee stack */ + ESP_ERROR_CHECK(esp_zb_start(false)); + + //NOTE: This is a workaround to make battery powered devices to be discovered as battery powered + if (((zigbee_role_t)Zigbee.getRole() == ZIGBEE_END_DEVICE) && edBatteryPowered) { + zb_set_ed_node_descriptor(0, Zigbee.getRxOnWhenIdle(), 1); + } + + esp_zb_stack_main_loop(); +} + +// Zigbee core init function +bool ZigbeeCore::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { + // Zigbee platform configuration + esp_zb_platform_config_t platform_config = { + .radio_config = _radio_config, + .host_config = _host_config, + }; + + esp_err_t err = esp_zb_platform_config(&platform_config); + if (err != ESP_OK) { + log_e("Failed to configure Zigbee platform"); + return false; + } + + // Initialize Zigbee stack + log_d("Initialize Zigbee stack"); + esp_zb_init(zb_cfg); + + // Register all Zigbee EPs in list + if (ep_objects.empty()) { + log_w("No Zigbee EPs to register"); + } else { + log_d("Register all Zigbee EPs in list"); + err = esp_zb_device_register(_zb_ep_list); + if (err != ESP_OK) { + log_e("Failed to register Zigbee EPs"); + return false; + } + + //print the list of Zigbee EPs from ep_objects + log_i("List of registered Zigbee EPs:"); + for (std::list::iterator it = ep_objects.begin(); it != ep_objects.end(); ++it) { + log_i("Device type: %s, Endpoint: %d, Device ID: 0x%04x", getDeviceTypeString((*it)->_device_id), (*it)->_endpoint, (*it)->_device_id); + if ((*it)->_power_source == ZB_POWER_SOURCE_BATTERY) { + edBatteryPowered = true; + } + } + } + // Register Zigbee action handler + esp_zb_core_action_handler_register(zb_action_handler); + err = esp_zb_set_primary_network_channel_set(_primary_channel_mask); + if (err != ESP_OK) { + log_e("Failed to set primary network channel mask"); + return false; + } + + //Erase NVRAM before creating connection to new Coordinator + if (erase_nvs) { + esp_zb_nvram_erase_at_start(true); + } + + // Create Zigbee task and start Zigbee stack + xTaskCreate(esp_zb_task, "Zigbee_main", 8192, NULL, 5, NULL); + + return true; +} + +void ZigbeeCore::setRadioConfig(esp_zb_radio_config_t config) { + _radio_config = config; +} + +esp_zb_radio_config_t ZigbeeCore::getRadioConfig() { + return _radio_config; +} + +void ZigbeeCore::setHostConfig(esp_zb_host_config_t config) { + _host_config = config; +} + +esp_zb_host_config_t ZigbeeCore::getHostConfig() { + return _host_config; +} + +void ZigbeeCore::setPrimaryChannelMask(uint32_t mask) { + _primary_channel_mask = mask; +} + +void ZigbeeCore::setScanDuration(uint8_t duration) { + if (duration < 1 || duration > 4) { + log_e("Invalid scan duration, must be between 1 and 4"); + return; + } + _scan_duration = duration; +} + +void ZigbeeCore::setRebootOpenNetwork(uint8_t time) { + _open_network = time; +} + +void ZigbeeCore::openNetwork(uint8_t time) { + if (started()) { + log_v("Opening network for joining for %d seconds", time); + esp_zb_bdb_open_network(time); + } +} + +static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { + ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); +} + +void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { + //common variables + uint32_t *p_sg_p = signal_struct->p_app_signal; + esp_err_t err_status = signal_struct->esp_err_status; + esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; + //coordinator variables + esp_zb_zdo_signal_device_annce_params_t *dev_annce_params = NULL; + + //main switch + switch (sig_type) { + case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: // Common + log_i("Zigbee stack initialized"); + log_d("Zigbee channel mask: 0x%08x", esp_zb_get_channel_mask()); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); + break; + case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: // Common + case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: // Common + if (err_status == ESP_OK) { + log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); + if (esp_zb_bdb_is_factory_new()) { + // Role specific code + if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { + log_i("Start network formation"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION); + } else { + log_i("Start network steering"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); + Zigbee._started = true; + xSemaphoreGive(Zigbee.lock); + } + } else { + log_i("Device rebooted"); + Zigbee._started = true; + xSemaphoreGive(Zigbee.lock); + if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR && Zigbee._open_network > 0) { + log_i("Opening network for joining for %d seconds", Zigbee._open_network); + esp_zb_bdb_open_network(Zigbee._open_network); + } else { + // Save the channel mask to NVRAM in case of reboot which may be on a different channel after a change in the network + Zigbee.setNVRAMChannelMask(1 << esp_zb_get_current_channel()); + Zigbee._connected = true; + } + Zigbee.searchBindings(); + } + } else { + /* commissioning failed */ + log_w("Commissioning failed, trying again...", esp_err_to_name(err_status)); + esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_INITIALIZATION, 500); + } + break; + case ESP_ZB_BDB_SIGNAL_FORMATION: // Coordinator + if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { + if (err_status == ESP_OK) { + esp_zb_ieee_addr_t extended_pan_id; + esp_zb_get_extended_pan_id(extended_pan_id); + log_i( + "Formed network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", + extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], + extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address() + ); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); + } else { + log_i("Restart network formation (status: %s)", esp_err_to_name(err_status)); + esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_FORMATION, 1000); + } + } + break; + case ESP_ZB_BDB_SIGNAL_STEERING: // Router and End Device + if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { + if (err_status == ESP_OK) { + log_i("Network steering started"); + } + Zigbee._started = true; + xSemaphoreGive(Zigbee.lock); + } else { + if (err_status == ESP_OK) { + esp_zb_ieee_addr_t extended_pan_id; + esp_zb_get_extended_pan_id(extended_pan_id); + log_i( + "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", + extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], + extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address() + ); + Zigbee._connected = true; + // Set channel mask and write to NVRAM, so that the device will re-join the network faster after reboot (scan only on the current channel) + Zigbee.setNVRAMChannelMask(1 << esp_zb_get_current_channel()); + } else { + log_i("Network steering was not successful (status: %s)", esp_err_to_name(err_status)); + esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); + } + } + break; + case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE: // Coordinator + if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { + dev_annce_params = (esp_zb_zdo_signal_device_annce_params_t *)esp_zb_app_signal_get_params(p_sg_p); + log_i("New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr); + esp_zb_zdo_match_desc_req_param_t cmd_req; + cmd_req.dst_nwk_addr = dev_annce_params->device_short_addr; + cmd_req.addr_of_interest = dev_annce_params->device_short_addr; + log_v("Device capabilities: 0x%02x", dev_annce_params->capability); + /* + capability: + Bit 0 – Alternate PAN Coordinator + Bit 1 – Device type: 1- ZigBee Router; 0 – End Device + Bit 2 – Power Source: 1 Main powered + Bit 3 – Receiver on when Idle + Bit 4 – Reserved + Bit 5 – Reserved + Bit 6 – Security capability + Bit 7 – Reserved + */ + // for each endpoint in the list call the findEndpoint function if not bounded or allowed to bind multiple devices + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (!(*it)->bound() || (*it)->epAllowMultipleBinding()) { + // Check if the device is already bound + bool found = false; + // Get the list of devices bound to the EP + std::list bound_devices = (*it)->getBoundDevices(); + for (std::list::iterator device = bound_devices.begin(); device != bound_devices.end(); ++device) { + if (((*device)->short_addr == dev_annce_params->device_short_addr) || (memcmp((*device)->ieee_addr, dev_annce_params->ieee_addr, 8) == 0)) { + found = true; + log_d("Device already bound to endpoint %d", (*it)->getEndpoint()); + break; + } + } + if (!found) { + (*it)->findEndpoint(&cmd_req); + } + } + } + } + break; + case ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: // Coordinator + if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { + if (err_status == ESP_OK) { + if (*(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)) { + log_i("Network(0x%04hx) is open for %d seconds", esp_zb_get_pan_id(), *(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)); + } else { + log_i("Network(0x%04hx) closed, devices joining not allowed.", esp_zb_get_pan_id()); + } + } + } + break; + case ESP_ZB_ZDO_SIGNAL_LEAVE: // End Device + Router + // Device was removed from the network, factory reset the device + if ((zigbee_role_t)Zigbee.getRole() != ZIGBEE_COORDINATOR) { + Zigbee.factoryReset(true); + } + break; + default: log_v("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; + } +} + +void ZigbeeCore::factoryReset(bool restart) { + if (restart) { + log_v("Factory resetting Zigbee stack, device will reboot"); + esp_zb_factory_reset(); + } else { + log_v("Factory resetting Zigbee NVRAM to factory default"); + log_w("The device will not reboot, to take effect please reboot the device manually"); + esp_zb_zcl_reset_nvram_to_factory_default(); + } +} + +void ZigbeeCore::scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor) { + log_v("Zigbee network scan complete"); + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_v("Found %d networks", count); + //print Zigbee networks + for (int i = 0; i < count; i++) { + log_v( + "Network %d: PAN ID: 0x%04hx, Permit Joining: %s, Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, Channel: %d, Router Capacity: %s, End " + "Device Capacity: %s", + i, nwk_descriptor[i].short_pan_id, nwk_descriptor[i].permit_joining ? "Yes" : "No", nwk_descriptor[i].extended_pan_id[7], + nwk_descriptor[i].extended_pan_id[6], nwk_descriptor[i].extended_pan_id[5], nwk_descriptor[i].extended_pan_id[4], nwk_descriptor[i].extended_pan_id[3], + nwk_descriptor[i].extended_pan_id[2], nwk_descriptor[i].extended_pan_id[1], nwk_descriptor[i].extended_pan_id[0], nwk_descriptor[i].logic_channel, + nwk_descriptor[i].router_capacity ? "Yes" : "No", nwk_descriptor[i].end_device_capacity ? "Yes" : "No" + ); + } + //save scan result and update scan status + //copy network descriptor to _scan_result to keep the data after the callback + Zigbee._scan_result = (esp_zb_network_descriptor_t *)malloc(count * sizeof(esp_zb_network_descriptor_t)); + memcpy(Zigbee._scan_result, nwk_descriptor, count * sizeof(esp_zb_network_descriptor_t)); + Zigbee._scan_status = count; + } else { + log_e("Failed to scan Zigbee network (status: 0x%x)", zdo_status); + Zigbee._scan_status = ZB_SCAN_FAILED; + Zigbee._scan_result = nullptr; + } +} + +void ZigbeeCore::scanNetworks(u_int32_t channel_mask, u_int8_t scan_duration) { + if (!started()) { + log_e("Zigbee stack is not started, cannot scan networks"); + return; + } + log_v("Scanning Zigbee networks"); + esp_zb_zdo_active_scan_request(channel_mask, scan_duration, scanCompleteCallback); + _scan_status = ZB_SCAN_RUNNING; +} + +int16_t ZigbeeCore::scanComplete() { + return _scan_status; +} + +zigbee_scan_result_t *ZigbeeCore::getScanResult() { + return _scan_result; +} + +void ZigbeeCore::scanDelete() { + if (_scan_result != nullptr) { + free(_scan_result); + _scan_result = nullptr; + } + _scan_status = ZB_SCAN_FAILED; +} + +// Recall bounded devices from the binding table after reboot +void ZigbeeCore::bindingTableCb(const esp_zb_zdo_binding_table_info_t *table_info, void *user_ctx) { + bool done = true; + esp_zb_zdo_mgmt_bind_param_t *req = (esp_zb_zdo_mgmt_bind_param_t *)user_ctx; + esp_zb_zdp_status_t zdo_status = (esp_zb_zdp_status_t)table_info->status; + log_d("Binding table callback for address 0x%04x with status %d", req->dst_addr, zdo_status); + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + // Print binding table log simple + log_d("Binding table info: total %d, index %d, count %d", table_info->total, table_info->index, table_info->count); + + if (table_info->total == 0) { + log_d("No binding table entries found"); + free(req); + return; + } + + esp_zb_zdo_binding_table_record_t *record = table_info->record; + for (int i = 0; i < table_info->count; i++) { + log_d( + "Binding table record: src_endp %d, dst_endp %d, cluster_id 0x%04x, dst_addr_mode %d", record->src_endp, record->dst_endp, record->cluster_id, + record->dst_addr_mode + ); + + zb_device_params_t *device = (zb_device_params_t *)calloc(1, sizeof(zb_device_params_t)); + device->endpoint = record->dst_endp; + if (record->dst_addr_mode == ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT || record->dst_addr_mode == ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT) { + device->short_addr = record->dst_address.addr_short; + } else { //ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT + memcpy(device->ieee_addr, record->dst_address.addr_long, sizeof(esp_zb_ieee_addr_t)); + } + + // Add to list of bound devices of proper endpoint + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if ((*it)->getEndpoint() == record->src_endp) { + (*it)->addBoundDevice(device); + log_d( + "Device bound to EP %d -> device endpoint: %d, short addr: 0x%04x, ieee addr: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", record->src_endp, + device->endpoint, device->short_addr, 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] + ); + } + } + record = record->next; + } + + // Continue reading the binding table + if (table_info->index + table_info->count < table_info->total) { + /* There are unreported binding table entries, request for them. */ + req->start_index = table_info->index + table_info->count; + esp_zb_zdo_binding_table_req(req, bindingTableCb, req); + done = false; + } + } + + if (done) { + // Print bound devices + log_d("Filling bounded devices finished"); + free(req); + } +} + +void ZigbeeCore::searchBindings() { + esp_zb_zdo_mgmt_bind_param_t *mb_req = (esp_zb_zdo_mgmt_bind_param_t *)malloc(sizeof(esp_zb_zdo_mgmt_bind_param_t)); + mb_req->dst_addr = esp_zb_get_short_address(); + mb_req->start_index = 0; + log_d("Requesting binding table for address 0x%04x", mb_req->dst_addr); + esp_zb_zdo_binding_table_req(mb_req, bindingTableCb, (void *)mb_req); +} + +void ZigbeeCore::resetNVRAMChannelMask() { + _primary_channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK; + esp_zb_set_channel_mask(_primary_channel_mask); + zb_nvram_write_dataset(ZB_NVRAM_COMMON_DATA); + log_v("Channel mask reset to all channels"); +} + +void ZigbeeCore::setNVRAMChannelMask(uint32_t mask) { + _primary_channel_mask = mask; + esp_zb_set_channel_mask(_primary_channel_mask); + zb_nvram_write_dataset(ZB_NVRAM_COMMON_DATA); + log_v("Channel mask set to 0x%08x", mask); +} + +// Function to convert enum value to string +const char *ZigbeeCore::getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId) { + switch (deviceId) { + case ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID: return "General On/Off switch"; + case ESP_ZB_HA_LEVEL_CONTROL_SWITCH_DEVICE_ID: return "Level Control Switch"; + case ESP_ZB_HA_ON_OFF_OUTPUT_DEVICE_ID: return "General On/Off output"; + case ESP_ZB_HA_LEVEL_CONTROLLABLE_OUTPUT_DEVICE_ID: return "Level Controllable Output"; + case ESP_ZB_HA_SCENE_SELECTOR_DEVICE_ID: return "Scene Selector"; + case ESP_ZB_HA_CONFIGURATION_TOOL_DEVICE_ID: return "Configuration Tool"; + case ESP_ZB_HA_REMOTE_CONTROL_DEVICE_ID: return "Remote Control"; + case ESP_ZB_HA_COMBINED_INTERFACE_DEVICE_ID: return "Combined Interface"; + case ESP_ZB_HA_RANGE_EXTENDER_DEVICE_ID: return "Range Extender"; + case ESP_ZB_HA_MAINS_POWER_OUTLET_DEVICE_ID: return "Mains Power Outlet"; + case ESP_ZB_HA_DOOR_LOCK_DEVICE_ID: return "Door lock client"; + case ESP_ZB_HA_DOOR_LOCK_CONTROLLER_DEVICE_ID: return "Door lock controller"; + case ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID: return "Simple Sensor device"; + case ESP_ZB_HA_CONSUMPTION_AWARENESS_DEVICE_ID: return "Consumption Awareness Device"; + case ESP_ZB_HA_HOME_GATEWAY_DEVICE_ID: return "Home Gateway"; + case ESP_ZB_HA_SMART_PLUG_DEVICE_ID: return "Smart plug"; + case ESP_ZB_HA_WHITE_GOODS_DEVICE_ID: return "White Goods"; + case ESP_ZB_HA_METER_INTERFACE_DEVICE_ID: return "Meter Interface"; + case ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID: return "On/Off Light Device"; + case ESP_ZB_HA_DIMMABLE_LIGHT_DEVICE_ID: return "Dimmable Light Device"; + case ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID: return "Color Dimmable Light Device"; + case ESP_ZB_HA_DIMMER_SWITCH_DEVICE_ID: return "Dimmer Switch Device"; + case ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID: return "Color Dimmer Switch Device"; + case ESP_ZB_HA_LIGHT_SENSOR_DEVICE_ID: return "Light Sensor"; + case ESP_ZB_HA_SHADE_DEVICE_ID: return "Shade"; + case ESP_ZB_HA_SHADE_CONTROLLER_DEVICE_ID: return "Shade controller"; + case ESP_ZB_HA_WINDOW_COVERING_DEVICE_ID: return "Window Covering client"; + case ESP_ZB_HA_WINDOW_COVERING_CONTROLLER_DEVICE_ID: return "Window Covering controller"; + case ESP_ZB_HA_HEATING_COOLING_UNIT_DEVICE_ID: return "Heating/Cooling Unit device"; + case ESP_ZB_HA_THERMOSTAT_DEVICE_ID: return "Thermostat Device"; + case ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID: return "Temperature Sensor"; + case ESP_ZB_HA_IAS_CONTROL_INDICATING_EQUIPMENT_ID: return "IAS Control and Indicating Equipment"; + case ESP_ZB_HA_IAS_ANCILLARY_CONTROL_EQUIPMENT_ID: return "IAS Ancillary Control Equipment"; + case ESP_ZB_HA_IAS_ZONE_ID: return "IAS Zone"; + case ESP_ZB_HA_IAS_WARNING_DEVICE_ID: return "IAS Warning Device"; + case ESP_ZB_HA_TEST_DEVICE_ID: return "Custom HA device for test"; + case ESP_ZB_HA_CUSTOM_TUNNEL_DEVICE_ID: return "Custom Tunnel device"; + case ESP_ZB_HA_CUSTOM_ATTR_DEVICE_ID: return "Custom Attributes Device"; + default: return "Unknown device type"; + } +} + +ZigbeeCore Zigbee = ZigbeeCore(); + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ZigbeeCore.h b/libraries/Zigbee/src/ZigbeeCore.h new file mode 100644 index 00000000000..06c3ec4551a --- /dev/null +++ b/libraries/Zigbee/src/ZigbeeCore.h @@ -0,0 +1,175 @@ +/* Zigbee core class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "esp_zigbee_core.h" +#include "zdo/esp_zigbee_zdo_common.h" +#include +#include +#include "ZigbeeEP.h" +class ZigbeeEP; + +typedef void (*voidFuncPtr)(void); +typedef void (*voidFuncPtrArg)(void *); + +typedef esp_zb_network_descriptor_t zigbee_scan_result_t; + +// enum of Zigbee Roles +typedef enum { + ZIGBEE_COORDINATOR = 0, + ZIGBEE_ROUTER = 1, + ZIGBEE_END_DEVICE = 2 +} zigbee_role_t; + +#define ZB_SCAN_RUNNING (-1) +#define ZB_SCAN_FAILED (-2) + +#define ZB_BEGIN_TIMEOUT_DEFAULT 30000 // 30 seconds + +#define ZIGBEE_DEFAULT_ED_CONFIG() \ + { \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, .install_code_policy = false, \ + .nwk_cfg = { \ + .zed_cfg = \ + { \ + .ed_timeout = ESP_ZB_ED_AGING_TIMEOUT_64MIN, \ + .keep_alive = 3000, \ + }, \ + }, \ + } + +#define ZIGBEE_DEFAULT_ROUTER_CONFIG() \ + { \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_ROUTER, .install_code_policy = false, .nwk_cfg = { \ + .zczr_cfg = \ + { \ + .max_children = 10, \ + }, \ + } \ + } + +#define ZIGBEE_DEFAULT_COORDINATOR_CONFIG() \ + { \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, .install_code_policy = false, .nwk_cfg = { \ + .zczr_cfg = \ + { \ + .max_children = 10, \ + }, \ + } \ + } + +#define ZIGBEE_DEFAULT_UART_RCP_RADIO_CONFIG() \ + { \ + .radio_mode = ZB_RADIO_MODE_UART_RCP, \ + .radio_uart_config = { \ + .port = UART_NUM_1, \ + .rx_pin = GPIO_NUM_NC, \ + .tx_pin = GPIO_NUM_NC, \ + .uart_config = \ + { \ + .baud_rate = 460800, \ + .data_bits = UART_DATA_8_BITS, \ + .parity = UART_PARITY_DISABLE, \ + .stop_bits = UART_STOP_BITS_1, \ + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ + .rx_flow_ctrl_thresh = 0, \ + .source_clk = UART_SCLK_DEFAULT, \ + }, \ + }, \ + } + +class ZigbeeCore { +private: + esp_zb_radio_config_t _radio_config; + esp_zb_host_config_t _host_config; + uint32_t _primary_channel_mask; + uint32_t _begin_timeout; + int16_t _scan_status; + uint8_t _scan_duration; + bool _rx_on_when_idle; + + esp_zb_ep_list_t *_zb_ep_list; + zigbee_role_t _role; + bool _started; + bool _connected; + + uint8_t _open_network; + zigbee_scan_result_t *_scan_result; + SemaphoreHandle_t lock; + + bool zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs); + static void scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor); + const char *getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId); + void searchBindings(); + static void bindingTableCb(const esp_zb_zdo_binding_table_info_t *table_info, void *user_ctx); + void resetNVRAMChannelMask(); // Reset to default mask also in NVRAM + void setNVRAMChannelMask(uint32_t mask); // Set channel mask in NVRAM + +public: + ZigbeeCore(); + ~ZigbeeCore() {} + + std::list ep_objects; + + bool begin(zigbee_role_t role = ZIGBEE_END_DEVICE, bool erase_nvs = false); + bool begin(esp_zb_cfg_t *role_cfg, bool erase_nvs = false); + // bool end(); + + bool started() { + return _started; + } + bool connected() { + return _connected; + } + zigbee_role_t getRole() { + return _role; + } + + bool addEndpoint(ZigbeeEP *ep); + //void removeEndpoint(ZigbeeEP *ep); + + void setRadioConfig(esp_zb_radio_config_t config); + esp_zb_radio_config_t getRadioConfig(); + + void setHostConfig(esp_zb_host_config_t config); + esp_zb_host_config_t getHostConfig(); + + void setPrimaryChannelMask(uint32_t mask); // By default all channels are scanned (11-26) -> mask 0x07FFF800 + + void setScanDuration(uint8_t duration); // Can be set from 1 - 4. 1 is fastest, 4 is slowest + uint8_t getScanDuration() { + return _scan_duration; + } + + void setRxOnWhenIdle(bool rx_on_when_idle) { + _rx_on_when_idle = rx_on_when_idle; + } + bool getRxOnWhenIdle() { + return _rx_on_when_idle; + } + void setTimeout(uint32_t timeout) { + _begin_timeout = timeout; + } + void setRebootOpenNetwork(uint8_t time); + void openNetwork(uint8_t time); + + //scan_duration Time spent scanning each channel, in units of ((1 << scan_duration) + 1) * a beacon time. (15.36 microseconds) + void scanNetworks(uint32_t channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK, uint8_t scan_duration = 5); + // Zigbee scan complete status check, -2: failed or not started, -1: running, 0: no networks found, >0: number of networks found + int16_t scanComplete(); + zigbee_scan_result_t *getScanResult(); + void scanDelete(); + + void factoryReset(bool restart = true); + + // Friend function declaration to allow access to private members + friend void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct); +}; + +extern ZigbeeCore Zigbee; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp new file mode 100644 index 00000000000..cf52a902983 --- /dev/null +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -0,0 +1,603 @@ +/* Common Class for Zigbee End Point */ + +#include "ZigbeeEP.h" + +#if CONFIG_ZB_ENABLED + +#include "esp_zigbee_cluster.h" +#include "zcl/esp_zigbee_zcl_power_config.h" + +bool ZigbeeEP::_is_bound = false; +bool ZigbeeEP::_allow_multiple_binding = false; + +//TODO: is_bound and allow_multiple_binding to make not static + +/* Zigbee End Device Class */ +ZigbeeEP::ZigbeeEP(uint8_t endpoint) { + _endpoint = endpoint; + log_v("Endpoint: %d", _endpoint); + _ep_config.endpoint = 0; + _cluster_list = nullptr; + _on_identify = nullptr; + _read_model = NULL; + _read_manufacturer = NULL; + _time_status = 0; + if (!lock) { + lock = xSemaphoreCreateBinary(); + if (lock == NULL) { + log_e("Semaphore creation failed"); + } + } +} + +void ZigbeeEP::setVersion(uint8_t version) { + _ep_config.app_device_version = version; +} + +bool ZigbeeEP::setManufacturerAndModel(const char *name, const char *model) { + // Allocate a new array of size length + 2 (1 for the length, 1 for null terminator) + char zb_name[ZB_MAX_NAME_LENGTH + 2]; + char zb_model[ZB_MAX_NAME_LENGTH + 2]; + + // Convert manufacturer to ZCL string + size_t name_length = strlen(name); + size_t model_length = strlen(model); + if (name_length > ZB_MAX_NAME_LENGTH || model_length > ZB_MAX_NAME_LENGTH) { + log_e("Manufacturer or model name is too long"); + return false; + } + // Get and check the basic cluster + esp_zb_attribute_list_t *basic_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (basic_cluster == nullptr) { + log_e("Failed to get basic cluster"); + return false; + } + // Store the length as the first element + zb_name[0] = static_cast(name_length); // Cast size_t to char + zb_model[0] = static_cast(model_length); + // Use memcpy to copy the characters to the result array + memcpy(zb_name + 1, name, name_length); + memcpy(zb_model + 1, model, model_length); + // Null-terminate the array + zb_name[name_length + 1] = '\0'; + zb_model[model_length + 1] = '\0'; + // Update the manufacturer and model attributes + esp_err_t ret_name = esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)zb_name); + if (ret_name != ESP_OK) { + log_e("Failed to set manufacturer: 0x%x: %s", ret_name, esp_err_to_name(ret_name)); + } + esp_err_t ret_model = esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)zb_model); + if (ret_model != ESP_OK) { + log_e("Failed to set model: 0x%x: %s", ret_model, esp_err_to_name(ret_model)); + } + return ret_name == ESP_OK && ret_model == ESP_OK; +} + +bool ZigbeeEP::setPowerSource(zb_power_source_t power_source, uint8_t battery_percentage, uint8_t battery_voltage) { + esp_zb_attribute_list_t *basic_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, (void *)&power_source); + if (ret != ESP_OK) { + log_e("Failed to set power source: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + + if (power_source == ZB_POWER_SOURCE_BATTERY) { + // Add power config cluster and battery percentage attribute + if (battery_percentage > 100) { + battery_percentage = 100; + } + battery_percentage = battery_percentage * 2; + esp_zb_attribute_list_t *power_config_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_POWER_CONFIG); + ret = esp_zb_power_config_cluster_add_attr(power_config_cluster, ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID, (void *)&battery_percentage); + if (ret != ESP_OK) { + log_e("Failed to add battery percentage attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_power_config_cluster_add_attr(power_config_cluster, ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_ID, (void *)&battery_voltage); + if (ret != ESP_OK) { + log_e("Failed to add battery voltage attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_list_add_power_config_cluster(_cluster_list, power_config_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (ret != ESP_OK) { + log_e("Failed to add power config cluster: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + } + _power_source = power_source; + return true; +} + +bool ZigbeeEP::setBatteryPercentage(uint8_t percentage) { + // 100% = 200 in decimal, 0% = 0 + // Convert percentage to 0-200 range + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + if (percentage > 100) { + percentage = 100; + } + percentage = percentage * 2; + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_POWER_CONFIG, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID, &percentage, + false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set battery percentage: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + log_v("Battery percentage updated"); + return true; +} + +bool ZigbeeEP::setBatteryVoltage(uint8_t voltage) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_POWER_CONFIG, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_ID, &voltage, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set battery voltage: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + log_v("Battery voltage updated"); + return true; +} + +bool ZigbeeEP::reportBatteryPercentage() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_POWER_CONFIG; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to report battery percentage: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("Battery percentage reported"); + return true; +} + +char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) { + /* Read peer Manufacture Name & Model Identifier */ + esp_zb_zcl_read_attr_cmd_t read_req; + + if (short_addr != 0) { + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + } else { + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + } + + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_BASIC; + + uint16_t attributes[] = { + ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, + }; + read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_field = attributes; + + if (_read_manufacturer != NULL) { + free(_read_manufacturer); + } + _read_manufacturer = NULL; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + + //Wait for response or timeout + if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) { + log_e("Error while reading manufacturer"); + } + return _read_manufacturer; +} + +char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) { + /* Read peer Manufacture Name & Model Identifier */ + esp_zb_zcl_read_attr_cmd_t read_req; + + if (short_addr != 0) { + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + } else { + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + } + + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_BASIC; + + uint16_t attributes[] = { + ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, + }; + read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_field = attributes; + + if (_read_model != NULL) { + free(_read_model); + } + _read_model = NULL; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + + //Wait for response or timeout + if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) { + log_e("Error while reading model"); + } + return _read_model; +} + +void ZigbeeEP::printBoundDevices() { + log_i("Bound devices:"); + for ([[maybe_unused]] + const auto &device : _bound_devices) { + log_i( + "Device on endpoint %d, short address: 0x%x, ieee address: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", device->endpoint, device->short_addr, + 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] + ); + } +} + +void ZigbeeEP::printBoundDevices(Print &print) { + print.println("Bound devices:"); + for ([[maybe_unused]] + const auto &device : _bound_devices) { + print.printf( + "Device on endpoint %d, short address: 0x%x, ieee address: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\r\n", device->endpoint, device->short_addr, + 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] + ); + } +} + +void ZigbeeEP::zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute) { + /* Basic cluster attributes */ + if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { + zbstring_t *zbstr = (zbstring_t *)attribute->data.value; + _read_manufacturer = (char *)malloc(zbstr->len + 1); + if (_read_manufacturer == NULL) { + log_e("Failed to allocate memory for manufacturer data"); + xSemaphoreGive(lock); + return; + } + memcpy(_read_manufacturer, zbstr->data, zbstr->len); + _read_manufacturer[zbstr->len] = '\0'; + log_i("Peer Manufacturer is \"%s\"", _read_manufacturer); + xSemaphoreGive(lock); + } + if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { + zbstring_t *zbstr = (zbstring_t *)attribute->data.value; + _read_model = (char *)malloc(zbstr->len + 1); + if (_read_model == NULL) { + log_e("Failed to allocate memory for model data"); + xSemaphoreGive(lock); + return; + } + memcpy(_read_model, zbstr->data, zbstr->len); + _read_model[zbstr->len] = '\0'; + log_i("Peer Model is \"%s\"", _read_model); + xSemaphoreGive(lock); + } +} + +void ZigbeeEP::zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message) { + if (message->attribute.id == ESP_ZB_ZCL_CMD_IDENTIFY_IDENTIFY_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + if (_on_identify != NULL) { + _on_identify(*(uint16_t *)message->attribute.data.value); + } + } else { + log_w("Other identify commands are not implemented yet."); + } +} + +bool ZigbeeEP::addTimeCluster(tm time, int32_t gmt_offset) { + time_t utc_time = 0; + // Check if time is set + if (time.tm_year > 0) { + // Convert time to UTC + utc_time = mktime(&time); + } + + // Create time cluster server attributes + esp_zb_attribute_list_t *time_cluster_server = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_TIME); + esp_err_t ret = esp_zb_time_cluster_add_attr(time_cluster_server, ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID, (void *)&gmt_offset); + if (ret != ESP_OK) { + log_e("Failed to add time zone attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_time_cluster_add_attr(time_cluster_server, ESP_ZB_ZCL_ATTR_TIME_TIME_ID, (void *)&utc_time); + if (ret != ESP_OK) { + log_e("Failed to add time attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_time_cluster_add_attr(time_cluster_server, ESP_ZB_ZCL_ATTR_TIME_TIME_STATUS_ID, (void *)&_time_status); + if (ret != ESP_OK) { + log_e("Failed to add time status attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + // Create time cluster client attributes + esp_zb_attribute_list_t *time_cluster_client = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_TIME); + // Add time clusters to cluster list + ret = esp_zb_cluster_list_add_time_cluster(_cluster_list, time_cluster_server, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (ret != ESP_OK) { + log_e("Failed to add time cluster (server role): 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_list_add_time_cluster(_cluster_list, time_cluster_client, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE); + if (ret != ESP_OK) { + log_e("Failed to add time cluster (client role): 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeEP::setTime(tm time) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + time_t utc_time = mktime(&time); + log_d("Setting time to %lld", utc_time); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TIME, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TIME_TIME_ID, &utc_time, false); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set time: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeEP::setTimezone(int32_t gmt_offset) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + log_d("Setting timezone to %d", gmt_offset); + esp_zb_lock_acquire(portMAX_DELAY); + ret = + esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TIME, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID, &gmt_offset, false); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set timezone: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) { + /* Read peer time */ + esp_zb_zcl_read_attr_cmd_t read_req; + + if (short_addr >= 0) { + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = (uint16_t)short_addr; + } else { + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + } + + uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TIME_TIME_ID}; + read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_field = attributes; + + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TIME; + + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + + // clear read time + _read_time = 0; + + log_v("Reading time from endpoint %d", endpoint); + esp_zb_zcl_read_attr_cmd_req(&read_req); + + //Wait for response or timeout + if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) { + log_e("Error while reading time"); + return tm(); + } + + struct tm *timeinfo = localtime(&_read_time); + if (timeinfo) { + // Update time + setTime(*timeinfo); + // Update time status to synced + _time_status |= 0x02; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_TIME, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TIME_TIME_STATUS_ID, &_time_status, false + ); + esp_zb_lock_release(); + + return *timeinfo; + } else { + log_e("Error while converting time"); + return tm(); + } +} + +int32_t ZigbeeEP::getTimezone(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) { + /* Read peer timezone */ + esp_zb_zcl_read_attr_cmd_t read_req; + + if (short_addr >= 0) { + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = (uint16_t)short_addr; + } else { + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + } + + uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID}; + read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_field = attributes; + + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TIME; + + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + + // clear read timezone + _read_timezone = 0; + + log_v("Reading timezone from endpoint %d", endpoint); + esp_zb_zcl_read_attr_cmd_req(&read_req); + + //Wait for response or timeout + if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) { + log_e("Error while reading timezone"); + return 0; + } + setTimezone(_read_timezone); + return _read_timezone; +} + +void ZigbeeEP::zbReadTimeCluster(const esp_zb_zcl_attribute_t *attribute) { + /* Time cluster attributes */ + if (attribute->id == ESP_ZB_ZCL_ATTR_TIME_TIME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_UTC_TIME) { + log_v("Time attribute received"); + log_v("Time: %lld", *(uint32_t *)attribute->data.value); + _read_time = *(uint32_t *)attribute->data.value; + xSemaphoreGive(lock); + } else if (attribute->id == ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S32) { + log_v("Timezone attribute received"); + log_v("Timezone: %d", *(int32_t *)attribute->data.value); + _read_timezone = *(int32_t *)attribute->data.value; + xSemaphoreGive(lock); + } +} + +// typedef struct esp_zb_ota_cluster_cfg_s { +// uint32_t ota_upgrade_file_version; /*!< The attribute indicates the file version of the running firmware image on the device */ +// uint16_t ota_upgrade_manufacturer; /*!< The attribute indicates the value for the manufacturer of the device */ +// uint16_t ota_upgrade_image_type; /*!< The attribute indicates the the image type of the file that the client is currently downloading */ +// uint32_t ota_upgrade_downloaded_file_ver; /*!< The attribute indicates the file version of the downloaded image on the device*/ +// esp_zb_ota_cluster_cfg_t; + +// typedef struct esp_zb_zcl_ota_upgrade_client_variable_s { +// uint16_t timer_query; /*!< The field indicates the time of querying OTA image for OTA upgrade client */ +// uint16_t hw_version; /*!< The hardware version */ +// uint8_t max_data_size; /*!< The maximum size of OTA data */ +// } esp_zb_zcl_ota_upgrade_client_variable_t; + +bool ZigbeeEP::addOTAClient( + uint32_t file_version, uint32_t downloaded_file_ver, uint16_t hw_version, uint16_t manufacturer, uint16_t image_type, uint8_t max_data_size +) { + + esp_zb_ota_cluster_cfg_t ota_cluster_cfg = {}; + ota_cluster_cfg.ota_upgrade_file_version = file_version; //OTA_UPGRADE_RUNNING_FILE_VERSION; + ota_cluster_cfg.ota_upgrade_downloaded_file_ver = downloaded_file_ver; //OTA_UPGRADE_DOWNLOADED_FILE_VERSION; + ota_cluster_cfg.ota_upgrade_manufacturer = manufacturer; //OTA_UPGRADE_MANUFACTURER; + ota_cluster_cfg.ota_upgrade_image_type = image_type; //OTA_UPGRADE_IMAGE_TYPE; + + esp_zb_attribute_list_t *ota_cluster = esp_zb_ota_cluster_create(&ota_cluster_cfg); + + esp_zb_zcl_ota_upgrade_client_variable_t variable_config = {}; + variable_config.timer_query = ESP_ZB_ZCL_OTA_UPGRADE_QUERY_TIMER_COUNT_DEF; + variable_config.hw_version = hw_version; //OTA_UPGRADE_HW_VERSION; + variable_config.max_data_size = max_data_size; //OTA_UPGRADE_MAX_DATA_SIZE; + + uint16_t ota_upgrade_server_addr = 0xffff; + uint8_t ota_upgrade_server_ep = 0xff; + + esp_err_t ret = esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_CLIENT_DATA_ID, (void *)&variable_config); + if (ret != ESP_OK) { + log_e("Failed to add OTA client data: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID, (void *)&ota_upgrade_server_addr); + if (ret != ESP_OK) { + log_e("Failed to add OTA server address: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID, (void *)&ota_upgrade_server_ep); + if (ret != ESP_OK) { + log_e("Failed to add OTA server endpoint: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_list_add_ota_cluster(_cluster_list, ota_cluster, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE); + if (ret != ESP_OK) { + log_e("Failed to add OTA cluster: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +static void findOTAServer(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + esp_zb_ota_upgrade_client_query_interval_set(*((uint8_t *)user_ctx), OTA_UPGRADE_QUERY_INTERVAL); + esp_zb_ota_upgrade_client_query_image_req(addr, endpoint); + log_i("Query OTA upgrade from server endpoint: %d after %d seconds", endpoint, OTA_UPGRADE_QUERY_INTERVAL); + } else { + log_w("No OTA Server found"); + } +} + +void ZigbeeEP::requestOTAUpdate() { + esp_zb_zdo_match_desc_req_param_t req; + uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_OTA_UPGRADE}; + + /* Match the OTA server of coordinator */ + req.addr_of_interest = 0x0000; + req.dst_nwk_addr = 0x0000; + req.num_in_clusters = 1; + req.num_out_clusters = 0; + req.profile_id = ESP_ZB_AF_HA_PROFILE_ID; + req.cluster_list = cluster_list; + esp_zb_lock_acquire(portMAX_DELAY); + if (esp_zb_bdb_dev_joined()) { + esp_zb_zdo_match_cluster(&req, findOTAServer, &_endpoint); + } + esp_zb_lock_release(); +} + +const char *ZigbeeEP::esp_zb_zcl_status_to_name(esp_zb_zcl_status_t status) { + switch (status) { + case ESP_ZB_ZCL_STATUS_SUCCESS: return "Success"; + case ESP_ZB_ZCL_STATUS_FAIL: return "Fail"; + case ESP_ZB_ZCL_STATUS_NOT_AUTHORIZED: return "Not authorized"; + case ESP_ZB_ZCL_STATUS_MALFORMED_CMD: return "Malformed command"; + case ESP_ZB_ZCL_STATUS_UNSUP_CLUST_CMD: return "Unsupported cluster command"; + case ESP_ZB_ZCL_STATUS_UNSUP_GEN_CMD: return "Unsupported general command"; + case ESP_ZB_ZCL_STATUS_UNSUP_MANUF_CLUST_CMD: return "Unsupported manufacturer cluster command"; + case ESP_ZB_ZCL_STATUS_UNSUP_MANUF_GEN_CMD: return "Unsupported manufacturer general command"; + case ESP_ZB_ZCL_STATUS_INVALID_FIELD: return "Invalid field"; + case ESP_ZB_ZCL_STATUS_UNSUP_ATTRIB: return "Unsupported attribute"; + case ESP_ZB_ZCL_STATUS_INVALID_VALUE: return "Invalid value"; + case ESP_ZB_ZCL_STATUS_READ_ONLY: return "Read only"; + case ESP_ZB_ZCL_STATUS_INSUFF_SPACE: return "Insufficient space"; + case ESP_ZB_ZCL_STATUS_DUPE_EXISTS: return "Duplicate exists"; + case ESP_ZB_ZCL_STATUS_NOT_FOUND: return "Not found"; + case ESP_ZB_ZCL_STATUS_UNREPORTABLE_ATTRIB: return "Unreportable attribute"; + case ESP_ZB_ZCL_STATUS_INVALID_TYPE: return "Invalid type"; + case ESP_ZB_ZCL_STATUS_WRITE_ONLY: return "Write only"; + case ESP_ZB_ZCL_STATUS_INCONSISTENT: return "Inconsistent"; + case ESP_ZB_ZCL_STATUS_ACTION_DENIED: return "Action denied"; + case ESP_ZB_ZCL_STATUS_TIMEOUT: return "Timeout"; + case ESP_ZB_ZCL_STATUS_ABORT: return "Abort"; + case ESP_ZB_ZCL_STATUS_INVALID_IMAGE: return "Invalid OTA upgrade image"; + case ESP_ZB_ZCL_STATUS_WAIT_FOR_DATA: return "Server does not have data block available yet"; + case ESP_ZB_ZCL_STATUS_NO_IMAGE_AVAILABLE: return "No image available"; + case ESP_ZB_ZCL_STATUS_REQUIRE_MORE_IMAGE: return "Require more image"; + case ESP_ZB_ZCL_STATUS_NOTIFICATION_PENDING: return "Notification pending"; + case ESP_ZB_ZCL_STATUS_HW_FAIL: return "Hardware failure"; + case ESP_ZB_ZCL_STATUS_SW_FAIL: return "Software failure"; + case ESP_ZB_ZCL_STATUS_CALIB_ERR: return "Calibration error"; + case ESP_ZB_ZCL_STATUS_UNSUP_CLUST: return "Cluster is not found on the target endpoint"; + case ESP_ZB_ZCL_STATUS_LIMIT_REACHED: return "Limit reached"; + default: return "Unknown status"; + } +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ZigbeeEP.h b/libraries/Zigbee/src/ZigbeeEP.h new file mode 100644 index 00000000000..e13b3b59de9 --- /dev/null +++ b/libraries/Zigbee/src/ZigbeeEP.h @@ -0,0 +1,170 @@ +/* Common Class for Zigbee End point */ + +#pragma once + +#include "ZigbeeCore.h" +#if CONFIG_ZB_ENABLED + +#include +#include + +/* Useful defines */ +#define ZB_CMD_TIMEOUT 10000 // 10 seconds +#define OTA_UPGRADE_QUERY_INTERVAL (1 * 60) // 1 hour = 60 minutes + +#define ZB_ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0])) + +#define RGB_TO_XYZ(r, g, b, X, Y, Z) \ + { \ + X = (float)(0.412453 * (r) + 0.357580 * (g) + 0.180423 * (b)); \ + Y = (float)(0.212671 * (r) + 0.715160 * (g) + 0.072169 * (b)); \ + Z = (float)(0.019334 * (r) + 0.119193 * (g) + 0.950227 * (b)); \ + } + +typedef struct zbstring_s { + uint8_t len; + char data[]; +} ESP_ZB_PACKED_STRUCT zbstring_t; + +typedef struct zb_device_params_s { + esp_zb_ieee_addr_t ieee_addr; + uint8_t endpoint; + uint16_t short_addr; +} zb_device_params_t; + +typedef enum { + ZB_POWER_SOURCE_UNKNOWN = 0x00, + ZB_POWER_SOURCE_MAINS = 0x01, + ZB_POWER_SOURCE_BATTERY = 0x03, +} zb_power_source_t; + +/* Zigbee End Device Class */ +class ZigbeeEP { +public: + // constants and limits + static constexpr size_t ZB_MAX_NAME_LENGTH = 32; + + // constructors and destructor + ZigbeeEP(uint8_t endpoint = 10); + ~ZigbeeEP() {} + + // Set ep config and cluster list + void setEpConfig(esp_zb_endpoint_config_t ep_config, esp_zb_cluster_list_t *cluster_list) { + _ep_config = ep_config; + _cluster_list = cluster_list; + } + + void setVersion(uint8_t version); + uint8_t getEndpoint() { + return _endpoint; + } + + void printBoundDevices(); + void printBoundDevices(Print &print); + + std::list getBoundDevices() const { + return _bound_devices; + } + + static bool bound() { + return _is_bound; + } + static void allowMultipleBinding(bool bind) { + _allow_multiple_binding = bind; + } + + // Set Manufacturer name and model + bool setManufacturerAndModel(const char *name, const char *model); + + // Methods to read manufacturer and model name from selected endpoint and short address + char *readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr); + char *readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr); + + // Set Power source and battery percentage for battery powered devices + bool setPowerSource(zb_power_source_t power_source, uint8_t percentage = 0xff, uint8_t voltage = 0xff); // voltage in 100mV + bool setBatteryPercentage(uint8_t percentage); // 0-100 % + bool setBatteryVoltage(uint8_t voltage); // voltage in 100mV (example value 35 for 3.5V) + bool reportBatteryPercentage(); // battery voltage is not reportable attribute + + // Set time + bool addTimeCluster(tm time = {}, int32_t gmt_offset = 0); // gmt offset in seconds + bool setTime(tm time); + bool setTimezone(int32_t gmt_offset); + + // Get time from Coordinator or specific endpoint (blocking until response) + struct tm getTime(uint8_t endpoint = 1, int32_t short_addr = 0x0000, esp_zb_ieee_addr_t ieee_addr = {0}); + int32_t getTimezone(uint8_t endpoint = 1, int32_t short_addr = 0x0000, esp_zb_ieee_addr_t ieee_addr = {0}); // gmt offset in seconds + + bool epAllowMultipleBinding() { + return _allow_multiple_binding; + } + + // OTA methods + /** + * @brief Add OTA client to the Zigbee endpoint. + * + * @param file_version The current file version of the OTA client. + * @param downloaded_file_ver The version of the downloaded file. + * @param hw_version The hardware version of the device. + * @param manufacturer The manufacturer code (default: 0x1001). + * @param image_type The image type code (default: 0x1011). + * @param max_data_size The maximum data size for OTA transfer (default and recommended: 223). + * @return true if the OTA client was added successfully, false otherwise. + */ + bool addOTAClient( + uint32_t file_version, uint32_t downloaded_file_ver, uint16_t hw_version, uint16_t manufacturer = 0x1001, uint16_t image_type = 0x1011, + uint8_t max_data_size = 223 + ); + /** + * @brief Request OTA update from the server, first request is within a minute and the next requests are sent every hour automatically. + */ + void requestOTAUpdate(); + + // findEndpoint may be implemented by EPs to find and bind devices + virtual void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) {}; + + // list of all handlers function calls, to be override by EPs implementation + virtual void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) {}; + virtual void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) {}; + virtual void zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented + virtual void zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message); + virtual void zbWindowCoveringMovementCmd(const esp_zb_zcl_window_covering_movement_message_t *message) {}; + virtual void zbReadTimeCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented + virtual void zbIASZoneStatusChangeNotification(const esp_zb_zcl_ias_zone_status_change_notification_message_t *message) {}; + virtual void zbIASZoneEnrollResponse(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) {}; + + virtual void addBoundDevice(zb_device_params_t *device) { + _bound_devices.push_back(device); + _is_bound = true; + } + + void onIdentify(void (*callback)(uint16_t)) { + _on_identify = callback; + } + +private: + char *_read_manufacturer; + char *_read_model; + void (*_on_identify)(uint16_t time); + time_t _read_time; + int32_t _read_timezone; + +protected: + // Convert ZCL status to name + const char *esp_zb_zcl_status_to_name(esp_zb_zcl_status_t status); + + uint8_t _endpoint; + esp_zb_ha_standard_devices_t _device_id; + esp_zb_endpoint_config_t _ep_config; + esp_zb_cluster_list_t *_cluster_list; + static bool _is_bound; + static bool _allow_multiple_binding; + std::list _bound_devices; + SemaphoreHandle_t lock; + zb_power_source_t _power_source; + uint8_t _time_status; + + friend class ZigbeeCore; +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ZigbeeHandlers.cpp b/libraries/Zigbee/src/ZigbeeHandlers.cpp new file mode 100644 index 00000000000..eeeb1e8013a --- /dev/null +++ b/libraries/Zigbee/src/ZigbeeHandlers.cpp @@ -0,0 +1,400 @@ +/* Zigbee Common Functions */ +#include "ZigbeeCore.h" +#include "Arduino.h" + +#if CONFIG_ZB_ENABLED + +#include "esp_ota_ops.h" +#if CONFIG_ZB_DELTA_OTA // Delta OTA, code is prepared for this feature but not enabled by default +#include "esp_delta_ota_ops.h" +#endif + +//OTA Upgrade defines and variables +#define OTA_ELEMENT_HEADER_LEN 6 /* OTA element format header size include tag identifier and length field */ + +/** + * @name Enumeration for the tag identifier denotes the type and format of the data within the element + * @anchor esp_ota_element_tag_id_t + */ +typedef enum esp_ota_element_tag_id_e { + UPGRADE_IMAGE = 0x0000, /*!< Upgrade image */ +} esp_ota_element_tag_id_t; + +static const esp_partition_t *s_ota_partition = NULL; +static esp_ota_handle_t s_ota_handle = 0; +static bool s_tagid_received = false; + +// forward declaration of all implemented handlers +static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message); +static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message); +static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_resp_message_t *message); +static esp_err_t zb_configure_report_resp_handler(const esp_zb_zcl_cmd_config_report_resp_message_t *message); +static esp_err_t zb_cmd_ias_zone_status_change_handler(const esp_zb_zcl_ias_zone_status_change_notification_message_t *message); +static esp_err_t zb_cmd_ias_zone_enroll_response_handler(const esp_zb_zcl_ias_zone_enroll_response_message_t *message); +static esp_err_t zb_cmd_default_resp_handler(const esp_zb_zcl_cmd_default_resp_message_t *message); +static esp_err_t zb_window_covering_movement_resp_handler(const esp_zb_zcl_window_covering_movement_message_t *message); +static esp_err_t zb_ota_upgrade_status_handler(const esp_zb_zcl_ota_upgrade_value_message_t *message); +static esp_err_t zb_ota_upgrade_query_image_resp_handler(const esp_zb_zcl_ota_upgrade_query_image_resp_message_t *message); + +// Zigbee action handlers +[[maybe_unused]] +static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { + esp_err_t ret = ESP_OK; + switch (callback_id) { + case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_set_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; + case ESP_ZB_CORE_REPORT_ATTR_CB_ID: ret = zb_attribute_reporting_handler((esp_zb_zcl_report_attr_message_t *)message); break; + case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: ret = zb_cmd_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); break; + case ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID: ret = zb_configure_report_resp_handler((esp_zb_zcl_cmd_config_report_resp_message_t *)message); break; + case ESP_ZB_CORE_CMD_IAS_ZONE_ZONE_STATUS_CHANGE_NOT_ID: + ret = zb_cmd_ias_zone_status_change_handler((esp_zb_zcl_ias_zone_status_change_notification_message_t *)message); + break; + case ESP_ZB_CORE_IAS_ZONE_ENROLL_RESPONSE_VALUE_CB_ID: + ret = zb_cmd_ias_zone_enroll_response_handler((esp_zb_zcl_ias_zone_enroll_response_message_t *)message); + break; + case ESP_ZB_CORE_WINDOW_COVERING_MOVEMENT_CB_ID: + ret = zb_window_covering_movement_resp_handler((esp_zb_zcl_window_covering_movement_message_t *)message); + break; + case ESP_ZB_CORE_OTA_UPGRADE_VALUE_CB_ID: ret = zb_ota_upgrade_status_handler((esp_zb_zcl_ota_upgrade_value_message_t *)message); break; + case ESP_ZB_CORE_OTA_UPGRADE_QUERY_IMAGE_RESP_CB_ID: + ret = zb_ota_upgrade_query_image_resp_handler((esp_zb_zcl_ota_upgrade_query_image_resp_message_t *)message); + break; + case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: ret = zb_cmd_default_resp_handler((esp_zb_zcl_cmd_default_resp_message_t *)message); break; + default: log_w("Receive unhandled Zigbee action(0x%x) callback", callback_id); break; + } + return ret; +} + +static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message) { + if (!message) { + log_e("Empty message"); + return ESP_FAIL; + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + return ESP_ERR_INVALID_ARG; + } + + log_v( + "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, + message->attribute.data.size + ); + + // List through all Zigbee EPs and call the callback function, with the message + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (message->info.dst_endpoint == (*it)->getEndpoint()) { + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY) { + (*it)->zbIdentify(message); //method zbIdentify implemented in the common EP class + } else { + (*it)->zbAttributeSet(message); //method zbAttributeSet must be implemented in specific EP class + } + } + } + return ESP_OK; +} + +static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message) { + if (!message) { + log_e("Empty message"); + return ESP_FAIL; + } + if (message->status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->status); + return ESP_ERR_INVALID_ARG; + } + log_v( + "Received report from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->src_address.u.short_addr, message->src_endpoint, + message->dst_endpoint, message->cluster + ); + // List through all Zigbee EPs and call the callback function, with the message + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (message->dst_endpoint == (*it)->getEndpoint()) { + (*it)->zbAttributeRead(message->cluster, &message->attribute); //method zbAttributeRead must be implemented in specific EP class + } + } + return ESP_OK; +} + +static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_resp_message_t *message) { + if (!message) { + log_e("Empty message"); + return ESP_FAIL; + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + return ESP_ERR_INVALID_ARG; + } + log_v( + "Read attribute response: from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->info.src_address.u.short_addr, + message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster + ); + + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (message->info.dst_endpoint == (*it)->getEndpoint()) { + esp_zb_zcl_read_attr_resp_variable_t *variable = message->variables; + while (variable) { + log_v( + "Read attribute response: status(%d), cluster(0x%x), attribute(0x%x), type(0x%x), value(%d)", variable->status, message->info.cluster, + variable->attribute.id, variable->attribute.data.type, variable->attribute.data.value ? *(uint8_t *)variable->attribute.data.value : 0 + ); + if (variable->status == ESP_ZB_ZCL_STATUS_SUCCESS) { + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_BASIC) { + (*it)->zbReadBasicCluster(&variable->attribute); //method zbReadBasicCluster implemented in the common EP class + } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_TIME) { + (*it)->zbReadTimeCluster(&variable->attribute); //method zbReadTimeCluster implemented in the common EP class + } else { + (*it)->zbAttributeRead(message->info.cluster, &variable->attribute); //method zbAttributeRead must be implemented in specific EP class + } + } + variable = variable->next; + } + } + } + return ESP_OK; +} + +static esp_err_t zb_configure_report_resp_handler(const esp_zb_zcl_cmd_config_report_resp_message_t *message) { + if (!message) { + log_e("Empty message"); + return ESP_FAIL; + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + return ESP_ERR_INVALID_ARG; + } + esp_zb_zcl_config_report_resp_variable_t *variable = message->variables; + while (variable) { + log_v( + "Configure report response: status(%d), cluster(0x%x), direction(0x%x), attribute(0x%x)", variable->status, message->info.cluster, variable->direction, + variable->attribute_id + ); + variable = variable->next; + } + return ESP_OK; +} + +static esp_err_t zb_cmd_ias_zone_status_change_handler(const esp_zb_zcl_ias_zone_status_change_notification_message_t *message) { + if (!message) { + log_e("Empty message"); + return ESP_FAIL; + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + return ESP_ERR_INVALID_ARG; + } + log_v( + "IAS Zone Status Notification: from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->info.src_address.u.short_addr, + message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster + ); + + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (message->info.dst_endpoint == (*it)->getEndpoint()) { + (*it)->zbIASZoneStatusChangeNotification(message); + } + } + return ESP_OK; +} + +static esp_err_t zb_cmd_ias_zone_enroll_response_handler(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) { + if (!message) { + log_e("Empty message"); + return ESP_FAIL; + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + return ESP_ERR_INVALID_ARG; + } + log_v("IAS Zone Enroll Response received"); + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (message->info.dst_endpoint == (*it)->getEndpoint()) { + (*it)->zbIASZoneEnrollResponse(message); + } + } + return ESP_OK; +} + +static esp_err_t zb_window_covering_movement_resp_handler(const esp_zb_zcl_window_covering_movement_message_t *message) { + if (!message) { + log_e("Empty message"); + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + } + + log_v( + "Received message: endpoint(%d), cluster(0x%x), command(0x%x), payload(%d)", message->info.dst_endpoint, message->info.cluster, message->command, + message->payload + ); + + // List through all Zigbee EPs and call the callback function, with the message + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (message->info.dst_endpoint == (*it)->getEndpoint()) { + (*it)->zbWindowCoveringMovementCmd(message); //method zbWindowCoveringMovementCmd must be implemented in specific EP class + } + } + return ESP_OK; +} + +static esp_err_t esp_element_ota_data(uint32_t total_size, const void *payload, uint16_t payload_size, void **outbuf, uint16_t *outlen) { + static uint16_t tagid = 0; + void *data_buf = NULL; + uint16_t data_len; + + if (!s_tagid_received) { + uint32_t length = 0; + if (!payload || payload_size <= OTA_ELEMENT_HEADER_LEN) { + log_e("Invalid element format"); + return ESP_ERR_INVALID_ARG; + } + + const uint8_t *payload_ptr = (const uint8_t *)payload; + tagid = *(const uint16_t *)payload_ptr; + length = *(const uint32_t *)(payload_ptr + sizeof(tagid)); + if ((length + OTA_ELEMENT_HEADER_LEN) != total_size) { + log_e("Invalid element length [%ld/%ld]", length, total_size); + return ESP_ERR_INVALID_ARG; + } + + s_tagid_received = true; + + data_buf = (void *)(payload_ptr + OTA_ELEMENT_HEADER_LEN); + data_len = payload_size - OTA_ELEMENT_HEADER_LEN; + } else { + data_buf = (void *)payload; + data_len = payload_size; + } + + switch (tagid) { + case UPGRADE_IMAGE: + *outbuf = data_buf; + *outlen = data_len; + break; + default: + log_e("Unsupported element tag identifier %d", tagid); + return ESP_ERR_INVALID_ARG; + break; + } + + return ESP_OK; +} + +static esp_err_t zb_ota_upgrade_status_handler(const esp_zb_zcl_ota_upgrade_value_message_t *message) { + static uint32_t total_size = 0; + static uint32_t offset = 0; + [[maybe_unused]] + static int64_t start_time = 0; + esp_err_t ret = ESP_OK; + + if (message->info.status == ESP_ZB_ZCL_STATUS_SUCCESS) { + switch (message->upgrade_status) { + case ESP_ZB_ZCL_OTA_UPGRADE_STATUS_START: + log_i("Zigbee - OTA upgrade start"); + start_time = esp_timer_get_time(); + s_ota_partition = esp_ota_get_next_update_partition(NULL); + assert(s_ota_partition); +#if CONFIG_ZB_DELTA_OTA + ret = esp_delta_ota_begin(s_ota_partition, 0, &s_ota_handle); +#else + ret = esp_ota_begin(s_ota_partition, 0, &s_ota_handle); +#endif + if (ret != ESP_OK) { + log_e("Zigbee - Failed to begin OTA partition, status: %s", esp_err_to_name(ret)); + return ret; + } + break; + case ESP_ZB_ZCL_OTA_UPGRADE_STATUS_RECEIVE: + total_size = message->ota_header.image_size; + offset += message->payload_size; + log_i("Zigbee - OTA Client receives data: progress [%ld/%ld]", offset, total_size); + if (message->payload_size && message->payload) { + uint16_t payload_size = 0; + void *payload = NULL; + ret = esp_element_ota_data(total_size, message->payload, message->payload_size, &payload, &payload_size); + if (ret != ESP_OK) { + log_e("Zigbee - Failed to element OTA data, status: %s", esp_err_to_name(ret)); + return ret; + } +#if CONFIG_ZB_DELTA_OTA + ret = esp_delta_ota_write(s_ota_handle, payload, payload_size); +#else + ret = esp_ota_write(s_ota_handle, (const void *)payload, payload_size); +#endif + if (ret != ESP_OK) { + log_e("Zigbee - Failed to write OTA data to partition, status: %s", esp_err_to_name(ret)); + return ret; + } + } + break; + case ESP_ZB_ZCL_OTA_UPGRADE_STATUS_APPLY: log_i("Zigbee - OTA upgrade apply"); break; + case ESP_ZB_ZCL_OTA_UPGRADE_STATUS_CHECK: + ret = offset == total_size ? ESP_OK : ESP_FAIL; + offset = 0; + total_size = 0; + s_tagid_received = false; + log_i("Zigbee - OTA upgrade check status: %s", esp_err_to_name(ret)); + break; + case ESP_ZB_ZCL_OTA_UPGRADE_STATUS_FINISH: + log_i("Zigbee - OTA Finish"); + log_i( + "Zigbee - OTA Information: version: 0x%lx, manufacturer code: 0x%x, image type: 0x%x, total size: %ld bytes, cost time: %lld ms,", + message->ota_header.file_version, message->ota_header.manufacturer_code, message->ota_header.image_type, message->ota_header.image_size, + (esp_timer_get_time() - start_time) / 1000 + ); +#if CONFIG_ZB_DELTA_OTA + ret = esp_delta_ota_end(s_ota_handle); +#else + ret = esp_ota_end(s_ota_handle); +#endif + if (ret != ESP_OK) { + log_e("Zigbee - Failed to end OTA partition, status: %s", esp_err_to_name(ret)); + return ret; + } + ret = esp_ota_set_boot_partition(s_ota_partition); + if (ret != ESP_OK) { + log_e("Zigbee - Failed to set OTA boot partition, status: %s", esp_err_to_name(ret)); + return ret; + } + log_w("Zigbee - Prepare to restart system"); + esp_restart(); + break; + default: log_i("Zigbee - OTA status: %d", message->upgrade_status); break; + } + } + return ret; +} + +static esp_err_t zb_ota_upgrade_query_image_resp_handler(const esp_zb_zcl_ota_upgrade_query_image_resp_message_t *message) { + if (message->info.status == ESP_ZB_ZCL_STATUS_SUCCESS) { + log_i("Zigbee - Queried OTA image from address: 0x%04hx, endpoint: %d", message->server_addr.u.short_addr, message->server_endpoint); + log_i("Zigbee - Image version: 0x%lx, manufacturer code: 0x%x, image size: %ld", message->file_version, message->manufacturer_code, message->image_size); + if (message->image_size == 0) { + log_i("Zigbee - Rejecting OTA image upgrade, image size is 0"); + return ESP_FAIL; + } + if (message->file_version == 0) { + log_i("Zigbee - Rejecting OTA image upgrade, file version is 0"); + return ESP_FAIL; + } + log_i("Zigbee - Approving OTA image upgrade"); + } else { + log_i("Zigbee - OTA image upgrade response status: 0x%x", message->info.status); + } + return ESP_OK; +} + +static esp_err_t zb_cmd_default_resp_handler(const esp_zb_zcl_cmd_default_resp_message_t *message) { + if (!message) { + log_e("Empty message"); + return ESP_FAIL; + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + return ESP_ERR_INVALID_ARG; + } + log_v( + "Received default response: from address(0x%x), src_endpoint(%d) to dst_endpoint(%d), cluster(0x%x) with status 0x%x", + message->info.src_address.u.short_addr, message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster, message->status_code + ); + return ESP_OK; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp b/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp new file mode 100644 index 00000000000..a95668b7afe --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp @@ -0,0 +1,123 @@ +#include "ZigbeeAnalog.h" +#if CONFIG_ZB_ENABLED + +ZigbeeAnalog::ZigbeeAnalog(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + //Create basic analog sensor clusters without configuration + _cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(_cluster_list, esp_zb_basic_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_identify_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +bool ZigbeeAnalog::addAnalogInput() { + esp_err_t ret = esp_zb_cluster_list_add_analog_input_cluster(_cluster_list, esp_zb_analog_input_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (ret != ESP_OK) { + log_e("Failed to add Analog Input cluster: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + _analog_clusters |= ANALOG_INPUT; + return true; +} + +bool ZigbeeAnalog::addAnalogOutput() { + esp_err_t ret = esp_zb_cluster_list_add_analog_output_cluster(_cluster_list, esp_zb_analog_output_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (ret != ESP_OK) { + log_e("Failed to add Analog Output cluster: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + _analog_clusters |= ANALOG_OUTPUT; + return true; +} + +//set attribute method -> method overridden in child class +void ZigbeeAnalog::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_PRESENT_VALUE_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_SINGLE) { + float analog_output = *(float *)message->attribute.data.value; + analogOutputChanged(analog_output); + } else { + log_w("Received message ignored. Attribute ID: %d not supported for Analog Output", message->attribute.id); + } + } else { + log_w("Received message ignored. Cluster ID: %d not supported for Analog endpoint", message->info.cluster); + } +} + +void ZigbeeAnalog::analogOutputChanged(float analog_output) { + if (_on_analog_output_change) { + _on_analog_output_change(analog_output); + } else { + log_w("No callback function set for analog output change"); + } +} + +bool ZigbeeAnalog::setAnalogInput(float analog) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + if (!(_analog_clusters & ANALOG_INPUT)) { + log_e("Analog Input cluster not added"); + return false; + } + log_d("Setting analog input to %.1f", analog); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_PRESENT_VALUE_ID, &analog, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set analog input: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeAnalog::reportAnalogInput() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_ANALOG_INPUT_PRESENT_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to send Analog Input report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("Analog Input report sent"); + return true; +} + +bool ZigbeeAnalog::setAnalogInputReporting(uint16_t min_interval, uint16_t max_interval, float delta) { + esp_zb_zcl_reporting_info_t reporting_info; + memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t)); + reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; + reporting_info.ep = _endpoint; + reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT; + reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + reporting_info.attr_id = ESP_ZB_ZCL_ATTR_ANALOG_INPUT_PRESENT_VALUE_ID; + reporting_info.u.send_info.min_interval = min_interval; + reporting_info.u.send_info.max_interval = max_interval; + reporting_info.u.send_info.def_min_interval = min_interval; + reporting_info.u.send_info.def_max_interval = max_interval; + reporting_info.u.send_info.delta.s32 = delta; + reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; + reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to set Analog Input reporting: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeAnalog.h b/libraries/Zigbee/src/ep/ZigbeeAnalog.h new file mode 100644 index 00000000000..03fbc678b6e --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeAnalog.h @@ -0,0 +1,57 @@ +/* Class of Zigbee Analog sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +//enum for bits set to check what analog cluster were added +enum zigbee_analog_clusters { + ANALOG_INPUT = 1, + ANALOG_OUTPUT = 2 +}; + +typedef struct zigbee_analog_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_analog_output_cluster_cfg_t analog_output_cfg; + esp_zb_analog_input_cluster_cfg_t analog_input_cfg; +} zigbee_analog_cfg_t; + +class ZigbeeAnalog : public ZigbeeEP { +public: + ZigbeeAnalog(uint8_t endpoint); + ~ZigbeeAnalog() {} + + // Add analog clusters + bool addAnalogInput(); + bool addAnalogOutput(); + + // Use to set a cb function to be called on analog output change + void onAnalogOutputChange(void (*callback)(float analog)) { + _on_analog_output_change = callback; + } + + // Set the analog input value + bool setAnalogInput(float analog); + + // Report Analog Input value + bool reportAnalogInput(); + + // Set reporting for Analog Input + bool setAnalogInputReporting(uint16_t min_interval, uint16_t max_interval, float delta); + +private: + void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; + + void (*_on_analog_output_change)(float); + void analogOutputChanged(float analog_output); + + uint8_t _analog_clusters; +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.cpp new file mode 100644 index 00000000000..2b8271f09a9 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.cpp @@ -0,0 +1,126 @@ +#include "ZigbeeCarbonDioxideSensor.h" +#if CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_carbon_dioxide_sensor_clusters_create(zigbee_carbon_dioxide_sensor_cfg_t *carbon_dioxide_sensor) { + esp_zb_basic_cluster_cfg_t *basic_cfg = carbon_dioxide_sensor ? &(carbon_dioxide_sensor->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = carbon_dioxide_sensor ? &(carbon_dioxide_sensor->identify_cfg) : NULL; + esp_zb_carbon_dioxide_measurement_cluster_cfg_t *carbon_dioxide_meas_cfg = carbon_dioxide_sensor ? &(carbon_dioxide_sensor->carbon_dioxide_meas_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_carbon_dioxide_measurement_cluster( + cluster_list, esp_zb_carbon_dioxide_measurement_cluster_create(carbon_dioxide_meas_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE + ); + return cluster_list; +} + +ZigbeeCarbonDioxideSensor::ZigbeeCarbonDioxideSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + //Create custom pressure sensor configuration + zigbee_carbon_dioxide_sensor_cfg_t carbon_dioxide_sensor_cfg = ZIGBEE_DEFAULT_CARBON_DIOXIDE_SENSOR_CONFIG(); + _cluster_list = zigbee_carbon_dioxide_sensor_clusters_create(&carbon_dioxide_sensor_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +bool ZigbeeCarbonDioxideSensor::setMinMaxValue(float min, float max) { + float zb_min = min / 1000000.0f; + float zb_max = max / 1000000.0f; + esp_zb_attribute_list_t *carbon_dioxide_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(carbon_dioxide_measure_cluster, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MIN_MEASURED_VALUE_ID, (void *)&zb_min); + if (ret != ESP_OK) { + log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(carbon_dioxide_measure_cluster, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MAX_MEASURED_VALUE_ID, (void *)&zb_max); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeCarbonDioxideSensor::setTolerance(float tolerance) { + float zb_tolerance = tolerance / 1000000.0f; + esp_zb_attribute_list_t *carbon_dioxide_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_carbon_dioxide_measurement_cluster_add_attr( + carbon_dioxide_measure_cluster, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance + ); + if (ret != ESP_OK) { + log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeCarbonDioxideSensor::setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta) { + esp_zb_zcl_reporting_info_t reporting_info; + memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t)); + reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; + reporting_info.ep = _endpoint; + reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT; + reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + reporting_info.attr_id = ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MEASURED_VALUE_ID; + reporting_info.u.send_info.min_interval = min_interval; + reporting_info.u.send_info.max_interval = max_interval; + reporting_info.u.send_info.def_min_interval = min_interval; + reporting_info.u.send_info.def_max_interval = max_interval; + reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; + reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + float delta_f = delta / 1000000.0f; + memcpy(&reporting_info.u.send_info.delta.s32, &delta_f, sizeof(float)); + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeCarbonDioxideSensor::setCarbonDioxide(float carbon_dioxide) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + float zb_carbon_dioxide = carbon_dioxide / 1000000.0f; + log_v("Updating carbon dioxide sensor value..."); + /* Update carbon dioxide sensor measured value */ + log_d("Setting carbon dioxide to %0.1f", carbon_dioxide); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MEASURED_VALUE_ID, + &zb_carbon_dioxide, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set carbon dioxide: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeCarbonDioxideSensor::report() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MEASURED_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to send carbon dioxide report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("Carbon dioxide report sent"); + return true; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.h b/libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.h new file mode 100644 index 00000000000..e0a6de48648 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.h @@ -0,0 +1,61 @@ +/* Class of Zigbee Pressure sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// clang-format off +#define ZIGBEE_DEFAULT_CARBON_DIOXIDE_SENSOR_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .carbon_dioxide_meas_cfg = \ + { \ + .measured_value = 0.0, \ + .min_measured_value = 0.0, \ + .max_measured_value = 1.0, \ + }, \ + } +// clang-format on + +typedef struct zigbee_carbon_dioxide_sensor_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_carbon_dioxide_measurement_cluster_cfg_t carbon_dioxide_meas_cfg; +} zigbee_carbon_dioxide_sensor_cfg_t; + +class ZigbeeCarbonDioxideSensor : public ZigbeeEP { +public: + ZigbeeCarbonDioxideSensor(uint8_t endpoint); + ~ZigbeeCarbonDioxideSensor() {} + + // Set the carbon dioxide value in ppm + bool setCarbonDioxide(float carbon_dioxide); + + // Set the min and max value for the carbon dioxide sensor in ppm + bool setMinMaxValue(float min, float max); + + // Set the tolerance value for the carbon dioxide sensor in ppm + bool setTolerance(float tolerance); + + // Set the reporting interval for carbon dioxide measurement in seconds and delta (carbon dioxide change in ppm) + // NOTE: Delta reporting is currently not supported by the carbon dioxide sensor + bool setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta); + + // Report the carbon dioxide value + bool report(); +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp new file mode 100644 index 00000000000..caac73b5c68 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp @@ -0,0 +1,209 @@ +#include "ZigbeeColorDimmableLight.h" +#if CONFIG_ZB_ENABLED + +ZigbeeColorDimmableLight::ZigbeeColorDimmableLight(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID; + + esp_zb_color_dimmable_light_cfg_t light_cfg = ZIGBEE_DEFAULT_COLOR_DIMMABLE_LIGHT_CONFIG(); + _cluster_list = esp_zb_color_dimmable_light_clusters_create(&light_cfg); + + //Add support for hue and saturation + uint8_t hue = 0; + uint8_t saturation = 0; + + esp_zb_attribute_list_t *color_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_color_control_cluster_add_attr(color_cluster, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, &hue); + esp_zb_color_control_cluster_add_attr(color_cluster, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, &saturation); + + _ep_config = { + .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID, .app_device_version = 0 + }; + + //set default values + _current_state = false; + _current_level = 255; + _current_color = {255, 255, 255}; +} + +uint16_t ZigbeeColorDimmableLight::getCurrentColorX() { + return (*(uint16_t *)esp_zb_zcl_get_attribute( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID + ) + ->data_p); +} + +uint16_t ZigbeeColorDimmableLight::getCurrentColorY() { + return (*(uint16_t *)esp_zb_zcl_get_attribute( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID + ) + ->data_p); +} + +uint8_t ZigbeeColorDimmableLight::getCurrentColorHue() { + return (*(uint8_t *)esp_zb_zcl_get_attribute( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID + ) + ->data_p); +} + +uint8_t ZigbeeColorDimmableLight::getCurrentColorSaturation() { + return (*(uint16_t *)esp_zb_zcl_get_attribute( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID + ) + ->data_p); +} + +//set attribute method -> method overridden in child class +void ZigbeeColorDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { + //check the data and call right method + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + if (_current_state != *(bool *)message->attribute.data.value) { + _current_state = *(bool *)message->attribute.data.value; + lightChanged(); + } + return; + } else { + log_w("Received message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); + } + } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + if (_current_level != *(uint8_t *)message->attribute.data.value) { + _current_level = *(uint8_t *)message->attribute.data.value; + lightChanged(); + } + return; + } else { + log_w("Received message ignored. Attribute ID: %d not supported for Level Control", message->attribute.id); + //TODO: implement more attributes -> includes/zcl/esp_zigbee_zcl_level.h + } + } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + uint16_t light_color_x = (*(uint16_t *)message->attribute.data.value); + uint16_t light_color_y = getCurrentColorY(); + //calculate RGB from XY and call setColor() + _current_color = espXYToRgbColor(255, light_color_x, light_color_y); //TODO: Check if level is correct + lightChanged(); + return; + + } else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + uint16_t light_color_x = getCurrentColorX(); + uint16_t light_color_y = (*(uint16_t *)message->attribute.data.value); + //calculate RGB from XY and call setColor() + _current_color = espXYToRgbColor(255, light_color_x, light_color_y); //TODO: Check if level is correct + lightChanged(); + return; + } else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + uint8_t light_color_hue = (*(uint8_t *)message->attribute.data.value); + _current_color = espHsvToRgbColor(light_color_hue, getCurrentColorSaturation(), 255); + lightChanged(); + return; + } else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + uint8_t light_color_saturation = (*(uint8_t *)message->attribute.data.value); + _current_color = espHsvToRgbColor(getCurrentColorHue(), light_color_saturation, 255); + lightChanged(); + return; + } else { + log_w("Received message ignored. Attribute ID: %d not supported for Color Control", message->attribute.id); + } + } else { + log_w("Received message ignored. Cluster ID: %d not supported for Color dimmable Light", message->info.cluster); + } +} + +void ZigbeeColorDimmableLight::lightChanged() { + if (_on_light_change) { + _on_light_change(_current_state, _current_color.r, _current_color.g, _current_color.b, _current_level); + } +} + +bool ZigbeeColorDimmableLight::setLight(bool state, uint8_t level, uint8_t red, uint8_t green, uint8_t blue) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + //Update all attributes + _current_state = state; + _current_level = level; + _current_color = {red, green, blue}; + lightChanged(); + + espXyColor_t xy_color = espRgbColorToXYColor(_current_color); + espHsvColor_t hsv_color = espRgbColorToHsvColor(_current_color); + uint8_t hue = (uint8_t)hsv_color.h; + + log_v("Updating light state: %d, level: %d, color: %d, %d, %d", state, level, red, green, blue); + /* Update light clusters */ + esp_zb_lock_acquire(portMAX_DELAY); + //set on/off state + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, &_current_state, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set light state: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } + //set level + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, &_current_level, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set light level: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } + //set x color + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, &xy_color.x, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set light xy color: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } + //set y color + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID, &xy_color.y, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set light y color: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } + //set hue + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, &hue, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set light hue: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } + //set saturation + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, &hsv_color.s, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set light saturation: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } +unlock_and_return: + esp_zb_lock_release(); + return ret == ESP_ZB_ZCL_STATUS_SUCCESS; +} + +bool ZigbeeColorDimmableLight::setLightState(bool state) { + return setLight(state, _current_level, _current_color.r, _current_color.g, _current_color.b); +} + +bool ZigbeeColorDimmableLight::setLightLevel(uint8_t level) { + return setLight(_current_state, level, _current_color.r, _current_color.g, _current_color.b); +} + +bool ZigbeeColorDimmableLight::setLightColor(uint8_t red, uint8_t green, uint8_t blue) { + return setLight(_current_state, _current_level, red, green, blue); +} + +bool ZigbeeColorDimmableLight::setLightColor(espRgbColor_t rgb_color) { + return setLight(_current_state, _current_level, rgb_color.r, rgb_color.g, rgb_color.b); +} + +bool ZigbeeColorDimmableLight::setLightColor(espHsvColor_t hsv_color) { + espRgbColor_t rgb_color = espHsvColorToRgbColor(hsv_color); + return setLight(_current_state, _current_level, rgb_color.r, rgb_color.g, rgb_color.b); +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h new file mode 100644 index 00000000000..6681f213ad0 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h @@ -0,0 +1,108 @@ +/* Class of Zigbee On/Off Light endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +#define ZIGBEE_DEFAULT_COLOR_DIMMABLE_LIGHT_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .groups_cfg = \ + { \ + .groups_name_support_id = ESP_ZB_ZCL_GROUPS_NAME_SUPPORT_DEFAULT_VALUE, \ + }, \ + .scenes_cfg = \ + { \ + .scenes_count = ESP_ZB_ZCL_SCENES_SCENE_COUNT_DEFAULT_VALUE, \ + .current_scene = ESP_ZB_ZCL_SCENES_CURRENT_SCENE_DEFAULT_VALUE, \ + .current_group = ESP_ZB_ZCL_SCENES_CURRENT_GROUP_DEFAULT_VALUE, \ + .scene_valid = ESP_ZB_ZCL_SCENES_SCENE_VALID_DEFAULT_VALUE, \ + .name_support = ESP_ZB_ZCL_SCENES_NAME_SUPPORT_DEFAULT_VALUE, \ + }, \ + .on_off_cfg = \ + { \ + .on_off = ESP_ZB_ZCL_ON_OFF_ON_OFF_DEFAULT_VALUE, \ + }, \ + .level_cfg = \ + { \ + .current_level = ESP_ZB_ZCL_LEVEL_CONTROL_CURRENT_LEVEL_DEFAULT_VALUE, \ + }, \ + .color_cfg = { \ + .current_x = ESP_ZB_ZCL_COLOR_CONTROL_CURRENT_X_DEF_VALUE, \ + .current_y = ESP_ZB_ZCL_COLOR_CONTROL_CURRENT_Y_DEF_VALUE, \ + .color_mode = ESP_ZB_ZCL_COLOR_CONTROL_COLOR_MODE_DEFAULT_VALUE, \ + .options = ESP_ZB_ZCL_COLOR_CONTROL_OPTIONS_DEFAULT_VALUE, \ + .enhanced_color_mode = ESP_ZB_ZCL_COLOR_CONTROL_ENHANCED_COLOR_MODE_DEFAULT_VALUE, \ + .color_capabilities = 0x0009, \ + }, \ + } + +class ZigbeeColorDimmableLight : public ZigbeeEP { +public: + ZigbeeColorDimmableLight(uint8_t endpoint); + ~ZigbeeColorDimmableLight() {} + + void onLightChange(void (*callback)(bool, uint8_t, uint8_t, uint8_t, uint8_t)) { + _on_light_change = callback; + } + void restoreLight() { + lightChanged(); + } + + bool setLightState(bool state); + bool setLightLevel(uint8_t level); + bool setLightColor(uint8_t red, uint8_t green, uint8_t blue); + bool setLightColor(espRgbColor_t rgb_color); + bool setLightColor(espHsvColor_t hsv_color); + bool setLight(bool state, uint8_t level, uint8_t red, uint8_t green, uint8_t blue); + + bool getLightState() { + return _current_state; + } + uint8_t getLightLevel() { + return _current_level; + } + espRgbColor_t getLightColor() { + return _current_color; + } + uint8_t getLightRed() { + return _current_color.r; + } + uint8_t getLightGreen() { + return _current_color.g; + } + uint8_t getLightBlue() { + return _current_color.b; + } + +private: + void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; + + uint16_t getCurrentColorX(); + uint16_t getCurrentColorY(); + uint8_t getCurrentColorHue(); + uint8_t getCurrentColorSaturation(); + + void lightChanged(); + //callback function to be called on light change (State, R, G, B, Level) + void (*_on_light_change)(bool, uint8_t, uint8_t, uint8_t, uint8_t); + + bool _current_state; + uint8_t _current_level; + espRgbColor_t _current_color; +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp new file mode 100644 index 00000000000..68f287153cb --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp @@ -0,0 +1,484 @@ +#include "ZigbeeColorDimmerSwitch.h" +#if CONFIG_ZB_ENABLED + +// Initialize the static instance pointer +ZigbeeColorDimmerSwitch *ZigbeeColorDimmerSwitch::_instance = nullptr; + +ZigbeeColorDimmerSwitch::ZigbeeColorDimmerSwitch(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID; + _instance = this; // Set the static pointer to this instance + + esp_zb_color_dimmable_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_COLOR_DIMMABLE_SWITCH_CONFIG(); + _cluster_list = esp_zb_color_dimmable_switch_clusters_create(&switch_cfg); + + _ep_config = { + .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID, .app_device_version = 0 + }; +} + +void ZigbeeColorDimmerSwitch::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_i("Bound successfully!"); + if (user_ctx) { + zb_device_params_t *light = (zb_device_params_t *)user_ctx; + log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); + _instance->_bound_devices.push_back(light); + } + _is_bound = true; + } else { + log_e("Binding failed!"); + } +} + +void ZigbeeColorDimmerSwitch::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_d("Found light endpoint"); + esp_zb_zdo_bind_req_param_t bind_req; + zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); + light->endpoint = endpoint; + light->short_addr = addr; + esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); + esp_zb_get_long_address(bind_req.src_address); + bind_req.src_endp = *((uint8_t *)user_ctx); //_endpoint; + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + memcpy(bind_req.dst_address_u.addr_long, light->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req.dst_endp = endpoint; + bind_req.req_dst_addr = esp_zb_get_short_address(); + log_v("Try to bind on/off control of dimmable light"); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, NULL); + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL; + log_v("Try to bind level control of dimmable light"); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, NULL); + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; + log_v("Try to bind color control of dimmable light"); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, (void *)light); + } else { + log_v("No color dimmable light endpoint found"); + } +} + +// find on_off light endpoint +void ZigbeeColorDimmerSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { + uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, + ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL}; + esp_zb_zdo_match_desc_req_param_t color_dimmable_light_req = { + .dst_nwk_addr = cmd_req->dst_nwk_addr, + .addr_of_interest = cmd_req->addr_of_interest, + .profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .num_in_clusters = 3, + .num_out_clusters = 3, + .cluster_list = cluster_list, + }; + esp_zb_zdo_match_cluster(&color_dimmable_light_req, findCb, &_endpoint); +} + +// Methods to control the light +void ZigbeeColorDimmerSwitch::lightToggle() { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_v("Sending 'light toggle' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightToggle(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_v("Sending 'light toggle' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_v("Sending 'light toggle' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + log_v( + "Sending 'light toggle' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], ieee_addr[5], + ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0] + ); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOn() { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_v("Sending 'light on' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOn(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_v("Sending 'light on' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_v("Sending 'light on' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + log_v( + "Sending 'light on' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], ieee_addr[5], + ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0] + ); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOff() { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_v("Sending 'light off' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOff(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_v("Sending 'light off' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_v("Sending 'light off' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + log_v( + "Sending 'light off' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], ieee_addr[5], + ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0] + ); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant) { + if (_is_bound) { + esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.effect_id = effect_id; + cmd_req.effect_variant = effect_variant; + log_v("Sending 'light off with effect' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_off_with_effect_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOnWithSceneRecall() { + if (_is_bound) { + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + log_v("Sending 'light on with scene recall' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off) { + if (_is_bound) { + esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.on_off_control = on_off_control; //TODO: Test how it works, then maybe change API + cmd_req.on_time = time_on; + cmd_req.off_wait_time = time_off; + log_v("Sending 'light on with time off' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_on_with_timed_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level) { + if (_is_bound) { + esp_zb_zcl_move_to_level_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.level = level; + cmd_req.transition_time = 0xffff; + log_v("Sending 'set light level' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_move_to_level_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + cmd_req.level = level; + cmd_req.transition_time = 0xffff; + log_v("Sending 'set light level' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_move_to_level_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.level = level; + cmd_req.transition_time = 0xffff; + log_v("Sending 'set light level' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + esp_zb_zcl_move_to_level_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + cmd_req.level = level; + cmd_req.transition_time = 0xffff; + log_v( + "Sending 'set light level' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], + ieee_addr[5], ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0] + ); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t blue) { + if (_is_bound) { + espXyColor_t xy_color = espRgbToXYColor(red, green, blue); + + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.color_x = xy_color.x; + cmd_req.color_y = xy_color.y; + cmd_req.transition_time = 0; + log_v("Sending 'set light color' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint16_t group_addr) { + if (_is_bound) { + espXyColor_t xy_color = espRgbToXYColor(red, green, blue); + + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + cmd_req.color_x = xy_color.x; + cmd_req.color_y = xy_color.y; + cmd_req.transition_time = 0; + log_v("Sending 'set light color' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + espXyColor_t xy_color = espRgbToXYColor(red, green, blue); + + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.color_x = xy_color.x; + cmd_req.color_y = xy_color.y; + cmd_req.transition_time = 0; + log_v("Sending 'set light color' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + espXyColor_t xy_color = espRgbToXYColor(red, green, blue); + + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + cmd_req.color_x = xy_color.x; + cmd_req.color_y = xy_color.y; + cmd_req.transition_time = 0; + log_v( + "Sending 'set light color' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], + ieee_addr[5], ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0] + ); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h new file mode 100644 index 00000000000..dbe50a20230 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h @@ -0,0 +1,58 @@ +/* Class of Zigbee On/Off Switch endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +class ZigbeeColorDimmerSwitch : public ZigbeeEP { +public: + ZigbeeColorDimmerSwitch(uint8_t endpoint); + ~ZigbeeColorDimmerSwitch() {} + + // methods to control the color dimmable light + void lightToggle(); + void lightToggle(uint16_t group_addr); + void lightToggle(uint8_t endpoint, uint16_t short_addr); + void lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + + void lightOn(); + void lightOn(uint16_t group_addr); + void lightOn(uint8_t endpoint, uint16_t short_addr); + void lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + + void lightOff(); + void lightOff(uint16_t group_addr); + void lightOff(uint8_t endpoint, uint16_t short_addr); + void lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + + void lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant); + void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off); + void lightOnWithSceneRecall(); + + void setLightLevel(uint8_t level); + void setLightLevel(uint8_t level, uint16_t group_addr); + void setLightLevel(uint8_t level, uint8_t endpoint, uint16_t short_addr); + void setLightLevel(uint8_t level, uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + + void setLightColor(uint8_t red, uint8_t green, uint8_t blue); + void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint16_t group_addr); + void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, uint16_t short_addr); + void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + +private: + // save instance of the class in order to use it in static functions + static ZigbeeColorDimmerSwitch *_instance; + + void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); + + void calculateXY(uint8_t red, uint8_t green, uint8_t blue, uint16_t &x, uint16_t &y); +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeContactSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeContactSwitch.cpp new file mode 100644 index 00000000000..ced8e43d6ea --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeContactSwitch.cpp @@ -0,0 +1,111 @@ +#include "ZigbeeContactSwitch.h" +#if CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_contact_switch_clusters_create(zigbee_contact_switch_cfg_t *contact_switch) { + esp_zb_basic_cluster_cfg_t *basic_cfg = contact_switch ? &(contact_switch->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = contact_switch ? &(contact_switch->identify_cfg) : NULL; + esp_zb_ias_zone_cluster_cfg_t *ias_zone_cfg = contact_switch ? &(contact_switch->ias_zone_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_ias_zone_cluster(cluster_list, esp_zb_ias_zone_cluster_create(ias_zone_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + return cluster_list; +} + +ZigbeeContactSwitch::ZigbeeContactSwitch(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_IAS_ZONE_ID; + _zone_status = 0; + _zone_id = 0xff; + _ias_cie_endpoint = 1; + + //Create custom contact switch configuration + zigbee_contact_switch_cfg_t contact_switch_cfg = ZIGBEE_DEFAULT_CONTACT_SWITCH_CONFIG(); + _cluster_list = zigbee_contact_switch_clusters_create(&contact_switch_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_IAS_ZONE_ID, .app_device_version = 0}; +} + +void ZigbeeContactSwitch::setIASClientEndpoint(uint8_t ep_number) { + _ias_cie_endpoint = ep_number; +} + +bool ZigbeeContactSwitch::setClosed() { + log_v("Setting Contact switch to closed"); + uint8_t closed = 0; // ALARM1 = 0, ALARM2 = 0 + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &closed, false + ); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to set contact switch to closed: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + _zone_status = closed; + return report(); +} + +bool ZigbeeContactSwitch::setOpen() { + log_v("Setting Contact switch to open"); + uint8_t open = ESP_ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM1 | ESP_ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM2; // ALARM1 = 1, ALARM2 = 1 + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &open, false + ); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to set contact switch to open: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + _zone_status = open; + return report(); +} + +bool ZigbeeContactSwitch::report() { + /* Send IAS Zone status changed notification command */ + + esp_zb_zcl_ias_zone_status_change_notif_cmd_t status_change_notif_cmd; + status_change_notif_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + status_change_notif_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + status_change_notif_cmd.zcl_basic_cmd.dst_endpoint = _ias_cie_endpoint; //default is 1 + memcpy(status_change_notif_cmd.zcl_basic_cmd.dst_addr_u.addr_long, _ias_cie_addr, sizeof(esp_zb_ieee_addr_t)); + + status_change_notif_cmd.zone_status = _zone_status; + status_change_notif_cmd.extend_status = 0; + status_change_notif_cmd.zone_id = _zone_id; + status_change_notif_cmd.delay = 0; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_ias_zone_status_change_notif_cmd_req(&status_change_notif_cmd); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to send IAS Zone status changed notification: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("IAS Zone status changed notification sent"); + return true; +} + +void ZigbeeContactSwitch::zbIASZoneEnrollResponse(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) { + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE) { + log_v("IAS Zone Enroll Response: zone id(%d), status(%d)", message->zone_id, message->response_code); + if (message->response_code == ESP_ZB_ZCL_IAS_ZONE_ENROLL_RESPONSE_CODE_SUCCESS) { + log_v("IAS Zone Enroll Response: success"); + esp_zb_lock_acquire(portMAX_DELAY); + memcpy( + _ias_cie_addr, + (*(esp_zb_ieee_addr_t *) + esp_zb_zcl_get_attribute(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID) + ->data_p), + sizeof(esp_zb_ieee_addr_t) + ); + esp_zb_lock_release(); + _zone_id = message->zone_id; + } + + } else { + log_w("Received message ignored. Cluster ID: %d not supported for On/Off Light", message->info.cluster); + } +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeContactSwitch.h b/libraries/Zigbee/src/ep/ZigbeeContactSwitch.h new file mode 100644 index 00000000000..b33effd8dfc --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeContactSwitch.h @@ -0,0 +1,67 @@ +/* Class of Zigbee contact switch (IAS Zone) endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// clang-format off +#define ZIGBEE_DEFAULT_CONTACT_SWITCH_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .ias_zone_cfg = \ + { \ + .zone_state = ESP_ZB_ZCL_IAS_ZONE_ZONESTATE_NOT_ENROLLED, \ + .zone_type = ESP_ZB_ZCL_IAS_ZONE_ZONETYPE_CONTACT_SWITCH, \ + .zone_status = 0, \ + .ias_cie_addr = ESP_ZB_ZCL_ZONE_IAS_CIE_ADDR_DEFAULT, \ + .zone_id = 0xff, \ + .zone_ctx = {0, 0, 0, 0}, \ + }, \ + } +// clang-format on + +typedef struct zigbee_contact_switch_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_ias_zone_cluster_cfg_t ias_zone_cfg; +} zigbee_contact_switch_cfg_t; + +class ZigbeeContactSwitch : public ZigbeeEP { +public: + ZigbeeContactSwitch(uint8_t endpoint); + ~ZigbeeContactSwitch() {} + + // Set the IAS Client endpoint number (default is 1) + void setIASClientEndpoint(uint8_t ep_number); + + // Set the contact switch value to closed + bool setClosed(); + + // Set the contact switch value to open + bool setOpen(); + + // Report the contact switch value, done automatically after setting the position + bool report(); + +private: + void zbIASZoneEnrollResponse(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) override; + uint8_t _zone_status; + uint8_t _zone_id; + esp_zb_ieee_addr_t _ias_cie_addr; + uint8_t _ias_cie_endpoint; +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeDimmableLight.cpp b/libraries/Zigbee/src/ep/ZigbeeDimmableLight.cpp new file mode 100644 index 00000000000..05a7e5ad6c1 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeDimmableLight.cpp @@ -0,0 +1,113 @@ +#include "ZigbeeDimmableLight.h" +#if CONFIG_ZB_ENABLED + +#include "esp_zigbee_cluster.h" + +ZigbeeDimmableLight::ZigbeeDimmableLight(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_DIMMABLE_LIGHT_DEVICE_ID; + + zigbee_dimmable_light_cfg_t light_cfg = ZIGBEE_DEFAULT_DIMMABLE_LIGHT_CONFIG(); + _cluster_list = zigbee_dimmable_light_clusters_create(&light_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_DIMMABLE_LIGHT_DEVICE_ID, .app_device_version = 0}; + + // set default values + _current_state = false; + _current_level = 255; +} + +// set attribute method -> method overridden in child class +void ZigbeeDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { + // check the data and call right method + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + if (_current_state != *(bool *)message->attribute.data.value) { + _current_state = *(bool *)message->attribute.data.value; + lightChanged(); + } + return; + } else { + log_w("Received message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); + } + } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + if (_current_level != *(uint8_t *)message->attribute.data.value) { + _current_level = *(uint8_t *)message->attribute.data.value; + lightChanged(); + } + return; + } else { + log_w("Received message ignored. Attribute ID: %d not supported for Level Control", message->attribute.id); + // TODO: implement more attributes -> includes/zcl/esp_zigbee_zcl_level.h + } + } else { + log_w("Received message ignored. Cluster ID: %d not supported for dimmable Light", message->info.cluster); + } +} + +void ZigbeeDimmableLight::lightChanged() { + if (_on_light_change) { + _on_light_change(_current_state, _current_level); + } +} + +bool ZigbeeDimmableLight::setLight(bool state, uint8_t level) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + // Update all attributes + _current_state = state; + _current_level = level; + lightChanged(); + + log_v("Updating on/off light state to %d", state); + /* Update light clusters */ + esp_zb_lock_acquire(portMAX_DELAY); + // set on/off state + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, &_current_state, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set light state: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } + // set level + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, &_current_level, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set light level: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } +unlock_and_return: + esp_zb_lock_release(); + return ret == ESP_ZB_ZCL_STATUS_SUCCESS; +} + +bool ZigbeeDimmableLight::setLightState(bool state) { + return setLight(state, _current_level); +} + +bool ZigbeeDimmableLight::setLightLevel(uint8_t level) { + return setLight(_current_state, level); +} + +esp_zb_cluster_list_t *ZigbeeDimmableLight::zigbee_dimmable_light_clusters_create(zigbee_dimmable_light_cfg_t *light_cfg) { + esp_zb_attribute_list_t *esp_zb_basic_cluster = esp_zb_basic_cluster_create(&light_cfg->basic_cfg); + esp_zb_attribute_list_t *esp_zb_identify_cluster = esp_zb_identify_cluster_create(&light_cfg->identify_cfg); + esp_zb_attribute_list_t *esp_zb_groups_cluster = esp_zb_groups_cluster_create(&light_cfg->groups_cfg); + esp_zb_attribute_list_t *esp_zb_scenes_cluster = esp_zb_scenes_cluster_create(&light_cfg->scenes_cfg); + esp_zb_attribute_list_t *esp_zb_on_off_cluster = esp_zb_on_off_cluster_create(&light_cfg->on_off_cfg); + esp_zb_attribute_list_t *esp_zb_level_cluster = esp_zb_level_cluster_create(&light_cfg->level_cfg); + + // ------------------------------ Create cluster list ------------------------------ + esp_zb_cluster_list_t *esp_zb_cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(esp_zb_cluster_list, esp_zb_basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(esp_zb_cluster_list, esp_zb_identify_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_groups_cluster(esp_zb_cluster_list, esp_zb_groups_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_scenes_cluster(esp_zb_cluster_list, esp_zb_scenes_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_on_off_cluster(esp_zb_cluster_list, esp_zb_on_off_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_level_cluster(esp_zb_cluster_list, esp_zb_level_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + return esp_zb_cluster_list; +} + +#endif // SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeDimmableLight.h b/libraries/Zigbee/src/ep/ZigbeeDimmableLight.h new file mode 100644 index 00000000000..747fdbafaef --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeDimmableLight.h @@ -0,0 +1,112 @@ +/* Class of Zigbee On/Off Light endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +/** + * @brief Zigbee HA standard dimmable light device clusters. + * Added here as not supported by ESP Zigbee library. + * + * + */ +typedef struct zigbee_dimmable_light_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; /*!< Basic cluster configuration, @ref esp_zb_basic_cluster_cfg_s */ + esp_zb_identify_cluster_cfg_t identify_cfg; /*!< Identify cluster configuration, @ref esp_zb_identify_cluster_cfg_s */ + esp_zb_groups_cluster_cfg_t groups_cfg; /*!< Groups cluster configuration, @ref esp_zb_groups_cluster_cfg_s */ + esp_zb_scenes_cluster_cfg_t scenes_cfg; /*!< Scenes cluster configuration, @ref esp_zb_scenes_cluster_cfg_s */ + esp_zb_on_off_cluster_cfg_t on_off_cfg; /*!< On off cluster configuration, @ref esp_zb_on_off_cluster_cfg_s */ + esp_zb_level_cluster_cfg_t level_cfg; /*!< Level cluster configuration, @ref esp_zb_level_cluster_cfg_s */ +} zigbee_dimmable_light_cfg_t; + +/** + * @brief Zigbee HA standard dimmable light device default config value. + * Added here as not supported by ESP Zigbee library. + * + */ +// clang-format off +#define ZIGBEE_DEFAULT_DIMMABLE_LIGHT_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .groups_cfg = \ + { \ + .groups_name_support_id = ESP_ZB_ZCL_GROUPS_NAME_SUPPORT_DEFAULT_VALUE, \ + }, \ + .scenes_cfg = \ + { \ + .scenes_count = ESP_ZB_ZCL_SCENES_SCENE_COUNT_DEFAULT_VALUE, \ + .current_scene = ESP_ZB_ZCL_SCENES_CURRENT_SCENE_DEFAULT_VALUE, \ + .current_group = ESP_ZB_ZCL_SCENES_CURRENT_GROUP_DEFAULT_VALUE, \ + .scene_valid = ESP_ZB_ZCL_SCENES_SCENE_VALID_DEFAULT_VALUE, \ + .name_support = ESP_ZB_ZCL_SCENES_NAME_SUPPORT_DEFAULT_VALUE, \ + }, \ + .on_off_cfg = \ + { \ + .on_off = ESP_ZB_ZCL_ON_OFF_ON_OFF_DEFAULT_VALUE, \ + }, \ + .level_cfg = \ + { \ + .current_level = ESP_ZB_ZCL_LEVEL_CONTROL_CURRENT_LEVEL_DEFAULT_VALUE, \ + }, \ + } +// clang-format on + +class ZigbeeDimmableLight : public ZigbeeEP { +public: + ZigbeeDimmableLight(uint8_t endpoint); + ~ZigbeeDimmableLight() {} + + void onLightChange(void (*callback)(bool, uint8_t)) { + _on_light_change = callback; + } + void restoreLight() { + lightChanged(); + } + + bool setLightState(bool state); + bool setLightLevel(uint8_t level); + bool setLight(bool state, uint8_t level); + + bool getLightState() { + return _current_state; + } + uint8_t getLightLevel() { + return _current_level; + } + +private: + void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; + void lightChanged(); + // callback function to be called on light change (State, Level) + void (*_on_light_change)(bool, uint8_t); + + /** + * @brief Create a standard HA dimmable light cluster list. + * Added here as not supported by ESP Zigbee library. + * + * @note This contains basic, identify, groups, scenes, on-off, level, as server side. + * @param[in] light_cfg Configuration parameters for this cluster lists defined by @ref zigbee_dimmable_light_cfg_t + * + * @return Pointer to cluster list @ref esp_zb_cluster_list_s + * + */ + esp_zb_cluster_list_t *zigbee_dimmable_light_clusters_create(zigbee_dimmable_light_cfg_t *light_cfg); + + bool _current_state; + uint8_t _current_level; +}; + +#endif // SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeDoorWindowHandle.cpp b/libraries/Zigbee/src/ep/ZigbeeDoorWindowHandle.cpp new file mode 100644 index 00000000000..c5b62ee2b75 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeDoorWindowHandle.cpp @@ -0,0 +1,127 @@ +#include "ZigbeeDoorWindowHandle.h" +#if CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_door_window_handle_clusters_create(zigbee_door_window_handle_cfg_t *door_window_handle) { + esp_zb_basic_cluster_cfg_t *basic_cfg = door_window_handle ? &(door_window_handle->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = door_window_handle ? &(door_window_handle->identify_cfg) : NULL; + esp_zb_ias_zone_cluster_cfg_t *ias_zone_cfg = door_window_handle ? &(door_window_handle->ias_zone_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_ias_zone_cluster(cluster_list, esp_zb_ias_zone_cluster_create(ias_zone_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + return cluster_list; +} + +ZigbeeDoorWindowHandle::ZigbeeDoorWindowHandle(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_IAS_ZONE_ID; + _zone_status = 0; + _zone_id = 0xff; + _ias_cie_endpoint = 1; + + //Create custom door window handle configuration + zigbee_door_window_handle_cfg_t door_window_handle_cfg = ZIGBEE_DEFAULT_DOOR_WINDOW_HANDLE_CONFIG(); + _cluster_list = zigbee_door_window_handle_clusters_create(&door_window_handle_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_IAS_ZONE_ID, .app_device_version = 0}; +} + +void ZigbeeDoorWindowHandle::setIASClientEndpoint(uint8_t ep_number) { + _ias_cie_endpoint = ep_number; +} + +bool ZigbeeDoorWindowHandle::setClosed() { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + log_v("Setting Door/Window handle to closed"); + uint8_t closed = 0; // ALARM1 = 0, ALARM2 = 0 + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &closed, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set door/window handle to closed: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + _zone_status = closed; + return report(); +} + +bool ZigbeeDoorWindowHandle::setOpen() { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + log_v("Setting Door/Window handle to open"); + uint8_t open = ESP_ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM1 | ESP_ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM2; // ALARM1 = 1, ALARM2 = 1 + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &open, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set door/window handle to open: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + _zone_status = open; + return report(); +} + +bool ZigbeeDoorWindowHandle::setTilted() { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + log_v("Setting Door/Window handle to tilted"); + uint8_t tilted = ESP_ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM1; // ALARM1 = 1, ALARM2 = 0 + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &tilted, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set door/window handle to tilted: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + _zone_status = tilted; + return report(); +} + +bool ZigbeeDoorWindowHandle::report() { + /* Send IAS Zone status changed notification command */ + + esp_zb_zcl_ias_zone_status_change_notif_cmd_t status_change_notif_cmd; + status_change_notif_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + status_change_notif_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + status_change_notif_cmd.zcl_basic_cmd.dst_endpoint = _ias_cie_endpoint; //default is 1 + memcpy(status_change_notif_cmd.zcl_basic_cmd.dst_addr_u.addr_long, _ias_cie_addr, sizeof(esp_zb_ieee_addr_t)); + + status_change_notif_cmd.zone_status = _zone_status; + status_change_notif_cmd.extend_status = 0; + status_change_notif_cmd.zone_id = _zone_id; + status_change_notif_cmd.delay = 0; + + //NOTE: Check result of esp_zb_zcl_ias_zone_status_change_notif_cmd_req() and return true if success, false if failure + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_ias_zone_status_change_notif_cmd_req(&status_change_notif_cmd); + esp_zb_lock_release(); + log_v("IAS Zone status changed notification sent"); + return true; +} + +void ZigbeeDoorWindowHandle::zbIASZoneEnrollResponse(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) { + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE) { + log_v("IAS Zone Enroll Response: zone id(%d), status(%d)", message->zone_id, message->response_code); + if (message->response_code == ESP_ZB_ZCL_IAS_ZONE_ENROLL_RESPONSE_CODE_SUCCESS) { + log_v("IAS Zone Enroll Response: success"); + esp_zb_lock_acquire(portMAX_DELAY); + memcpy( + _ias_cie_addr, + (*(esp_zb_ieee_addr_t *) + esp_zb_zcl_get_attribute(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID) + ->data_p), + sizeof(esp_zb_ieee_addr_t) + ); + esp_zb_lock_release(); + _zone_id = message->zone_id; + } + + } else { + log_w("Received message ignored. Cluster ID: %d not supported for On/Off Light", message->info.cluster); + } +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeDoorWindowHandle.h b/libraries/Zigbee/src/ep/ZigbeeDoorWindowHandle.h new file mode 100644 index 00000000000..efffd34b12f --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeDoorWindowHandle.h @@ -0,0 +1,71 @@ +/* Class of Zigbee door window handle (IAS Zone) endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +#define ESP_ZB_ZCL_IAS_ZONE_ZONETYPE_DOOR_WINDOW_HANDLE 0x0016 +// clang-format off +#define ZIGBEE_DEFAULT_DOOR_WINDOW_HANDLE_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .ias_zone_cfg = \ + { \ + .zone_state = ESP_ZB_ZCL_IAS_ZONE_ZONESTATE_NOT_ENROLLED, \ + .zone_type = ESP_ZB_ZCL_IAS_ZONE_ZONETYPE_DOOR_WINDOW_HANDLE, \ + .zone_status = 0, \ + .ias_cie_addr = ESP_ZB_ZCL_ZONE_IAS_CIE_ADDR_DEFAULT, \ + .zone_id = 0xff, \ + .zone_ctx = {0, 0, 0, 0}, \ + }, \ + } +// clang-format on + +typedef struct zigbee_door_window_handle_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_ias_zone_cluster_cfg_t ias_zone_cfg; +} zigbee_door_window_handle_cfg_t; + +class ZigbeeDoorWindowHandle : public ZigbeeEP { +public: + ZigbeeDoorWindowHandle(uint8_t endpoint); + ~ZigbeeDoorWindowHandle() {} + + // Set the IAS Client endpoint number (default is 1) + void setIASClientEndpoint(uint8_t ep_number); + + // Set the door/window handle value to closed + bool setClosed(); + + // Set the door/window handle value to open + bool setOpen(); + + // Set the door/window handle value to tilted + bool setTilted(); + + // Report the door/window handle value, done automatically after setting the position + bool report(); + +private: + void zbIASZoneEnrollResponse(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) override; + uint8_t _zone_status; + uint8_t _zone_id; + esp_zb_ieee_addr_t _ias_cie_addr; + uint8_t _ias_cie_endpoint; +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeFlowSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeFlowSensor.cpp new file mode 100644 index 00000000000..8a60af5a8e1 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeFlowSensor.cpp @@ -0,0 +1,124 @@ +#include "ZigbeeFlowSensor.h" +#if CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_flow_sensor_clusters_create(zigbee_flow_sensor_cfg_t *flow_sensor) { + esp_zb_basic_cluster_cfg_t *basic_cfg = flow_sensor ? &(flow_sensor->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = flow_sensor ? &(flow_sensor->identify_cfg) : NULL; + esp_zb_flow_meas_cluster_cfg_t *flow_meas_cfg = flow_sensor ? &(flow_sensor->flow_meas_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_flow_meas_cluster(cluster_list, esp_zb_flow_meas_cluster_create(flow_meas_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + return cluster_list; +} + +ZigbeeFlowSensor::ZigbeeFlowSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + //Create custom pressure sensor configuration + zigbee_flow_sensor_cfg_t flow_sensor_cfg = ZIGBEE_DEFAULT_FLOW_SENSOR_CONFIG(); + _cluster_list = zigbee_flow_sensor_clusters_create(&flow_sensor_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +bool ZigbeeFlowSensor::setMinMaxValue(float min, float max) { + uint16_t zb_min = (uint16_t)(min * 10); + uint16_t zb_max = (uint16_t)(max * 10); + esp_zb_attribute_list_t *flow_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(flow_measure_cluster, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_MIN_VALUE_ID, (void *)&zb_min); + if (ret != ESP_OK) { + log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(flow_measure_cluster, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_MAX_VALUE_ID, (void *)&zb_max); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeFlowSensor::setTolerance(float tolerance) { + uint16_t zb_tolerance = (uint16_t)(tolerance * 10); + esp_zb_attribute_list_t *flow_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_flow_meas_cluster_add_attr(flow_measure_cluster, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance); + if (ret != ESP_OK) { + log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeFlowSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) { + esp_zb_zcl_reporting_info_t reporting_info; + memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t)); + reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; + reporting_info.ep = _endpoint; + reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT; + reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + reporting_info.attr_id = ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_VALUE_ID; + reporting_info.u.send_info.min_interval = min_interval; + reporting_info.u.send_info.max_interval = max_interval; + reporting_info.u.send_info.def_min_interval = min_interval; + reporting_info.u.send_info.def_max_interval = max_interval; + reporting_info.u.send_info.delta.u16 = (uint16_t)(delta * 10); // Convert delta to ZCL uint16_t + reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; + reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); + + if (ret != ESP_OK) { + log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeFlowSensor::setFlow(float flow) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + uint16_t zb_flow = (uint16_t)(flow * 10); + log_v("Updating flow sensor value..."); + /* Update temperature sensor measured value */ + log_d("Setting flow to %d", zb_flow); + + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_VALUE_ID, &zb_flow, false + ); + esp_zb_lock_release(); + + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set flow value: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeFlowSensor::report() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + + if (ret != ESP_OK) { + log_e("Failed to send flow report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("Flow report sent"); + return true; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeFlowSensor.h b/libraries/Zigbee/src/ep/ZigbeeFlowSensor.h new file mode 100644 index 00000000000..fa16b4a5636 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeFlowSensor.h @@ -0,0 +1,60 @@ +/* Class of Zigbee Flow sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// clang-format off +#define ZIGBEE_DEFAULT_FLOW_SENSOR_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .flow_meas_cfg = \ + { \ + .measured_value = 0, \ + .min_value = 0, \ + .max_value = 0x7FFF, \ + }, \ + } +// clang-format on + +typedef struct zigbee_flow_sensor_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_flow_meas_cluster_cfg_t flow_meas_cfg; +} zigbee_flow_sensor_cfg_t; + +class ZigbeeFlowSensor : public ZigbeeEP { +public: + ZigbeeFlowSensor(uint8_t endpoint); + ~ZigbeeFlowSensor() {} + + // Set the flow value in 0,1 m3/h + bool setFlow(float value); + + // Set the min and max value for the flow sensor in 0,1 m3/h + bool setMinMaxValue(float min, float max); + + // Set the tolerance value for the flow sensor in 0,01 m3/h + bool setTolerance(float tolerance); + + // Set the reporting interval for flow measurement in seconds and delta (temp change in 0,1 m3/h) + bool setReporting(uint16_t min_interval, uint16_t max_interval, float delta); + + // Report the flow value + bool report(); +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeGateway.cpp b/libraries/Zigbee/src/ep/ZigbeeGateway.cpp new file mode 100644 index 00000000000..b0be81395ca --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeGateway.cpp @@ -0,0 +1,15 @@ +#include "ZigbeeGateway.h" +#if CONFIG_ZB_ENABLED + +ZigbeeGateway::ZigbeeGateway(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_HOME_GATEWAY_DEVICE_ID; + + _cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(_cluster_list, esp_zb_basic_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_identify_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_HOME_GATEWAY_DEVICE_ID, .app_device_version = 0}; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeGateway.h b/libraries/Zigbee/src/ep/ZigbeeGateway.h new file mode 100644 index 00000000000..3925630c0b8 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeGateway.h @@ -0,0 +1,18 @@ +/* Class of Zigbee Gateway endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +class ZigbeeGateway : public ZigbeeEP { +public: + ZigbeeGateway(uint8_t endpoint); + ~ZigbeeGateway() {} +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeIlluminanceSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeIlluminanceSensor.cpp new file mode 100644 index 00000000000..f1661c3a026 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeIlluminanceSensor.cpp @@ -0,0 +1,106 @@ +#include "ZigbeeIlluminanceSensor.h" +#if CONFIG_ZB_ENABLED + +ZigbeeIlluminanceSensor::ZigbeeIlluminanceSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_LIGHT_SENSOR_DEVICE_ID; + + esp_zb_light_sensor_cfg_t light_sensor_cfg = ZIGBEE_DEFAULT_ILLUMINANCE_SENSOR_CONFIG(); + _cluster_list = esp_zb_light_sensor_clusters_create(&light_sensor_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_LIGHT_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +bool ZigbeeIlluminanceSensor::setMinMaxValue(uint16_t min, uint16_t max) { + esp_zb_attribute_list_t *light_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(light_measure_cluster, ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_ID, (void *)&min); + if (ret != ESP_OK) { + log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(light_measure_cluster, ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_ID, (void *)&max); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeIlluminanceSensor::setTolerance(uint16_t tolerance) { + esp_zb_attribute_list_t *light_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_illuminance_meas_cluster_add_attr(light_measure_cluster, ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_TOLERANCE_ID, (void *)&tolerance); + if (ret != ESP_OK) { + log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeIlluminanceSensor::setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta) { + esp_zb_zcl_reporting_info_t reporting_info; + memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t)); + reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; + reporting_info.ep = _endpoint; + reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT; + reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + reporting_info.attr_id = ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID; + reporting_info.u.send_info.min_interval = min_interval; + reporting_info.u.send_info.max_interval = max_interval; + reporting_info.u.send_info.def_min_interval = min_interval; + reporting_info.u.send_info.def_max_interval = max_interval; + reporting_info.u.send_info.delta.u16 = delta; + reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; + reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); + + if (ret != ESP_OK) { + log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeIlluminanceSensor::setIlluminance(uint16_t illuminanceValue) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + log_v("Updating Illuminance..."); + /* Update illuminance sensor measured illuminance */ + log_d("Setting Illuminance to %d", illuminanceValue); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID, + &illuminanceValue, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set illuminance: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeIlluminanceSensor::report() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to send illuminance report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("Illuminance report sent"); + return true; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeIlluminanceSensor.h b/libraries/Zigbee/src/ep/ZigbeeIlluminanceSensor.h new file mode 100644 index 00000000000..133dfc315db --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeIlluminanceSensor.h @@ -0,0 +1,51 @@ +/* Class of Zigbee Illuminance sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +#define ZIGBEE_DEFAULT_ILLUMINANCE_SENSOR_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .illuminance_cfg = { \ + .measured_value = ESP_ZB_ZCL_ILLUMINANCE_MEASUREMENT_LIGHT_SENSOR_TYPE_DEFAULT_VALUE, \ + .min_value = ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_MIN_VALUE, \ + .max_value = ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_MAX_VALUE, \ + }, \ + } + +class ZigbeeIlluminanceSensor : public ZigbeeEP { +public: + ZigbeeIlluminanceSensor(uint8_t endpoint); + ~ZigbeeIlluminanceSensor() {} + + // Set the illuminance value + bool setIlluminance(uint16_t value); + + // Set the min and max value for the illuminance sensor + bool setMinMaxValue(uint16_t min, uint16_t max); + + // Set the tolerance value for the illuminance sensor + bool setTolerance(uint16_t tolerance); + + // Set the reporting interval for illuminance measurement in seconds and delta + bool setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta); + + // Report the illuminance value + bool report(); +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeLight.cpp b/libraries/Zigbee/src/ep/ZigbeeLight.cpp new file mode 100644 index 00000000000..edfac04fcdf --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeLight.cpp @@ -0,0 +1,56 @@ +#include "ZigbeeLight.h" +#if CONFIG_ZB_ENABLED + +ZigbeeLight::ZigbeeLight(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; + + esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); + _cluster_list = esp_zb_on_off_light_clusters_create(&light_cfg); // use esp_zb_zcl_cluster_list_create() instead of esp_zb_on_off_light_clusters_create() + _ep_config = {.endpoint = endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID, .app_device_version = 0}; + log_v("Light endpoint created %d", _endpoint); +} + +//set attribute method -> method overridden in child class +void ZigbeeLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { + //check the data and call right method + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + _current_state = *(bool *)message->attribute.data.value; + lightChanged(); + } else { + log_w("Received message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); + } + } else { + log_w("Received message ignored. Cluster ID: %d not supported for On/Off Light", message->info.cluster); + } +} + +void ZigbeeLight::lightChanged() { + if (_on_light_change) { + _on_light_change(_current_state); + } else { + log_w("No callback function set for light change"); + } +} + +bool ZigbeeLight::setLight(bool state) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + _current_state = state; + lightChanged(); + + log_v("Updating on/off light state to %d", state); + /* Update on/off light state */ + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, &_current_state, false + ); + esp_zb_lock_release(); + + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set light state: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeLight.h b/libraries/Zigbee/src/ep/ZigbeeLight.h new file mode 100644 index 00000000000..773fbb14ec5 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeLight.h @@ -0,0 +1,41 @@ +/* Class of Zigbee On/Off Light endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +class ZigbeeLight : public ZigbeeEP { +public: + ZigbeeLight(uint8_t endpoint); + ~ZigbeeLight() {} + + // Use to set a cb function to be called on light change + void onLightChange(void (*callback)(bool)) { + _on_light_change = callback; + } + // Use to restore light state + void restoreLight() { + lightChanged(); + } + // Use to control light state + bool setLight(bool state); + // Use to get light state + bool getLightState() { + return _current_state; + } + +private: + void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; + //callback function to be called on light change + void (*_on_light_change)(bool); + void lightChanged(); + + bool _current_state; +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeOccupancySensor.cpp b/libraries/Zigbee/src/ep/ZigbeeOccupancySensor.cpp new file mode 100644 index 00000000000..b8f88fed4a4 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeOccupancySensor.cpp @@ -0,0 +1,80 @@ +#include "ZigbeeOccupancySensor.h" +#if CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_occupancy_sensor_clusters_create(zigbee_occupancy_sensor_cfg_t *occupancy_sensor) { + esp_zb_basic_cluster_cfg_t *basic_cfg = occupancy_sensor ? &(occupancy_sensor->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = occupancy_sensor ? &(occupancy_sensor->identify_cfg) : NULL; + esp_zb_occupancy_sensing_cluster_cfg_t *occupancy_meas_cfg = occupancy_sensor ? &(occupancy_sensor->occupancy_meas_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_occupancy_sensing_cluster(cluster_list, esp_zb_occupancy_sensing_cluster_create(occupancy_meas_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + return cluster_list; +} + +ZigbeeOccupancySensor::ZigbeeOccupancySensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + //Create custom occupancy sensor configuration + zigbee_occupancy_sensor_cfg_t occupancy_sensor_cfg = ZIGBEE_DEFAULT_OCCUPANCY_SENSOR_CONFIG(); + _cluster_list = zigbee_occupancy_sensor_clusters_create(&occupancy_sensor_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +bool ZigbeeOccupancySensor::setSensorType(uint8_t sensor_type) { + uint8_t sensor_type_bitmap = 1 << sensor_type; + esp_zb_attribute_list_t *occupancy_sens_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_ID, (void *)&sensor_type); + if (ret != ESP_OK) { + log_e("Failed to set sensor type: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_BITMAP_ID, (void *)&sensor_type_bitmap); + if (ret != ESP_OK) { + log_e("Failed to set sensor type bitmap: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeOccupancySensor::setOccupancy(bool occupied) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + log_v("Updating occupancy sensor value..."); + /* Update occupancy sensor value */ + log_d("Setting occupancy to %d", occupied); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_ID, &occupied, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set occupancy: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeOccupancySensor::report() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to send occupancy report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("Occupancy report sent"); + return true; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeOccupancySensor.h b/libraries/Zigbee/src/ep/ZigbeeOccupancySensor.h new file mode 100644 index 00000000000..7408e10a76b --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeOccupancySensor.h @@ -0,0 +1,54 @@ +/* Class of Zigbee Pressure sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// clang-format off +#define ZIGBEE_DEFAULT_OCCUPANCY_SENSOR_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .occupancy_meas_cfg = \ + { \ + .occupancy = ESP_ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_UNOCCUPIED, \ + .sensor_type = ESP_ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_PIR, \ + .sensor_type_bitmap = (1 << ESP_ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_PIR), \ + }, \ + } +// clang-format on + +typedef struct zigbee_occupancy_sensor_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_occupancy_sensing_cluster_cfg_t occupancy_meas_cfg; +} zigbee_occupancy_sensor_cfg_t; + +class ZigbeeOccupancySensor : public ZigbeeEP { +public: + ZigbeeOccupancySensor(uint8_t endpoint); + ~ZigbeeOccupancySensor() {} + + // Set the occupancy value. True for occupied, false for unoccupied + bool setOccupancy(bool occupied); + + // Set the sensor type, see esp_zb_zcl_occupancy_sensing_occupancy_sensor_type_t + bool setSensorType(uint8_t sensor_type); + + // Report the occupancy value + bool report(); +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeePM25Sensor.cpp b/libraries/Zigbee/src/ep/ZigbeePM25Sensor.cpp new file mode 100644 index 00000000000..d25d15e5de3 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeePM25Sensor.cpp @@ -0,0 +1,118 @@ +#include "ZigbeePM25Sensor.h" +#if CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_pm2_5_sensor_clusters_create(zigbee_pm2_5_sensor_cfg_t *pm2_5_sensor) { + esp_zb_basic_cluster_cfg_t *basic_cfg = pm2_5_sensor ? &(pm2_5_sensor->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = pm2_5_sensor ? &(pm2_5_sensor->identify_cfg) : NULL; + esp_zb_pm2_5_measurement_cluster_cfg_t *pm2_5_meas_cfg = pm2_5_sensor ? &(pm2_5_sensor->pm2_5_meas_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_pm2_5_measurement_cluster(cluster_list, esp_zb_pm2_5_measurement_cluster_create(pm2_5_meas_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + return cluster_list; +} + +ZigbeePM25Sensor::ZigbeePM25Sensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + //Create custom PM2.5 sensor configuration + zigbee_pm2_5_sensor_cfg_t pm2_5_sensor_cfg = ZIGBEE_DEFAULT_PM2_5_SENSOR_CONFIG(); + _cluster_list = zigbee_pm2_5_sensor_clusters_create(&pm2_5_sensor_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +bool ZigbeePM25Sensor::setMinMaxValue(float min, float max) { + esp_zb_attribute_list_t *pm2_5_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_PM2_5_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(pm2_5_measure_cluster, ESP_ZB_ZCL_ATTR_PM2_5_MEASUREMENT_MIN_MEASURED_VALUE_ID, (void *)&min); + if (ret != ESP_OK) { + log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(pm2_5_measure_cluster, ESP_ZB_ZCL_ATTR_PM2_5_MEASUREMENT_MAX_MEASURED_VALUE_ID, (void *)&max); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeePM25Sensor::setTolerance(float tolerance) { + esp_zb_attribute_list_t *pm2_5_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_PM2_5_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_pm2_5_measurement_cluster_add_attr(pm2_5_measure_cluster, ESP_ZB_ZCL_ATTR_PM2_5_MEASUREMENT_TOLERANCE_ID, (void *)&tolerance); + if (ret != ESP_OK) { + log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeePM25Sensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) { + esp_zb_zcl_reporting_info_t reporting_info; + memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t)); + reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; + reporting_info.ep = _endpoint; + reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_PM2_5_MEASUREMENT; + reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + reporting_info.attr_id = ESP_ZB_ZCL_ATTR_PM2_5_MEASUREMENT_MEASURED_VALUE_ID; + reporting_info.u.send_info.min_interval = min_interval; + reporting_info.u.send_info.max_interval = max_interval; + reporting_info.u.send_info.def_min_interval = min_interval; + reporting_info.u.send_info.def_max_interval = max_interval; + // reporting_info.u.send_info.delta.u16 = (uint16_t)(delta * 100); // Convert delta to ZCL uint16_t + reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; + reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + float delta_f = delta; + memcpy(&reporting_info.u.send_info.delta.s32, &delta_f, sizeof(float)); + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeePM25Sensor::setPM25(float pm25) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + log_v("Updating PM2.5 sensor value..."); + /* Update PM2.5 sensor measured value */ + log_d("Setting PM2.5 to %0.1f", pm25); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_PM2_5_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_PM2_5_MEASUREMENT_MEASURED_VALUE_ID, &pm25, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set PM2.5: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeePM25Sensor::report() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_PM2_5_MEASUREMENT_MEASURED_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_PM2_5_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to send PM2.5 report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("PM2.5 report sent"); + return true; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeePM25Sensor.h b/libraries/Zigbee/src/ep/ZigbeePM25Sensor.h new file mode 100644 index 00000000000..344f3e1f479 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeePM25Sensor.h @@ -0,0 +1,60 @@ +/* Class of Zigbee PM2.5 sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// clang-format off +#define ZIGBEE_DEFAULT_PM2_5_SENSOR_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .pm2_5_meas_cfg = \ + { \ + .measured_value = 0.0, \ + .min_measured_value = 0.0, \ + .max_measured_value = 500.0, \ + }, \ + } +// clang-format on + +typedef struct zigbee_pm2_5_sensor_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_pm2_5_measurement_cluster_cfg_t pm2_5_meas_cfg; +} zigbee_pm2_5_sensor_cfg_t; + +class ZigbeePM25Sensor : public ZigbeeEP { +public: + ZigbeePM25Sensor(uint8_t endpoint); + ~ZigbeePM25Sensor() {} + + // Set the PM2.5 value in 0.1 µg/m³ + bool setPM25(float pm25); + + // Set the min and max value for the PM2.5 sensor in 0.1 µg/m³ + bool setMinMaxValue(float min, float max); + + // Set the tolerance value for the PM2.5 sensor in 0.1 µg/m³ + bool setTolerance(float tolerance); + + // Set the reporting interval for PM2.5 measurement in seconds and delta (PM2.5 change in 0.1 µg/m³) + bool setReporting(uint16_t min_interval, uint16_t max_interval, float delta); + + // Report the PM2.5 value + bool report(); +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeePressureSensor.cpp b/libraries/Zigbee/src/ep/ZigbeePressureSensor.cpp new file mode 100644 index 00000000000..bca06a35d0c --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeePressureSensor.cpp @@ -0,0 +1,114 @@ +#include "ZigbeePressureSensor.h" +#if CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_pressure_sensor_clusters_create(zigbee_pressure_sensor_cfg_t *pressure_sensor) { + esp_zb_basic_cluster_cfg_t *basic_cfg = pressure_sensor ? &(pressure_sensor->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = pressure_sensor ? &(pressure_sensor->identify_cfg) : NULL; + esp_zb_pressure_meas_cluster_cfg_t *pressure_meas_cfg = pressure_sensor ? &(pressure_sensor->pressure_meas_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_pressure_meas_cluster(cluster_list, esp_zb_pressure_meas_cluster_create(pressure_meas_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + return cluster_list; +} + +ZigbeePressureSensor::ZigbeePressureSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + //Create custom pressure sensor configuration + zigbee_pressure_sensor_cfg_t presssure_sensor_cfg = ZIGBEE_DEFAULT_PRESSURE_SENSOR_CONFIG(); + _cluster_list = zigbee_pressure_sensor_clusters_create(&presssure_sensor_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +bool ZigbeePressureSensor::setMinMaxValue(int16_t min, int16_t max) { + esp_zb_attribute_list_t *pressure_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(pressure_measure_cluster, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_ID, (void *)&min); + if (ret != ESP_OK) { + log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(pressure_measure_cluster, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_ID, (void *)&max); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeePressureSensor::setTolerance(uint16_t tolerance) { + esp_zb_attribute_list_t *pressure_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_pressure_meas_cluster_add_attr(pressure_measure_cluster, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_TOLERANCE_ID, (void *)&tolerance); + if (ret != ESP_OK) { + log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret)); + } + return ret == ESP_OK; +} + +bool ZigbeePressureSensor::setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta) { + esp_zb_zcl_reporting_info_t reporting_info; + memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t)); + reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; + reporting_info.ep = _endpoint; + reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT; + reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + reporting_info.attr_id = ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_ID; + reporting_info.u.send_info.min_interval = min_interval; + reporting_info.u.send_info.max_interval = max_interval; + reporting_info.u.send_info.def_min_interval = min_interval; + reporting_info.u.send_info.def_max_interval = max_interval; + reporting_info.u.send_info.delta.u16 = delta; // x hPa + reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; + reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeePressureSensor::setPressure(int16_t pressure) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + log_v("Updating pressure sensor value..."); + /* Update pressure sensor measured value */ + log_d("Setting pressure to %d hPa", pressure); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_ID, &pressure, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set pressure: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeePressureSensor::report() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to send pressure report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("Pressure report sent"); + return true; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeePressureSensor.h b/libraries/Zigbee/src/ep/ZigbeePressureSensor.h new file mode 100644 index 00000000000..f93df7a7411 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeePressureSensor.h @@ -0,0 +1,60 @@ +/* Class of Zigbee Pressure sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// clang-format off +#define ZIGBEE_DEFAULT_PRESSURE_SENSOR_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .pressure_meas_cfg = \ + { \ + .measured_value = ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_DEFAULT_VALUE, \ + .min_value = ESP_ZB_ZCL_PATTR_RESSURE_MEASUREMENT_MIN_VALUE_DEFAULT_VALUE, \ + .max_value = ESP_ZB_ZCL_PATTR_RESSURE_MEASUREMENT_MAX_VALUE_DEFAULT_VALUE, \ + }, \ + } +// clang-format on + +typedef struct zigbee_pressure_sensor_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_pressure_meas_cluster_cfg_t pressure_meas_cfg; +} zigbee_pressure_sensor_cfg_t; + +class ZigbeePressureSensor : public ZigbeeEP { +public: + ZigbeePressureSensor(uint8_t endpoint); + ~ZigbeePressureSensor() {} + + // Set the pressure value in 1 hPa + bool setPressure(int16_t value); + + // Set the min and max value for the pressure sensor in 1 hPa + bool setMinMaxValue(int16_t min, int16_t max); + + // Set the tolerance value for the pressure sensor in 1 hPa + bool setTolerance(uint16_t tolerance); + + // Set the reporting interval for pressure measurement in seconds and delta (pressure change in 1 hPa) + bool setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta); + + // Report the pressure value + bool report(); +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeRangeExtender.cpp b/libraries/Zigbee/src/ep/ZigbeeRangeExtender.cpp new file mode 100644 index 00000000000..20db20d758a --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeRangeExtender.cpp @@ -0,0 +1,15 @@ +#include "ZigbeeRangeExtender.h" +#if CONFIG_ZB_ENABLED + +ZigbeeRangeExtender::ZigbeeRangeExtender(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_RANGE_EXTENDER_DEVICE_ID; + + _cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(_cluster_list, esp_zb_basic_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_identify_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_RANGE_EXTENDER_DEVICE_ID, .app_device_version = 0}; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeRangeExtender.h b/libraries/Zigbee/src/ep/ZigbeeRangeExtender.h new file mode 100644 index 00000000000..f9e4a963164 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeRangeExtender.h @@ -0,0 +1,18 @@ +/* Class of Zigbee Range Extender endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +class ZigbeeRangeExtender : public ZigbeeEP { +public: + ZigbeeRangeExtender(uint8_t endpoint); + ~ZigbeeRangeExtender() {} +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp new file mode 100644 index 00000000000..86c68ae1870 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp @@ -0,0 +1,316 @@ +#include "ZigbeeSwitch.h" +#if CONFIG_ZB_ENABLED + +// Initialize the static instance pointer +ZigbeeSwitch *ZigbeeSwitch::_instance = nullptr; + +ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID; + _instance = this; // Set the static pointer to this instance + + esp_zb_on_off_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_ON_OFF_SWITCH_CONFIG(); + _cluster_list = esp_zb_on_off_switch_clusters_create(&switch_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID, .app_device_version = 0}; +} + +void ZigbeeSwitch::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_i("Bound successfully!"); + if (user_ctx) { + zb_device_params_t *light = (zb_device_params_t *)user_ctx; + log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); + _instance->_bound_devices.push_back(light); + } + _is_bound = true; + } +} + +void ZigbeeSwitch::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_d("Found light endpoint"); + esp_zb_zdo_bind_req_param_t bind_req; + zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); + light->endpoint = endpoint; + light->short_addr = addr; + esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); + esp_zb_get_long_address(bind_req.src_address); + bind_req.src_endp = *((uint8_t *)user_ctx); //_endpoint; + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + memcpy(bind_req.dst_address_u.addr_long, light->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req.dst_endp = endpoint; + bind_req.req_dst_addr = esp_zb_get_short_address(); + log_i("Try to bind On/Off"); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, (void *)light); + } else { + log_d("No light endpoint found"); + } +} + +// find on_off light endpoint +void ZigbeeSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { + uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF}; + esp_zb_zdo_match_desc_req_param_t on_off_req = { + .dst_nwk_addr = cmd_req->dst_nwk_addr, + .addr_of_interest = cmd_req->addr_of_interest, + .profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .num_in_clusters = 1, + .num_out_clusters = 1, + .cluster_list = cluster_list, + }; + esp_zb_zdo_match_cluster(&on_off_req, findCb, &_endpoint); +} + +// Methods to control the light +void ZigbeeSwitch::lightToggle() { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_v("Sending 'light toggle' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightToggle(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_v("Sending 'light toggle' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_v("Sending 'light toggle' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + log_v( + "Sending 'light toggle' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], ieee_addr[5], + ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0] + ); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOn() { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_v("Sending 'light on' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOn(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_v("Sending 'light on' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_v("Sending 'light on' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + log_v( + "Sending 'light on' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], ieee_addr[5], + ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0] + ); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOff() { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_v("Sending 'light off' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOff(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_v("Sending 'light off' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_v("Sending 'light off' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + log_v( + "Sending 'light off' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], ieee_addr[5], + ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0] + ); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant) { + if (_is_bound) { + esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.effect_id = effect_id; + cmd_req.effect_variant = effect_variant; + log_v("Sending 'light off with effect' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_off_with_effect_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOnWithSceneRecall() { + if (_is_bound) { + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + log_v("Sending 'light on with scene recall' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} +void ZigbeeSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off) { + if (_is_bound) { + esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.on_off_control = on_off_control; //TODO: Test how it works, then maybe change API + cmd_req.on_time = time_on; + cmd_req.off_wait_time = time_off; + log_v("Sending 'light on with time off' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_on_with_timed_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.h b/libraries/Zigbee/src/ep/ZigbeeSwitch.h new file mode 100644 index 00000000000..5c527bec6e3 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.h @@ -0,0 +1,46 @@ +/* Class of Zigbee On/Off Switch endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +class ZigbeeSwitch : public ZigbeeEP { +public: + ZigbeeSwitch(uint8_t endpoint); + ~ZigbeeSwitch() {} + + // methods to control the on/off light + void lightToggle(); + void lightToggle(uint16_t group_addr); + void lightToggle(uint8_t endpoint, uint16_t short_addr); + void lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + + void lightOn(); + void lightOn(uint16_t group_addr); + void lightOn(uint8_t endpoint, uint16_t short_addr); + void lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + + void lightOff(); + void lightOff(uint16_t group_addr); + void lightOff(uint8_t endpoint, uint16_t short_addr); + void lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + + void lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant); + void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off); + void lightOnWithSceneRecall(); + +private: + // save instance of the class in order to use it in static functions + static ZigbeeSwitch *_instance; + + void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp new file mode 100644 index 00000000000..7126dae15cf --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp @@ -0,0 +1,203 @@ +#include "ZigbeeTempSensor.h" +#if CONFIG_ZB_ENABLED + +ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID; + _humidity_sensor = false; + + esp_zb_temperature_sensor_cfg_t temp_sensor_cfg = ESP_ZB_DEFAULT_TEMPERATURE_SENSOR_CONFIG(); + _cluster_list = esp_zb_temperature_sensor_clusters_create(&temp_sensor_cfg); + + _ep_config = { + .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID, .app_device_version = 0 + }; +} + +static int16_t zb_float_to_s16(float temp) { + return (int16_t)(temp * 100); +} + +bool ZigbeeTempSensor::setMinMaxValue(float min, float max) { + int16_t zb_min = zb_float_to_s16(min); + int16_t zb_max = zb_float_to_s16(max); + esp_zb_attribute_list_t *temp_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, (void *)&zb_min); + if (ret != ESP_OK) { + log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, (void *)&zb_max); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeTempSensor::setTolerance(float tolerance) { + // Convert tolerance to ZCL uint16_t + uint16_t zb_tolerance = (uint16_t)(tolerance * 100); + esp_zb_attribute_list_t *temp_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_temperature_meas_cluster_add_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance); + if (ret != ESP_OK) { + log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeTempSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) { + esp_zb_zcl_reporting_info_t reporting_info; + memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t)); + reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; + reporting_info.ep = _endpoint; + reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + reporting_info.attr_id = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID; + reporting_info.u.send_info.min_interval = min_interval; + reporting_info.u.send_info.max_interval = max_interval; + reporting_info.u.send_info.def_min_interval = min_interval; + reporting_info.u.send_info.def_max_interval = max_interval; + reporting_info.u.send_info.delta.u16 = (uint16_t)(delta * 100); // Convert delta to ZCL uint16_t + reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; + reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeTempSensor::setTemperature(float temperature) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + int16_t zb_temperature = zb_float_to_s16(temperature); + log_v("Updating temperature sensor value..."); + /* Update temperature sensor measured value */ + log_d("Setting temperature to %d", zb_temperature); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &zb_temperature, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set temperature: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeTempSensor::reportTemperature() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to send temperature report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("Temperature report sent"); + return true; +} + +void ZigbeeTempSensor::addHumiditySensor(float min, float max, float tolerance) { + int16_t zb_min = zb_float_to_s16(min); + int16_t zb_max = zb_float_to_s16(max); + uint16_t zb_tolerance = (uint16_t)(tolerance * 100); + int16_t default_hum = ESP_ZB_ZCL_REL_HUMIDITY_MEASUREMENT_MEASURED_VALUE_DEFAULT; + esp_zb_attribute_list_t *humidity_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT); + esp_zb_humidity_meas_cluster_add_attr(humidity_cluster, ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID, &default_hum); + esp_zb_humidity_meas_cluster_add_attr(humidity_cluster, ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_ID, &zb_min); + esp_zb_humidity_meas_cluster_add_attr(humidity_cluster, ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID, &zb_max); + esp_zb_humidity_meas_cluster_add_attr(humidity_cluster, ESP_ZB_ZCL_ATTR_REL_HUMIDITY_TOLERANCE_ID, &zb_tolerance); + esp_zb_cluster_list_add_humidity_meas_cluster(_cluster_list, humidity_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + _humidity_sensor = true; +} + +bool ZigbeeTempSensor::setHumidity(float humidity) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + int16_t zb_humidity = zb_float_to_s16(humidity); + log_v("Updating humidity sensor value..."); + /* Update humidity sensor measured value */ + log_d("Setting humidity to %d", zb_humidity); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID, &zb_humidity, + false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set humidity: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeTempSensor::reportHumidity() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to send humidity report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("Humidity report sent"); + return true; +} + +bool ZigbeeTempSensor::setHumidityReporting(uint16_t min_interval, uint16_t max_interval, float delta) { + esp_zb_zcl_reporting_info_t reporting_info; + memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t)); + reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; + reporting_info.ep = _endpoint; + reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT; + reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + reporting_info.attr_id = ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID; + reporting_info.u.send_info.min_interval = min_interval; + reporting_info.u.send_info.max_interval = max_interval; + reporting_info.u.send_info.def_min_interval = min_interval; + reporting_info.u.send_info.def_max_interval = max_interval; + reporting_info.u.send_info.delta.u16 = (uint16_t)(delta * 100); // Convert delta to ZCL uint16_t + reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; + reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to set humidity reporting: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeTempSensor::report() { + bool temp_ret = reportTemperature(); + bool hum_ret = true; + if (_humidity_sensor) { + hum_ret = reportHumidity(); + } + return temp_ret && hum_ret; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeTempSensor.h b/libraries/Zigbee/src/ep/ZigbeeTempSensor.h new file mode 100644 index 00000000000..bc769b32de6 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.h @@ -0,0 +1,51 @@ +/* Class of Zigbee Temperature + Humidity sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +class ZigbeeTempSensor : public ZigbeeEP { +public: + ZigbeeTempSensor(uint8_t endpoint); + ~ZigbeeTempSensor() {} + + // Set the temperature value in 0,01°C + bool setTemperature(float value); + + // Set the min and max value for the temperature sensor in 0,01°C + bool setMinMaxValue(float min, float max); + + // Set the tolerance value for the temperature sensor in 0,01°C + bool setTolerance(float tolerance); + + // Set the reporting interval for temperature measurement in seconds and delta (temp change in 0,01 °C) + bool setReporting(uint16_t min_interval, uint16_t max_interval, float delta); + + // Report the temperature value + bool reportTemperature(); + + // Add humidity cluster to the temperature sensor device + void addHumiditySensor(float min, float max, float tolerance); + + // Set the humidity value in 0,01% + bool setHumidity(float value); + + // Set the reporting interval for humidity measurement in seconds and delta (humidity change in 0,01%) + bool setHumidityReporting(uint16_t min_interval, uint16_t max_interval, float delta); + + // Report the humidity value + bool reportHumidity(); + + // Report the temperature and humidity values if humidity sensor is added + bool report(); + +private: + bool _humidity_sensor; +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp new file mode 100644 index 00000000000..357bcaed1bc --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp @@ -0,0 +1,205 @@ +#include "ZigbeeThermostat.h" +#if CONFIG_ZB_ENABLED + +static float zb_s16_to_temperature(int16_t value) { + return 1.0 * value / 100; +} + +// Initialize the static instance of the class +ZigbeeThermostat *ZigbeeThermostat::_instance = nullptr; + +ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID; + _instance = this; // Set the static pointer to this instance + + //use custom config to avoid narrowing error -> must be fixed in zigbee-sdk + esp_zb_thermostat_cfg_t thermostat_cfg = ZB_DEFAULT_THERMOSTAT_CONFIG(); + + //use custom cluster creating to accept reportings from temperature sensor + _cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_attribute_list_t *basic_cluster = esp_zb_basic_cluster_create(&(thermostat_cfg.basic_cfg)); + esp_zb_cluster_list_add_basic_cluster(_cluster_list, basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_identify_cluster_create(&(thermostat_cfg.identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE); + esp_zb_cluster_list_add_thermostat_cluster(_cluster_list, esp_zb_thermostat_cluster_create(&(thermostat_cfg.thermostat_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + /* Add temperature measurement cluster for attribute reporting */ + esp_zb_cluster_list_add_temperature_meas_cluster(_cluster_list, esp_zb_temperature_meas_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID, .app_device_version = 0}; +} + +void ZigbeeThermostat::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + if (user_ctx) { + zb_device_params_t *sensor = (zb_device_params_t *)user_ctx; + log_i("The temperature sensor originating from address(0x%x) on endpoint(%d)", sensor->short_addr, sensor->endpoint); + _instance->_bound_devices.push_back(sensor); + } else { + log_v("Local binding success"); + } + _is_bound = true; + } else { + log_e("Binding failed!"); + } +} + +void ZigbeeThermostat::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_i("Found temperature sensor"); + esp_zb_zdo_bind_req_param_t bind_req; + /* Store the information of the remote device */ + zb_device_params_t *sensor = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); + sensor->endpoint = endpoint; + sensor->short_addr = addr; + esp_zb_ieee_address_by_short(sensor->short_addr, sensor->ieee_addr); + log_d("Temperature sensor found: short address(0x%x), endpoint(%d)", sensor->short_addr, sensor->endpoint); + + /* 1. Send binding request to the sensor */ + bind_req.req_dst_addr = addr; + log_d("Request temperature sensor to bind us"); + + /* populate the src information of the binding */ + memcpy(bind_req.src_address, sensor->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req.src_endp = endpoint; + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + log_d("Bind temperature sensor"); + + /* populate the dst information of the binding */ + bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + esp_zb_get_long_address(bind_req.dst_address_u.addr_long); + bind_req.dst_endp = *((uint8_t *)user_ctx); //_endpoint; + + log_i("Request temperature sensor to bind us"); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, NULL); + + /* 2. Send binding request to self */ + bind_req.req_dst_addr = esp_zb_get_short_address(); + + /* populate the src information of the binding */ + esp_zb_get_long_address(bind_req.src_address); + bind_req.src_endp = *((uint8_t *)user_ctx); //_endpoint; + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + + /* populate the dst information of the binding */ + bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + memcpy(bind_req.dst_address_u.addr_long, sensor->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req.dst_endp = endpoint; + + log_i("Bind temperature sensor"); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, (void *)sensor); + } +} + +void ZigbeeThermostat::findEndpoint(esp_zb_zdo_match_desc_req_param_t *param) { + uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT}; + param->profile_id = ESP_ZB_AF_HA_PROFILE_ID; + param->num_in_clusters = 1; + param->num_out_clusters = 0; + param->cluster_list = cluster_list; + esp_zb_zdo_match_cluster(param, findCb, &_endpoint); +} + +void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { + static uint8_t read_config = 0; + if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT) { + if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) { + int16_t value = attribute->data.value ? *(int16_t *)attribute->data.value : 0; + if (_on_temp_recieve) { + _on_temp_recieve(zb_s16_to_temperature(value)); + } + } + if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) { + int16_t min_value = attribute->data.value ? *(int16_t *)attribute->data.value : 0; + _min_temp = zb_s16_to_temperature(min_value); + read_config++; + } + if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) { + int16_t max_value = attribute->data.value ? *(int16_t *)attribute->data.value : 0; + _max_temp = zb_s16_to_temperature(max_value); + read_config++; + } + if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0; + _tolerance = 1.0 * tolerance / 100; + read_config++; + } + if (read_config == 3) { + read_config = 0; + xSemaphoreGive(lock); + } + } +} + +void ZigbeeThermostat::getTemperature() { + /* Send "read attributes" command to the bound sensor */ + esp_zb_zcl_read_attr_cmd_t read_req; + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + + uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID}; + read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_field = attributes; + + log_i("Sending 'read temperature' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); +} + +void ZigbeeThermostat::getSensorSettings() { + /* Send "read attributes" command to the bound sensor */ + esp_zb_zcl_read_attr_cmd_t read_req; + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + + uint16_t attributes[] = { + ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID + }; + read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_field = attributes; + + log_i("Sending 'read temperature' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + + //Take semaphore to wait for response of all attributes + if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) { + log_e("Error while reading attributes"); + return; + } else { + //Call the callback function when all attributes are read + _on_config_recieve(_min_temp, _max_temp, _tolerance); + } +} + +void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta) { + /* Send "configure report attribute" command to the bound sensor */ + esp_zb_zcl_config_report_cmd_t report_cmd; + report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + + int16_t report_change = (int16_t)delta * 100; + esp_zb_zcl_config_report_record_t records[] = { + { + .direction = ESP_ZB_ZCL_REPORT_DIRECTION_SEND, + .attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, + .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16, + .min_interval = min_interval, + .max_interval = max_interval, + .reportable_change = &report_change, + }, + }; + report_cmd.record_number = ZB_ARRAY_LENTH(records); + report_cmd.record_field = records; + + log_i("Sending 'configure reporting' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_config_report_cmd_req(&report_cmd); + esp_zb_lock_release(); +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.h b/libraries/Zigbee/src/ep/ZigbeeThermostat.h new file mode 100644 index 00000000000..7895115e1d1 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.h @@ -0,0 +1,65 @@ +/* Class of Zigbee Temperature sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +//define the thermostat configuration to avoid narrowing conversion issue in zigbee-sdk +#define ZB_DEFAULT_THERMOSTAT_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .thermostat_cfg = { \ + .local_temperature = (int16_t)ESP_ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_DEFAULT_VALUE, \ + .occupied_cooling_setpoint = ESP_ZB_ZCL_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_DEFAULT_VALUE, \ + .occupied_heating_setpoint = ESP_ZB_ZCL_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_DEFAULT_VALUE, \ + .control_sequence_of_operation = ESP_ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_DEFAULT_VALUE, \ + .system_mode = ESP_ZB_ZCL_THERMOSTAT_CONTROL_SYSTEM_MODE_DEFAULT_VALUE, \ + }, \ + } +class ZigbeeThermostat : public ZigbeeEP { +public: + ZigbeeThermostat(uint8_t endpoint); + ~ZigbeeThermostat() {} + + void onTempRecieve(void (*callback)(float)) { + _on_temp_recieve = callback; + } + void onConfigRecieve(void (*callback)(float, float, float)) { + _on_config_recieve = callback; + } + + void getTemperature(); + void getSensorSettings(); + void setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta); + +private: + // save instance of the class in order to use it in static functions + static ZigbeeThermostat *_instance; + + void (*_on_temp_recieve)(float); + void (*_on_config_recieve)(float, float, float); + float _min_temp; + float _max_temp; + float _tolerance; + + void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); + + void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) override; +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeVibrationSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeVibrationSensor.cpp new file mode 100644 index 00000000000..6be457c389a --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeVibrationSensor.cpp @@ -0,0 +1,91 @@ +#include "ZigbeeVibrationSensor.h" +#if CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_vibration_sensor_clusters_create(zigbee_vibration_sensor_cfg_t *vibration_sensor) { + esp_zb_basic_cluster_cfg_t *basic_cfg = vibration_sensor ? &(vibration_sensor->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = vibration_sensor ? &(vibration_sensor->identify_cfg) : NULL; + esp_zb_ias_zone_cluster_cfg_t *ias_zone_cfg = vibration_sensor ? &(vibration_sensor->ias_zone_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_ias_zone_cluster(cluster_list, esp_zb_ias_zone_cluster_create(ias_zone_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + return cluster_list; +} + +ZigbeeVibrationSensor::ZigbeeVibrationSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_IAS_ZONE_ID; + _zone_status = 0; + _zone_id = 0xff; + _ias_cie_endpoint = 1; + + //Create custom vibration sensor configuration + zigbee_vibration_sensor_cfg_t vibration_sensor_cfg = ZIGBEE_DEFAULT_VIBRATION_SENSOR_CONFIG(); + _cluster_list = zigbee_vibration_sensor_clusters_create(&vibration_sensor_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_IAS_ZONE_ID, .app_device_version = 0}; +} + +void ZigbeeVibrationSensor::setIASClientEndpoint(uint8_t ep_number) { + _ias_cie_endpoint = ep_number; +} + +bool ZigbeeVibrationSensor::setVibration(bool sensed) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + log_v("Setting Vibration sensor to %s", sensed ? "sensed" : "not sensed"); + uint8_t vibration = (uint8_t)sensed; + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &vibration, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set vibration status: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + _zone_status = vibration; + report(); + return true; +} + +void ZigbeeVibrationSensor::report() { + /* Send IAS Zone status changed notification command */ + + esp_zb_zcl_ias_zone_status_change_notif_cmd_t status_change_notif_cmd; + status_change_notif_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + status_change_notif_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + status_change_notif_cmd.zcl_basic_cmd.dst_endpoint = _ias_cie_endpoint; //default is 1 + memcpy(status_change_notif_cmd.zcl_basic_cmd.dst_addr_u.addr_long, _ias_cie_addr, sizeof(esp_zb_ieee_addr_t)); + status_change_notif_cmd.zone_status = _zone_status; + status_change_notif_cmd.extend_status = 0; + status_change_notif_cmd.zone_id = _zone_id; + status_change_notif_cmd.delay = 0; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_ias_zone_status_change_notif_cmd_req(&status_change_notif_cmd); + esp_zb_lock_release(); + log_v("IAS Zone status changed notification sent"); +} + +void ZigbeeVibrationSensor::zbIASZoneEnrollResponse(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) { + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE) { + log_v("IAS Zone Enroll Response: zone id(%d), status(%d)", message->zone_id, message->response_code); + if (message->response_code == ESP_ZB_ZCL_IAS_ZONE_ENROLL_RESPONSE_CODE_SUCCESS) { + log_v("IAS Zone Enroll Response: success"); + esp_zb_lock_acquire(portMAX_DELAY); + memcpy( + _ias_cie_addr, + (*(esp_zb_ieee_addr_t *) + esp_zb_zcl_get_attribute(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID) + ->data_p), + sizeof(esp_zb_ieee_addr_t) + ); + esp_zb_lock_release(); + _zone_id = message->zone_id; + } + + } else { + log_w("Received message ignored. Cluster ID: %d not supported for On/Off Light", message->info.cluster); + } +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeVibrationSensor.h b/libraries/Zigbee/src/ep/ZigbeeVibrationSensor.h new file mode 100644 index 00000000000..2f67c7bb6b4 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeVibrationSensor.h @@ -0,0 +1,64 @@ +/* Class of Zigbee contact switch (IAS Zone) endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// clang-format off +#define ZIGBEE_DEFAULT_VIBRATION_SENSOR_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .ias_zone_cfg = \ + { \ + .zone_state = ESP_ZB_ZCL_IAS_ZONE_ZONESTATE_NOT_ENROLLED, \ + .zone_type = ESP_ZB_ZCL_IAS_ZONE_ZONETYPE_VIBRATION_MOVEMENT, \ + .zone_status = 0, \ + .ias_cie_addr = ESP_ZB_ZCL_ZONE_IAS_CIE_ADDR_DEFAULT, \ + .zone_id = 0xff, \ + .zone_ctx = {0, 0, 0, 0}, \ + }, \ + } +// clang-format on + +typedef struct zigbee_vibration_sensor_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_ias_zone_cluster_cfg_t ias_zone_cfg; +} zigbee_vibration_sensor_cfg_t; + +class ZigbeeVibrationSensor : public ZigbeeEP { +public: + ZigbeeVibrationSensor(uint8_t endpoint); + ~ZigbeeVibrationSensor() {} + + // Set the IAS Client endpoint number (default is 1) + void setIASClientEndpoint(uint8_t ep_number); + + // Set the vibration sensor value (true = sensed, false = not sensed) + bool setVibration(bool sensed); + + // Report the vibration sensor value, done automatically after setting the sensed value + void report(); + +private: + void zbIASZoneEnrollResponse(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) override; + uint8_t _zone_status; + uint8_t _zone_id; + esp_zb_ieee_addr_t _ias_cie_addr; + uint8_t _ias_cie_endpoint; +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.cpp new file mode 100644 index 00000000000..72184927d4d --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.cpp @@ -0,0 +1,128 @@ +#include "ZigbeeWindSpeedSensor.h" +#if CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_wind_speed_sensor_clusters_create(zigbee_wind_speed_sensor_cfg_t *wind_speed_sensor) { + esp_zb_basic_cluster_cfg_t *basic_cfg = wind_speed_sensor ? &(wind_speed_sensor->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = wind_speed_sensor ? &(wind_speed_sensor->identify_cfg) : NULL; + esp_zb_wind_speed_measurement_cluster_cfg_t *wind_speed_cfg = wind_speed_sensor ? &(wind_speed_sensor->wind_speed_meas_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_wind_speed_measurement_cluster( + cluster_list, esp_zb_wind_speed_measurement_cluster_create(wind_speed_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE + ); + return cluster_list; +} + +// There is no device_id for wind speed sensor, we use a generic one +ZigbeeWindSpeedSensor::ZigbeeWindSpeedSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + zigbee_wind_speed_sensor_cfg_t windspeed_sensor_cfg = ZIGBEE_DEFAULT_WIND_SPEED_SENSOR_CONFIG(); + _cluster_list = zigbee_wind_speed_sensor_clusters_create(&windspeed_sensor_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +static uint16_t zb_windspeed_to_u16(float windspeed) { + return (uint16_t)(windspeed * 100); +} + +bool ZigbeeWindSpeedSensor::setMinMaxValue(float min, float max) { + uint16_t zb_min = zb_windspeed_to_u16(min); + uint16_t zb_max = zb_windspeed_to_u16(max); + esp_zb_attribute_list_t *windspeed_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(windspeed_measure_cluster, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MIN_MEASURED_VALUE_ID, (void *)&zb_min); + if (ret != ESP_OK) { + log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(windspeed_measure_cluster, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MAX_MEASURED_VALUE_ID, (void *)&zb_max); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeWindSpeedSensor::setTolerance(float tolerance) { + // Convert tolerance to ZCL uint16_t + uint16_t zb_tolerance = zb_windspeed_to_u16(tolerance); + esp_zb_attribute_list_t *windspeed_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = + esp_zb_wind_speed_measurement_cluster_add_attr(windspeed_measure_cluster, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance); + if (ret != ESP_OK) { + log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeWindSpeedSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) { + esp_zb_zcl_reporting_info_t reporting_info; + memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t)); + reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; + reporting_info.ep = _endpoint; + reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT; + reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + reporting_info.attr_id = ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MEASURED_VALUE_ID; + reporting_info.u.send_info.min_interval = min_interval; + reporting_info.u.send_info.max_interval = max_interval; + reporting_info.u.send_info.def_min_interval = min_interval; + reporting_info.u.send_info.def_max_interval = max_interval; + reporting_info.u.send_info.delta.u16 = (uint16_t)(delta * 100); // Convert delta to ZCL uint16_t + reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; + reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeWindSpeedSensor::setWindSpeed(float windspeed) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + uint16_t zb_windspeed = zb_windspeed_to_u16(windspeed); + log_v("Updating windspeed sensor value..."); + /* Update windspeed sensor measured value */ + log_d("Setting windspeed to %d", zb_windspeed); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MEASURED_VALUE_ID, + &zb_windspeed, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set wind speed: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeWindSpeedSensor::reportWindSpeed() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MEASURED_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to send wind speed report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("Wind speed measurement report sent"); + return true; +} + +#endif //CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.h b/libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.h new file mode 100644 index 00000000000..641c1d84780 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.h @@ -0,0 +1,56 @@ +/* Class of Zigbee WindSpeed sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +#define ZIGBEE_DEFAULT_WIND_SPEED_SENSOR_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .wind_speed_meas_cfg = { \ + .measured_value = ESP_ZB_ZCL_WIND_SPEED_MEASUREMENT_MEASURED_VALUE_DEFAULT, \ + .min_measured_value = ESP_ZB_ZCL_WIND_SPEED_MEASUREMENT_MIN_MEASURED_VALUE_DEFAULT, \ + .max_measured_value = ESP_ZB_ZCL_WIND_SPEED_MEASUREMENT_MAX_MEASURED_VALUE_DEFAULT, \ + }, \ + } + +typedef struct zigbee_wind_speed_sensor_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; /*!< Basic cluster configuration, @ref esp_zb_basic_cluster_cfg_s */ + esp_zb_identify_cluster_cfg_t identify_cfg; /*!< Identify cluster configuration, @ref esp_zb_identify_cluster_cfg_s */ + esp_zb_wind_speed_measurement_cluster_cfg_t + wind_speed_meas_cfg; /*!< Wind speed measurement cluster configuration, @ref esp_zb_wind_speed_measurement_cluster_cfg_s */ +} zigbee_wind_speed_sensor_cfg_t; + +class ZigbeeWindSpeedSensor : public ZigbeeEP { +public: + ZigbeeWindSpeedSensor(uint8_t endpoint); + ~ZigbeeWindSpeedSensor() {} + + // Set the WindSpeed value in 0,01 m/s + bool setWindSpeed(float value); + + // Set the min and max value for the WindSpeed sensor + bool setMinMaxValue(float min, float max); + + // Set the tolerance value for the WindSpeed sensor + bool setTolerance(float tolerance); + + // Set the reporting interval for WindSpeed measurement in seconds and delta + bool setReporting(uint16_t min_interval, uint16_t max_interval, float delta); + bool reportWindSpeed(); +}; + +#endif //CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeWindowCovering.cpp b/libraries/Zigbee/src/ep/ZigbeeWindowCovering.cpp new file mode 100644 index 00000000000..7c7889dbbf7 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeWindowCovering.cpp @@ -0,0 +1,394 @@ +#include "ZigbeeWindowCovering.h" +#if CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *ZigbeeWindowCovering::zigbee_window_covering_clusters_create(zigbee_window_covering_cfg_t *window_covering_cfg) { + esp_zb_attribute_list_t *esp_zb_basic_cluster = esp_zb_basic_cluster_create(&window_covering_cfg->basic_cfg); + esp_zb_attribute_list_t *esp_zb_identify_cluster = esp_zb_identify_cluster_create(&window_covering_cfg->identify_cfg); + esp_zb_attribute_list_t *esp_zb_groups_cluster = esp_zb_groups_cluster_create(&window_covering_cfg->groups_cfg); + esp_zb_attribute_list_t *esp_zb_scenes_cluster = esp_zb_scenes_cluster_create(&window_covering_cfg->scenes_cfg); + esp_zb_attribute_list_t *esp_zb_window_covering_cluster = esp_zb_window_covering_cluster_create(&window_covering_cfg->window_covering_cfg); + + esp_zb_window_covering_cluster_add_attr( + esp_zb_window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID, &_current_lift_percentage + ); + esp_zb_window_covering_cluster_add_attr( + esp_zb_window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_ID, &_current_tilt_percentage + ); + esp_zb_window_covering_cluster_add_attr(esp_zb_window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_ID, &_current_lift_position); + esp_zb_window_covering_cluster_add_attr(esp_zb_window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_ID, &_current_lift_position); + esp_zb_window_covering_cluster_add_attr( + esp_zb_window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_ID, &_installed_open_limit_lift + ); + esp_zb_window_covering_cluster_add_attr( + esp_zb_window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_TILT_ID, &_installed_open_limit_tilt + ); + esp_zb_window_covering_cluster_add_attr( + esp_zb_window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_LIFT_ID, &_installed_closed_limit_lift + ); + esp_zb_window_covering_cluster_add_attr( + esp_zb_window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_TILT_ID, &_installed_closed_limit_tilt + ); + esp_zb_window_covering_cluster_add_attr( + esp_zb_window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_PHYSICAL_CLOSED_LIMIT_LIFT_ID, &_physical_closed_limit_lift + ); + esp_zb_window_covering_cluster_add_attr( + esp_zb_window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_PHY_CLOSED_LIMIT_TILT_ID, &_physical_closed_limit_lift + ); + + // ------------------------------ Create cluster list ------------------------------ + esp_zb_cluster_list_t *esp_zb_cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(esp_zb_cluster_list, esp_zb_basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(esp_zb_cluster_list, esp_zb_identify_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_groups_cluster(esp_zb_cluster_list, esp_zb_groups_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_scenes_cluster(esp_zb_cluster_list, esp_zb_scenes_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_window_covering_cluster(esp_zb_cluster_list, esp_zb_window_covering_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + return esp_zb_cluster_list; +} + +ZigbeeWindowCovering::ZigbeeWindowCovering(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_WINDOW_COVERING_DEVICE_ID; + + // set default values for window covering attributes + _current_lift_percentage = ESP_ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_DEFAULT_VALUE; + _current_tilt_percentage = ESP_ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_DEFAULT_VALUE; + _installed_open_limit_lift = ESP_ZB_ZCL_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_DEFAULT_VALUE; + _installed_closed_limit_lift = ESP_ZB_ZCL_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_LIFT_DEFAULT_VALUE; + _installed_open_limit_tilt = ESP_ZB_ZCL_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_TILT_DEFAULT_VALUE; + _installed_closed_limit_tilt = ESP_ZB_ZCL_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_TILT_DEFAULT_VALUE; + _current_lift_position = ESP_ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_LIFT_DEFAULT_VALUE; + _current_tilt_position = ESP_ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_TILT_DEFAULT_VALUE; + _physical_closed_limit_lift = ESP_ZB_ZCL_WINDOW_COVERING_PHYSICAL_CLOSED_LIMIT_LIFT_DEFAULT_VALUE; + _physical_closed_limit_tilt = ESP_ZB_ZCL_WINDOW_COVERING_PHY_CLOSED_LIMIT_TILT_DEFAULT_VALUE; + + // Create custom window covering configuration + zigbee_window_covering_cfg_t window_covering_cfg = ZIGBEE_DEFAULT_WINDOW_COVERING_CONFIG(); + _cluster_list = zigbee_window_covering_clusters_create(&window_covering_cfg); + + _ep_config = { + .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_WINDOW_COVERING_DEVICE_ID, .app_device_version = 0 + }; +} + +// Configuration methods for window covering +bool ZigbeeWindowCovering::setCoveringType(ZigbeeWindowCoveringType covering_type) { + esp_zb_attribute_list_t *window_covering_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_WINDOW_COVERING_TYPE_ID, (void *)&covering_type); + if (ret != ESP_OK) { + log_e("Failed to set covering type: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeWindowCovering::setConfigStatus( + bool operational, bool online, bool commands_reversed, bool lift_closed_loop, bool tilt_closed_loop, bool lift_encoder_controlled, + bool tilt_encoder_controlled +) { + uint8_t config_status = (operational ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_OPERATIONAL : 0) | (online ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_ONLINE : 0) + | (commands_reversed ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_REVERSE_COMMANDS : 0) + | (lift_closed_loop ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_LIFT_CONTROL_IS_CLOSED_LOOP : 0) + | (tilt_closed_loop ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_TILT_CONTROL_IS_CLOSED_LOOP : 0) + | (lift_encoder_controlled ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_LIFT_ENCODER_CONTROLLED : 0) + | (tilt_encoder_controlled ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_TILT_ENCODER_CONTROLLED : 0); + + log_v("Updating window covering config status to %d", config_status); + + esp_zb_attribute_list_t *window_covering_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_ID, (void *)&config_status); + if (ret != ESP_OK) { + log_e("Failed to set config status: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeWindowCovering::setMode(bool motor_reversed, bool calibration_mode, bool maintenance_mode, bool leds_on) { + uint8_t mode = (motor_reversed ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_REVERSED_MOTOR_DIRECTION : 0) + | (calibration_mode ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_RUN_IN_CALIBRATION_MODE : 0) + | (maintenance_mode ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_MOTOR_IS_RUNNING_IN_MAINTENANCE_MODE : 0) + | (leds_on ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_LEDS_WILL_DISPLAY_FEEDBACK : 0); + + log_v("Updating window covering mode to %d", mode); + + esp_zb_attribute_list_t *window_covering_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_MODE_ID, (void *)&mode); + if (ret != ESP_OK) { + log_e("Failed to set mode: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeWindowCovering::setLimits( + uint16_t installed_open_limit_lift, uint16_t installed_closed_limit_lift, uint16_t installed_open_limit_tilt, uint16_t installed_closed_limit_tilt +) { + _installed_open_limit_lift = installed_open_limit_lift; + _installed_closed_limit_lift = installed_closed_limit_lift; + _physical_closed_limit_lift = installed_closed_limit_lift; + _installed_open_limit_tilt = installed_open_limit_tilt; + _installed_closed_limit_tilt = installed_closed_limit_tilt; + _physical_closed_limit_tilt = installed_closed_limit_tilt; + + esp_zb_attribute_list_t *window_covering_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = + esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_ID, (void *)&_installed_open_limit_lift); + if (ret != ESP_OK) { + log_e("Failed to set installed open limit lift: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = + esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_LIFT_ID, (void *)&_installed_closed_limit_lift); + if (ret != ESP_OK) { + log_e("Failed to set installed closed limit lift: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_TILT_ID, (void *)&_installed_open_limit_tilt); + if (ret != ESP_OK) { + log_e("Failed to set installed open limit tilt: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = + esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_TILT_ID, (void *)&_installed_closed_limit_tilt); + if (ret != ESP_OK) { + log_e("Failed to set installed closed limit tilt: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = + esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_PHYSICAL_CLOSED_LIMIT_LIFT_ID, (void *)&_physical_closed_limit_lift); + if (ret != ESP_OK) { + log_e("Failed to set physical closed limit lift: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_PHY_CLOSED_LIMIT_TILT_ID, (void *)&_physical_closed_limit_tilt); + if (ret != ESP_OK) { + log_e("Failed to set physical closed limit tilt: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +// Callback for handling incoming messages and commands +void ZigbeeWindowCovering::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { + //check the data and call right method + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING) { + log_v("Received attribute id: 0x%x / data.type: 0x%x", message->attribute.id, message->attribute.data.type); + if (message->attribute.id == ESP_ZB_ZCL_ATTR_WINDOW_COVERING_MODE_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_8BITMAP) { + uint8_t mode = *(uint8_t *)message->attribute.data.value; + bool motor_reversed = mode & ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_REVERSED_MOTOR_DIRECTION; + bool calibration_mode = mode & ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_RUN_IN_CALIBRATION_MODE; + bool maintenance_mode = mode & ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_MOTOR_IS_RUNNING_IN_MAINTENANCE_MODE; + bool leds_on = mode & ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_LEDS_WILL_DISPLAY_FEEDBACK; + log_v( + "Updating window covering mode to motor reversed: %d, calibration mode: %d, maintenance mode: %d, leds on: %d", motor_reversed, calibration_mode, + maintenance_mode, leds_on + ); + setMode(motor_reversed, calibration_mode, maintenance_mode, leds_on); + //Update Configuration status with motor reversed status + uint8_t config_status; + config_status = (*(uint8_t *)esp_zb_zcl_get_attribute( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_ID + ) + ->data_p); + config_status = motor_reversed ? config_status | ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_REVERSE_COMMANDS + : config_status & ~ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_REVERSE_COMMANDS; + log_v("Updating window covering config status to %d", config_status); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_ID, &config_status, + false + ); + esp_zb_lock_release(); + return; + } + } else { + log_w("Received message ignored. Cluster ID: %d not supported for Window Covering", message->info.cluster); + } +} + +void ZigbeeWindowCovering::zbWindowCoveringMovementCmd(const esp_zb_zcl_window_covering_movement_message_t *message) { + // check the data and call right method + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING) { + if (message->command == ESP_ZB_ZCL_CMD_WINDOW_COVERING_UP_OPEN) { + open(); + return; + } else if (message->command == ESP_ZB_ZCL_CMD_WINDOW_COVERING_DOWN_CLOSE) { + close(); + return; + } else if (message->command == ESP_ZB_ZCL_CMD_WINDOW_COVERING_STOP) { + stop(); + return; + } else if (message->command == ESP_ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_LIFT_PERCENTAGE) { + if (_current_lift_percentage != message->payload.percentage_lift_value) { + _current_lift_percentage = message->payload.percentage_lift_value; + goToLiftPercentage(_current_lift_percentage); + return; + } + } else if (message->command == ESP_ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_TILT_PERCENTAGE) { + if (_current_tilt_percentage != message->payload.percentage_tilt_value) { + _current_tilt_percentage = message->payload.percentage_tilt_value; + goToTiltPercentage(_current_tilt_percentage); + return; + } + } else { + log_w("Received message ignored. Command: %d not supported for Window Covering", message->command); + } + } else { + log_w("Received message ignored. Cluster ID: %d not supported for Window Covering", message->info.cluster); + } +} + +void ZigbeeWindowCovering::open() { + if (_on_open) { + _on_open(); + } +} + +void ZigbeeWindowCovering::close() { + if (_on_close) { + _on_close(); + } +} + +void ZigbeeWindowCovering::goToLiftPercentage(uint8_t lift_percentage) { + if (_on_go_to_lift_percentage) { + _on_go_to_lift_percentage(lift_percentage); + } +} + +void ZigbeeWindowCovering::goToTiltPercentage(uint8_t tilt_percentage) { + if (_on_go_to_tilt_percentage) { + _on_go_to_tilt_percentage(tilt_percentage); + } +} + +void ZigbeeWindowCovering::stop() { + if (_on_stop) { + _on_stop(); + } +} + +// Methods to control window covering from user application +bool ZigbeeWindowCovering::setLiftPosition(uint16_t lift_position) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + // Update both lift attributes + _current_lift_position = lift_position; + _current_lift_percentage = ((lift_position - _installed_open_limit_lift) * 100) / (_installed_closed_limit_lift - _installed_open_limit_lift); + log_v("Updating window covering lift position to %d (%d%)", _current_lift_position, _current_lift_percentage); + + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_ID, + &_current_lift_position, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set lift position: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID, + &_current_lift_percentage, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set lift percentage: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } +unlock_and_return: + esp_zb_lock_release(); + return ret == ESP_ZB_ZCL_STATUS_SUCCESS; +} + +bool ZigbeeWindowCovering::setLiftPercentage(uint8_t lift_percentage) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + // Update both lift attributes + _current_lift_percentage = lift_percentage; + _current_lift_position = _installed_open_limit_lift + ((_installed_closed_limit_lift - _installed_open_limit_lift) * lift_percentage) / 100; + log_v("Updating window covering lift percentage to %d%% (%d)", _current_lift_percentage, _current_lift_position); + + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_ID, + &_current_lift_position, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set lift position: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID, + &_current_lift_percentage, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set lift percentage: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } +unlock_and_return: + esp_zb_lock_release(); + return ret == ESP_ZB_ZCL_STATUS_SUCCESS; +} + +bool ZigbeeWindowCovering::setTiltPosition(uint16_t tilt_position) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + // Update both tilt attributes + _current_tilt_position = tilt_position; + _current_tilt_percentage = ((tilt_position - _installed_open_limit_tilt) * 100) / (_installed_closed_limit_tilt - _installed_open_limit_tilt); + + log_v("Updating window covering tilt position to %d (%d%)", _current_tilt_position, _current_tilt_percentage); + + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_ID, + &_current_tilt_position, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set tilt position: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_ID, + &_current_tilt_percentage, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set tilt percentage: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } +unlock_and_return: + esp_zb_lock_release(); + return ret == ESP_ZB_ZCL_STATUS_SUCCESS; +} + +bool ZigbeeWindowCovering::setTiltPercentage(uint8_t tilt_percentage) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + // Update both tilt attributes + _current_tilt_percentage = tilt_percentage; + _current_tilt_position = _installed_open_limit_tilt + ((_installed_closed_limit_tilt - _installed_open_limit_tilt) * tilt_percentage) / 100; + + log_v("Updating window covering tilt percentage to %d%% (%d)", _current_tilt_percentage, _current_tilt_position); + + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_ID, + &_current_tilt_position, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set tilt position: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_ID, + &_current_tilt_percentage, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set tilt percentage: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } +unlock_and_return: + esp_zb_lock_release(); + return ret == ESP_ZB_ZCL_STATUS_SUCCESS; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeWindowCovering.h b/libraries/Zigbee/src/ep/ZigbeeWindowCovering.h new file mode 100644 index 00000000000..288d92c5765 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeWindowCovering.h @@ -0,0 +1,147 @@ +/* Class of Zigbee Window Covering endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// Window covering types supported by Zigbee Window Covering cluster +enum ZigbeeWindowCoveringType { + ROLLERSHADE = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_ROLLERSHADE, // LIFT support + ROLLERSHADE_2_MOTOR = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_ROLLERSHADE_2_MOTOR, // LIFT support + ROLLERSHADE_EXTERIOR = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_ROLLERSHADE_EXTERIOR, // LIFT support + ROLLERSHADE_EXTERIOR_2_MOTOR = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_ROLLERSHADE_EXTERIOR_2_MOTOR, // LIFT support + DRAPERY = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_DRAPERY, // LIFT support + AWNING = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_AWNING, // LIFT support + SHUTTER = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_SHUTTER, // TILT support + BLIND_TILT_ONLY = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_TILT_BLIND_TILT_ONLY, // TILT support + BLIND_LIFT_AND_TILT = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_TILT_BLIND_LIFT_AND_TILT, // LIFT and TILT support + PROJECTOR_SCREEN = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_PROJECTOR_SCREEN, // LIFT support +}; + +// clang-format off +#define ZIGBEE_DEFAULT_WINDOW_COVERING_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .groups_cfg = \ + { \ + .groups_name_support_id = ESP_ZB_ZCL_GROUPS_NAME_SUPPORT_DEFAULT_VALUE, \ + }, \ + .scenes_cfg = \ + { \ + .scenes_count = ESP_ZB_ZCL_SCENES_SCENE_COUNT_DEFAULT_VALUE, \ + .current_scene = ESP_ZB_ZCL_SCENES_CURRENT_SCENE_DEFAULT_VALUE, \ + .current_group = ESP_ZB_ZCL_SCENES_CURRENT_GROUP_DEFAULT_VALUE, \ + .scene_valid = ESP_ZB_ZCL_SCENES_SCENE_VALID_DEFAULT_VALUE, \ + .name_support = ESP_ZB_ZCL_SCENES_NAME_SUPPORT_DEFAULT_VALUE, \ + }, \ + .window_covering_cfg = \ + { \ + .covering_type = ESP_ZB_ZCL_WINDOW_COVERING_WINDOW_COVERING_TYPE_DEFAULT_VALUE, \ + .covering_status = ESP_ZB_ZCL_WINDOW_COVERING_CONFIG_STATUS_DEFAULT_VALUE, \ + .covering_mode = ESP_ZB_ZCL_WINDOW_COVERING_MODE_DEFAULT_VALUE, \ + }, \ + } +// clang-format on + +typedef struct zigbee_window_covering_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_groups_cluster_cfg_t groups_cfg; + esp_zb_scenes_cluster_cfg_t scenes_cfg; + esp_zb_window_covering_cluster_cfg_t window_covering_cfg; +} zigbee_window_covering_cfg_t; + +class ZigbeeWindowCovering : public ZigbeeEP { +public: + ZigbeeWindowCovering(uint8_t endpoint); + ~ZigbeeWindowCovering() {} + + // Set the callback functions for the window covering commands + void onOpen(void (*callback)()) { + _on_open = callback; + } + void onClose(void (*callback)()) { + _on_close = callback; + } + void onGoToLiftPercentage(void (*callback)(uint8_t)) { + _on_go_to_lift_percentage = callback; + } + void onGoToTiltPercentage(void (*callback)(uint8_t)) { + _on_go_to_tilt_percentage = callback; + } + void onStop(void (*callback)()) { + _on_stop = callback; + } + + // Set the window covering position in centimeters or percentage (0-100) + bool setLiftPosition(uint16_t lift_position); + bool setLiftPercentage(uint8_t lift_percentage); + bool setTiltPosition(uint16_t tilt_position); + bool setTiltPercentage(uint8_t tilt_percentage); + + // Set the window covering type (see ZigbeeWindowCoveringType) + bool setCoveringType(ZigbeeWindowCoveringType covering_type); + + // Set window covering config/status, for more info see esp_zb_zcl_window_covering_config_status_t + bool setConfigStatus( + bool operational, bool online, bool commands_reversed, bool lift_closed_loop, bool tilt_closed_loop, bool lift_encoder_controlled, + bool tilt_encoder_controlled + ); + + // Set configuration mode of window covering, for more info see esp_zb_zcl_window_covering_mode_t + bool setMode(bool motor_reversed, bool calibration_mode, bool maintenance_mode, bool leds_on); + + // Set limits of motion, for more info see esp_zb_zcl_window_covering_info_attr_t + bool setLimits( + uint16_t installed_open_limit_lift, uint16_t installed_closed_limit_lift, uint16_t installed_open_limit_tilt, uint16_t installed_closed_limit_tilt + ); + +private: + void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; + void zbWindowCoveringMovementCmd(const esp_zb_zcl_window_covering_movement_message_t *message) override; + + // Create window covering cluster list + esp_zb_cluster_list_t *zigbee_window_covering_clusters_create(zigbee_window_covering_cfg_t *window_covering_cfg); + + void open(); + void close(); + void goToLiftPercentage(uint8_t); + void goToTiltPercentage(uint8_t); + void stop(); + + // callback function to be called on lift percentage change (lift percentage) + void (*_on_open)(); + void (*_on_close)(); + void (*_on_go_to_lift_percentage)(uint8_t); + void (*_on_go_to_tilt_percentage)(uint8_t); + void (*_on_stop)(); + + // Widows covering lift attributes + uint8_t _current_lift_percentage; + uint16_t _current_lift_position; + uint16_t _installed_open_limit_lift; + uint16_t _installed_closed_limit_lift; + uint16_t _physical_closed_limit_lift; + + // Windows covering tilt attributes + uint8_t _current_tilt_percentage; + uint16_t _current_tilt_position; + uint16_t _installed_open_limit_tilt; + uint16_t _installed_closed_limit_tilt; + uint16_t _physical_closed_limit_tilt; +}; + +#endif // CONFIG_ZB_ENABLED diff --git a/package.json b/package.json index f261149b498..9c918733209 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "framework-arduinoespressif32", - "version": "3.0.1", - "description": "Arduino Wiring-based Framework for the Espressif ESP32, ESP32-S and ESP32-C series of SoCs", + "version": "3.2.0", + "description": "Arduino Wiring-based Framework for the Espressif ESP32, ESP32-P4, ESP32-S and ESP32-C series of SoCs", "keywords": [ "framework", "arduino", diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index b2e27bee7ef..19254d11682 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -26,13 +26,22 @@ "name": "ESP32 Dev Board" }, { - "name": "ESP32-S2 Dev Board" + "name": "ESP32-C3 Dev Board" }, { - "name": "ESP32-S3 Dev Board" + "name": "ESP32-C6 Dev Board" }, { - "name": "ESP32-C3 Dev Board" + "name": "ESP32-H2 Dev Board" + }, + { + "name": "ESP32-P4 Dev Board" + }, + { + "name": "ESP32-S2 Dev Board" + }, + { + "name": "ESP32-S3 Dev Board" }, { "name": "Arduino Nano ESP32" @@ -42,47 +51,37 @@ { "packager": "esp32", "name": "esp32-arduino-libs", - "version": "idf-release_v5.1-3f9ab2d6a6" - }, - { - "packager": "esp32", - "name": "xtensa-esp32-elf-gcc", - "version": "esp-12.2.0_20230208" - }, - { - "packager": "esp32", - "name": "xtensa-esp32s2-elf-gcc", - "version": "esp-12.2.0_20230208" + "version": "idf-release_v5.4-2f7dcd86-v1" }, { "packager": "esp32", - "name": "xtensa-esp32s3-elf-gcc", - "version": "esp-12.2.0_20230208" + "name": "xtensa-esp-elf-gcc", + "version": "esp-14.2.0_20241119" }, { "packager": "esp32", "name": "xtensa-esp-elf-gdb", - "version": "12.1_20231023" + "version": "14.2_20240403" }, { "packager": "esp32", "name": "riscv32-esp-elf-gcc", - "version": "esp-12.2.0_20230208" + "version": "esp-14.2.0_20241119" }, { "packager": "esp32", "name": "riscv32-esp-elf-gdb", - "version": "12.1_20231023" + "version": "14.2_20240403" }, { "packager": "esp32", "name": "openocd-esp32", - "version": "v0.12.0-esp32-20240318" + "version": "v0.12.0-esp32-20241016" }, { "packager": "esp32", "name": "esptool_py", - "version": "4.6" + "version": "4.9.dev3" }, { "packager": "esp32", @@ -105,545 +104,421 @@ "tools": [ { "name": "esp32-arduino-libs", - "version": "idf-release_v5.1-3f9ab2d6a6", + "version": "idf-release_v5.4-2f7dcd86-v1", "systems": [ { "host": "i686-mingw32", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6", - "archiveFileName": "esp32-arduino-libs-a6dac936bfcfa4c11468e003f550b41c76efeae6.zip", - "checksum": "SHA-256:b9173333fca2c6caa265dab050c62f1bb71e52dcb7cf21bd91b7fe1c37b3b444", - "size": "297521768" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.4/esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "checksum": "SHA-256:11f1271fe5e2857155d90384690069e4d33f0f97a4c04e7474b29a7cbc7ededd", + "size": "352347498" }, { "host": "x86_64-mingw32", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6", - "archiveFileName": "esp32-arduino-libs-a6dac936bfcfa4c11468e003f550b41c76efeae6.zip", - "checksum": "SHA-256:b9173333fca2c6caa265dab050c62f1bb71e52dcb7cf21bd91b7fe1c37b3b444", - "size": "297521768" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.4/esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "checksum": "SHA-256:11f1271fe5e2857155d90384690069e4d33f0f97a4c04e7474b29a7cbc7ededd", + "size": "352347498" }, { "host": "arm64-apple-darwin", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6", - "archiveFileName": "esp32-arduino-libs-a6dac936bfcfa4c11468e003f550b41c76efeae6.zip", - "checksum": "SHA-256:b9173333fca2c6caa265dab050c62f1bb71e52dcb7cf21bd91b7fe1c37b3b444", - "size": "297521768" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.4/esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "checksum": "SHA-256:11f1271fe5e2857155d90384690069e4d33f0f97a4c04e7474b29a7cbc7ededd", + "size": "352347498" }, { "host": "x86_64-apple-darwin", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6", - "archiveFileName": "esp32-arduino-libs-a6dac936bfcfa4c11468e003f550b41c76efeae6.zip", - "checksum": "SHA-256:b9173333fca2c6caa265dab050c62f1bb71e52dcb7cf21bd91b7fe1c37b3b444", - "size": "297521768" - }, - { - "host": "x86_64-pc-linux-gnu", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6", - "archiveFileName": "esp32-arduino-libs-a6dac936bfcfa4c11468e003f550b41c76efeae6.zip", - "checksum": "SHA-256:b9173333fca2c6caa265dab050c62f1bb71e52dcb7cf21bd91b7fe1c37b3b444", - "size": "297521768" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.4/esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "checksum": "SHA-256:11f1271fe5e2857155d90384690069e4d33f0f97a4c04e7474b29a7cbc7ededd", + "size": "352347498" }, - { - "host": "i686-pc-linux-gnu", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6", - "archiveFileName": "esp32-arduino-libs-a6dac936bfcfa4c11468e003f550b41c76efeae6.zip", - "checksum": "SHA-256:b9173333fca2c6caa265dab050c62f1bb71e52dcb7cf21bd91b7fe1c37b3b444", - "size": "297521768" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6", - "archiveFileName": "esp32-arduino-libs-a6dac936bfcfa4c11468e003f550b41c76efeae6.zip", - "checksum": "SHA-256:b9173333fca2c6caa265dab050c62f1bb71e52dcb7cf21bd91b7fe1c37b3b444", - "size": "297521768" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6", - "archiveFileName": "esp32-arduino-libs-a6dac936bfcfa4c11468e003f550b41c76efeae6.zip", - "checksum": "SHA-256:b9173333fca2c6caa265dab050c62f1bb71e52dcb7cf21bd91b7fe1c37b3b444", - "size": "297521768" - } - ] - }, - { - "name": "xtensa-esp32-elf-gcc", - "version": "esp-12.2.0_20230208", - "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:e8d35938385447cf9c34735fee2a3b2b61cca6be07db77a45856a1c2a347e423", - "size": "111766903" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:569988acfc2673369f222037c64bac96990cee08cebeebc4f8860e0d984f8bd9", - "size": "106473247" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:6a844f16021e936cc9b87b203978356f57ab2144554f6f2a0f73ffa3d3d316c5", - "size": "105576049" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.4/esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "checksum": "SHA-256:11f1271fe5e2857155d90384690069e4d33f0f97a4c04e7474b29a7cbc7ededd", + "size": "352347498" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "checksum": "SHA-256:743d6f03a89329bb09f9550d27fcab677f5cf06b4720793bbcef7883a932681d", - "size": "114870843" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "checksum": "SHA-256:4d32d764e984f3a570aacfb2f4957619540fb4629534d969b2e83997901334c3", - "size": "119424029" - }, - { - "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "checksum": "SHA-256:dc8fa7f4933bf5cb08e83bacce6160cc9dfe93d7aad1e8f92599bb81ff5b2e28", - "size": "106136827" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "checksum": "SHA-256:62bb6428d107ed3f44c212c77ecf24804b74c97327b0f0ad2029c656c6dbd6ee", - "size": "130847086" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "archiveFileName": "xtensa-esp32-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:8febfe4a6476efc69012390106c8c660a14418f025137b0513670c72124339cf", - "size": "134985117" - } - ] - }, - { - "name": "xtensa-esp32s2-elf-gcc", - "version": "esp-12.2.0_20230208", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:2ff838520a5003d2768b275f5bb5ead69dd2388c3b7cd9043cb59891ba43147f", - "size": "112199211" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.4/esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "checksum": "SHA-256:11f1271fe5e2857155d90384690069e4d33f0f97a4c04e7474b29a7cbc7ededd", + "size": "352347498" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:6d79d5b14fc7129a9b8208d54e19b05dedb565f50f7a96264c9df84b06ad3be0", - "size": "106953064" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.4/esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "checksum": "SHA-256:11f1271fe5e2857155d90384690069e4d33f0f97a4c04e7474b29a7cbc7ededd", + "size": "352347498" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:e5bd03b6ad19179b015a93ada9992adc3610036ebf6aeb0835a09c9aadb50a14", - "size": "106026829" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "checksum": "SHA-256:fb45943557b2d201bbb1bdc7514a1872f9bb96c2dfb48b95abdba281cc792f75", - "size": "115288662" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "checksum": "SHA-256:e965236cb80e45282d16f40184af183e013b63b177bd1884736c463eac636564", - "size": "119711811" - }, - { - "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "checksum": "SHA-256:78a55eec18650b21378d97494989ffe208748e0f49bb2b2d6756b264e1863919", - "size": "106540817" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "checksum": "SHA-256:1e6dac5162ab75f94b88c47ebeabb6600c652fb4f615ed07c1724d037c02fd19", - "size": "131273859" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s2-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "archiveFileName": "xtensa-esp32s2-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:8a785cc4e0838cebe404f82c0ead7a0f9ac5fabc660a742e33a41ddac6326cc1", - "size": "135373049" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.4/esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.4-2f7dcd86-v1.zip", + "checksum": "SHA-256:11f1271fe5e2857155d90384690069e4d33f0f97a4c04e7474b29a7cbc7ededd", + "size": "352347498" } ] }, { - "name": "xtensa-esp32s3-elf-gcc", - "version": "esp-12.2.0_20230208", + "name": "xtensa-esp-elf-gcc", + "version": "esp-14.2.0_20241119", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:61495ffe575e00c6998ae7274ff917658c04bded62ece0937c7042d6dcbf46de", - "size": "111971129" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-x86_64-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-x86_64-linux-gnu.tar.gz", + "checksum": "SHA-256:b1859df334a85541ae746e1b86439f59180d87f8cf1cc04c2e770fadf9f006e9", + "size": "323678089" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:9008d395be46fcfe68c7de6edc850fc1595f28323a28e7922e5c085bd310cb90", - "size": "106616800" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-aarch64-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-aarch64-linux-gnu.tar.gz", + "checksum": "SHA-256:7ff023033a5c00e55b9fc0a0b26d18fb0e476c24e24c5b0459bcb2e05a3729f1", + "size": "320064691" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:568857bdac7dea389dffc7fbc6871b4af299150a8ecf1bf965f224d2a1655edb", - "size": "105700326" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-arm-linux-gnueabi.tar.gz", + "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-arm-linux-gnueabi.tar.gz", + "checksum": "SHA-256:bb11dbf3ed25d4e0cc9e938749519e8236cfa2609e85742d311f1d869111805a", + "size": "319454139" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "checksum": "SHA-256:d122738bcc6c2f52d05fa89b2fb1afe6a7894cda8a07a1879aca867a31507ed0", - "size": "115098400" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-i586-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-i586-linux-gnu.tar.gz", + "checksum": "SHA-256:5ac611dca62ec791d413d1f417d566c444b006d2a4f97bd749b15f782d87249b", + "size": "328335914" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "checksum": "SHA-256:7defcddb98788b0991416ad2e0cb6a3b248b8030f22d5d76b8832117cc1494ca", - "size": "119883189" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-x86_64-apple-darwin_signed.tar.gz", + "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-x86_64-apple-darwin_signed.tar.gz", + "checksum": "SHA-256:15b3e60362028eaeff9156dc82dac3f1436b4aeef3920b28d7650974d8c34751", + "size": "336215844" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "checksum": "SHA-256:b59e076f8e4b9ca99535d449f9fc4cbb443188051dce4ad934e38f16b095f8d9", - "size": "106464677" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-aarch64-apple-darwin_signed.tar.gz", + "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-aarch64-apple-darwin_signed.tar.gz", + "checksum": "SHA-256:45c475518735133789bacccad31f872318b7ecc0b31cc9b7924aad880034f0bf", + "size": "318797396" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "checksum": "SHA-256:3ddf51774817e815e5d41c312a90c1159226978fb45fd0d4f7085c567f8b73ab", - "size": "131134034" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-i686-w64-mingw32.zip", + "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-i686-w64-mingw32.zip", + "checksum": "SHA-256:b30e450e0af279783c54a9ae77c3b367dd556b78eda930a92ec7b784a74c28c8", + "size": "382457717" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/xtensa-esp32s3-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "archiveFileName": "xtensa-esp32s3-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:1d15ca65e3508388a86d8bed3048c46d07538f5bc88d3e4296f9c03152087cd1", - "size": "135381926" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-x86_64-w64-mingw32.zip", + "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-x86_64-w64-mingw32.zip", + "checksum": "SHA-256:62ae704777d73c30689efff6e81178632a1ca44d1a2d60f4621eb997e040e028", + "size": "386316009" } ] }, { "name": "xtensa-esp-elf-gdb", - "version": "12.1_20231023", + "version": "14.2_20240403", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-x86_64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:d0743ec43cd92c35452a9097f7863281de4e72f04120d63cfbcf9d591a373529", - "size": "36942094" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-x86_64-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-x86_64-linux-gnu.tar.gz", + "checksum": "SHA-256:9d68472d4cba5cf8c2b79d94f86f92c828e76a632bd1e6be5e7706e5b304d36e", + "size": "31010320" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-aarch64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:bc1fac0366c6a08e26c45896ca21c8c90efc2cdd431b8ba084e8772e15502d0e", - "size": "37134601" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-aarch64-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-aarch64-linux-gnu.tar.gz", + "checksum": "SHA-256:bdabc3217994815fc311c4e16e588b78f6596b5ad4ffa46c80b40e982cfb1e66", + "size": "30954580" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-arm-linux-gnueabi.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:25efc51d52b71f097ccec763c5c885c8f5026b432fec4b5badd6a5f36fe34d04", - "size": "34579556" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-arm-linux-gnueabi.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-arm-linux-gnueabi.tar.gz", + "checksum": "SHA-256:d54b8d703ba897b28c627da3d27106a3906dd01ba298778a67064710bc33c76d", + "size": "28697281" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-i586-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-i586-linux-gnu.tar.gz", - "checksum": "SHA-256:e0af0b3b4a6b29a843cd5f47e331a966d9258f7d825b4656c6251490f71b05b2", - "size": "35676578" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-i586-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-i586-linux-gnu.tar.gz", + "checksum": "SHA-256:64d3bc992ed8fdec383d49e8b803ac494605a38117c8293db8da055037de96b0", + "size": "29890994" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-x86_64-apple-darwin14.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-x86_64-apple-darwin14.tar.gz", - "checksum": "SHA-256:bd146fd99a52b2d71c7ce0f62b9e18f3423d6cae7b2b2c954046b0dd7a23142f", - "size": "52863941" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-x86_64-apple-darwin14.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-x86_64-apple-darwin14.tar.gz", + "checksum": "SHA-256:023e74b3fda793da4bc0509b02de776ee0dad6efaaac17bef5916fb7dc9c26b9", + "size": "44446611" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-aarch64-apple-darwin21.1.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-aarch64-apple-darwin21.1.tar.gz", - "checksum": "SHA-256:5edc76565bf9d2fadf24e443ddf3df7567354f336a65d4af5b2ee805cdfcec24", - "size": "33504923" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-aarch64-apple-darwin21.1.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-aarch64-apple-darwin21.1.tar.gz", + "checksum": "SHA-256:ea757c6bf8c25238f6d2fdcc6bbab25a1b00608a0f9e19b7ddd2f37ddbdc3fb1", + "size": "37021423" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-i686-w64-mingw32.zip", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-i686-w64-mingw32.zip", - "checksum": "SHA-256:ea4f3ee6b95ad1ad2e07108a21a50037a3e64a420cdeb34b2ba95d612faed898", - "size": "31068749" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-i686-w64-mingw32.zip", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-i686-w64-mingw32.zip", + "checksum": "SHA-256:322e8d9b700dc32d8158e3dc55fb85ec55de48d0bb7789375ee39a28d5d655e2", + "size": "26302466" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/xtensa-esp-elf-gdb-12.1_20231023-x86_64-w64-mingw32.zip", - "archiveFileName": "xtensa-esp-elf-gdb-12.1_20231023-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:13bb97f39173948d1cfb6e651d9b335ea9d52f1fdd0dda1eda3a2d23d8c63644", - "size": "33514906" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/xtensa-esp-elf-gdb-14.2_20240403-x86_64-w64-mingw32.zip", + "archiveFileName": "xtensa-esp-elf-gdb-14.2_20240403-x86_64-w64-mingw32.zip", + "checksum": "SHA-256:a27a2fe20f192f8e0a51b8936428b4e1cf8935cfe008ee445cc49f6fc7f6db2e", + "size": "28366035" } ] }, { "name": "riscv32-esp-elf-gcc", - "version": "esp-12.2.0_20230208", + "version": "esp-14.2.0_20241119", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:1eb0d65990547ee9706b90406600cbc3638814d5feb7c1f7b44bb5416478a5bd", - "size": "257615266" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-x86_64-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-x86_64-linux-gnu.tar.gz", + "checksum": "SHA-256:a16942465d33c7f0334c16e83bc6feb62e06eeb79cf19099293480bb8d48c0cd", + "size": "593721156" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:921fcdc170c7fe5d6a0a30470ed1875c8926d910c19739fc950c8d1836e4c1c5", - "size": "253094184" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-aarch64-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-aarch64-linux-gnu.tar.gz", + "checksum": "SHA-256:22486233d0e0fd58a54ae453b701f195f1432fc6f2e17085b9d6c8d5d9acefb7", + "size": "587879927" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:f66e06312b58251c2121c1b1df1102565708573b86b2a9fe0c03ea1b0e9a7511", - "size": "252558021" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-arm-linux-gnueabi.tar.gz", + "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-arm-linux-gnueabi.tar.gz", + "checksum": "SHA-256:27a72d5d96cdb56dae2a1da5dfde1717c18a8c1f9a1454c8e34a8bd34abe662d", + "size": "586531522" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-i686-linux-gnu.tar.gz", - "checksum": "SHA-256:8abcac0331ef8973d1c705e77523364ebec7e98b37640d4a1d036912f3cbe946", - "size": "261248375" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-i586-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-i586-linux-gnu.tar.gz", + "checksum": "SHA-256:b7bd6e4cd53a4c55831d48e96a3d500bfffb091bec84a30bc8c3ad687e3eb3a2", + "size": "597070471" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-x86_64-apple-darwin.tar.gz", - "checksum": "SHA-256:76a334bc75a4e3891c222c84d7968817f2d0699d2976fc2a1658e56395283bec", - "size": "268987133" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-x86_64-apple-darwin_signed.tar.gz", + "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-x86_64-apple-darwin_signed.tar.gz", + "checksum": "SHA-256:5f8b571e1aedbe9f856f3bdeca6600cd5510ccff1ca102c4f001421eda560585", + "size": "602343061" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-aarch64-apple-darwin.tar.gz", - "checksum": "SHA-256:f30571945b257a10a26901bba3c5892e07c192aacf9ed6e8fcd11ca36ed827d2", - "size": "252159713" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-aarch64-apple-darwin_signed.tar.gz", + "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-aarch64-apple-darwin_signed.tar.gz", + "checksum": "SHA-256:a7276042a7eb2d33c2dff7167539e445c32c07d43a2c6827e86d035642503e0b", + "size": "578521565" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-i686-w64-mingw32.zip", - "checksum": "SHA-256:a5dfbb6dbf6fc6c6ea9beb2723af059ba3c5b2c86c2f0dc3b21afdc7bb229bf5", - "size": "324863847" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-i686-w64-mingw32.zip", + "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-i686-w64-mingw32.zip", + "checksum": "SHA-256:54193a97bd75205678ead8d11f00b351cfa3c2a6e5ab5d966341358b9f9422d7", + "size": "672055172" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-12.2.0_20230208/riscv32-esp-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "archiveFileName": "riscv32-esp-elf-12.2.0_20230208-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:9deae9e0013b2f7bbf017f9c8135755bfa89522f337c7dca35872bf12ec08176", - "size": "328092732" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-x86_64-w64-mingw32.zip", + "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-x86_64-w64-mingw32.zip", + "checksum": "SHA-256:24c8407fa467448d394e0639436a5ede31caf1838e35e8435e19df58ebed438c", + "size": "677812937" } ] }, { "name": "riscv32-esp-elf-gdb", - "version": "12.1_20231023", + "version": "14.2_20240403", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-x86_64-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:2c78b806be176b1e449e07ff83429d38dfc39a13f89a127ac1ffa6c1230537a0", - "size": "36630145" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-x86_64-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-x86_64-linux-gnu.tar.gz", + "checksum": "SHA-256:ce004bc0bbd71b246800d2d13b239218b272a38bd528e316f21f1af2db8a4b13", + "size": "30707431" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-aarch64-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:33f80117c8777aaff9179e27953e41764c5c46b3c576dc96a37ecc7a368807ec", - "size": "36980143" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-aarch64-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-aarch64-linux-gnu.tar.gz", + "checksum": "SHA-256:ba10f2866c61410b88c65957274280b1a62e3bed05131654ed9b6758efe18e55", + "size": "30824065" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-arm-linux-gnueabi.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:292e6ec0a9381c1480bbadf5caae25e86428b68fb5d030c9be7deda5e7f070e0", - "size": "34950318" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-arm-linux-gnueabi.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-arm-linux-gnueabi.tar.gz", + "checksum": "SHA-256:88539db5d987f28827efac7e26080a2803b9b539342ccd2963ccfdd56d7f08f7", + "size": "29000575" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-i586-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-i586-linux-gnu.tar.gz", - "checksum": "SHA-256:68a25fbcfc6371ec4dbe503ec92211977eb2006f0c29e67dbce6b93c70c6b7ec", - "size": "35801607" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-i586-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-i586-linux-gnu.tar.gz", + "checksum": "SHA-256:0e628ee37438ab6ba05eb889a76d09e50cb98e0020a16b8e2b935c5cf19b4ed2", + "size": "29947521" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-x86_64-apple-darwin14.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-x86_64-apple-darwin14.tar.gz", - "checksum": "SHA-256:322c722e6c12225ed8cd97f95a0375105756dc5113d369958ce0858ad1a90257", - "size": "52618688" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-x86_64-apple-darwin14.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-x86_64-apple-darwin14.tar.gz", + "checksum": "SHA-256:8f6bda832d70dad5860a639d55aba4237bd10cbac9f4822db1eece97357b34a9", + "size": "44196117" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-aarch64-apple-darwin21.1.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-aarch64-apple-darwin21.1.tar.gz", - "checksum": "SHA-256:c2224b3a8d02451c530cf004c29653292d963a1b4021b4b472b862b6dbe97e0b", - "size": "33149392" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-aarch64-apple-darwin21.1.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-aarch64-apple-darwin21.1.tar.gz", + "checksum": "SHA-256:d88b6116e86456c8480ce9bc95aed375a35c0d091f1da0a53b86be0e6ef3d320", + "size": "36794404" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-i686-w64-mingw32.zip", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-i686-w64-mingw32.zip", - "checksum": "SHA-256:4b42149a99dd87ee7e6dde25c99bad966c7f964253fa8f771593d7cef69f5602", - "size": "31635103" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-i686-w64-mingw32.zip", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-i686-w64-mingw32.zip", + "checksum": "SHA-256:d6e7ce05805b0d8d4dd138ad239b98a1adf8da98941867d60760eb1ae5361730", + "size": "26486295" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20231023/riscv32-esp-elf-gdb-12.1_20231023-x86_64-w64-mingw32.zip", - "archiveFileName": "riscv32-esp-elf-gdb-12.1_20231023-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:728231546ad5006d34463f972658b2a89e52f660a42abab08a29bedd4a8046ad", - "size": "33400816" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v14.2_20240403/riscv32-esp-elf-gdb-14.2_20240403-x86_64-w64-mingw32.zip", + "archiveFileName": "riscv32-esp-elf-gdb-14.2_20240403-x86_64-w64-mingw32.zip", + "checksum": "SHA-256:5c9f211dc46daf6b96fad09d709284a0f0186fef8947d9f6edd6bca5b5ad4317", + "size": "27942579" } ] }, { "name": "openocd-esp32", - "version": "v0.12.0-esp32-20240318", + "version": "v0.12.0-esp32-20241016", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-linux-amd64-0.12.0-esp32-20240318.tar.gz", - "archiveFileName": "openocd-esp32-linux-amd64-0.12.0-esp32-20240318.tar.gz", - "checksum": "SHA-256:cf26c5cef4f6b04aa23cd2778675604e5a74a4ce4d8d17b854d05fbcb782d52c", - "size": "2252682" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-linux-amd64-0.12.0-esp32-20241016.tar.gz", + "archiveFileName": "openocd-esp32-linux-amd64-0.12.0-esp32-20241016.tar.gz", + "checksum": "SHA-256:e82b0f036dc99244bead5f09a86e91bb2365cbcd1122ac68261e5647942485df", + "size": "2398717" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-linux-arm64-0.12.0-esp32-20240318.tar.gz", - "archiveFileName": "openocd-esp32-linux-arm64-0.12.0-esp32-20240318.tar.gz", - "checksum": "SHA-256:9b97a37aa2cab94424a778c25c0b4aa0f90d6ef9cda764a1d9289d061305f4b7", - "size": "2132904" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-linux-arm64-0.12.0-esp32-20241016.tar.gz", + "archiveFileName": "openocd-esp32-linux-arm64-0.12.0-esp32-20241016.tar.gz", + "checksum": "SHA-256:8f8daf5bd22ec5d2fa9257b0862ec33da18ee677e023fb9a9eb17f74ce208c76", + "size": "2271584" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-linux-armel-0.12.0-esp32-20240318.tar.gz", - "archiveFileName": "openocd-esp32-linux-armel-0.12.0-esp32-20240318.tar.gz", - "checksum": "SHA-256:b7e82776ec374983807d3389df09c632ad9bc8341f2075690b6b500319dfeaf4", - "size": "2271761" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-linux-armel-0.12.0-esp32-20241016.tar.gz", + "archiveFileName": "openocd-esp32-linux-armel-0.12.0-esp32-20241016.tar.gz", + "checksum": "SHA-256:bc9c020ecf20e2000f76cffa44305fd5bc44d2e688ea78cce423399d33f19767", + "size": "2414206" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-macos-0.12.0-esp32-20240318.tar.gz", - "archiveFileName": "openocd-esp32-macos-0.12.0-esp32-20240318.tar.gz", - "checksum": "SHA-256:b16c3082c94df1079367c44d99f7a8605534cd48aabc18898e46e94a2c8c57e7", - "size": "2365588" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-macos-0.12.0-esp32-20241016.tar.gz", + "archiveFileName": "openocd-esp32-macos-0.12.0-esp32-20241016.tar.gz", + "checksum": "SHA-256:02a2dffe801a2d005fa9e614d80ff8173395b2cb0b5d3118d0229d094a9946a7", + "size": "2508089" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-macos-arm64-0.12.0-esp32-20240318.tar.gz", - "archiveFileName": "openocd-esp32-macos-arm64-0.12.0-esp32-20240318.tar.gz", - "checksum": "SHA-256:534ec925ae6e35e869e4e4e6e4d2c4a1eb081f97ebcc2dd5efdc52d12f4c2f86", - "size": "2406377" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-macos-arm64-0.12.0-esp32-20241016.tar.gz", + "archiveFileName": "openocd-esp32-macos-arm64-0.12.0-esp32-20241016.tar.gz", + "checksum": "SHA-256:c382f9e884d6565cb6089bff5f200f4810994667d885f062c3d3c5625a0fa9d6", + "size": "2552569" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-win32-0.12.0-esp32-20240318.zip", - "archiveFileName": "openocd-esp32-win32-0.12.0-esp32-20240318.zip", - "checksum": "SHA-256:d379329eba052435173ab0d69c9b15bc164a6ce489e2a67cd11169d2dabff633", - "size": "2783915" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-win32-0.12.0-esp32-20241016.zip", + "archiveFileName": "openocd-esp32-win32-0.12.0-esp32-20241016.zip", + "checksum": "SHA-256:3b5d615e0a72cc771a45dd469031312d5881c01d7b6bc9edb29b8b6bda8c2e90", + "size": "2946244" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20240318/openocd-esp32-win32-0.12.0-esp32-20240318.zip", - "archiveFileName": "openocd-esp32-win32-0.12.0-esp32-20240318.zip", - "checksum": "SHA-256:d379329eba052435173ab0d69c9b15bc164a6ce489e2a67cd11169d2dabff633", - "size": "2783915" + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.12.0-esp32-20241016/openocd-esp32-win64-0.12.0-esp32-20241016.zip", + "archiveFileName": "openocd-esp32-win64-0.12.0-esp32-20241016.zip", + "checksum": "SHA-256:5e7b2fd1947d3a8625f6a11db7a2340cf2f41ff4c61284c022c7d7c32b18780a", + "size": "2946244" } ] }, { "name": "esptool_py", - "version": "4.6", + "version": "4.9.dev3", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-src.tar.gz", - "archiveFileName": "esptool-v4.6-src.tar.gz", - "checksum": "SHA-256:22f9bad0cd1cea14e554ac1f4a6d8f67415ff7029a66ce9130756276e7264e5a", - "size": "99141" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-linux-amd64.tar.gz", + "archiveFileName": "esptool-v4.9.dev3-linux-amd64.tar.gz", + "checksum": "SHA-256:4ecaf51836cbf4ea3c19840018bfef3b0b8cd8fc3c95f6e1e043ca5bbeab9bf0", + "size": "64958202" }, { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-src.tar.gz", - "archiveFileName": "esptool-v4.6-src.tar.gz", - "checksum": "SHA-256:22f9bad0cd1cea14e554ac1f4a6d8f67415ff7029a66ce9130756276e7264e5a", - "size": "99141" + "host": "arm-linux-gnueabihf", + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-linux-armv7.tar.gz", + "archiveFileName": "esptool-v4.9.dev3-linux-armv7.tar.gz", + "checksum": "SHA-256:fff818573bce483ee793ac83c8211f6abf764aa3350f198228859f696a0a0b36", + "size": "31530030" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-src.tar.gz", - "archiveFileName": "esptool-v4.6-src.tar.gz", - "checksum": "SHA-256:22f9bad0cd1cea14e554ac1f4a6d8f67415ff7029a66ce9130756276e7264e5a", - "size": "99141" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-src.tar.gz", - "archiveFileName": "esptool-v4.6-src.tar.gz", - "checksum": "SHA-256:22f9bad0cd1cea14e554ac1f4a6d8f67415ff7029a66ce9130756276e7264e5a", - "size": "99141" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-linux-aarch64.tar.gz", + "archiveFileName": "esptool-v4.9.dev3-linux-aarch64.tar.gz", + "checksum": "SHA-256:5b274bdff2f62e6a07c3c1dfa51b1128924621f661747eca3dbe0f77972f2f06", + "size": "33663882" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-macos.tar.gz", - "archiveFileName": "esptool-v4.6-macos.tar.gz", - "checksum": "SHA-256:885ec69fcffdcb9e7c6eacd2589f13a45ce6bcb6742bea368ec3a73bcca6dd59", - "size": "5851297" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-macos-amd64.tar.gz", + "archiveFileName": "esptool-v4.9.dev3-macos-amd64.tar.gz", + "checksum": "SHA-256:c733c83b58fcf5f642fbb2fddb8ff24640c2c785126cba0821fb70c4a5ceea7a", + "size": "32767836" }, { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-win64.zip", - "archiveFileName": "esptool-v4.6-win64.zip", - "checksum": "SHA-256:c7c68cd1aa520cbfce488ff6a77818ece272272eb012831b9d9ab1280a7c393f", - "size": "6638480" + "host": "arm64-apple-darwin", + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-macos-arm64.tar.gz", + "archiveFileName": "esptool-v4.9.dev3-macos-arm64.tar.gz", + "checksum": "SHA-256:83c195a15981e6a5e7a130db2ccfb21e2d8093912e5b003681f9a5abadd71af7", + "size": "30121441" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.9/esptool-v4.6-win64.zip", - "archiveFileName": "esptool-v4.6-win64.zip", - "checksum": "SHA-256:c7c68cd1aa520cbfce488ff6a77818ece272272eb012831b9d9ab1280a7c393f", - "size": "6638480" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-win64.zip", + "archiveFileName": "esptool-v4.9.dev3-win64.zip", + "checksum": "SHA-256:890051a4fdc684ff6f4af18d0bb27d274ca940ee0eef716a9455f8c64b25b215", + "size": "36072564" + }, + { + "host": "x86_64-mingw32", + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-win64.zip", + "archiveFileName": "esptool-v4.9.dev3-win64.zip", + "checksum": "SHA-256:890051a4fdc684ff6f4af18d0bb27d274ca940ee0eef716a9455f8c64b25b215", + "size": "36072564" } ] }, diff --git a/platform.txt b/platform.txt index e9e284f833b..65be05b3bf4 100644 --- a/platform.txt +++ b/platform.txt @@ -1,18 +1,15 @@ name=ESP32 Arduino -version=3.0.1 +version=3.2.0 tools.esp32-arduino-libs.path={runtime.platform.path}/tools/esp32-arduino-libs tools.esp32-arduino-libs.path.windows={runtime.platform.path}\tools\esp32-arduino-libs -tools.xtensa-esp32-elf-gcc.path={runtime.platform.path}/tools/xtensa-esp32-elf -tools.xtensa-esp32s2-elf-gcc.path={runtime.platform.path}/tools/xtensa-esp32s2-elf -tools.xtensa-esp32s3-elf-gcc.path={runtime.platform.path}/tools/xtensa-esp32s3-elf +tools.xtensa-esp-elf-gcc.path={runtime.platform.path}/tools/xtensa-esp-elf tools.xtensa-esp-elf-gdb.path={runtime.platform.path}/tools/xtensa-esp-elf-gdb tools.riscv32-esp-elf-gcc.path={runtime.platform.path}/tools/riscv32-esp-elf tools.riscv32-esp-elf-gdb.path={runtime.platform.path}/tools/riscv32-esp-elf-gdb tools.esptool_py.path={runtime.platform.path}/tools/esptool tools.esptool_py.cmd=esptool -tools.esptool_py.cmd.linux=esptool.py tools.esptool_py.cmd.windows=esptool.exe tools.esptool_py.network_cmd=python3 "{runtime.platform.path}/tools/espota.py" -r @@ -27,7 +24,7 @@ tools.gen_esp32part.cmd.windows="{runtime.platform.path}\tools\gen_esp32part.exe tools.gen_insights_pkg.cmd=python3 "{runtime.platform.path}"/tools/gen_insights_package.py tools.gen_insights_pkg.cmd.windows="{runtime.platform.path}\tools\gen_insights_package.exe" -compiler.path={tools.{build.tarch}-{build.target}-elf-gcc.path}/bin/ +compiler.path={tools.{build.tarch}-esp-elf-gcc.path}/bin/ compiler.prefix={build.tarch}-{build.target}-elf- compiler.sdk.path={tools.esp32-arduino-libs.path}/{build.mcu} @@ -46,12 +43,16 @@ compiler.warning_flags.default= compiler.warning_flags.more=-Wall compiler.warning_flags.all=-Wall -Wextra +# Additional flags specific to Arduino (not based on IDF flags). +# Update tools/pioarduino-build.py when changing these flags. +compiler.common_werror_flags=-Werror=return-type + # Compile Flags compiler.cpreprocessor.flags="@{compiler.sdk.path}/flags/defines" "-I{build.source.path}" -iprefix "{compiler.sdk.path}/include/" "@{compiler.sdk.path}/flags/includes" "-I{compiler.sdk.path}/{build.memory_type}/include" -compiler.c.flags="@{compiler.sdk.path}/flags/c_flags" {compiler.warning_flags} {compiler.optimization_flags} -compiler.cpp.flags="@{compiler.sdk.path}/flags/cpp_flags" {compiler.warning_flags} {compiler.optimization_flags} -compiler.S.flags="@{compiler.sdk.path}/flags/S_flags" {compiler.warning_flags} {compiler.optimization_flags} -compiler.c.elf.flags="@{compiler.sdk.path}/flags/ld_flags" "@{compiler.sdk.path}/flags/ld_scripts" +compiler.c.flags=-MMD -c "@{compiler.sdk.path}/flags/c_flags" {compiler.warning_flags} {compiler.optimization_flags} {compiler.common_werror_flags} +compiler.cpp.flags=-MMD -c "@{compiler.sdk.path}/flags/cpp_flags" {compiler.warning_flags} {compiler.optimization_flags} {compiler.common_werror_flags} +compiler.S.flags=-MMD -c -x assembler-with-cpp "@{compiler.sdk.path}/flags/S_flags" {compiler.warning_flags} {compiler.optimization_flags} +compiler.c.elf.flags="-Wl,--Map={build.path}/{build.project_name}.map" "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.sdk.path}/{build.memory_type}" "-Wl,--wrap=esp_panic_handler" "@{compiler.sdk.path}/flags/ld_flags" "@{compiler.sdk.path}/flags/ld_scripts" compiler.c.elf.libs="@{compiler.sdk.path}/flags/ld_libs" compiler.ar.flags=cr @@ -65,10 +66,10 @@ compiler.ar.cmd={compiler.prefix}gcc-ar compiler.size.cmd={compiler.prefix}size # These can be overridden in platform.local.txt -compiler.c.extra_flags=-MMD -c -compiler.cpp.extra_flags=-MMD -c -compiler.S.extra_flags=-MMD -c -x assembler-with-cpp -compiler.c.elf.extra_flags="-Wl,--Map={build.path}/{build.project_name}.map" "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.sdk.path}/{build.memory_type}" "-Wl,--wrap=esp_panic_handler" +compiler.c.extra_flags= +compiler.cpp.extra_flags= +compiler.S.extra_flags= +compiler.c.elf.extra_flags= compiler.ar.extra_flags= compiler.objcopy.eep.extra_flags= compiler.elf2hex.extra_flags= @@ -82,6 +83,7 @@ build.extra_flags.esp32c2=-DARDUINO_USB_CDC_ON_BOOT=0 build.extra_flags.esp32c3=-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} build.extra_flags.esp32c6=-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} build.extra_flags.esp32h2=-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} +build.extra_flags.esp32p4=-DARDUINO_USB_MODE={build.usb_mode} -DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} -DARDUINO_USB_MSC_ON_BOOT={build.msc_on_boot} -DARDUINO_USB_DFU_ON_BOOT={build.dfu_on_boot} # This can be overriden in boards.txt build.zigbee_mode= @@ -99,7 +101,7 @@ build.code_debug=0 build.defines= build.loop_core= build.event_core= -build.extra_flags=-DARDUINO_HOST_OS="{runtime.os}" -DARDUINO_FQBN="{build.fqbn}" -DESP32 -DCORE_DEBUG_LEVEL={build.code_debug} {build.loop_core} {build.event_core} {build.defines} {build.extra_flags.{build.mcu}} {build.zigbee_mode} +build.extra_flags=-DARDUINO_HOST_OS="{runtime.os}" -DARDUINO_FQBN="{build.fqbn}" -DESP32=ESP32 -DCORE_DEBUG_LEVEL={build.code_debug} {build.loop_core} {build.event_core} {build.defines} {build.extra_flags.{build.mcu}} {build.zigbee_mode} build.extra_libs= build.memory_type={build.boot}_qspi @@ -119,7 +121,6 @@ recipe.hooks.prebuild.3.pattern.windows=cmd /c if not exist "{build.path}\partit # Check if custom bootloader exist: source > variant > build.boot recipe.hooks.prebuild.4.pattern_args=--chip {build.mcu} elf2image --flash_mode {build.flash_mode} --flash_freq {build.img_freq} --flash_size {build.flash_size} -o recipe.hooks.prebuild.4.pattern=/usr/bin/env bash -c "[ -f "{build.source.path}"/bootloader.bin ] && cp -f "{build.source.path}"/bootloader.bin "{build.path}"/{build.project_name}.bootloader.bin || ( [ -f "{build.variant.path}"/{build.custom_bootloader}.bin ] && cp "{build.variant.path}"/{build.custom_bootloader}.bin "{build.path}"/{build.project_name}.bootloader.bin || "{tools.esptool_py.path}"/{tools.esptool_py.cmd} {recipe.hooks.prebuild.4.pattern_args} "{build.path}"/{build.project_name}.bootloader.bin "{compiler.sdk.path}"/bin/bootloader_{build.boot}_{build.boot_freq}.elf )" -recipe.hooks.prebuild.4.pattern.linux=/usr/bin/env bash -c "[ -f "{build.source.path}"/bootloader.bin ] && cp -f "{build.source.path}"/bootloader.bin "{build.path}"/{build.project_name}.bootloader.bin || ( [ -f "{build.variant.path}"/{build.custom_bootloader}.bin ] && cp "{build.variant.path}"/{build.custom_bootloader}.bin "{build.path}"/{build.project_name}.bootloader.bin || python3 "{tools.esptool_py.path}"/{tools.esptool_py.cmd} {recipe.hooks.prebuild.4.pattern_args} "{build.path}"/{build.project_name}.bootloader.bin "{compiler.sdk.path}"/bin/bootloader_{build.boot}_{build.boot_freq}.elf )" recipe.hooks.prebuild.4.pattern.windows=cmd /c IF EXIST "{build.source.path}\bootloader.bin" ( COPY /y "{build.source.path}\bootloader.bin" "{build.path}\{build.project_name}.bootloader.bin" ) ELSE ( IF EXIST "{build.variant.path}\{build.custom_bootloader}.bin" ( COPY "{build.variant.path}\{build.custom_bootloader}.bin" "{build.path}\{build.project_name}.bootloader.bin" ) ELSE ( "{tools.esptool_py.path}\{tools.esptool_py.cmd}" {recipe.hooks.prebuild.4.pattern_args} "{build.path}\{build.project_name}.bootloader.bin" "{compiler.sdk.path}\bin\bootloader_{build.boot}_{build.boot_freq}.elf" ) ) # Check if custom build options exist in the sketch folder @@ -139,6 +140,10 @@ recipe.hooks.prebuild.7.pattern.windows=cmd /c type nul > "{file_opts.path}" recipe.hooks.core.prebuild.1.pattern.windows=cmd /c echo "-DARDUINO_CORE_BUILD" > "{file_opts.path}" recipe.hooks.core.postbuild.1.pattern.windows=cmd /c type nul > "{file_opts.path}" +# Copy sdkconfig to build folder +recipe.hooks.prebuild.8.pattern=/usr/bin/env bash -c "cp -f "{compiler.sdk.path}"/sdkconfig "{build.path}"/sdkconfig" +recipe.hooks.prebuild.8.pattern.windows=cmd /c COPY /y "{compiler.sdk.path}\sdkconfig" "{build.path}\sdkconfig" + ## Compile c files recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.extra_flags} {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" -DARDUINO_VARIANT="{build.variant}" -DARDUINO_PARTITION_{build.partitions} {build.extra_flags} {compiler.cpreprocessor.flags} {includes} "@{build.opt.path}" "@{file_opts.path}" "{source_file}" -o "{object_file}" @@ -160,7 +165,6 @@ recipe.objcopy.partitions.bin.pattern={tools.gen_esp32part.cmd} -q "{build.path} ## Create bin recipe.objcopy.bin.pattern_args=--chip {build.mcu} elf2image --flash_mode "{build.flash_mode}" --flash_freq "{build.img_freq}" --flash_size "{build.flash_size}" --elf-sha256-offset 0xb0 -o "{build.path}/{build.project_name}.bin" "{build.path}/{build.project_name}.elf" recipe.objcopy.bin.pattern="{tools.esptool_py.path}/{tools.esptool_py.cmd}" {recipe.objcopy.bin.pattern_args} -recipe.objcopy.bin.pattern.linux=python3 "{tools.esptool_py.path}/{tools.esptool_py.cmd}" {recipe.objcopy.bin.pattern_args} ## Create Insights Firmware Package recipe.hooks.objcopy.postobjcopy.1.pattern_args={build.path} {build.project_name} "{build.source.path}" @@ -174,7 +178,6 @@ recipe.hooks.objcopy.postobjcopy.2.pattern.windows=cmd /c if exist "{build.path} # Create merged binary recipe.hooks.objcopy.postobjcopy.3.pattern_args=--chip {build.mcu} merge_bin -o "{build.path}/{build.project_name}.merged.bin" --fill-flash-size {build.flash_size} --flash_mode keep --flash_freq keep --flash_size keep {build.bootloader_addr} "{build.path}/{build.project_name}.bootloader.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin" 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0x10000 "{build.path}/{build.project_name}.bin" recipe.hooks.objcopy.postobjcopy.3.pattern="{tools.esptool_py.path}/{tools.esptool_py.cmd}" {recipe.hooks.objcopy.postobjcopy.3.pattern_args} -recipe.hooks.objcopy.postobjcopy.3.pattern.linux=python3 "{tools.esptool_py.path}/{tools.esptool_py.cmd}" {recipe.hooks.objcopy.postobjcopy.3.pattern_args} ## Save bin recipe.output.tmp_file={build.project_name}.bin @@ -182,8 +185,8 @@ recipe.output.save_file={build.project_name}.{build.variant}.bin ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -recipe.size.regex=^(?:\.iram0\.text|\.iram0\.vectors|\.dram0\.data|\.flash\.text|\.flash\.rodata|)\s+([0-9]+).* -recipe.size.regex.data=^(?:\.dram0\.data|\.dram0\.bss|\.noinit)\s+([0-9]+).* +recipe.size.regex=^(?:\.iram0\.text|\.iram0\.vectors|\.dram0\.data|\.dram1\.data|\.flash\.text|\.flash\.rodata|\.flash\.appdesc|\.flash\.init_array|\.eh_frame|)\s+([0-9]+).* +recipe.size.regex.data=^(?:\.dram0\.data|\.dram0\.bss|\.dram1\.data|\.dram1\.bss|\.noinit)\s+([0-9]+).* ## Required discoveries and monitors ## --------------------------------- @@ -284,7 +287,6 @@ tools.esptool_py.upload.params.verbose= tools.esptool_py.upload.params.quiet= tools.esptool_py.upload.pattern_args=--chip {build.mcu} --port "{serial.port}" --baud {upload.speed} {upload.flags} --before default_reset --after hard_reset write_flash {upload.erase_cmd} -z --flash_mode keep --flash_freq keep --flash_size keep {build.bootloader_addr} "{build.path}/{build.project_name}.bootloader.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin" 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0x10000 "{build.path}/{build.project_name}.bin" {upload.extra_flags} tools.esptool_py.upload.pattern="{path}/{cmd}" {upload.pattern_args} -tools.esptool_py.upload.pattern.linux=python3 "{path}/{cmd}" {upload.pattern_args} ## Program Application ## ------------------- @@ -292,7 +294,6 @@ tools.esptool_py.program.params.verbose= tools.esptool_py.program.params.quiet= tools.esptool_py.program.pattern_args=--chip {build.mcu} --port "{serial.port}" --baud {upload.speed} {upload.flags} --before default_reset --after hard_reset write_flash -z --flash_mode keep --flash_freq keep --flash_size keep 0x10000 "{build.path}/{build.project_name}.bin" tools.esptool_py.program.pattern="{path}/{cmd}" {program.pattern_args} -tools.esptool_py.program.pattern.linux=python3 "{path}/{cmd}" {program.pattern_args} ## Erase Chip (before burning the bootloader) ## ------------------------------------------ @@ -301,7 +302,6 @@ tools.esptool_py.erase.params.verbose= tools.esptool_py.erase.params.quiet= tools.esptool_py.erase.pattern_args=--chip {build.mcu} --port "{serial.port}" --baud {upload.speed} {upload.flags} --before default_reset --after hard_reset erase_flash tools.esptool_py.erase.pattern="{path}/{cmd}" {erase.pattern_args} -tools.esptool_py.erase.pattern.linux=python3 "{path}/{cmd}" {erase.pattern_args} ## Burn Bootloader ## --------------- @@ -321,7 +321,7 @@ tools.esptool_py.upload.network_pattern={network_cmd} -i "{serial.port}" -p "{ne tools.esp_ota.upload.protocol=network tools.esp_ota.upload.field.password=Password tools.esp_ota.upload.field.password.secret=true -tools.esp_ota.upload.pattern={cmd} -i {upload.port.address} -p {upload.port.properties.port} --auth={upload.field.password} -f "{build.path}/{build.project_name}.bin" +tools.esp_ota.upload.pattern={cmd} -i {upload.port.address} -p {upload.port.properties.port} "--auth={upload.field.password}" -f "{build.path}/{build.project_name}.bin" ## Upload Sketch Through DFU OTA ## ------------------------------------------- diff --git a/tests/performance/coremark/coremark.ino b/tests/performance/coremark/coremark.ino index 776db7874db..872b53050f0 100644 --- a/tests/performance/coremark/coremark.ino +++ b/tests/performance/coremark/coremark.ino @@ -40,7 +40,7 @@ void setup() { Serial.printf("Cores: %d\n", CONFIG_SOC_CPU_CORES_NUM); Serial.flush(); for (int i = 0; i < N_RUNS; i++) { - Serial.printf("Run %d", i); + Serial.printf("Run %d\n", i); coremark_main(); Serial.flush(); } diff --git a/tests/performance/fibonacci/fibonacci.ino b/tests/performance/fibonacci/fibonacci.ino index 01fd6f7bee2..c82fd6b70d8 100644 --- a/tests/performance/fibonacci/fibonacci.ino +++ b/tests/performance/fibonacci/fibonacci.ino @@ -31,7 +31,7 @@ void setup() { Serial.printf("N: %d\n", FIB_N); Serial.flush(); for (int i = 0; i < N_RUNS; i++) { - Serial.printf("Run %d", i); + Serial.printf("Run %d\n", i); unsigned long start = millis(); fibonacci = fib(FIB_N); unsigned long elapsed = millis() - start; diff --git a/tests/performance/fibonacci/test_fibonacci.py b/tests/performance/fibonacci/test_fibonacci.py index 622ea77ee4b..cf560d9691c 100644 --- a/tests/performance/fibonacci/test_fibonacci.py +++ b/tests/performance/fibonacci/test_fibonacci.py @@ -2,24 +2,22 @@ import logging import os +fib_results = {} + + +def fib(n): + if n < 2: + return n + elif str(n) in fib_results: + return fib_results[str(n)] + else: + fib_results[str(n)] = fib(n - 1) + fib(n - 2) + return fib_results[str(n)] + def test_fibonacci(dut, request): LOGGER = logging.getLogger(__name__) - # Fibonacci results starting from fib(35) to fib(45) - fib_results = [ - 9227465, - 14930352, - 24157817, - 39088169, - 63245986, - 102334155, - 165580141, - 267914296, - 433494437, - 701408733, - ] - # Match "Runs: %d" res = dut.expect(r"Runs: (\d+)", timeout=60) runs = int(res.group(0).decode("utf-8").split(" ")[1]) @@ -30,7 +28,11 @@ def test_fibonacci(dut, request): res = dut.expect(r"N: (\d+)", timeout=300) fib_n = int(res.group(0).decode("utf-8").split(" ")[1]) LOGGER.info("Calculating Fibonacci({})".format(fib_n)) - assert fib_n > 30 and fib_n < 50, "Invalid Fibonacci number" + assert fib_n > 0, "Invalid Fibonacci number" + + # Calculate Fibonacci results + expected_result = fib(fib_n) + LOGGER.info("Expected Fibonacci result: {}".format(expected_result)) list_time = [] @@ -48,7 +50,7 @@ def test_fibonacci(dut, request): assert fib_result > 0, "Invalid Fibonacci result" # Check if the result is correct - assert fib_result == fib_results[fib_n - 35] + assert fib_result == expected_result # Match "Time: %lu.%03lu s" res = dut.expect(r"Time: (\d+)\.(\d+) s", timeout=300) diff --git a/tests/performance/linpack_double/ci.json b/tests/performance/linpack_double/ci.json new file mode 100644 index 00000000000..accee2b2135 --- /dev/null +++ b/tests/performance/linpack_double/ci.json @@ -0,0 +1,6 @@ +{ + "platforms": { + "qemu": false, + "wokwi": false + } +} diff --git a/tests/performance/linpack_double/linpack_double.ino b/tests/performance/linpack_double/linpack_double.ino new file mode 100644 index 00000000000..5148b6ef591 --- /dev/null +++ b/tests/performance/linpack_double/linpack_double.ino @@ -0,0 +1,1094 @@ +/* + Linpack test for Arduino and ESP32. + Based on https://github.com/VioletGiraffe/EmbeddedLinpack + Created by Violet Giraffe, 2018 + Adapted by Lucas Saavedra Vaz, 2024 +*/ + +#include +#include + +// Number of runs to average +#define N_RUNS 1000 + +using floating_point_t = double; +bool type_float; + +floating_point_t benchmark(void); +floating_point_t cpu_time(void); +void daxpy(int n, floating_point_t da, floating_point_t dx[], int incx, floating_point_t dy[], int incy); +floating_point_t ddot(int n, floating_point_t dx[], int incx, floating_point_t dy[], int incy); +int dgefa(floating_point_t a[], int lda, int n, int ipvt[]); +void dgesl(floating_point_t a[], int lda, int n, int ipvt[], floating_point_t b[], int job); +void dscal(int n, floating_point_t sa, floating_point_t x[], int incx); +int idamax(int n, floating_point_t dx[], int incx); +floating_point_t r8_abs(floating_point_t x); +floating_point_t r8_epsilon(void); +floating_point_t r8_max(floating_point_t x, floating_point_t y); +floating_point_t r8_random(int iseed[4]); +void r8mat_gen(int lda, int n, floating_point_t *a); + +void setup() { + Serial.begin(115200); + while (!Serial) { + delay(10); + } + + String data_type; + + if (sizeof(floating_point_t) == sizeof(float)) { + data_type = "float"; + type_float = true; + } else if (sizeof(floating_point_t) == sizeof(double)) { + data_type = "double"; + type_float = false; + } else { + data_type = "unknown"; + log_e("Unknown data type size. Aborting."); + while (1); + } + + log_d("Starting Linpack %s test", data_type.c_str()); + Serial.printf("Runs: %d\n", N_RUNS); + Serial.printf("Type: %s\n", data_type.c_str()); + Serial.flush(); + int i = 0; + + floating_point_t minMflops = 1000000000.0, maxMflops = 0.0, avgMflops = 0.0; + for (i = 0; i < N_RUNS; ++i) { + Serial.printf("Run %d\n", i); + const auto mflops = benchmark(); + avgMflops += mflops; + minMflops = fmin(mflops, minMflops); + maxMflops = fmax(mflops, maxMflops); + Serial.flush(); + } + + avgMflops /= N_RUNS; + Serial.println(String("Runs completed: ") + i); + Serial.println(String("Average MFLOPS: ") + avgMflops); + Serial.println(String("Min MFLOPS: ") + minMflops); + Serial.println(String("Max MFLOPS: ") + maxMflops); + Serial.flush(); +} + +void loop() { + vTaskDelete(NULL); +} + +/******************************************************************************/ + +floating_point_t benchmark(void) + +/******************************************************************************/ +/* + Purpose: + + MAIN is the main program for LINPACK_BENCH. + + Discussion: + + LINPACK_BENCH drives the floating_point_t precision LINPACK benchmark program. + + Modified: + + 25 July 2008 + + Parameters: + + N is the problem size. +*/ +{ +#define N 8 +#define LDA (N + 1) + + static floating_point_t a[N * LDA]; + static floating_point_t a_max; + static floating_point_t b[N]; + static floating_point_t b_max; + const floating_point_t cray = 0.056; + static floating_point_t eps; + int i; + int info; + static int ipvt[N]; + int j; + int job; + floating_point_t ops; + static floating_point_t resid[N]; + floating_point_t resid_max; + [[maybe_unused]] + floating_point_t residn; + static floating_point_t rhs[N]; + floating_point_t t1; + floating_point_t t2; + static floating_point_t time[6]; + floating_point_t total; + floating_point_t x[N]; + + log_d("LINPACK_BENCH"); + log_d(" C version"); + log_d(" The LINPACK benchmark."); + log_d(" Language: C"); + if (!type_float) { + log_d(" Datatype: Double precision real"); + } else if (type_float) { + log_d(" Datatype: Single precision real"); + } else { + log_d(" Datatype: unknown"); + } + log_d(" Matrix order N = %d", N); + log_d(" Leading matrix dimension LDA = %d", LDA); + + ops = (floating_point_t)(2L * N * N * N) / 3.0 + 2.0 * (floating_point_t)((long)N * N); + + /* + Allocate space for arrays. +*/ + r8mat_gen(LDA, N, a); + + a_max = 0.0; + for (j = 0; j < N; j++) { + for (i = 0; i < N; i++) { + a_max = r8_max(a_max, a[i + j * LDA]); + } + } + + for (i = 0; i < N; i++) { + x[i] = 1.0; + } + + for (i = 0; i < N; i++) { + b[i] = 0.0; + for (j = 0; j < N; j++) { + b[i] = b[i] + a[i + j * LDA] * x[j]; + } + } + t1 = cpu_time(); + + info = dgefa(a, LDA, N, ipvt); + + if (info != 0) { + log_d("LINPACK_BENCH - Fatal error!"); + log_d(" The matrix A is apparently singular."); + log_d(" Abnormal end of execution."); + return 1; + } + + t2 = cpu_time(); + time[0] = t2 - t1; + + t1 = cpu_time(); + + job = 0; + dgesl(a, LDA, N, ipvt, b, job); + + t2 = cpu_time(); + time[1] = t2 - t1; + + total = time[0] + time[1]; + + /* + Compute a residual to verify results. +*/ + r8mat_gen(LDA, N, a); + + for (i = 0; i < N; i++) { + x[i] = 1.0; + } + + for (i = 0; i < N; i++) { + rhs[i] = 0.0; + for (j = 0; j < N; j++) { + rhs[i] = rhs[i] + a[i + j * LDA] * x[j]; + } + } + + for (i = 0; i < N; i++) { + resid[i] = -rhs[i]; + for (j = 0; j < N; j++) { + resid[i] = resid[i] + a[i + j * LDA] * b[j]; + } + } + + resid_max = 0.0; + for (i = 0; i < N; i++) { + resid_max = r8_max(resid_max, r8_abs(resid[i])); + } + + b_max = 0.0; + for (i = 0; i < N; i++) { + b_max = r8_max(b_max, r8_abs(b[i])); + } + + eps = r8_epsilon(); + + residn = resid_max / (floating_point_t)N / a_max / b_max / eps; + + time[2] = total; + if (0.0 < total) { + time[3] = ops / (1.0E+06 * total); + } else { + time[3] = -1.0; + } + time[4] = 2.0 / time[3]; + time[5] = total / cray; + + log_d(""); + log_d(" Norm. Resid Resid MACHEP X[1] X[N]"); + log_d(" %14f %14f %14e %14f %14f", residn, resid_max, eps, b[0], b[N - 1]); + log_d(""); + log_d(" Factor Solve Total MFLOPS Unit Cray-Ratio"); + log_d(" %9f %9f %9f %9f %9f %9f", time[0], time[1], time[2], time[3], time[4], time[5]); + + /* + Terminate. +*/ + log_d(""); + log_d("LINPACK_BENCH"); + log_d(" Normal end of execution."); + log_d(""); + + return time[3]; +#undef LDA +#undef N +} +/******************************************************************************/ + +floating_point_t cpu_time(void) + +/******************************************************************************/ +/* + Purpose: + + CPU_TIME returns the current reading on the CPU clock. + + Discussion: + + The CPU time measurements available through this routine are often + not very accurate. In some cases, the accuracy is no better than + a hundredth of a second. + + Licensing: + + This code is distributed under the GNU LGPL license. + + Modified: + + 06 June 2005 + + Author: + + John Burkardt + + Parameters: + + Output, floating_point_t CPU_TIME, the current reading of the CPU clock, in seconds. +*/ +{ + floating_point_t value; + + value = (floating_point_t)micros() / (floating_point_t)1000000; + + return value; +} +/******************************************************************************/ + +void daxpy(int n, floating_point_t da, floating_point_t dx[], int incx, floating_point_t dy[], int incy) + +/******************************************************************************/ +/* + Purpose: + + DAXPY computes constant times a vector plus a vector. + + Discussion: + + This routine uses unrolled loops for increments equal to one. + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of elements in DX and DY. + + Input, floating_point_t DA, the multiplier of DX. + + Input, floating_point_t DX[*], the first vector. + + Input, int INCX, the increment between successive entries of DX. + + Input/output, floating_point_t DY[*], the second vector. + On output, DY[*] has been replaced by DY[*] + DA * DX[*]. + + Input, int INCY, the increment between successive entries of DY. +*/ +{ + int i; + int ix; + int iy; + int m; + + if (n <= 0) { + return; + } + + if (da == 0.0) { + return; + } + /* + Code for unequal increments or equal increments + not equal to 1. +*/ + if (incx != 1 || incy != 1) { + if (0 <= incx) { + ix = 0; + } else { + ix = (-n + 1) * incx; + } + + if (0 <= incy) { + iy = 0; + } else { + iy = (-n + 1) * incy; + } + + for (i = 0; i < n; i++) { + dy[iy] = dy[iy] + da * dx[ix]; + ix = ix + incx; + iy = iy + incy; + } + } + /* + Code for both increments equal to 1. +*/ + else { + m = n % 4; + + for (i = 0; i < m; i++) { + dy[i] = dy[i] + da * dx[i]; + } + + for (i = m; i < n; i = i + 4) { + dy[i] = dy[i] + da * dx[i]; + dy[i + 1] = dy[i + 1] + da * dx[i + 1]; + dy[i + 2] = dy[i + 2] + da * dx[i + 2]; + dy[i + 3] = dy[i + 3] + da * dx[i + 3]; + } + } + return; +} +/******************************************************************************/ + +floating_point_t ddot(int n, floating_point_t dx[], int incx, floating_point_t dy[], int incy) + +/******************************************************************************/ +/* + Purpose: + + DDOT forms the dot product of two vectors. + + Discussion: + + This routine uses unrolled loops for increments equal to one. + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of entries in the vectors. + + Input, floating_point_t DX[*], the first vector. + + Input, int INCX, the increment between successive entries in DX. + + Input, floating_point_t DY[*], the second vector. + + Input, int INCY, the increment between successive entries in DY. + + Output, floating_point_t DDOT, the sum of the product of the corresponding + entries of DX and DY. +*/ +{ + floating_point_t dtemp; + int i; + int ix; + int iy; + int m; + + dtemp = 0.0; + + if (n <= 0) { + return dtemp; + } + /* + Code for unequal increments or equal increments + not equal to 1. +*/ + if (incx != 1 || incy != 1) { + if (0 <= incx) { + ix = 0; + } else { + ix = (-n + 1) * incx; + } + + if (0 <= incy) { + iy = 0; + } else { + iy = (-n + 1) * incy; + } + + for (i = 0; i < n; i++) { + dtemp = dtemp + dx[ix] * dy[iy]; + ix = ix + incx; + iy = iy + incy; + } + } + /* + Code for both increments equal to 1. +*/ + else { + m = n % 5; + + for (i = 0; i < m; i++) { + dtemp = dtemp + dx[i] * dy[i]; + } + + for (i = m; i < n; i = i + 5) { + dtemp = dtemp + dx[i] * dy[i] + dx[i + 1] * dy[i + 1] + dx[i + 2] * dy[i + 2] + dx[i + 3] * dy[i + 3] + dx[i + 4] * dy[i + 4]; + } + } + return dtemp; +} +/******************************************************************************/ + +int dgefa(floating_point_t a[], int lda, int n, int ipvt[]) + +/******************************************************************************/ +/* + Purpose: + + DGEFA factors a real general matrix. + + Modified: + + 16 May 2005 + + Author: + + C version by John Burkardt. + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart, + LINPACK User's Guide, + SIAM, (Society for Industrial and Applied Mathematics), + 3600 University City Science Center, + Philadelphia, PA, 19104-2688. + ISBN 0-89871-172-X + + Parameters: + + Input/output, floating_point_t A[LDA*N]. + On input, the matrix to be factored. + On output, an upper triangular matrix and the multipliers used to obtain + it. The factorization can be written A=L*U, where L is a product of + permutation and unit lower triangular matrices, and U is upper triangular. + + Input, int LDA, the leading dimension of A. + + Input, int N, the order of the matrix A. + + Output, int IPVT[N], the pivot indices. + + Output, int DGEFA, singularity indicator. + 0, normal value. + K, if U(K,K) == 0. This is not an error condition for this subroutine, + but it does indicate that DGESL or DGEDI will divide by zero if called. + Use RCOND in DGECO for a reliable indication of singularity. +*/ +{ + int info; + int j; + int k; + int l; + floating_point_t t; + /* + Gaussian elimination with partial pivoting. +*/ + info = 0; + + for (k = 1; k <= n - 1; k++) { + /* + Find L = pivot index. +*/ + l = idamax(n - k + 1, a + (k - 1) + (k - 1) * lda, 1) + k - 1; + ipvt[k - 1] = l; + /* + Zero pivot implies this column already triangularized. +*/ + if (a[l - 1 + (k - 1) * lda] == 0.0) { + info = k; + continue; + } + /* + Interchange if necessary. +*/ + if (l != k) { + t = a[l - 1 + (k - 1) * lda]; + a[l - 1 + (k - 1) * lda] = a[k - 1 + (k - 1) * lda]; + a[k - 1 + (k - 1) * lda] = t; + } + /* + Compute multipliers. +*/ + t = -1.0 / a[k - 1 + (k - 1) * lda]; + + dscal(n - k, t, a + k + (k - 1) * lda, 1); + /* + Row elimination with column indexing. +*/ + for (j = k + 1; j <= n; j++) { + t = a[l - 1 + (j - 1) * lda]; + if (l != k) { + a[l - 1 + (j - 1) * lda] = a[k - 1 + (j - 1) * lda]; + a[k - 1 + (j - 1) * lda] = t; + } + daxpy(n - k, t, a + k + (k - 1) * lda, 1, a + k + (j - 1) * lda, 1); + } + } + + ipvt[n - 1] = n; + + if (a[n - 1 + (n - 1) * lda] == 0.0) { + info = n; + } + + return info; +} +/******************************************************************************/ + +void dgesl(floating_point_t a[], int lda, int n, int ipvt[], floating_point_t b[], int job) + +/******************************************************************************/ +/* + Purpose: + + DGESL solves a real general linear system A * X = B. + + Discussion: + + DGESL can solve either of the systems A * X = B or A' * X = B. + + The system matrix must have been factored by DGECO or DGEFA. + + A division by zero will occur if the input factor contains a + zero on the diagonal. Technically this indicates singularity + but it is often caused by improper arguments or improper + setting of LDA. It will not occur if the subroutines are + called correctly and if DGECO has set 0.0 < RCOND + or DGEFA has set INFO == 0. + + Modified: + + 16 May 2005 + + Author: + + C version by John Burkardt. + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart, + LINPACK User's Guide, + SIAM, (Society for Industrial and Applied Mathematics), + 3600 University City Science Center, + Philadelphia, PA, 19104-2688. + ISBN 0-89871-172-X + + Parameters: + + Input, floating_point_t A[LDA*N], the output from DGECO or DGEFA. + + Input, int LDA, the leading dimension of A. + + Input, int N, the order of the matrix A. + + Input, int IPVT[N], the pivot vector from DGECO or DGEFA. + + Input/output, floating_point_t B[N]. + On input, the right hand side vector. + On output, the solution vector. + + Input, int JOB. + 0, solve A * X = B; + nonzero, solve A' * X = B. +*/ +{ + int k; + int l; + floating_point_t t; + /* + Solve A * X = B. +*/ + if (job == 0) { + for (k = 1; k <= n - 1; k++) { + l = ipvt[k - 1]; + t = b[l - 1]; + + if (l != k) { + b[l - 1] = b[k - 1]; + b[k - 1] = t; + } + + daxpy(n - k, t, a + k + (k - 1) * lda, 1, b + k, 1); + } + + for (k = n; 1 <= k; k--) { + b[k - 1] = b[k - 1] / a[k - 1 + (k - 1) * lda]; + t = -b[k - 1]; + daxpy(k - 1, t, a + 0 + (k - 1) * lda, 1, b, 1); + } + } + /* + Solve A' * X = B. +*/ + else { + for (k = 1; k <= n; k++) { + t = ddot(k - 1, a + 0 + (k - 1) * lda, 1, b, 1); + b[k - 1] = (b[k - 1] - t) / a[k - 1 + (k - 1) * lda]; + } + + for (k = n - 1; 1 <= k; k--) { + b[k - 1] = b[k - 1] + ddot(n - k, a + k + (k - 1) * lda, 1, b + k, 1); + l = ipvt[k - 1]; + + if (l != k) { + t = b[l - 1]; + b[l - 1] = b[k - 1]; + b[k - 1] = t; + } + } + } + return; +} +/******************************************************************************/ + +void dscal(int n, floating_point_t sa, floating_point_t x[], int incx) + +/******************************************************************************/ +/* + Purpose: + + DSCAL scales a vector by a constant. + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of entries in the vector. + + Input, floating_point_t SA, the multiplier. + + Input/output, floating_point_t X[*], the vector to be scaled. + + Input, int INCX, the increment between successive entries of X. +*/ +{ + int i; + int ix; + int m; + + if (n <= 0) { + } else if (incx == 1) { + m = n % 5; + + for (i = 0; i < m; i++) { + x[i] = sa * x[i]; + } + + for (i = m; i < n; i = i + 5) { + x[i] = sa * x[i]; + x[i + 1] = sa * x[i + 1]; + x[i + 2] = sa * x[i + 2]; + x[i + 3] = sa * x[i + 3]; + x[i + 4] = sa * x[i + 4]; + } + } else { + if (0 <= incx) { + ix = 0; + } else { + ix = (-n + 1) * incx; + } + + for (i = 0; i < n; i++) { + x[ix] = sa * x[ix]; + ix = ix + incx; + } + } + return; +} +/******************************************************************************/ + +int idamax(int n, floating_point_t dx[], int incx) + +/******************************************************************************/ +/* + Purpose: + + IDAMAX finds the index of the vector element of maximum absolute value. + + Discussion: + + WARNING: This index is a 1-based index, not a 0-based index! + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of entries in the vector. + + Input, floating_point_t X[*], the vector to be examined. + + Input, int INCX, the increment between successive entries of SX. + + Output, int IDAMAX, the index of the element of maximum + absolute value. +*/ +{ + floating_point_t dmax; + int i; + int ix; + int value; + + value = 0; + + if (n < 1 || incx <= 0) { + return value; + } + + value = 1; + + if (n == 1) { + return value; + } + + if (incx == 1) { + dmax = r8_abs(dx[0]); + + for (i = 1; i < n; i++) { + if (dmax < r8_abs(dx[i])) { + value = i + 1; + dmax = r8_abs(dx[i]); + } + } + } else { + ix = 0; + dmax = r8_abs(dx[0]); + ix = ix + incx; + + for (i = 1; i < n; i++) { + if (dmax < r8_abs(dx[ix])) { + value = i + 1; + dmax = r8_abs(dx[ix]); + } + ix = ix + incx; + } + } + + return value; +} +/******************************************************************************/ + +floating_point_t r8_abs(floating_point_t x) + +/******************************************************************************/ +/* + Purpose: + + R8_ABS returns the absolute value of a R8. + + Modified: + + 02 April 2005 + + Author: + + John Burkardt + + Parameters: + + Input, floating_point_t X, the quantity whose absolute value is desired. + + Output, floating_point_t R8_ABS, the absolute value of X. +*/ +{ + floating_point_t value; + + if (0.0 <= x) { + value = x; + } else { + value = -x; + } + return value; +} +/******************************************************************************/ + +floating_point_t r8_epsilon(void) + +/******************************************************************************/ +/* + Purpose: + + R8_EPSILON returns the R8 round off unit. + + Discussion: + + R8_EPSILON is a number R which is a power of 2 with the property that, + to the precision of the computer's arithmetic, + 1 < 1 + R + but + 1 = ( 1 + R / 2 ) + + Licensing: + + This code is distributed under the GNU LGPL license. + + Modified: + + 08 May 2006 + + Author: + + John Burkardt + + Parameters: + + Output, floating_point_t R8_EPSILON, the floating_point_t precision round-off unit. +*/ +{ + floating_point_t r; + + r = 1.0; + + while (1.0 < (floating_point_t)(1.0 + r)) { + r = r / 2.0; + } + r = 2.0 * r; + + return r; +} +/******************************************************************************/ + +floating_point_t r8_max(floating_point_t x, floating_point_t y) + +/******************************************************************************/ +/* + Purpose: + + R8_MAX returns the maximum of two R8's. + + Modified: + + 18 August 2004 + + Author: + + John Burkardt + + Parameters: + + Input, floating_point_t X, Y, the quantities to compare. + + Output, floating_point_t R8_MAX, the maximum of X and Y. +*/ +{ + floating_point_t value; + + if (y < x) { + value = x; + } else { + value = y; + } + return value; +} +/******************************************************************************/ + +floating_point_t r8_random(int iseed[4]) + +/******************************************************************************/ +/* + Purpose: + + R8_RANDOM returns a uniformly distributed random number between 0 and 1. + + Discussion: + + This routine uses a multiplicative congruential method with modulus + 2**48 and multiplier 33952834046453 (see G.S.Fishman, + 'Multiplicative congruential random number generators with modulus + 2**b: an exhaustive analysis for b = 32 and a partial analysis for + b = 48', Math. Comp. 189, pp 331-344, 1990). + + 48-bit integers are stored in 4 integer array elements with 12 bits + per element. Hence the routine is portable across machines with + integers of 32 bits or more. + + Parameters: + + Input/output, integer ISEED(4). + On entry, the seed of the random number generator; the array + elements must be between 0 and 4095, and ISEED(4) must be odd. + On exit, the seed is updated. + + Output, floating_point_t R8_RANDOM, the next pseudorandom number. +*/ +{ + int ipw2 = 4096; + int it1; + int it2; + int it3; + int it4; + int m1 = 494; + int m2 = 322; + int m3 = 2508; + int m4 = 2549; + floating_point_t r = 1.0 / 4096.0; + floating_point_t value; + /* + Multiply the seed by the multiplier modulo 2**48. +*/ + it4 = iseed[3] * m4; + it3 = it4 / ipw2; + it4 = it4 - ipw2 * it3; + it3 = it3 + iseed[2] * m4 + iseed[3] * m3; + it2 = it3 / ipw2; + it3 = it3 - ipw2 * it2; + it2 = it2 + iseed[1] * m4 + iseed[2] * m3 + iseed[3] * m2; + it1 = it2 / ipw2; + it2 = it2 - ipw2 * it1; + it1 = it1 + iseed[0] * m4 + iseed[1] * m3 + iseed[2] * m2 + iseed[3] * m1; + it1 = (it1 % ipw2); + /* + Return updated seed +*/ + iseed[0] = it1; + iseed[1] = it2; + iseed[2] = it3; + iseed[3] = it4; + /* + Convert 48-bit integer to a real number in the interval (0,1) +*/ + value = r * ((floating_point_t)(it1) + r * ((floating_point_t)(it2) + r * ((floating_point_t)(it3) + r * ((floating_point_t)(it4))))); + + return value; +} +/******************************************************************************/ + +void r8mat_gen(int lda, int n, floating_point_t *a) + +/******************************************************************************/ +/* + Purpose: + + R8MAT_GEN generates a random R8MAT. + + Modified: + + 06 June 2005 + + Parameters: + + Input, integer LDA, the leading dimension of the matrix. + + Input, integer N, the order of the matrix. + + Output, floating_point_t R8MAT_GEN[LDA*N], the N by N matrix. +*/ +{ + int i; + int init[4] = {1, 2, 3, 1325}; + int j; + + for (j = 1; j <= n; j++) { + for (i = 1; i <= n; i++) { + a[i - 1 + (j - 1) * lda] = r8_random(init) - 0.5; + } + } +} +/******************************************************************************/ diff --git a/tests/performance/linpack_double/test_linpack_double.py b/tests/performance/linpack_double/test_linpack_double.py new file mode 100644 index 00000000000..0a6e2f90ef3 --- /dev/null +++ b/tests/performance/linpack_double/test_linpack_double.py @@ -0,0 +1,61 @@ +import json +import logging +import os + + +def test_linpack_double(dut, request): + LOGGER = logging.getLogger(__name__) + + # Match "Runs: %d" + res = dut.expect(r"Runs: (\d+)", timeout=60) + runs = int(res.group(0).decode("utf-8").split(" ")[1]) + LOGGER.info("Number of runs: {}".format(runs)) + assert runs > 0, "Invalid number of runs" + + # Match "Type: %s" + res = dut.expect(r"Type: (\w+)", timeout=60) + data_type = res.group(0).decode("utf-8").split(" ")[1] + LOGGER.info("Data type: {}".format(data_type)) + assert data_type == "double", "Invalid data type" + + # Match "Runs completed: %d" + res = dut.expect(r"Runs completed: (\d+)", timeout=120) + runs_completed = int(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Runs completed: {}".format(runs_completed)) + assert runs_completed == runs, "Invalid number of runs completed" + + # Match "Average MFLOPS: %f" + res = dut.expect(r"Average MFLOPS: (\d+\.\d+)", timeout=120) + avg_score = float(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Average MFLOPS: {}".format(avg_score)) + assert avg_score > 0, "Invalid average MFLOPS" + + # Match "Min MFLOPS: %f" + res = dut.expect(r"Min MFLOPS: (\d+\.\d+)", timeout=120) + min_score = float(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Min MFLOPS: {}".format(min_score)) + assert min_score > 0 and min_score < 1000000000.0, "Invalid min MFLOPS" + + # Match "Max MFLOPS: %f" + res = dut.expect(r"Max MFLOPS: (\d+\.\d+)", timeout=120) + max_score = float(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Max MFLOPS: {}".format(max_score)) + assert max_score > 0, "Invalid max MFLOPS" + + # Create JSON with results and write it to file + # Always create a JSON with this format (so it can be merged later on): + # { TEST_NAME_STR: TEST_RESULTS_DICT } + results = {"linpack_double": {"runs": runs, "avg_score": avg_score, "min_score": min_score, "max_score": max_score}} + + current_folder = os.path.dirname(request.path) + file_index = 0 + report_file = os.path.join(current_folder, "result_linpack_double" + str(file_index) + ".json") + while os.path.exists(report_file): + report_file = report_file.replace(str(file_index) + ".json", str(file_index + 1) + ".json") + file_index += 1 + + with open(report_file, "w") as f: + try: + f.write(json.dumps(results)) + except Exception as e: + LOGGER.warning("Failed to write results to file: {}".format(e)) diff --git a/tests/performance/linpack_float/ci.json b/tests/performance/linpack_float/ci.json new file mode 100644 index 00000000000..accee2b2135 --- /dev/null +++ b/tests/performance/linpack_float/ci.json @@ -0,0 +1,6 @@ +{ + "platforms": { + "qemu": false, + "wokwi": false + } +} diff --git a/tests/performance/linpack_float/linpack_float.ino b/tests/performance/linpack_float/linpack_float.ino new file mode 100644 index 00000000000..24dd9e7c461 --- /dev/null +++ b/tests/performance/linpack_float/linpack_float.ino @@ -0,0 +1,1094 @@ +/* + Linpack test for Arduino and ESP32. + Based on https://github.com/VioletGiraffe/EmbeddedLinpack + Created by Violet Giraffe, 2018 + Adapted by Lucas Saavedra Vaz, 2024 +*/ + +#include +#include + +// Number of runs to average +#define N_RUNS 1000 + +using floating_point_t = float; +bool type_float; + +floating_point_t benchmark(void); +floating_point_t cpu_time(void); +void daxpy(int n, floating_point_t da, floating_point_t dx[], int incx, floating_point_t dy[], int incy); +floating_point_t ddot(int n, floating_point_t dx[], int incx, floating_point_t dy[], int incy); +int dgefa(floating_point_t a[], int lda, int n, int ipvt[]); +void dgesl(floating_point_t a[], int lda, int n, int ipvt[], floating_point_t b[], int job); +void dscal(int n, floating_point_t sa, floating_point_t x[], int incx); +int idamax(int n, floating_point_t dx[], int incx); +floating_point_t r8_abs(floating_point_t x); +floating_point_t r8_epsilon(void); +floating_point_t r8_max(floating_point_t x, floating_point_t y); +floating_point_t r8_random(int iseed[4]); +void r8mat_gen(int lda, int n, floating_point_t *a); + +void setup() { + Serial.begin(115200); + while (!Serial) { + delay(10); + } + + String data_type; + + if (sizeof(floating_point_t) == sizeof(float)) { + data_type = "float"; + type_float = true; + } else if (sizeof(floating_point_t) == sizeof(double)) { + data_type = "double"; + type_float = false; + } else { + data_type = "unknown"; + log_e("Unknown data type size. Aborting."); + while (1); + } + + log_d("Starting Linpack %s test", data_type.c_str()); + Serial.printf("Runs: %d\n", N_RUNS); + Serial.printf("Type: %s\n", data_type.c_str()); + Serial.flush(); + int i = 0; + + floating_point_t minMflops = 1000000000.0, maxMflops = 0.0, avgMflops = 0.0; + for (i = 0; i < N_RUNS; ++i) { + Serial.printf("Run %d\n", i); + const auto mflops = benchmark(); + avgMflops += mflops; + minMflops = fmin(mflops, minMflops); + maxMflops = fmax(mflops, maxMflops); + Serial.flush(); + } + + avgMflops /= N_RUNS; + Serial.println(String("Runs completed: ") + i); + Serial.println(String("Average MFLOPS: ") + avgMflops); + Serial.println(String("Min MFLOPS: ") + minMflops); + Serial.println(String("Max MFLOPS: ") + maxMflops); + Serial.flush(); +} + +void loop() { + vTaskDelete(NULL); +} + +/******************************************************************************/ + +floating_point_t benchmark(void) + +/******************************************************************************/ +/* + Purpose: + + MAIN is the main program for LINPACK_BENCH. + + Discussion: + + LINPACK_BENCH drives the floating_point_t precision LINPACK benchmark program. + + Modified: + + 25 July 2008 + + Parameters: + + N is the problem size. +*/ +{ +#define N 8 +#define LDA (N + 1) + + static floating_point_t a[N * LDA]; + static floating_point_t a_max; + static floating_point_t b[N]; + static floating_point_t b_max; + const floating_point_t cray = 0.056; + static floating_point_t eps; + int i; + int info; + static int ipvt[N]; + int j; + int job; + floating_point_t ops; + static floating_point_t resid[N]; + floating_point_t resid_max; + [[maybe_unused]] + floating_point_t residn; + static floating_point_t rhs[N]; + floating_point_t t1; + floating_point_t t2; + static floating_point_t time[6]; + floating_point_t total; + floating_point_t x[N]; + + log_d("LINPACK_BENCH"); + log_d(" C version"); + log_d(" The LINPACK benchmark."); + log_d(" Language: C"); + if (!type_float) { + log_d(" Datatype: Double precision real"); + } else if (type_float) { + log_d(" Datatype: Single precision real"); + } else { + log_d(" Datatype: unknown"); + } + log_d(" Matrix order N = %d", N); + log_d(" Leading matrix dimension LDA = %d", LDA); + + ops = (floating_point_t)(2L * N * N * N) / 3.0 + 2.0 * (floating_point_t)((long)N * N); + + /* + Allocate space for arrays. +*/ + r8mat_gen(LDA, N, a); + + a_max = 0.0; + for (j = 0; j < N; j++) { + for (i = 0; i < N; i++) { + a_max = r8_max(a_max, a[i + j * LDA]); + } + } + + for (i = 0; i < N; i++) { + x[i] = 1.0; + } + + for (i = 0; i < N; i++) { + b[i] = 0.0; + for (j = 0; j < N; j++) { + b[i] = b[i] + a[i + j * LDA] * x[j]; + } + } + t1 = cpu_time(); + + info = dgefa(a, LDA, N, ipvt); + + if (info != 0) { + log_d("LINPACK_BENCH - Fatal error!"); + log_d(" The matrix A is apparently singular."); + log_d(" Abnormal end of execution."); + return 1; + } + + t2 = cpu_time(); + time[0] = t2 - t1; + + t1 = cpu_time(); + + job = 0; + dgesl(a, LDA, N, ipvt, b, job); + + t2 = cpu_time(); + time[1] = t2 - t1; + + total = time[0] + time[1]; + + /* + Compute a residual to verify results. +*/ + r8mat_gen(LDA, N, a); + + for (i = 0; i < N; i++) { + x[i] = 1.0; + } + + for (i = 0; i < N; i++) { + rhs[i] = 0.0; + for (j = 0; j < N; j++) { + rhs[i] = rhs[i] + a[i + j * LDA] * x[j]; + } + } + + for (i = 0; i < N; i++) { + resid[i] = -rhs[i]; + for (j = 0; j < N; j++) { + resid[i] = resid[i] + a[i + j * LDA] * b[j]; + } + } + + resid_max = 0.0; + for (i = 0; i < N; i++) { + resid_max = r8_max(resid_max, r8_abs(resid[i])); + } + + b_max = 0.0; + for (i = 0; i < N; i++) { + b_max = r8_max(b_max, r8_abs(b[i])); + } + + eps = r8_epsilon(); + + residn = resid_max / (floating_point_t)N / a_max / b_max / eps; + + time[2] = total; + if (0.0 < total) { + time[3] = ops / (1.0E+06 * total); + } else { + time[3] = -1.0; + } + time[4] = 2.0 / time[3]; + time[5] = total / cray; + + log_d(""); + log_d(" Norm. Resid Resid MACHEP X[1] X[N]"); + log_d(" %14f %14f %14e %14f %14f", residn, resid_max, eps, b[0], b[N - 1]); + log_d(""); + log_d(" Factor Solve Total MFLOPS Unit Cray-Ratio"); + log_d(" %9f %9f %9f %9f %9f %9f", time[0], time[1], time[2], time[3], time[4], time[5]); + + /* + Terminate. +*/ + log_d(""); + log_d("LINPACK_BENCH"); + log_d(" Normal end of execution."); + log_d(""); + + return time[3]; +#undef LDA +#undef N +} +/******************************************************************************/ + +floating_point_t cpu_time(void) + +/******************************************************************************/ +/* + Purpose: + + CPU_TIME returns the current reading on the CPU clock. + + Discussion: + + The CPU time measurements available through this routine are often + not very accurate. In some cases, the accuracy is no better than + a hundredth of a second. + + Licensing: + + This code is distributed under the GNU LGPL license. + + Modified: + + 06 June 2005 + + Author: + + John Burkardt + + Parameters: + + Output, floating_point_t CPU_TIME, the current reading of the CPU clock, in seconds. +*/ +{ + floating_point_t value; + + value = (floating_point_t)micros() / (floating_point_t)1000000; + + return value; +} +/******************************************************************************/ + +void daxpy(int n, floating_point_t da, floating_point_t dx[], int incx, floating_point_t dy[], int incy) + +/******************************************************************************/ +/* + Purpose: + + DAXPY computes constant times a vector plus a vector. + + Discussion: + + This routine uses unrolled loops for increments equal to one. + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of elements in DX and DY. + + Input, floating_point_t DA, the multiplier of DX. + + Input, floating_point_t DX[*], the first vector. + + Input, int INCX, the increment between successive entries of DX. + + Input/output, floating_point_t DY[*], the second vector. + On output, DY[*] has been replaced by DY[*] + DA * DX[*]. + + Input, int INCY, the increment between successive entries of DY. +*/ +{ + int i; + int ix; + int iy; + int m; + + if (n <= 0) { + return; + } + + if (da == 0.0) { + return; + } + /* + Code for unequal increments or equal increments + not equal to 1. +*/ + if (incx != 1 || incy != 1) { + if (0 <= incx) { + ix = 0; + } else { + ix = (-n + 1) * incx; + } + + if (0 <= incy) { + iy = 0; + } else { + iy = (-n + 1) * incy; + } + + for (i = 0; i < n; i++) { + dy[iy] = dy[iy] + da * dx[ix]; + ix = ix + incx; + iy = iy + incy; + } + } + /* + Code for both increments equal to 1. +*/ + else { + m = n % 4; + + for (i = 0; i < m; i++) { + dy[i] = dy[i] + da * dx[i]; + } + + for (i = m; i < n; i = i + 4) { + dy[i] = dy[i] + da * dx[i]; + dy[i + 1] = dy[i + 1] + da * dx[i + 1]; + dy[i + 2] = dy[i + 2] + da * dx[i + 2]; + dy[i + 3] = dy[i + 3] + da * dx[i + 3]; + } + } + return; +} +/******************************************************************************/ + +floating_point_t ddot(int n, floating_point_t dx[], int incx, floating_point_t dy[], int incy) + +/******************************************************************************/ +/* + Purpose: + + DDOT forms the dot product of two vectors. + + Discussion: + + This routine uses unrolled loops for increments equal to one. + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of entries in the vectors. + + Input, floating_point_t DX[*], the first vector. + + Input, int INCX, the increment between successive entries in DX. + + Input, floating_point_t DY[*], the second vector. + + Input, int INCY, the increment between successive entries in DY. + + Output, floating_point_t DDOT, the sum of the product of the corresponding + entries of DX and DY. +*/ +{ + floating_point_t dtemp; + int i; + int ix; + int iy; + int m; + + dtemp = 0.0; + + if (n <= 0) { + return dtemp; + } + /* + Code for unequal increments or equal increments + not equal to 1. +*/ + if (incx != 1 || incy != 1) { + if (0 <= incx) { + ix = 0; + } else { + ix = (-n + 1) * incx; + } + + if (0 <= incy) { + iy = 0; + } else { + iy = (-n + 1) * incy; + } + + for (i = 0; i < n; i++) { + dtemp = dtemp + dx[ix] * dy[iy]; + ix = ix + incx; + iy = iy + incy; + } + } + /* + Code for both increments equal to 1. +*/ + else { + m = n % 5; + + for (i = 0; i < m; i++) { + dtemp = dtemp + dx[i] * dy[i]; + } + + for (i = m; i < n; i = i + 5) { + dtemp = dtemp + dx[i] * dy[i] + dx[i + 1] * dy[i + 1] + dx[i + 2] * dy[i + 2] + dx[i + 3] * dy[i + 3] + dx[i + 4] * dy[i + 4]; + } + } + return dtemp; +} +/******************************************************************************/ + +int dgefa(floating_point_t a[], int lda, int n, int ipvt[]) + +/******************************************************************************/ +/* + Purpose: + + DGEFA factors a real general matrix. + + Modified: + + 16 May 2005 + + Author: + + C version by John Burkardt. + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart, + LINPACK User's Guide, + SIAM, (Society for Industrial and Applied Mathematics), + 3600 University City Science Center, + Philadelphia, PA, 19104-2688. + ISBN 0-89871-172-X + + Parameters: + + Input/output, floating_point_t A[LDA*N]. + On input, the matrix to be factored. + On output, an upper triangular matrix and the multipliers used to obtain + it. The factorization can be written A=L*U, where L is a product of + permutation and unit lower triangular matrices, and U is upper triangular. + + Input, int LDA, the leading dimension of A. + + Input, int N, the order of the matrix A. + + Output, int IPVT[N], the pivot indices. + + Output, int DGEFA, singularity indicator. + 0, normal value. + K, if U(K,K) == 0. This is not an error condition for this subroutine, + but it does indicate that DGESL or DGEDI will divide by zero if called. + Use RCOND in DGECO for a reliable indication of singularity. +*/ +{ + int info; + int j; + int k; + int l; + floating_point_t t; + /* + Gaussian elimination with partial pivoting. +*/ + info = 0; + + for (k = 1; k <= n - 1; k++) { + /* + Find L = pivot index. +*/ + l = idamax(n - k + 1, a + (k - 1) + (k - 1) * lda, 1) + k - 1; + ipvt[k - 1] = l; + /* + Zero pivot implies this column already triangularized. +*/ + if (a[l - 1 + (k - 1) * lda] == 0.0) { + info = k; + continue; + } + /* + Interchange if necessary. +*/ + if (l != k) { + t = a[l - 1 + (k - 1) * lda]; + a[l - 1 + (k - 1) * lda] = a[k - 1 + (k - 1) * lda]; + a[k - 1 + (k - 1) * lda] = t; + } + /* + Compute multipliers. +*/ + t = -1.0 / a[k - 1 + (k - 1) * lda]; + + dscal(n - k, t, a + k + (k - 1) * lda, 1); + /* + Row elimination with column indexing. +*/ + for (j = k + 1; j <= n; j++) { + t = a[l - 1 + (j - 1) * lda]; + if (l != k) { + a[l - 1 + (j - 1) * lda] = a[k - 1 + (j - 1) * lda]; + a[k - 1 + (j - 1) * lda] = t; + } + daxpy(n - k, t, a + k + (k - 1) * lda, 1, a + k + (j - 1) * lda, 1); + } + } + + ipvt[n - 1] = n; + + if (a[n - 1 + (n - 1) * lda] == 0.0) { + info = n; + } + + return info; +} +/******************************************************************************/ + +void dgesl(floating_point_t a[], int lda, int n, int ipvt[], floating_point_t b[], int job) + +/******************************************************************************/ +/* + Purpose: + + DGESL solves a real general linear system A * X = B. + + Discussion: + + DGESL can solve either of the systems A * X = B or A' * X = B. + + The system matrix must have been factored by DGECO or DGEFA. + + A division by zero will occur if the input factor contains a + zero on the diagonal. Technically this indicates singularity + but it is often caused by improper arguments or improper + setting of LDA. It will not occur if the subroutines are + called correctly and if DGECO has set 0.0 < RCOND + or DGEFA has set INFO == 0. + + Modified: + + 16 May 2005 + + Author: + + C version by John Burkardt. + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart, + LINPACK User's Guide, + SIAM, (Society for Industrial and Applied Mathematics), + 3600 University City Science Center, + Philadelphia, PA, 19104-2688. + ISBN 0-89871-172-X + + Parameters: + + Input, floating_point_t A[LDA*N], the output from DGECO or DGEFA. + + Input, int LDA, the leading dimension of A. + + Input, int N, the order of the matrix A. + + Input, int IPVT[N], the pivot vector from DGECO or DGEFA. + + Input/output, floating_point_t B[N]. + On input, the right hand side vector. + On output, the solution vector. + + Input, int JOB. + 0, solve A * X = B; + nonzero, solve A' * X = B. +*/ +{ + int k; + int l; + floating_point_t t; + /* + Solve A * X = B. +*/ + if (job == 0) { + for (k = 1; k <= n - 1; k++) { + l = ipvt[k - 1]; + t = b[l - 1]; + + if (l != k) { + b[l - 1] = b[k - 1]; + b[k - 1] = t; + } + + daxpy(n - k, t, a + k + (k - 1) * lda, 1, b + k, 1); + } + + for (k = n; 1 <= k; k--) { + b[k - 1] = b[k - 1] / a[k - 1 + (k - 1) * lda]; + t = -b[k - 1]; + daxpy(k - 1, t, a + 0 + (k - 1) * lda, 1, b, 1); + } + } + /* + Solve A' * X = B. +*/ + else { + for (k = 1; k <= n; k++) { + t = ddot(k - 1, a + 0 + (k - 1) * lda, 1, b, 1); + b[k - 1] = (b[k - 1] - t) / a[k - 1 + (k - 1) * lda]; + } + + for (k = n - 1; 1 <= k; k--) { + b[k - 1] = b[k - 1] + ddot(n - k, a + k + (k - 1) * lda, 1, b + k, 1); + l = ipvt[k - 1]; + + if (l != k) { + t = b[l - 1]; + b[l - 1] = b[k - 1]; + b[k - 1] = t; + } + } + } + return; +} +/******************************************************************************/ + +void dscal(int n, floating_point_t sa, floating_point_t x[], int incx) + +/******************************************************************************/ +/* + Purpose: + + DSCAL scales a vector by a constant. + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of entries in the vector. + + Input, floating_point_t SA, the multiplier. + + Input/output, floating_point_t X[*], the vector to be scaled. + + Input, int INCX, the increment between successive entries of X. +*/ +{ + int i; + int ix; + int m; + + if (n <= 0) { + } else if (incx == 1) { + m = n % 5; + + for (i = 0; i < m; i++) { + x[i] = sa * x[i]; + } + + for (i = m; i < n; i = i + 5) { + x[i] = sa * x[i]; + x[i + 1] = sa * x[i + 1]; + x[i + 2] = sa * x[i + 2]; + x[i + 3] = sa * x[i + 3]; + x[i + 4] = sa * x[i + 4]; + } + } else { + if (0 <= incx) { + ix = 0; + } else { + ix = (-n + 1) * incx; + } + + for (i = 0; i < n; i++) { + x[ix] = sa * x[ix]; + ix = ix + incx; + } + } + return; +} +/******************************************************************************/ + +int idamax(int n, floating_point_t dx[], int incx) + +/******************************************************************************/ +/* + Purpose: + + IDAMAX finds the index of the vector element of maximum absolute value. + + Discussion: + + WARNING: This index is a 1-based index, not a 0-based index! + + Modified: + + 30 March 2007 + + Author: + + FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart. + C version by John Burkardt + + Reference: + + Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart, + LINPACK User's Guide, + SIAM, 1979. + + Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh, + Basic Linear Algebra Subprograms for Fortran Usage, + Algorithm 539, + ACM Transactions on Mathematical Software, + Volume 5, Number 3, September 1979, pages 308-323. + + Parameters: + + Input, int N, the number of entries in the vector. + + Input, floating_point_t X[*], the vector to be examined. + + Input, int INCX, the increment between successive entries of SX. + + Output, int IDAMAX, the index of the element of maximum + absolute value. +*/ +{ + floating_point_t dmax; + int i; + int ix; + int value; + + value = 0; + + if (n < 1 || incx <= 0) { + return value; + } + + value = 1; + + if (n == 1) { + return value; + } + + if (incx == 1) { + dmax = r8_abs(dx[0]); + + for (i = 1; i < n; i++) { + if (dmax < r8_abs(dx[i])) { + value = i + 1; + dmax = r8_abs(dx[i]); + } + } + } else { + ix = 0; + dmax = r8_abs(dx[0]); + ix = ix + incx; + + for (i = 1; i < n; i++) { + if (dmax < r8_abs(dx[ix])) { + value = i + 1; + dmax = r8_abs(dx[ix]); + } + ix = ix + incx; + } + } + + return value; +} +/******************************************************************************/ + +floating_point_t r8_abs(floating_point_t x) + +/******************************************************************************/ +/* + Purpose: + + R8_ABS returns the absolute value of a R8. + + Modified: + + 02 April 2005 + + Author: + + John Burkardt + + Parameters: + + Input, floating_point_t X, the quantity whose absolute value is desired. + + Output, floating_point_t R8_ABS, the absolute value of X. +*/ +{ + floating_point_t value; + + if (0.0 <= x) { + value = x; + } else { + value = -x; + } + return value; +} +/******************************************************************************/ + +floating_point_t r8_epsilon(void) + +/******************************************************************************/ +/* + Purpose: + + R8_EPSILON returns the R8 round off unit. + + Discussion: + + R8_EPSILON is a number R which is a power of 2 with the property that, + to the precision of the computer's arithmetic, + 1 < 1 + R + but + 1 = ( 1 + R / 2 ) + + Licensing: + + This code is distributed under the GNU LGPL license. + + Modified: + + 08 May 2006 + + Author: + + John Burkardt + + Parameters: + + Output, floating_point_t R8_EPSILON, the floating_point_t precision round-off unit. +*/ +{ + floating_point_t r; + + r = 1.0; + + while (1.0 < (floating_point_t)(1.0 + r)) { + r = r / 2.0; + } + r = 2.0 * r; + + return r; +} +/******************************************************************************/ + +floating_point_t r8_max(floating_point_t x, floating_point_t y) + +/******************************************************************************/ +/* + Purpose: + + R8_MAX returns the maximum of two R8's. + + Modified: + + 18 August 2004 + + Author: + + John Burkardt + + Parameters: + + Input, floating_point_t X, Y, the quantities to compare. + + Output, floating_point_t R8_MAX, the maximum of X and Y. +*/ +{ + floating_point_t value; + + if (y < x) { + value = x; + } else { + value = y; + } + return value; +} +/******************************************************************************/ + +floating_point_t r8_random(int iseed[4]) + +/******************************************************************************/ +/* + Purpose: + + R8_RANDOM returns a uniformly distributed random number between 0 and 1. + + Discussion: + + This routine uses a multiplicative congruential method with modulus + 2**48 and multiplier 33952834046453 (see G.S.Fishman, + 'Multiplicative congruential random number generators with modulus + 2**b: an exhaustive analysis for b = 32 and a partial analysis for + b = 48', Math. Comp. 189, pp 331-344, 1990). + + 48-bit integers are stored in 4 integer array elements with 12 bits + per element. Hence the routine is portable across machines with + integers of 32 bits or more. + + Parameters: + + Input/output, integer ISEED(4). + On entry, the seed of the random number generator; the array + elements must be between 0 and 4095, and ISEED(4) must be odd. + On exit, the seed is updated. + + Output, floating_point_t R8_RANDOM, the next pseudorandom number. +*/ +{ + int ipw2 = 4096; + int it1; + int it2; + int it3; + int it4; + int m1 = 494; + int m2 = 322; + int m3 = 2508; + int m4 = 2549; + floating_point_t r = 1.0 / 4096.0; + floating_point_t value; + /* + Multiply the seed by the multiplier modulo 2**48. +*/ + it4 = iseed[3] * m4; + it3 = it4 / ipw2; + it4 = it4 - ipw2 * it3; + it3 = it3 + iseed[2] * m4 + iseed[3] * m3; + it2 = it3 / ipw2; + it3 = it3 - ipw2 * it2; + it2 = it2 + iseed[1] * m4 + iseed[2] * m3 + iseed[3] * m2; + it1 = it2 / ipw2; + it2 = it2 - ipw2 * it1; + it1 = it1 + iseed[0] * m4 + iseed[1] * m3 + iseed[2] * m2 + iseed[3] * m1; + it1 = (it1 % ipw2); + /* + Return updated seed +*/ + iseed[0] = it1; + iseed[1] = it2; + iseed[2] = it3; + iseed[3] = it4; + /* + Convert 48-bit integer to a real number in the interval (0,1) +*/ + value = r * ((floating_point_t)(it1) + r * ((floating_point_t)(it2) + r * ((floating_point_t)(it3) + r * ((floating_point_t)(it4))))); + + return value; +} +/******************************************************************************/ + +void r8mat_gen(int lda, int n, floating_point_t *a) + +/******************************************************************************/ +/* + Purpose: + + R8MAT_GEN generates a random R8MAT. + + Modified: + + 06 June 2005 + + Parameters: + + Input, integer LDA, the leading dimension of the matrix. + + Input, integer N, the order of the matrix. + + Output, floating_point_t R8MAT_GEN[LDA*N], the N by N matrix. +*/ +{ + int i; + int init[4] = {1, 2, 3, 1325}; + int j; + + for (j = 1; j <= n; j++) { + for (i = 1; i <= n; i++) { + a[i - 1 + (j - 1) * lda] = r8_random(init) - 0.5; + } + } +} +/******************************************************************************/ diff --git a/tests/performance/linpack_float/test_linpack_float.py b/tests/performance/linpack_float/test_linpack_float.py new file mode 100644 index 00000000000..d11f6c74136 --- /dev/null +++ b/tests/performance/linpack_float/test_linpack_float.py @@ -0,0 +1,61 @@ +import json +import logging +import os + + +def test_linpack_float(dut, request): + LOGGER = logging.getLogger(__name__) + + # Match "Runs: %d" + res = dut.expect(r"Runs: (\d+)", timeout=60) + runs = int(res.group(0).decode("utf-8").split(" ")[1]) + LOGGER.info("Number of runs: {}".format(runs)) + assert runs > 0, "Invalid number of runs" + + # Match "Type: %s" + res = dut.expect(r"Type: (\w+)", timeout=60) + data_type = res.group(0).decode("utf-8").split(" ")[1] + LOGGER.info("Data type: {}".format(data_type)) + assert data_type == "float", "Invalid data type" + + # Match "Runs completed: %d" + res = dut.expect(r"Runs completed: (\d+)", timeout=120) + runs_completed = int(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Runs completed: {}".format(runs_completed)) + assert runs_completed == runs, "Invalid number of runs completed" + + # Match "Average MFLOPS: %f" + res = dut.expect(r"Average MFLOPS: (\d+\.\d+)", timeout=120) + avg_score = float(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Average MFLOPS: {}".format(avg_score)) + assert avg_score > 0, "Invalid average MFLOPS" + + # Match "Min MFLOPS: %f" + res = dut.expect(r"Min MFLOPS: (\d+\.\d+)", timeout=120) + min_score = float(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Min MFLOPS: {}".format(min_score)) + assert min_score > 0 and min_score < 1000000000.0, "Invalid min MFLOPS" + + # Match "Max MFLOPS: %f" + res = dut.expect(r"Max MFLOPS: (\d+\.\d+)", timeout=120) + max_score = float(res.group(0).decode("utf-8").split(" ")[2]) + LOGGER.info("Max MFLOPS: {}".format(max_score)) + assert max_score > 0, "Invalid max MFLOPS" + + # Create JSON with results and write it to file + # Always create a JSON with this format (so it can be merged later on): + # { TEST_NAME_STR: TEST_RESULTS_DICT } + results = {"linpack_float": {"runs": runs, "avg_score": avg_score, "min_score": min_score, "max_score": max_score}} + + current_folder = os.path.dirname(request.path) + file_index = 0 + report_file = os.path.join(current_folder, "result_linpack_float" + str(file_index) + ".json") + while os.path.exists(report_file): + report_file = report_file.replace(str(file_index) + ".json", str(file_index + 1) + ".json") + file_index += 1 + + with open(report_file, "w") as f: + try: + f.write(json.dumps(results)) + except Exception as e: + LOGGER.warning("Failed to write results to file: {}".format(e)) diff --git a/tests/performance/psramspeed/ci.json b/tests/performance/psramspeed/ci.json index 275da6cf4d5..341df103671 100644 --- a/tests/performance/psramspeed/ci.json +++ b/tests/performance/psramspeed/ci.json @@ -3,10 +3,7 @@ "qemu": false, "wokwi": false }, - - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SPIRAM=y" + ] } diff --git a/tests/performance/psramspeed/psramspeed.ino b/tests/performance/psramspeed/psramspeed.ino index 81175e6b3a5..be91733abfc 100644 --- a/tests/performance/psramspeed/psramspeed.ino +++ b/tests/performance/psramspeed/psramspeed.ino @@ -252,7 +252,7 @@ void setup() { Serial.printf("Max test size: %d\n", MAX_TEST_SIZE); Serial.flush(); for (int i = 0; i < N_RUNS; i++) { - Serial.printf("Run %d", i); + Serial.printf("Run %d\n", i); memcpy_speed_test(dest, src, MAX_TEST_SIZE, N_COPIES); Serial.flush(); memset_speed_test(dest, FILL_VALUE, MAX_TEST_SIZE, N_COPIES); diff --git a/tests/performance/psramspeed/test_psramspeed.py b/tests/performance/psramspeed/test_psramspeed.py index 8d051580799..9e96e158504 100644 --- a/tests/performance/psramspeed/test_psramspeed.py +++ b/tests/performance/psramspeed/test_psramspeed.py @@ -74,7 +74,7 @@ def test_psramspeed(dut, request): sums[(test, size, impl)]["time_sum"] += time avg_results = {} - for (test, size, impl) in sums: + for test, size, impl in sums: rate_avg = round(sums[(test, size, impl)]["rate_sum"] / runs, 2) time_avg = round(sums[(test, size, impl)]["time_sum"] / runs, 2) LOGGER.info( diff --git a/tests/performance/ramspeed/ci.json b/tests/performance/ramspeed/ci.json index e0614d1870f..d880ca64dfb 100644 --- a/tests/performance/ramspeed/ci.json +++ b/tests/performance/ramspeed/ci.json @@ -1,9 +1,4 @@ { - "platform": { - "qemu": false, - "wokwi": false - }, - "fqbn": { "esp32": [ "espressif:esp32:esp32:PSRAM=disabled,PartitionScheme=huge_app" @@ -14,5 +9,9 @@ "esp32s3": [ "espressif:esp32:esp32s3:PSRAM=disabled,USBMode=default,PartitionScheme=huge_app" ] + }, + "platform": { + "qemu": false, + "wokwi": false } } diff --git a/tests/performance/ramspeed/ramspeed.ino b/tests/performance/ramspeed/ramspeed.ino index e0ab0db4c5f..776f6540679 100644 --- a/tests/performance/ramspeed/ramspeed.ino +++ b/tests/performance/ramspeed/ramspeed.ino @@ -248,7 +248,7 @@ void setup() { Serial.printf("Max test size: %d\n", MAX_TEST_SIZE); Serial.flush(); for (int i = 0; i < N_RUNS; i++) { - Serial.printf("Run %d", i); + Serial.printf("Run %d\n", i); memcpy_speed_test(dest, src, MAX_TEST_SIZE, N_COPIES); Serial.flush(); memset_speed_test(dest, FILL_VALUE, MAX_TEST_SIZE, N_COPIES); diff --git a/tests/performance/ramspeed/test_ramspeed.py b/tests/performance/ramspeed/test_ramspeed.py index b4c3cee7f9b..dbe1670d329 100644 --- a/tests/performance/ramspeed/test_ramspeed.py +++ b/tests/performance/ramspeed/test_ramspeed.py @@ -74,7 +74,7 @@ def test_ramspeed(dut, request): sums[(test, size, impl)]["time_sum"] += time avg_results = {} - for (test, size, impl) in sums: + for test, size, impl in sums: rate_avg = round(sums[(test, size, impl)]["rate_sum"] / runs, 2) time_avg = round(sums[(test, size, impl)]["time_sum"] / runs, 2) LOGGER.info( diff --git a/tests/performance/superpi/superpi.ino b/tests/performance/superpi/superpi.ino index ffa6c932b35..7ac4b2f13d7 100644 --- a/tests/performance/superpi/superpi.ino +++ b/tests/performance/superpi/superpi.ino @@ -25,7 +25,7 @@ void setup() { Serial.printf("Digits: %d\n", DIGITS); Serial.flush(); for (int i = 0; i < N_RUNS; i++) { - Serial.printf("Run %d", i); + Serial.printf("Run %d\n", i); unsigned long start = millis(); pi_calc(DIGITS); unsigned long elapsed = millis() - start; diff --git a/tests/requirements.txt b/tests/requirements.txt index 7acb197d6ad..b2bae3b86d0 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,7 +1,8 @@ -cryptography==42.0.7 +cryptography==44.0.1 --only-binary cryptography pytest-cov==5.0.0 -pytest-embedded-serial-esp==1.10.2 -pytest-embedded-arduino==1.10.2 -pytest-embedded-wokwi==1.10.2 -pytest-embedded-qemu==1.10.2 +pytest-embedded-serial-esp==1.12.0 +pytest-embedded-arduino==1.12.0 +pytest-embedded-wokwi==1.12.0 +pytest-embedded-qemu==1.12.0 +esptool==4.8.1 diff --git a/tests/validation/democfg/ci.json b/tests/validation/democfg/ci.json index e3270117dc6..cf5c796644e 100644 --- a/tests/validation/democfg/ci.json +++ b/tests/validation/democfg/ci.json @@ -1,19 +1,4 @@ { - "platforms": { - "qemu": false, - "hardware": true, - "wokwi": true - }, - - "targets": { - "esp32": true, - "esp32s2": true, - "esp32s3": true, - "esp32c3": true, - "esp32c6": true, - "esp32h2": false - }, - "fqbn": { "esp32": [ "espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio", @@ -25,5 +10,22 @@ "esp32s3": [ "espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=huge_app" ] + }, + "platforms": { + "hardware": true, + "qemu": false, + "wokwi": false + }, + "requires": [ + "CONFIG_SOC_UART_SUPPORTED=y" + ], + "targets": { + "esp32": true, + "esp32c3": false, + "esp32c6": true, + "esp32h2": false, + "esp32s2": true, + "esp32s3": true, + "esp32p4": false } } diff --git a/tests/validation/democfg/test_democfg.py b/tests/validation/democfg/test_democfg.py index c34128d7e16..c19e51b5906 100644 --- a/tests/validation/democfg/test_democfg.py +++ b/tests/validation/democfg/test_democfg.py @@ -1,2 +1,2 @@ def test_cfg(dut): - dut.expect("Hello cfg!") + dut.expect_exact("Hello cfg!") diff --git a/tests/validation/gpio/ci.json b/tests/validation/gpio/ci.json index 13a4b8c1a31..7bc6a6ed163 100644 --- a/tests/validation/gpio/ci.json +++ b/tests/validation/gpio/ci.json @@ -1,7 +1,6 @@ { "platforms": { - "qemu": false, "hardware": false, - "wokwi": false + "qemu": false } } diff --git a/tests/validation/gpio/esp32.diagram.json b/tests/validation/gpio/diagram.esp32.json similarity index 100% rename from tests/validation/gpio/esp32.diagram.json rename to tests/validation/gpio/diagram.esp32.json diff --git a/tests/validation/gpio/esp32c3.diagram.json b/tests/validation/gpio/diagram.esp32c3.json similarity index 100% rename from tests/validation/gpio/esp32c3.diagram.json rename to tests/validation/gpio/diagram.esp32c3.json diff --git a/tests/validation/gpio/esp32c6.diagram.json b/tests/validation/gpio/diagram.esp32c6.json similarity index 100% rename from tests/validation/gpio/esp32c6.diagram.json rename to tests/validation/gpio/diagram.esp32c6.json diff --git a/tests/validation/gpio/esp32h2.diagram.json b/tests/validation/gpio/diagram.esp32h2.json similarity index 100% rename from tests/validation/gpio/esp32h2.diagram.json rename to tests/validation/gpio/diagram.esp32h2.json diff --git a/tests/validation/gpio/diagram.esp32p4.json b/tests/validation/gpio/diagram.esp32p4.json new file mode 100644 index 00000000000..ffb0cde2775 --- /dev/null +++ b/tests/validation/gpio/diagram.esp32p4.json @@ -0,0 +1,28 @@ +{ + "version": 1, + "author": "lucasssvaz", + "editor": "wokwi", + "parts": [ + { + "type": "board-esp32-p4-function-ev", + "id": "esp32", + "top": -66.32, + "left": -277.63, + "attrs": {} + }, + { + "type": "wokwi-pushbutton", + "id": "btn1", + "top": -128.2, + "left": -19.2, + "attrs": { "color": "green", "bounce": "1" } + } + ], + "connections": [ + [ "esp32:38", "$serialMonitor:TX", "", [] ], + [ "esp32:37", "$serialMonitor:RX", "", [] ], + [ "btn1:2.r", "esp32:GND.3", "black", [ "h19.4", "v29" ] ], + [ "esp32:0", "btn1:1.l", "blue", [ "h-48", "v-67.2" ] ] + ], + "dependencies": {} +} diff --git a/tests/validation/gpio/esp32s2.diagram.json b/tests/validation/gpio/diagram.esp32s2.json similarity index 100% rename from tests/validation/gpio/esp32s2.diagram.json rename to tests/validation/gpio/diagram.esp32s2.json diff --git a/tests/validation/gpio/esp32s3.diagram.json b/tests/validation/gpio/diagram.esp32s3.json similarity index 100% rename from tests/validation/gpio/esp32s3.diagram.json rename to tests/validation/gpio/diagram.esp32s3.json diff --git a/tests/validation/gpio/scenario.yaml b/tests/validation/gpio/scenario.yaml index a915b546b49..957f58b2176 100644 --- a/tests/validation/gpio/scenario.yaml +++ b/tests/validation/gpio/scenario.yaml @@ -6,31 +6,31 @@ steps: - wait-serial: "Button test" # Need for 1s delay for scenario to run properly - - delay: 1000ms + - delay: 5000ms # Press once - set-control: part-id: btn1 control: pressed value: 1 - - delay: 200ms + - delay: 2000ms - set-control: part-id: btn1 control: pressed value: 0 - - delay: 300ms + - delay: 3000ms # Press 2nd time - set-control: part-id: btn1 control: pressed value: 1 - - delay: 200ms + - delay: 2000ms - set-control: part-id: btn1 control: pressed value: 0 - - delay: 300ms + - delay: 3000ms # Press for the 3rd time - set-control: diff --git a/tests/validation/gpio/test_gpio.py b/tests/validation/gpio/test_gpio.py index e36282561b5..8aa3a42dcc6 100644 --- a/tests/validation/gpio/test_gpio.py +++ b/tests/validation/gpio/test_gpio.py @@ -1,5 +1,16 @@ +import logging + + def test_gpio(dut): + LOGGER = logging.getLogger(__name__) + dut.expect_exact("Button test") + + LOGGER.info("Expecting button press 1") dut.expect_exact("Button pressed 1 times") + + LOGGER.info("Expecting button press 2") dut.expect_exact("Button pressed 2 times") + + LOGGER.info("Expecting button press 3") dut.expect_exact("Button pressed 3 times") diff --git a/tests/validation/hello_world/test_hello_world.py b/tests/validation/hello_world/test_hello_world.py index bec1a73fc37..725e9a713c5 100644 --- a/tests/validation/hello_world/test_hello_world.py +++ b/tests/validation/hello_world/test_hello_world.py @@ -1,2 +1,2 @@ def test_hello_world(dut): - dut.expect("Hello Arduino!") + dut.expect_exact("Hello Arduino!") diff --git a/tests/validation/i2c_master/ci.json b/tests/validation/i2c_master/ci.json new file mode 100644 index 00000000000..2b8792cd131 --- /dev/null +++ b/tests/validation/i2c_master/ci.json @@ -0,0 +1,9 @@ +{ + "platforms": { + "hardware": false, + "qemu": false + }, + "requires": [ + "CONFIG_SOC_I2C_SUPPORTED=y" + ] +} diff --git a/tests/validation/i2c_master/diagram.esp32.json b/tests/validation/i2c_master/diagram.esp32.json new file mode 100644 index 00000000000..28e5d2e9c23 --- /dev/null +++ b/tests/validation/i2c_master/diagram.esp32.json @@ -0,0 +1,24 @@ +{ + "version": 1, + "author": "lucasssvaz", + "editor": "wokwi", + "parts": [ + { + "type": "board-esp32-devkit-c-v4", + "id": "esp32", + "top": -57.6, + "left": -177.56, + "attrs": {} + }, + { "type": "wokwi-ds1307", "id": "rtc1", "top": -43.8, "left": -19.1, "attrs": {} } + ], + "connections": [ + [ "esp32:RX", "$serialMonitor:TX", "", [] ], + [ "esp32:TX", "$serialMonitor:RX", "", [] ], + [ "esp32:22", "rtc1:SCL", "green", [ "h38.4", "v-9.6" ] ], + [ "esp32:21", "rtc1:SDA", "blue", [ "h48", "v-28.8", "h19.2" ] ], + [ "esp32:GND.2", "rtc1:GND", "black", [ "v0" ] ], + [ "rtc1:5V", "esp32:5V", "red", [ "h-28.8", "v-67.6", "h-172.8", "v230.4" ] ] + ], + "dependencies": {} +} diff --git a/tests/validation/i2c_master/diagram.esp32c3.json b/tests/validation/i2c_master/diagram.esp32c3.json new file mode 100644 index 00000000000..a7471ec3ca1 --- /dev/null +++ b/tests/validation/i2c_master/diagram.esp32c3.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "author": "lucasssvaz", + "editor": "wokwi", + "parts": [ + { + "type": "board-esp32-c3-devkitm-1", + "id": "esp32", + "top": -57.6, + "left": -177.56, + "attrs": {} + }, + { "type": "wokwi-ds1307", "id": "rtc1", "top": -43.8, "left": -19.1, "attrs": {} } + ], + "connections": [ + [ "esp32:RX", "$serialMonitor:TX", "", [] ], + [ "esp32:TX", "$serialMonitor:RX", "", [] ], + [ "rtc1:5V", "esp32:5V", "red", [ "h-28.8", "v-67.6", "h-172.8", "v230.4" ] ], + [ "esp32:5V.1", "rtc1:5V", "red", [ "h-18.22", "v-144.3", "h153.6", "v48" ] ], + [ "esp32:GND.10", "rtc1:GND", "black", [ "h56.16", "v9.3" ] ], + [ "esp32:8", "rtc1:SDA", "green", [ "h17.76", "v-19.5" ] ], + [ "esp32:9", "rtc1:SCL", "blue", [ "h0" ] ] + ], + "dependencies": {} +} diff --git a/tests/validation/i2c_master/diagram.esp32c6.json b/tests/validation/i2c_master/diagram.esp32c6.json new file mode 100644 index 00000000000..9c759682ae5 --- /dev/null +++ b/tests/validation/i2c_master/diagram.esp32c6.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "author": "lucasssvaz", + "editor": "wokwi", + "parts": [ + { + "type": "board-esp32-c6-devkitc-1", + "id": "esp32", + "top": -57.6, + "left": -177.56, + "attrs": {} + }, + { "type": "wokwi-ds1307", "id": "rtc1", "top": -43.8, "left": -19.1, "attrs": {} } + ], + "connections": [ + [ "esp32:RX", "$serialMonitor:TX", "", [] ], + [ "esp32:TX", "$serialMonitor:RX", "", [] ], + [ "rtc1:5V", "esp32:5V", "red", [ "h-28.8", "v-67.6", "h-172.8", "v230.4" ] ], + [ "esp32:5V.1", "rtc1:5V", "red", [ "h-18.22", "v-144.3", "h153.6", "v48" ] ], + [ "esp32:GND.10", "rtc1:GND", "black", [ "h56.16", "v9.3" ] ], + [ "esp32:23", "rtc1:SDA", "green", [ "h17.38", "v-23.51" ] ], + [ "esp32:GND.4", "rtc1:GND", "black", [ "h55.78", "v-4.31" ] ], + [ "esp32:22", "rtc1:SCL", "blue", [ "h26.98", "v-23.51" ] ] + ], + "dependencies": {} +} diff --git a/tests/validation/i2c_master/diagram.esp32h2.json b/tests/validation/i2c_master/diagram.esp32h2.json new file mode 100644 index 00000000000..d2a2acfecd7 --- /dev/null +++ b/tests/validation/i2c_master/diagram.esp32h2.json @@ -0,0 +1,24 @@ +{ + "version": 1, + "author": "lucasssvaz", + "editor": "wokwi", + "parts": [ + { + "type": "board-esp32-h2-devkitm-1", + "id": "esp32", + "top": -57.6, + "left": -177.56, + "attrs": {} + }, + { "type": "wokwi-ds1307", "id": "rtc1", "top": -43.8, "left": -19.1, "attrs": {} } + ], + "connections": [ + [ "esp32:RX", "$serialMonitor:TX", "", [] ], + [ "esp32:TX", "$serialMonitor:RX", "", [] ], + [ "esp32:GND.6", "rtc1:GND", "black", [ "h0" ] ], + [ "esp32:5V", "rtc1:5V", "red", [ "h-29.14", "v-160.97", "h172.8", "v48" ] ], + [ "esp32:12", "rtc1:SDA", "green", [ "h36.58", "v-36.17" ] ], + [ "esp32:22", "rtc1:SCL", "blue", [ "v-7.37", "h46.18", "v-38.4" ] ] + ], + "dependencies": {} +} diff --git a/tests/validation/i2c_master/diagram.esp32p4.json b/tests/validation/i2c_master/diagram.esp32p4.json new file mode 100644 index 00000000000..ab250c2aafd --- /dev/null +++ b/tests/validation/i2c_master/diagram.esp32p4.json @@ -0,0 +1,24 @@ +{ + "version": 1, + "author": "lucasssvaz", + "editor": "wokwi", + "parts": [ + { + "type": "board-esp32-p4-function-ev", + "id": "esp32", + "top": -57.6, + "left": -177.56, + "attrs": {} + }, + { "type": "wokwi-ds1307", "id": "rtc1", "top": -197.4, "left": 57.7, "attrs": {} } + ], + "connections": [ + [ "esp32:38", "$serialMonitor:TX", "", [] ], + [ "esp32:37", "$serialMonitor:RX", "", [] ], + [ "esp32:5V.1", "rtc1:5V", "red", [ "v0" ] ], + [ "esp32:GND.1", "rtc1:GND", "black", [ "v-133.52", "h5.53" ] ], + [ "esp32:7", "rtc1:SDA", "green", [ "v0" ] ], + [ "esp32:8", "rtc1:SCL", "blue", [ "h15.13", "v-114.12" ] ] + ], + "dependencies": {} +} diff --git a/tests/validation/i2c_master/diagram.esp32s2.json b/tests/validation/i2c_master/diagram.esp32s2.json new file mode 100644 index 00000000000..c34a176bd7e --- /dev/null +++ b/tests/validation/i2c_master/diagram.esp32s2.json @@ -0,0 +1,24 @@ +{ + "version": 1, + "author": "lucasssvaz", + "editor": "wokwi", + "parts": [ + { + "type": "board-esp32-s2-devkitm-1", + "id": "esp32", + "top": -57.6, + "left": -177.56, + "attrs": {} + }, + { "type": "wokwi-ds1307", "id": "rtc1", "top": -43.8, "left": -19.1, "attrs": {} } + ], + "connections": [ + [ "esp32:RX", "$serialMonitor:TX", "", [] ], + [ "esp32:TX", "$serialMonitor:RX", "", [] ], + [ "esp32:GND.2", "rtc1:GND", "black", [ "v0" ] ], + [ "rtc1:5V", "esp32:5V", "red", [ "h-28.8", "v-67.6", "h-172.8", "v230.4" ] ], + [ "esp32:8", "rtc1:SDA", "green", [ "h-19.47", "v-119.51", "h144", "v57.6" ] ], + [ "esp32:9", "rtc1:SCL", "blue", [ "h-29.07", "v-138.71", "h144", "v76.8" ] ] + ], + "dependencies": {} +} diff --git a/tests/validation/i2c_master/diagram.esp32s3.json b/tests/validation/i2c_master/diagram.esp32s3.json new file mode 100644 index 00000000000..6d168fb42e6 --- /dev/null +++ b/tests/validation/i2c_master/diagram.esp32s3.json @@ -0,0 +1,24 @@ +{ + "version": 1, + "author": "lucasssvaz", + "editor": "wokwi", + "parts": [ + { + "type": "board-esp32-s3-devkitc-1", + "id": "esp32", + "top": -57.6, + "left": -177.56, + "attrs": {} + }, + { "type": "wokwi-ds1307", "id": "rtc1", "top": -43.8, "left": -19.1, "attrs": {} } + ], + "connections": [ + [ "esp32:RX", "$serialMonitor:TX", "", [] ], + [ "esp32:TX", "$serialMonitor:RX", "", [] ], + [ "esp32:GND.2", "rtc1:GND", "black", [ "v0" ] ], + [ "rtc1:5V", "esp32:5V", "red", [ "h-28.8", "v-67.6", "h-172.8", "v230.4" ] ], + [ "esp32:8", "rtc1:SDA", "green", [ "h-19.47", "v-119.51", "h144", "v32.93", "h38.35" ] ], + [ "esp32:9", "rtc1:SCL", "blue", [ "h-29.07", "v-138.71", "h144", "v32.93", "h47.95" ] ] + ], + "dependencies": {} +} diff --git a/tests/validation/i2c_master/i2c_master.ino b/tests/validation/i2c_master/i2c_master.ino new file mode 100644 index 00000000000..41e7d2ae5f9 --- /dev/null +++ b/tests/validation/i2c_master/i2c_master.ino @@ -0,0 +1,319 @@ +/* + I2C Master Test for +*/ + +#include +#include +#include +#include +#include +#include + +#include "sdkconfig.h" + +/* DS1307 functions */ + +const uint8_t DS1307_ADDR = 0x68; +const uint8_t start_sec = 1; +const uint8_t start_min = 2; +const uint8_t start_hour = 3; +const uint8_t start_day = 4; +const uint8_t start_month = 5; +const uint16_t start_year = 2020; + +static uint8_t read_sec = 0; +static uint8_t read_min = 0; +static uint8_t read_hour = 0; +static uint8_t read_day = 0; +static uint8_t read_month = 0; +static uint16_t read_year = 0; +static int peek_data = -1; + +const char *ssid = "Wokwi-GUEST"; +const char *password = ""; + +const auto BCD2DEC = [](uint8_t num) -> uint8_t { + return ((num / 16 * 10) + (num % 16)); +}; + +const auto DEC2BCD = [](uint8_t num) -> uint8_t { + return ((num / 10 * 16) + (num % 10)); +}; + +void reset_read_values() { + read_sec = 0; + read_min = 0; + read_hour = 0; + read_day = 0; + read_month = 0; + read_year = 0; +} + +void ds1307_start(void) { + uint8_t sec; + + //Get seconds + Wire.beginTransmission(DS1307_ADDR); + Wire.write(0x00); + Wire.endTransmission(); + Wire.requestFrom(DS1307_ADDR, 1); + sec = Wire.read() & 0x7F; //Seconds without halt bit + + //Set seconds and start clock + Wire.beginTransmission(DS1307_ADDR); + Wire.write(0x00); + Wire.write(sec); + Wire.endTransmission(); +} + +void ds1307_stop(void) { + uint8_t sec; + + //Get seconds + Wire.beginTransmission(DS1307_ADDR); + Wire.write(0x00); + Wire.endTransmission(); + Wire.requestFrom(DS1307_ADDR, 1); + sec = Wire.read() | 0x80; //Seconds with halt bit + + //Set seconds and halt clock + Wire.beginTransmission(DS1307_ADDR); + Wire.write(0x00); + Wire.write(sec); + Wire.endTransmission(); +} + +void ds1307_get_time(uint8_t *sec, uint8_t *min, uint8_t *hour, uint8_t *day, uint8_t *month, uint16_t *year) { + //Get time + Wire.beginTransmission(DS1307_ADDR); + Wire.write(0x00); + Wire.endTransmission(); + Wire.requestFrom(DS1307_ADDR, 7); + + TEST_ASSERT_EQUAL(7, Wire.available()); + + if (peek_data == -1 && Wire.peek() != -1) { + peek_data = Wire.peek(); + } + + *sec = BCD2DEC(Wire.read() & 0x7F); //Seconds without halt bit + *min = BCD2DEC(Wire.read()); + *hour = BCD2DEC(Wire.read() & 0x3F); + Wire.read(); //Ignore day of week + *day = BCD2DEC(Wire.read()); + *month = BCD2DEC(Wire.read()); + *year = BCD2DEC(Wire.read()) + 2000; +} + +void ds1307_set_time(uint8_t sec, uint8_t min, uint8_t hour, uint8_t day, uint8_t month, uint16_t year) { + Wire.beginTransmission(DS1307_ADDR); + Wire.write(0x00); + Wire.write(DEC2BCD(sec)); + Wire.write(DEC2BCD(min)); + Wire.write(DEC2BCD(hour)); + Wire.write(DEC2BCD(0)); //Ignore day of week + Wire.write(DEC2BCD(day)); + Wire.write(DEC2BCD(month)); + Wire.write(DEC2BCD(year - 2000)); + Wire.endTransmission(); +} + +/* Unity functions */ + +// This function is automatically called by unity before each test is run +void setUp(void) { + reset_read_values(); + Wire.begin(); +} + +// This function is automatically called by unity after each test is run +void tearDown(void) { + //Reset time + ds1307_set_time(start_sec, start_min, start_hour, start_day, start_month, start_year); + + Wire.end(); +} + +void rtc_set_time() { + //Set time + ds1307_set_time(start_sec, start_min, start_hour, start_day, start_month, start_year); + + //Get time + ds1307_get_time(&read_sec, &read_min, &read_hour, &read_day, &read_month, &read_year); + + //Check time + TEST_ASSERT_EQUAL(start_sec, read_sec); + TEST_ASSERT_EQUAL(start_min, read_min); + TEST_ASSERT_EQUAL(start_hour, read_hour); + TEST_ASSERT_EQUAL(start_day, read_day); + TEST_ASSERT_EQUAL(start_month, read_month); + TEST_ASSERT_EQUAL(start_year, read_year); +} + +void rtc_run_clock() { + uint8_t old_sec = 0; + + //Run clock for 5 seconds + ds1307_start(); + delay(5000); + ds1307_stop(); + + //Get time + ds1307_get_time(&read_sec, &read_min, &read_hour, &read_day, &read_month, &read_year); + + //Check time + TEST_ASSERT_NOT_EQUAL(start_sec, read_sec); //Seconds should have changed + TEST_ASSERT_EQUAL(start_min, read_min); + TEST_ASSERT_EQUAL(start_hour, read_hour); + TEST_ASSERT_EQUAL(start_day, read_day); + TEST_ASSERT_EQUAL(start_month, read_month); + TEST_ASSERT_EQUAL(start_year, read_year); + + old_sec = read_sec; + reset_read_values(); + + //Get time again to check that clock is stopped + delay(2000); + ds1307_get_time(&read_sec, &read_min, &read_hour, &read_day, &read_month, &read_year); + + //Check time + TEST_ASSERT_EQUAL(old_sec, read_sec); + TEST_ASSERT_EQUAL(start_min, read_min); + TEST_ASSERT_EQUAL(start_hour, read_hour); + TEST_ASSERT_EQUAL(start_day, read_day); + TEST_ASSERT_EQUAL(start_month, read_month); + TEST_ASSERT_EQUAL(start_year, read_year); +} + +void change_clock() { + //Get time + ds1307_get_time(&read_sec, &read_min, &read_hour, &read_day, &read_month, &read_year); + + //Check time + TEST_ASSERT_EQUAL(start_sec, read_sec); + TEST_ASSERT_EQUAL(start_min, read_min); + TEST_ASSERT_EQUAL(start_hour, read_hour); + TEST_ASSERT_EQUAL(start_day, read_day); + TEST_ASSERT_EQUAL(start_month, read_month); + TEST_ASSERT_EQUAL(start_year, read_year); + + Wire.setClock(400000); + reset_read_values(); + + TEST_ASSERT_EQUAL(400000, Wire.getClock()); + + //Get time + ds1307_get_time(&read_sec, &read_min, &read_hour, &read_day, &read_month, &read_year); + + //Check time + TEST_ASSERT_EQUAL(start_sec, read_sec); + TEST_ASSERT_EQUAL(start_min, read_min); + TEST_ASSERT_EQUAL(start_hour, read_hour); + TEST_ASSERT_EQUAL(start_day, read_day); + TEST_ASSERT_EQUAL(start_month, read_month); + TEST_ASSERT_EQUAL(start_year, read_year); +} + +void swap_pins() { + Wire.setPins(SCL, SDA); + Wire.begin(); + //Set time + ds1307_set_time(start_sec, start_min, start_hour, start_day, start_month, start_year); + + //Get time + ds1307_get_time(&read_sec, &read_min, &read_hour, &read_day, &read_month, &read_year); + + //Check time + TEST_ASSERT_EQUAL(start_sec, read_sec); + TEST_ASSERT_EQUAL(start_min, read_min); + TEST_ASSERT_EQUAL(start_hour, read_hour); + TEST_ASSERT_EQUAL(start_day, read_day); + TEST_ASSERT_EQUAL(start_month, read_month); + TEST_ASSERT_EQUAL(start_year, read_year); + + Wire.setPins(SDA, SCL); +} + +void test_api() { + int integer_ret; + + // Set Buffer Size + integer_ret = Wire.setBufferSize(32); + TEST_ASSERT_EQUAL(32, integer_ret); + integer_ret = Wire.setBufferSize(I2C_BUFFER_LENGTH); + TEST_ASSERT_EQUAL(I2C_BUFFER_LENGTH, integer_ret); + + // Set TimeOut + Wire.setTimeOut(100); + TEST_ASSERT_EQUAL(100, Wire.getTimeOut()); + + // Check if buffer can be peeked + TEST_ASSERT_GREATER_THAN(-1, peek_data); + + Wire.flush(); +} + +bool device_found() { + uint8_t err; + + for (uint8_t address = 1; address < 127; ++address) { + Wire.beginTransmission(address); + err = Wire.endTransmission(); + log_d("Address: 0x%02X, Error: %d", address, err); + if (err == 0) { + log_i("Found device at address: 0x%02X", address); + } else if (address == DS1307_ADDR) { + log_e("Failed to find DS1307"); + return false; + } + } + + return true; +} + +void scan_bus() { + TEST_ASSERT_TRUE(device_found()); +} + +#if SOC_WIFI_SUPPORTED +void scan_bus_with_wifi() { + // delete old config + WiFi.disconnect(true, true, 1000); + delay(1000); + WiFi.begin(ssid, password); + delay(5000); + bool found = device_found(); + WiFi.disconnect(true, true, 1000); + + TEST_ASSERT_TRUE(found); +} +#endif + +/* Main */ + +void setup() { + Serial.begin(115200); + while (!Serial) { + delay(10); + } + + log_d("Starting I2C Master"); + Wire.begin(); + + log_d("Starting tests"); + UNITY_BEGIN(); + RUN_TEST(scan_bus); +#if SOC_WIFI_SUPPORTED + RUN_TEST(scan_bus_with_wifi); +#endif + RUN_TEST(rtc_set_time); + RUN_TEST(rtc_run_clock); + RUN_TEST(change_clock); + RUN_TEST(swap_pins); + RUN_TEST(test_api); + UNITY_END(); +} + +void loop() { + vTaskDelete(NULL); +} diff --git a/tests/validation/i2c_master/test_i2c_master.py b/tests/validation/i2c_master/test_i2c_master.py new file mode 100644 index 00000000000..da5f790c0f8 --- /dev/null +++ b/tests/validation/i2c_master/test_i2c_master.py @@ -0,0 +1,2 @@ +def test_i2c_master(dut): + dut.expect_unity_test_output(timeout=240) diff --git a/tests/validation/nvs/ci.json b/tests/validation/nvs/ci.json index 4bc2893da08..7f8ce83ec54 100644 --- a/tests/validation/nvs/ci.json +++ b/tests/validation/nvs/ci.json @@ -1,26 +1,13 @@ { - "platforms": { - "qemu": false - }, - "fqbn": { "esp32": [ "espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio", "espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app,FlashMode=qio" ], - "esp32s2": [ - "espressif:esp32:esp32s2:PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio", - "espressif:esp32:esp32s2:PSRAM=enabled,PartitionScheme=huge_app,FlashMode=qio" - ], "esp32c3": [ "espressif:esp32:esp32c3:PartitionScheme=huge_app,FlashMode=dio", "espressif:esp32:esp32c3:PartitionScheme=huge_app,FlashMode=qio" ], - "esp32s3": [ - "espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=huge_app,FlashMode=qio", - "espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=huge_app,FlashMode=qio120", - "espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=huge_app,FlashMode=dio" - ], "esp32c6": [ "espressif:esp32:esp32c6:PartitionScheme=huge_app,FlashMode=dio", "espressif:esp32:esp32c6:PartitionScheme=huge_app,FlashMode=dio,FlashFreq=40", @@ -32,6 +19,24 @@ "espressif:esp32:esp32h2:PartitionScheme=huge_app,FlashMode=dio,FlashFreq=16", "espressif:esp32:esp32h2:PartitionScheme=huge_app,FlashMode=qio", "espressif:esp32:esp32h2:PartitionScheme=huge_app,FlashMode=qio,FlashFreq=16" + ], + "esp32s2": [ + "espressif:esp32:esp32s2:PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio", + "espressif:esp32:esp32s2:PSRAM=enabled,PartitionScheme=huge_app,FlashMode=qio" + ], + "esp32s3": [ + "espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=huge_app,FlashMode=qio", + "espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=huge_app,FlashMode=qio120", + "espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=huge_app,FlashMode=dio" + ], + "esp32p4": [ + "espressif:esp32:esp32p4:PSRAM=enabled,USBMode=default,PartitionScheme=huge_app,FlashMode=dio", + "espressif:esp32:esp32p4:PSRAM=enabled,USBMode=default,PartitionScheme=huge_app,FlashMode=dio,FlashFreq=40", + "espressif:esp32:esp32p4:PSRAM=enabled,USBMode=default,PartitionScheme=huge_app,FlashMode=qio", + "espressif:esp32:esp32p4:PSRAM=enabled,USBMode=default,PartitionScheme=huge_app,FlashMode=qio,FlashFreq=40" ] + }, + "platforms": { + "qemu": false } } diff --git a/tests/validation/nvs/test_nvs.py b/tests/validation/nvs/test_nvs.py index e40549971be..424095a49ba 100644 --- a/tests/validation/nvs/test_nvs.py +++ b/tests/validation/nvs/test_nvs.py @@ -1,4 +1,14 @@ +import logging + + def test_nvs(dut): - dut.expect("Current counter value: 0") - dut.expect("Current counter value: 1") - dut.expect("Current counter value: 2") + LOGGER = logging.getLogger(__name__) + + LOGGER.info("Expecting counter value 0") + dut.expect_exact("Current counter value: 0") + + LOGGER.info("Expecting counter value 1") + dut.expect_exact("Current counter value: 1") + + LOGGER.info("Expecting counter value 2") + dut.expect_exact("Current counter value: 2") diff --git a/tests/validation/periman/ci.json b/tests/validation/periman/ci.json index accee2b2135..22ff71c54ff 100644 --- a/tests/validation/periman/ci.json +++ b/tests/validation/periman/ci.json @@ -2,5 +2,8 @@ "platforms": { "qemu": false, "wokwi": false + }, + "targets": { + "esp32p4": false } } diff --git a/tests/validation/periman/test_periman.py b/tests/validation/periman/test_periman.py index d8dc4b8eeb5..2728abcef80 100644 --- a/tests/validation/periman/test_periman.py +++ b/tests/validation/periman/test_periman.py @@ -1,4 +1,8 @@ +import logging + + def test_periman(dut): + LOGGER = logging.getLogger(__name__) peripherals = [ "GPIO", "SigmaDelta", @@ -29,9 +33,10 @@ def test_periman(dut): if peripheral in peripherals: if "not" in console_output: - assert False, f"Peripheral {peripheral} printed when it should not" + assert False, f"Output printed when it should not after peripheral {peripheral}" + LOGGER.info(f"Correct output after peripheral: {peripheral}") peripherals.remove(peripheral) else: assert False, f"Unknown peripheral: {peripheral}" - assert peripherals == [], f"Missing peripherals output: {peripherals}" + assert peripherals == [], f"Missing output after peripherals: {peripherals}" diff --git a/tests/validation/psram/ci.json b/tests/validation/psram/ci.json new file mode 100644 index 00000000000..999d3be953e --- /dev/null +++ b/tests/validation/psram/ci.json @@ -0,0 +1,8 @@ +{ + "platforms": { + "qemu": false + }, + "requires": [ + "CONFIG_SPIRAM=y" + ] +} diff --git a/tests/validation/psram/diagram.esp32s3.json b/tests/validation/psram/diagram.esp32s3.json new file mode 100644 index 00000000000..837ff1eed33 --- /dev/null +++ b/tests/validation/psram/diagram.esp32s3.json @@ -0,0 +1,24 @@ +{ + "version": 1, + "author": "lucasssvaz", + "editor": "wokwi", + "parts": [ + { + "type": "board-esp32-s3-devkitc-1", + "id": "esp", + "attrs": { "psramType": "octal" } + } + ], + "connections": [ + [ + "esp:TX", + "$serialMonitor:RX", + "" + ], + [ + "esp:RX", + "$serialMonitor:TX", + "" + ] + ] +} diff --git a/tests/validation/psram/psram.ino b/tests/validation/psram/psram.ino new file mode 100644 index 00000000000..7bf7bc11c5d --- /dev/null +++ b/tests/validation/psram/psram.ino @@ -0,0 +1,128 @@ +#include +#include + +#define MAX_TEST_SIZE 512 * 1024 // 512KB + +void *buf = NULL; +uint32_t psram_size = 0; + +void psram_found(void) { + psram_size = ESP.getPsramSize(); + TEST_ASSERT_TRUE(psram_size > 0); +} + +void test_malloc_success(void) { + buf = ps_malloc(MAX_TEST_SIZE); + TEST_ASSERT_NOT_NULL(buf); + free(buf); + buf = NULL; +} + +void test_calloc_success(void) { + buf = ps_calloc(MAX_TEST_SIZE, 1); + TEST_ASSERT_NOT_NULL(buf); + free(buf); + buf = NULL; +} + +void test_realloc_success(void) { + buf = ps_malloc(MAX_TEST_SIZE); + TEST_ASSERT_NOT_NULL(buf); + buf = ps_realloc(buf, MAX_TEST_SIZE + 1024); + TEST_ASSERT_NOT_NULL(buf); + free(buf); + buf = NULL; +} + +void test_malloc_fail(void) { + buf = ps_malloc(0xFFFFFFFF); + TEST_ASSERT_NULL(buf); +} + +void test_memset_all_zeroes(void) { + memset(buf, 0, MAX_TEST_SIZE); + for (size_t i = 0; i < MAX_TEST_SIZE; i++) { + TEST_ASSERT_EQUAL(0, ((uint8_t *)buf)[i]); + } +} + +void test_memset_all_ones(void) { + memset(buf, 0xFF, MAX_TEST_SIZE); + for (size_t i = 0; i < MAX_TEST_SIZE; i++) { + TEST_ASSERT_EQUAL(0xFF, ((uint8_t *)buf)[i]); + } +} + +void test_memset_alternating(void) { + for (size_t i = 0; i < MAX_TEST_SIZE; i++) { + ((uint8_t *)buf)[i] = i % 2 == 0 ? 0x00 : 0xFF; + } + memset(buf, 0xAA, MAX_TEST_SIZE); + for (size_t i = 0; i < MAX_TEST_SIZE; i++) { + TEST_ASSERT_EQUAL(0xAA, ((uint8_t *)buf)[i]); + } +} + +void test_memset_random(void) { + for (size_t i = 0; i < MAX_TEST_SIZE; i++) { + ((uint8_t *)buf)[i] = random(0, 256); + } + memset(buf, 0x55, MAX_TEST_SIZE); + for (size_t i = 0; i < MAX_TEST_SIZE; i++) { + TEST_ASSERT_EQUAL(0x55, ((uint8_t *)buf)[i]); + } +} + +void test_memcpy(void) { + void *buf2 = malloc(1024); // 1KB + TEST_ASSERT_NOT_NULL(buf2); + memset(buf, 0x55, MAX_TEST_SIZE); + memset(buf2, 0xAA, 1024); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpointer-arith" + + for (size_t i = 0; i < MAX_TEST_SIZE; i += 1024) { + memcpy(buf + i, buf2, 1024); + } + + for (size_t i = 0; i < MAX_TEST_SIZE; i += 1024) { + TEST_ASSERT_NULL(memcmp(buf + i, buf2, 1024)); + } + +#pragma GCC diagnostic pop + + free(buf2); +} + +void setup() { + Serial.begin(115200); + while (!Serial) { + delay(10); + } + + UNITY_BEGIN(); + RUN_TEST(psram_found); + + if (psram_size == 0) { + UNITY_END(); + return; + } + + RUN_TEST(test_malloc_success); + RUN_TEST(test_malloc_fail); + RUN_TEST(test_calloc_success); + RUN_TEST(test_realloc_success); + buf = ps_malloc(MAX_TEST_SIZE); + RUN_TEST(test_memset_all_zeroes); + RUN_TEST(test_memset_all_ones); + RUN_TEST(test_memset_alternating); +#ifndef CONFIG_IDF_TARGET_ESP32P4 + // These tests are taking too long on ESP32-P4 in Wokwi + RUN_TEST(test_memset_random); + RUN_TEST(test_memcpy); +#endif + UNITY_END(); +} + +void loop() {} diff --git a/tests/validation/psram/test_psram.py b/tests/validation/psram/test_psram.py new file mode 100644 index 00000000000..7bd1d9d735d --- /dev/null +++ b/tests/validation/psram/test_psram.py @@ -0,0 +1,2 @@ +def test_psram(dut): + dut.expect_unity_test_output(timeout=120) diff --git a/tests/validation/touch/ci.json b/tests/validation/touch/ci.json index 275da6cf4d5..855e9bd964d 100644 --- a/tests/validation/touch/ci.json +++ b/tests/validation/touch/ci.json @@ -3,10 +3,7 @@ "qemu": false, "wokwi": false }, - - "targets": { - "esp32c3": false, - "esp32c6": false, - "esp32h2": false - } + "requires": [ + "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" + ] } diff --git a/tests/validation/touch/touch.ino b/tests/validation/touch/touch.ino index 60f6e7f7966..97aac8a65e6 100644 --- a/tests/validation/touch/touch.ino +++ b/tests/validation/touch/touch.ino @@ -2,6 +2,10 @@ #include "soc/soc_caps.h" #include "driver/touch_pad.h" +#if SOC_TOUCH_SENSOR_VERSION == 3 +#include "hal/touch_sensor_ll.h" +#endif + #if CONFIG_IDF_TARGET_ESP32 #define TEST_TOUCH_CHANNEL (9) @@ -15,11 +19,7 @@ uint8_t TOUCH_GPIOS[] = {4, 2, 15, 13, 12, 14, 27, 33, 32}; #define NO_TOUCH_GPIO 25 -#define RELEASED_VALUE 75 //75+ read value to pass test -#define PRESSED_VALUE 20 //20- read value to pass test -#define INTERRUPT_THRESHOLD 40 - -#else //ESP32S2 and ESP32S3 +#elif (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3) #define TEST_TOUCH_CHANNEL (12) //14 static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { @@ -33,7 +33,25 @@ uint8_t TOUCH_GPIOS[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 /*,13,14*/}; #define NO_TOUCH_GPIO 17 -#if CONFIG_IDF_TARGET_ESP32S2 +#else //ESP32P4 + +#define TEST_TOUCH_CHANNEL (5) //14 +static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { + TOUCH_PAD_NUM0, TOUCH_PAD_NUM1, TOUCH_PAD_NUM2, + TOUCH_PAD_NUM3, TOUCH_PAD_NUM4, /* TOUCH_PAD_NUM5, TOUCH_PAD_NUM6, + TOUCH_PAD_NUM7, TOUCH_PAD_NUM8, TOUCH_PAD_NUM9, TOUCH_PAD_NUM10, TOUCH_PAD_NUM11, TOUCH_PAD_NUM12, TOUCH_PAD_NUM13*/ +}; + +uint8_t TOUCH_GPIOS[] = {2, 3, 4, 5, 6 /*, 7, 8, 9, 10, 11, 12 ,13, 14, 15*/}; + +#define NO_TOUCH_GPIO 17 +#endif + +#if CONFIG_IDF_TARGET_ESP32 +#define RELEASED_VALUE 75 //75+ read value to pass test +#define PRESSED_VALUE 20 //20- read value to pass test +#define INTERRUPT_THRESHOLD 40 +#elif CONFIG_IDF_TARGET_ESP32S2 #define RELEASED_VALUE 10000 //10000- read value to pass test #define PRESSED_VALUE 42000 //40000+ read value to pass test #define INTERRUPT_THRESHOLD 30000 @@ -41,12 +59,13 @@ uint8_t TOUCH_GPIOS[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 /*,13,14*/}; #define RELEASED_VALUE 25000 //25000- read value to pass test #define PRESSED_VALUE 90000 //90000+ read value to pass test #define INTERRUPT_THRESHOLD 80000 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define PRESSED_VALUE_DIFFERENCE 200 //200+ read value difference against the unpressed value +#define INTERRUPT_THRESHOLD 0 // Use benchmarked threshold #else #error Test not currently supported on this chip. Please adjust and try again! #endif -#endif - bool touch1detected = false; bool touch2detected = false; @@ -59,17 +78,25 @@ void gotTouch2() { } /* - * Change the slope to get larger value from touch sensor. + * Change the slope to get larger value from touch sensor. (Capacitor for ESP32P4) */ static void test_press_fake(touch_pad_t pad_num) { +#if SOC_TOUCH_SENSOR_VERSION <= 2 touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_1, TOUCH_PAD_TIE_OPT_DEFAULT); +#else + touch_ll_set_internal_capacitor(0x7f); +#endif } /* - * Change the slope to get smaller value from touch sensor. + * Change the slope to get smaller value from touch sensor. (Capacitor for ESP32P4) */ static void test_release_fake(touch_pad_t pad_num) { +#if SOC_TOUCH_SENSOR_VERSION <= 2 touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT); +#else + touch_ll_set_internal_capacitor(0); +#endif } /* These functions are intended to be called before and after each test. */ @@ -87,6 +114,7 @@ void tearDown(void) { */ void test_touch_read(void) { +#if SOC_TOUCH_SENSOR_VERSION <= 2 //TEST RELEASE STATE for (int i = 0; i < sizeof(TOUCH_GPIOS); i++) { #ifdef CONFIG_IDF_TARGET_ESP32 @@ -109,6 +137,29 @@ void test_touch_read(void) { TEST_ASSERT_GREATER_THAN(PRESSED_VALUE, touchRead(TOUCH_GPIOS[k])); #endif } +#else //TOUCH V3 + //TEST RELEASE STATE + touch_value_t touch_unpressed[sizeof(TOUCH_GPIOS)]; + for (int i = 0; i < sizeof(TOUCH_GPIOS); i++) { + touch_unpressed[i] = touchRead(TOUCH_GPIOS[i]); + } + + // TEST PRESS STATE + for (int j = 0; j < TEST_TOUCH_CHANNEL; j++) { + test_press_fake(touch_list[j]); + } + delay(100); + + touch_value_t touch_pressed[sizeof(TOUCH_GPIOS)]; + for (int k = 0; k < sizeof(TOUCH_GPIOS); k++) { + touch_pressed[k] = touchRead(TOUCH_GPIOS[k]); + } + + // COMPARE PRESSED > UNPRESSED + for (int l = 0; l < sizeof(TOUCH_GPIOS); l++) { + TEST_ASSERT_GREATER_THAN((touch_unpressed[l] + PRESSED_VALUE_DIFFERENCE), touch_pressed[l]); + } +#endif } void test_touch_interrtupt(void) { @@ -146,4 +197,6 @@ void setup() { UNITY_END(); } -void loop() {} +void loop() { + delay(10); +} diff --git a/tests/validation/uart/diagram.esp32.json b/tests/validation/uart/diagram.esp32.json new file mode 100644 index 00000000000..c2fbd952fd0 --- /dev/null +++ b/tests/validation/uart/diagram.esp32.json @@ -0,0 +1,24 @@ +{ + "version": 1, + "author": "lucasssvaz", + "editor": "wokwi", + "parts": [ + { + "type": "board-esp32-devkit-c-v4", + "id": "esp", + "attrs": { "cpuFrequency": "120" } + } + ], + "connections": [ + [ + "esp:TX", + "$serialMonitor:RX", + "" + ], + [ + "esp:RX", + "$serialMonitor:TX", + "" + ] + ] +} diff --git a/tests/validation/uart/uart.ino b/tests/validation/uart/uart.ino index 527d28241d9..794fc9affc2 100644 --- a/tests/validation/uart/uart.ino +++ b/tests/validation/uart/uart.ino @@ -2,25 +2,20 @@ * * This test is using UART0 (Serial) only for reporting test status and helping with the auto * baudrate detection test. - * UART1 (Serial1) and UART2 (Serial2), where available, are used for testing. + * The other serials are used for testing. */ -#include -#include "HardwareSerial.h" -#include "esp_rom_gpio.h" -#include "Wire.h" - // Default pins: -// | Name | ESP32 | S2 | S3 | C3 | C6 | H2 | -// UART0 RX | SOC_RX0 | 3 | 44 | 44 | 20 | 17 | 23 | -// UART0 TX | SOC_TX0 | 1 | 43 | 43 | 21 | 16 | 24 | -// UART1 RX | RX1 | 26 | 4 | 15 | 18 | 4 | 0 | -// UART1 TX | TX1 | 27 | 5 | 16 | 19 | 5 | 1 | -// UART2 RX | RX2 | 4 | -- | 19 | -- | -- | -- | -// UART2 TX | TX2 | 25 | -- | 20 | -- | -- | -- | +// | Name | ESP32 | S2 | S3 | C3 | C6 | H2 | P4 | +// UART0 RX | SOC_RX0 | 3 | 44 | 44 | 20 | 17 | 23 | 38 | +// UART0 TX | SOC_TX0 | 1 | 43 | 43 | 21 | 16 | 24 | 37 | +// UART1 RX | RX1 | 26 | 4 | 15 | 18 | 4 | 0 | 11 | +// UART1 TX | TX1 | 27 | 5 | 16 | 19 | 5 | 1 | 10 | +// UART2 RX | RX2 | 4 | -- | 19 | -- | -- | -- | -- | +// UART2 TX | TX2 | 25 | -- | 20 | -- | -- | -- | -- | /* - * For 2 UARTS: + * For each UART: * * terminal * | ^ @@ -30,111 +25,97 @@ * report status * | * TX <---> RX - * UART1 - * - * For 3 UARTS: - * - * =====terminal====== - * ^ | ^ ^ - * | v UART0 | | - * | RX TX | - * | | - * ^ report status ^ - * | | - * | TX ---> RX | - * UART2 RX <--- TX UART1 - * + * UARTx */ -#if SOC_UART_NUM == 2 -// Used for the pin swap test -#define NEW_RX1 9 -#define NEW_TX1 10 -#endif +#include +#include +#include "HardwareSerial.h" +#include "esp_rom_gpio.h" +#include "Wire.h" -/* Utility global variables */ +/* Utility defines */ -static String recv_msg = ""; -static int peeked_char = -1; +#define TEST_UART_NUM (uart_test_configs.size()) -/* Utility functions */ +/* Utility classes */ -extern int8_t uart_get_RxPin(uint8_t uart_num); -extern int8_t uart_get_TxPin(uint8_t uart_num); +class UARTTestConfig { +public: + int uart_num; + HardwareSerial &serial; + int peeked_char; + int8_t default_rx_pin; + int8_t default_tx_pin; + String recv_msg; -// This function starts all the available test UARTs -void start_serial(unsigned long baudrate = 115200) { -#if SOC_UART_NUM >= 2 - Serial1.begin(baudrate); - while (!Serial1) { - delay(10); - } -#endif + UARTTestConfig(int num, HardwareSerial &serial_ref, int8_t rx_pin, int8_t tx_pin) + : uart_num(num), serial(serial_ref), peeked_char(-1), default_rx_pin(rx_pin), default_tx_pin(tx_pin), recv_msg("") {} -#if SOC_UART_NUM >= 3 - Serial2.begin(baudrate); - while (!Serial2) { - delay(10); + void begin(unsigned long baudrate) { + // pinMode will force enabling the internal pullup resistor (IDF 5.3.2 Change) + pinMode(default_rx_pin, INPUT_PULLUP); + serial.begin(baudrate, SERIAL_8N1, default_rx_pin, default_tx_pin); + while (!serial) { + delay(10); + } } -#endif -} - -// This function stops all the available test UARTs -void stop_serial(bool hard_stop = false) { -#if SOC_UART_NUM >= 2 - Serial1.end(/*hard_stop*/); -#endif -#if SOC_UART_NUM >= 3 - Serial2.end(/*hard_stop*/); -#endif -} + void end() { + serial.end(); + } -// This function transmits a message and checks if it was received correctly -void transmit_and_check_msg(const String msg_append, bool perform_assert = true) { - delay(100); // Wait for some settings changes to take effect -#if SOC_UART_NUM == 2 - Serial1.print("Hello from Serial1 (UART1) >>> via loopback >>> Serial1 (UART1) " + msg_append); - Serial1.flush(); - delay(100); - if (perform_assert) { - TEST_ASSERT_EQUAL_STRING(("Hello from Serial1 (UART1) >>> via loopback >>> Serial1 (UART1) " + msg_append).c_str(), recv_msg.c_str()); + void reset_buffers() { + recv_msg = ""; + peeked_char = -1; } -#elif SOC_UART_NUM == 3 - Serial1.print("Hello from Serial1 (UART1) >>> to >>> Serial2 (UART2) " + msg_append); - Serial1.flush(); - delay(100); - if (perform_assert) { - TEST_ASSERT_EQUAL_STRING(("Hello from Serial1 (UART1) >>> to >>> Serial2 (UART2) " + msg_append).c_str(), recv_msg.c_str()); + + void transmit_and_check_msg(const String &msg_append, bool perform_assert = true) { + reset_buffers(); + delay(100); + serial.print("Hello from Serial" + String(uart_num) + " " + msg_append); + serial.flush(); + delay(100); + if (perform_assert) { + TEST_ASSERT_EQUAL_STRING(("Hello from Serial" + String(uart_num) + " " + msg_append).c_str(), recv_msg.c_str()); + log_d("UART%d received message: %s\n", uart_num, recv_msg.c_str()); + } } - Serial2.print("Hello from Serial2 (UART2) >>> to >>> Serial1 (UART1) " + msg_append); - Serial2.flush(); - delay(100); - if (perform_assert) { - TEST_ASSERT_EQUAL_STRING(("Hello from Serial2 (UART2) >>> to >>> Serial1 (UART1) " + msg_append).c_str(), recv_msg.c_str()); + void onReceive() { + char c; + size_t available = serial.available(); + if (peeked_char == -1) { + peeked_char = serial.peek(); + } + while (available--) { + c = (char)serial.read(); + recv_msg += c; + } } -#else - log_d("No UARTs available for transmission"); - TEST_FAIL(); -#endif -} +}; + +/* Utility global variables */ + +[[maybe_unused]] +static const int NEW_RX1 = 9; +[[maybe_unused]] +static const int NEW_TX1 = 10; +std::vector uart_test_configs; + +/* Utility functions */ + +extern "C" int8_t uart_get_RxPin(uint8_t uart_num); +extern "C" int8_t uart_get_TxPin(uint8_t uart_num); /* Tasks */ // This task is used to send a message after a delay to test the auto baudrate detection void task_delayed_msg(void *pvParameters) { - HardwareSerial *selected_serial; - -#if SOC_UART_NUM == 2 - selected_serial = &Serial; -#elif SOC_UART_NUM == 3 - selected_serial = &Serial1; -#endif - + HardwareSerial &selected_serial = uart_test_configs.size() == 1 ? Serial : Serial1; delay(2000); - selected_serial->println("Hello from Serial1 to detect baudrate"); - selected_serial->flush(); + selected_serial.println("Hello to detect baudrate"); + selected_serial.flush(); vTaskDelete(NULL); } @@ -142,67 +123,23 @@ void task_delayed_msg(void *pvParameters) { // This function is automatically called by unity before each test is run void setUp(void) { - start_serial(115200); -#if SOC_UART_NUM == 2 - log_d("Setup internal loop-back from and back to Serial1 (UART1) TX >> Serial1 (UART1) RX"); - - Serial1.onReceive([]() { - onReceive_cb(Serial1); - }); - uart_internal_loopback(1, RX1); -#elif SOC_UART_NUM == 3 - log_d("Setup internal loop-back between Serial1 (UART1) <<--->> Serial2 (UART2)"); - - Serial1.onReceive([]() { - onReceive_cb(Serial1); - }); - Serial2.onReceive([]() { - onReceive_cb(Serial2); - }); - uart_internal_loopback(1, RX2); - uart_internal_loopback(2, RX1); -#endif + for (auto *ref : uart_test_configs) { + UARTTestConfig &config = *ref; + //log_d("Setup internal loop-back from and back to UART%d TX >> UART%d RX", config.uart_num, config.uart_num); + config.begin(115200); + config.serial.onReceive([&config]() { + config.onReceive(); + }); + uart_internal_loopback(config.uart_num, uart_get_RxPin(config.uart_num)); + } } // This function is automatically called by unity after each test is run void tearDown(void) { - stop_serial(); -} - -/* Callback functions */ - -// This is a callback function that will be activated on UART RX events -void onReceive_cb(HardwareSerial &selected_serial) { - int uart_num = -1; - char c; - - (void)uart_num; // Avoid compiler warning when debug level is set to none - - if (&selected_serial == &Serial) { - uart_num = 0; -#if SOC_UART_NUM >= 2 - } else if (&selected_serial == &Serial1) { - uart_num = 1; -#endif -#if SOC_UART_NUM >= 3 - } else if (&selected_serial == &Serial2) { - uart_num = 2; -#endif - } - - recv_msg = ""; - size_t available = selected_serial.available(); - - if (available != 0) { - peeked_char = selected_serial.peek(); + for (auto *ref : uart_test_configs) { + UARTTestConfig &config = *ref; + config.end(); } - - while (available--) { - c = (char)selected_serial.read(); - recv_msg += c; - } - - log_d("UART %d received message: %s\n", uart_num, recv_msg.c_str()); } /* Test functions */ @@ -211,40 +148,33 @@ void onReceive_cb(HardwareSerial &selected_serial) { void basic_transmission_test(void) { log_d("Performing basic transmission test"); - transmit_and_check_msg(""); + for (auto *ref : uart_test_configs) { + UARTTestConfig &config = *ref; + config.transmit_and_check_msg(""); + } Serial.println("Basic transmission test successful"); } // This test checks if the baudrate can be changed and if the message can be transmitted and received correctly after the change void change_baudrate_test(void) { - //Test first using the updateBaudRate method and then using the begin method - log_d("Changing baudrate to 9600"); - - //Baudrate error should be within 2% of the target baudrate - Serial1.updateBaudRate(9600); - TEST_ASSERT_UINT_WITHIN(192, 9600, Serial1.baudRate()); + for (auto *ref : uart_test_configs) { + UARTTestConfig &config = *ref; + log_d("Changing baudrate of UART%d to 9600", config.uart_num); -#if SOC_UART_NUM == 3 - Serial2.updateBaudRate(9600); - TEST_ASSERT_UINT_WITHIN(192, 9600, Serial2.baudRate()); -#endif - - log_d("Sending string using 9600 baudrate"); - transmit_and_check_msg("using 9600 baudrate"); + //Baudrate error should be within 2% of the target baudrate + config.serial.updateBaudRate(9600); + TEST_ASSERT_UINT_WITHIN(192, 9600, config.serial.baudRate()); - log_d("Changing baudrate back to 115200"); - start_serial(115200); + log_d("Sending string on UART%d using 9600 baudrate", config.uart_num); + config.transmit_and_check_msg("using 9600 baudrate"); - //Baudrate error should be within 2% of the target baudrate - TEST_ASSERT_UINT_WITHIN(2304, 115200, Serial1.baudRate()); + config.serial.begin(115200); + TEST_ASSERT_UINT_WITHIN(2304, 115200, config.serial.baudRate()); -#if SOC_UART_NUM == 3 - TEST_ASSERT_UINT_WITHIN(2304, 115200, Serial2.baudRate()); -#endif - - log_d("Sending string using 115200 baudrate"); - transmit_and_check_msg("using 115200 baudrate"); + log_d("Sending string on UART%d using 115200 baudrate", config.uart_num); + config.transmit_and_check_msg("using 115200 baudrate"); + } Serial.println("Change baudrate test successful"); } @@ -261,7 +191,7 @@ void resize_buffers_test(void) { ret = Serial1.setTxBufferSize(256); TEST_ASSERT_EQUAL(0, ret); - stop_serial(); + Serial1.end(); log_d("Trying to resize RX buffer while stopped."); ret = Serial1.setRxBufferSize(256); @@ -277,7 +207,12 @@ void resize_buffers_test(void) { // This test checks if the begin function can be called when the UART is already running void begin_when_running_test(void) { log_d("Trying to set up serial twice"); - start_serial(115200); + for (auto *ref : uart_test_configs) { + UARTTestConfig &config = *ref; + // Calling twice should not crash + config.begin(115200); + config.begin(115200); + } Serial.println("Begin when running test successful"); } @@ -285,9 +220,12 @@ void begin_when_running_test(void) { void end_when_stopped_test(void) { log_d("Trying to end serial twice"); - // Calling end(true) twice should not crash - stop_serial(true); - stop_serial(true); + for (auto *ref : uart_test_configs) { + UARTTestConfig &config = *ref; + // Calling twice should not crash + config.end(); + config.end(); + } Serial.println("End when stopped test successful"); } @@ -311,7 +249,7 @@ void enabled_uart_calls_test(void) { TEST_ASSERT_EQUAL(true, boolean_ret); log_d("Checking if Serial 1 is peekable while running"); - TEST_ASSERT_GREATER_OR_EQUAL(0, peeked_char); + TEST_ASSERT_GREATER_OR_EQUAL(0, uart_test_configs[0]->peeked_char); log_d("Checking if Serial 1 can read bytes while running"); integer_ret = Serial1.readBytes(test_buf, 1); @@ -347,7 +285,10 @@ void disabled_uart_calls_test(void) { int integer_ret; uint8_t test_buf[1]; - stop_serial(); + for (auto *ref : uart_test_configs) { + UARTTestConfig &config = *ref; + config.end(); + } log_d("Checking if Serial 1 can set the RX timeout when stopped"); boolean_ret = Serial1.setRxTimeout(1); @@ -415,44 +356,37 @@ void disabled_uart_calls_test(void) { // This test checks if the pins can be changed and if the message can be transmitted and received correctly after the change void change_pins_test(void) { - //stop_serial(); - log_d("Disabling UART loopback"); -#if SOC_UART_NUM == 2 - esp_rom_gpio_connect_out_signal(SOC_RX0, SIG_GPIO_OUT_IDX, false, false); -#elif SOC_UART_NUM == 3 - esp_rom_gpio_connect_out_signal(RX1, SIG_GPIO_OUT_IDX, false, false); - esp_rom_gpio_connect_out_signal(RX2, SIG_GPIO_OUT_IDX, false, false); -#endif - - log_d("Swapping UART pins"); - -#if SOC_UART_NUM == 2 - Serial1.setPins(NEW_RX1, NEW_TX1); - TEST_ASSERT_EQUAL(NEW_RX1, uart_get_RxPin(1)); - TEST_ASSERT_EQUAL(NEW_TX1, uart_get_TxPin(1)); -#elif SOC_UART_NUM == 3 - Serial1.setPins(RX2, TX2); - Serial2.setPins(RX1, TX1); - TEST_ASSERT_EQUAL(RX2, uart_get_RxPin(1)); - TEST_ASSERT_EQUAL(TX2, uart_get_TxPin(1)); - TEST_ASSERT_EQUAL(RX1, uart_get_RxPin(2)); - TEST_ASSERT_EQUAL(TX1, uart_get_TxPin(2)); -#endif - - start_serial(115200); - - log_d("Re-enabling UART loopback"); - -#if SOC_UART_NUM == 2 - uart_internal_loopback(1, NEW_RX1); -#elif SOC_UART_NUM == 3 - uart_internal_loopback(1, RX1); - uart_internal_loopback(2, RX2); -#endif + for (auto *ref : uart_test_configs) { + UARTTestConfig &config = *ref; + esp_rom_gpio_connect_out_signal(config.default_rx_pin, SIG_GPIO_OUT_IDX, false, false); + } - transmit_and_check_msg("using new pins"); + log_d("Swapping UART pins and testing transmission"); + + if (TEST_UART_NUM == 1) { + UARTTestConfig &config = *uart_test_configs[0]; + // pinMode will force enabling the internal pullup resistor (IDF 5.3.2 Change) + pinMode(NEW_RX1, INPUT_PULLUP); + config.serial.setPins(NEW_RX1, NEW_TX1); + TEST_ASSERT_EQUAL(NEW_RX1, uart_get_RxPin(config.uart_num)); + TEST_ASSERT_EQUAL(NEW_TX1, uart_get_TxPin(config.uart_num)); + + uart_internal_loopback(config.uart_num, NEW_RX1); + config.transmit_and_check_msg("using new pins"); + } else { + for (int i = 0; i < TEST_UART_NUM; i++) { + UARTTestConfig &config = *uart_test_configs[i]; + UARTTestConfig &next_uart = *uart_test_configs[(i + 1) % TEST_UART_NUM]; + config.serial.setPins(next_uart.default_rx_pin, next_uart.default_tx_pin); + TEST_ASSERT_EQUAL(uart_get_RxPin(config.uart_num), next_uart.default_rx_pin); + TEST_ASSERT_EQUAL(uart_get_TxPin(config.uart_num), next_uart.default_tx_pin); + + uart_internal_loopback(config.uart_num, next_uart.default_rx_pin); + config.transmit_and_check_msg("using new pins"); + } + } Serial.println("Change pins test successful"); } @@ -467,12 +401,16 @@ void auto_baudrate_test(void) { log_d("Stopping test serial. Using Serial2 for ESP32 and Serial1 for ESP32-S2."); -#if SOC_UART_NUM == 2 - selected_serial = &Serial1; - uart_internal_loopback(0, RX1); -#elif SOC_UART_NUM == 3 - selected_serial = &Serial2; + if (TEST_UART_NUM == 1) { + selected_serial = &Serial1; + // UART1 pins were swapped because of ESP32-P4 + uart_internal_loopback(0, /*RX1*/ TX1); + } else { +#ifdef RX2 + selected_serial = &Serial2; + uart_internal_loopback(1, RX2); #endif + } //selected_serial->end(false); @@ -485,10 +423,10 @@ void auto_baudrate_test(void) { selected_serial->begin(0); baudrate = selected_serial->baudRate(); -#if SOC_UART_NUM == 2 - Serial.end(); - Serial.begin(115200); -#endif + if (TEST_UART_NUM == 1) { + Serial.end(); + Serial.begin(115200); + } TEST_ASSERT_UINT_WITHIN(2304, 115200, baudrate); @@ -502,32 +440,23 @@ void periman_test(void) { log_d("Setting up I2C on the same pins as UART"); - Wire.begin(RX1, TX1); - -#if SOC_UART_NUM == 3 - Wire1.begin(RX2, TX2); -#endif - - recv_msg = ""; - - log_d("Trying to send message using UART with I2C enabled"); - transmit_and_check_msg("while used by I2C", false); - TEST_ASSERT_EQUAL_STRING("", recv_msg.c_str()); + for (auto *ref : uart_test_configs) { + UARTTestConfig &config = *ref; + Wire.begin(config.default_rx_pin, config.default_tx_pin); + config.recv_msg = ""; - log_d("Disabling I2C and re-enabling UART"); + log_d("Trying to send message using UART%d with I2C enabled", config.uart_num); + config.transmit_and_check_msg("while used by I2C", false); + TEST_ASSERT_EQUAL_STRING("", config.recv_msg.c_str()); - Serial1.setPins(RX1, TX1); + log_d("Disabling I2C and re-enabling UART%d", config.uart_num); -#if SOC_UART_NUM == 3 - Serial2.setPins(RX2, TX2); - uart_internal_loopback(1, RX2); - uart_internal_loopback(2, RX1); -#elif SOC_UART_NUM == 2 - uart_internal_loopback(1, RX1); -#endif + config.serial.setPins(config.default_rx_pin, config.default_tx_pin); + uart_internal_loopback(config.uart_num, config.default_rx_pin); - log_d("Trying to send message using UART with I2C disabled"); - transmit_and_check_msg("while I2C is disabled"); + log_d("Trying to send message using UART%d with I2C disabled", config.uart_num); + config.transmit_and_check_msg("while I2C is disabled"); + } Serial.println("Peripheral manager test successful"); } @@ -543,8 +472,11 @@ void change_cpu_frequency_test(void) { Serial.updateBaudRate(115200); - log_d("Trying to send message with the new CPU frequency"); - transmit_and_check_msg("with new CPU frequency"); + for (auto *ref : uart_test_configs) { + UARTTestConfig &config = *ref; + log_d("Trying to send message with the new CPU frequency on UART%d", config.uart_num); + config.transmit_and_check_msg("with new CPU frequency"); + } log_d("Changing CPU frequency back to %dMHz", old_freq); Serial.flush(); @@ -552,8 +484,11 @@ void change_cpu_frequency_test(void) { Serial.updateBaudRate(115200); - log_d("Trying to send message with the original CPU frequency"); - transmit_and_check_msg("with the original CPU frequency"); + for (auto *ref : uart_test_configs) { + UARTTestConfig &config = *ref; + log_d("Trying to send message with the original CPU frequency on UART%d", config.uart_num); + config.transmit_and_check_msg("with the original CPU frequency"); + } Serial.println("Change CPU frequency test successful"); } @@ -565,30 +500,39 @@ void setup() { while (!Serial) { delay(10); } - log_d("SOC_UART_NUM = %d", SOC_UART_NUM); - - // Begin needs to be called before setting up the loopback because it creates the serial object - start_serial(115200); - -#if SOC_UART_NUM == 2 - log_d("Setup internal loop-back from and back to Serial1 (UART1) TX >> Serial1 (UART1) RX"); - - Serial1.onReceive([]() { - onReceive_cb(Serial1); - }); - uart_internal_loopback(1, RX1); -#elif SOC_UART_NUM == 3 - log_d("Setup internal loop-back between Serial1 (UART1) <<--->> Serial2 (UART2)"); - - Serial1.onReceive([]() { - onReceive_cb(Serial1); - }); - Serial2.onReceive([]() { - onReceive_cb(Serial2); - }); - uart_internal_loopback(1, RX2); - uart_internal_loopback(2, RX1); + + uart_test_configs = { +#if SOC_UART_HP_NUM >= 2 && defined(RX1) && defined(TX1) + // inverting RX1<->TX1 because ESP32-P4 has a problem with loopback on RX1 :: GPIO11 <-- UART_TX SGINAL + new UARTTestConfig(1, Serial1, TX1, RX1), +#endif +#if SOC_UART_HP_NUM >= 3 && defined(RX2) && defined(TX2) + new UARTTestConfig(2, Serial2, RX2, TX2), +#endif +#if SOC_UART_HP_NUM >= 4 && defined(RX3) && defined(TX3) + new UARTTestConfig(3, Serial3, RX3, TX3), #endif +#if SOC_UART_HP_NUM >= 5 && defined(RX4) && defined(TX4) + new UARTTestConfig(4, Serial4, RX4, TX4) +#endif + }; + + if (TEST_UART_NUM == 0) { + log_e("This test requires at least one UART besides UART0 configured"); + abort(); + } + + log_d("TEST_UART_NUM = %d", TEST_UART_NUM); + + for (auto *ref : uart_test_configs) { + UARTTestConfig &config = *ref; + config.begin(115200); + log_d("Setup internal loop-back from and back to UART%d TX >> UART%d RX", config.uart_num, config.uart_num); + config.serial.onReceive([&config]() { + config.onReceive(); + }); + uart_internal_loopback(config.uart_num, uart_get_RxPin(config.uart_num)); + } log_d("Setup done. Starting tests"); diff --git a/tests/validation/wifi/ci.json b/tests/validation/wifi/ci.json index b36524cced9..36e91b221cb 100644 --- a/tests/validation/wifi/ci.json +++ b/tests/validation/wifi/ci.json @@ -1,17 +1,7 @@ { - "platforms": { - "qemu": false, - "hardware": false - }, - - "targets": { - "esp32h2": false - }, - "extra_tags": [ "wifi" ], - "fqbn": { "esp32": [ "espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio", @@ -26,5 +16,12 @@ "espressif:esp32:esp32s3:PSRAM=disabled,USBMode=default,PartitionScheme=huge_app,FlashMode=qio", "espressif:esp32:esp32s3:PSRAM=enabled,USBMode=default,PartitionScheme=huge_app,FlashMode=qio" ] - } + }, + "platforms": { + "hardware": false, + "qemu": false + }, + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y" + ] } diff --git a/tests/validation/wifi/test_wifi.py b/tests/validation/wifi/test_wifi.py index 49dd22797d2..5049aae7b85 100644 --- a/tests/validation/wifi/test_wifi.py +++ b/tests/validation/wifi/test_wifi.py @@ -1,6 +1,16 @@ +import logging + + def test_wifi(dut): + LOGGER = logging.getLogger(__name__) + + LOGGER.info("Starting WiFi Scan") dut.expect_exact("Scan start") dut.expect_exact("Scan done") dut.expect_exact("Wokwi-GUEST") + LOGGER.info("WiFi Scan done") + + LOGGER.info("Connecting to WiFi") dut.expect_exact("WiFi connected") dut.expect_exact("IP address:") + LOGGER.info("WiFi connected") diff --git a/tools/add_lib.sh b/tools/add_lib.sh index 4ec73c4f7f7..9760f8114c6 100755 --- a/tools/add_lib.sh +++ b/tools/add_lib.sh @@ -1,4 +1,5 @@ #!/bin/bash + HELP="This script help to add library when using arduino-esp32 as an ESP-IDF component The script accepts up to three arguments: -n NEW: URL address to new library on GIThub (cannot be combined with -e) @@ -26,119 +27,126 @@ n_param="" # Parse the command-line arguments using getopts while getopts "he:l:n:" opt; do - case $opt in - h) - echo "$HELP" - exit 0 - ;; - e) - #e_param="$OPTARG" - e_param="${OPTARG/#~/$HOME}" - ;; - l) - #l_param="$OPTARG" - l_param="${OPTARG/#~/$HOME}" - ;; - n) - n_param=$OPTARG - ;; - \?) - echo "Invalid option: -$OPTARG" >&2 - echo $HELP - exit 1 - ;; - :) - echo "Option -$OPTARG requires an argument." >&2 - echo $HELP - exit 1 - ;; - esac + case $opt in + h) + echo "$HELP" + exit 0 + ;; + e) + #e_param="$OPTARG" + e_param="${OPTARG/#~/$HOME}" + ;; + l) + #l_param="$OPTARG" + l_param="${OPTARG/#~/$HOME}" + ;; + n) + n_param=$OPTARG + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + echo "$HELP" + exit 1 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + echo "$HELP" + exit 1 + ;; + *) + echo "Invalid option: -$OPTARG" >&2 + echo "$HELP" + exit 1 + ;; + esac done # No parameter check if [[ -z "$e_param" ]] && [[ -z "$l_param" ]] && [[ -z "$n_param" ]]; then - echo "Error: No parameters" >&2 - echo "$HELP" - exit 1 + echo "Error: No parameters" >&2 + echo "$HELP" + exit 1 fi # Only local path check (not permitted) -if [[ -z "$e_param" ]] && [[ ! -z "$l_param" ]] && [[ -z "$n_param" ]]; then - echo "Error: -l parameter must be paired with -e or -n" >&2 - echo "$HELP" - exit 1 +if [[ -z "$e_param" ]] && [[ -n "$l_param" ]] && [[ -z "$n_param" ]]; then + echo "Error: -l parameter must be paired with -e or -n" >&2 + echo "$HELP" + exit 1 fi # Invalid combination check -if [[ ! -z $e_param ]] && [[ ! -z $n_param ]]; then - echo "ERROR: Cannot combine -n with -e" >&2 - echo "$HELP" - exit 1 +if [[ -n $e_param ]] && [[ -n $n_param ]]; then + echo "ERROR: Cannot combine -n with -e" >&2 + echo "$HELP" + exit 1 fi # Check existing lib -if [[ ! -z "$e_param" ]]; then - if [[ ! -d "${e_param/#~/$HOME}" ]]; then # this works! - echo "Error: existing library parameter - path does not exist" >&2 - exit 1 - fi +if [[ -n "$e_param" ]]; then + if [[ ! -d "${e_param/#~/$HOME}" ]]; then # this works! + echo "Error: existing library parameter - path does not exist" >&2 + exit 1 + fi fi LIBRARY="" # Only existing library was supplied -if [[ ! -z $e_param ]] && [[ -z $l_param ]] && [[ -z $n_param ]]; then - LIBRARY=$e_param +if [[ -n $e_param ]] && [[ -z $l_param ]] && [[ -z $n_param ]]; then + LIBRARY=$e_param fi # Install new lib -if [ ! -z $n_param ]; then - INSTALL_TARGET="" - if [ -z $l_param ]; then - # If local path for project is not supplied - use as INSTALL_TARGET Arduino libraries path - INSTALL_TARGET=$ARDUINO_LIBS_PATH/$(basename "$n_param") - else - INSTALL_TARGET=$l_param/components/$(basename "$n_param") - if [ ! -d "$l_param/components" ]; then - echo "Folder components does not exist yet: mkdir -p "$l_param/components"" - mkdir -p "$l_param/components" +if [ -n "$n_param" ]; then + INSTALL_TARGET="" + if [ -z "$l_param" ]; then + # If local path for project is not supplied - use as INSTALL_TARGET Arduino libraries path + INSTALL_TARGET=$ARDUINO_LIBS_PATH/$(basename "$n_param") + else + INSTALL_TARGET=$l_param/components/$(basename "$n_param") + if [ ! -d "$l_param/components" ]; then + echo "Folder components does not exist yet: mkdir -p \"$l_param/components\"" + mkdir -p "$l_param/components" + fi fi - fi - # clone the new lib - echo "Cloning: git clone --recursive $n_param $INSTALL_TARGET" - git clone --recursive $n_param $INSTALL_TARGET - LIBRARY=$INSTALL_TARGET + # clone the new lib + echo "Cloning: git clone --recursive $n_param $INSTALL_TARGET" + git clone --recursive "$n_param" "$INSTALL_TARGET" + LIBRARY=$INSTALL_TARGET fi # Copy existing lib to local project -if [[ ! -z $e_param ]] && [[ ! -z $l_param ]]; then - if [ ! -d "$l_param/components" ]; then - echo "Folder components does not exist yet: mkdir -p "$l_param/components"" - mkdir -p "$l_param/components" - fi - echo "Copy from $e_param to $l_param" - echo "cp -r $e_param $l_param/components/$(basename "$e_param")" - cp -r $e_param $l_param/components/$(basename "$e_param") - LIBRARY=$l_param/components/$(basename "$e_param") +if [[ -n $e_param ]] && [[ -n $l_param ]]; then + if [ ! -d "$l_param/components" ]; then + echo "Folder components does not exist yet: mkdir -p \"$l_param/components\"" + mkdir -p "$l_param/components" + fi + echo "Copy from $e_param to $l_param" + echo "cp -r $e_param $l_param/components/\"$(basename "$e_param")\"" + cp -r "$e_param" "$l_param"/components/"$(basename "$e_param")" + LIBRARY=$l_param/components/"$(basename "$e_param")" fi if [ -z "$LIBRARY" ]; then - echo "ERROR: No library path" >&2 - exit 1 + echo "ERROR: No library path" >&2 + exit 1 fi # 1. get the source list: -FILES=$(find $LIBRARY -name '*.c' -o -name '*.cpp' | xargs -I{} basename {}) +FILES=$(find "$LIBRARY" -print0 -name '*.c' -o -name '*.cpp' | xargs -0 -I{} basename {}) # Fresh start -if [ -f $LIBRARY/CMakeLists.txt ]; then - rm $LIBRARY/CMakeLists.txt - touch $LIBRARY/CMakeLists.txt +if [ -f "$LIBRARY"/CMakeLists.txt ]; then + rm "$LIBRARY"/CMakeLists.txt + touch "$LIBRARY"/CMakeLists.txt fi # Generate CMakeLists.txt -echo "idf_component_register(SRCS $(echo $FILES | sed -e 's/ /" "/g' | sed -e 's/^/"/' -e 's/$/"/')" >> $LIBRARY/CMakeLists.txt -echo " INCLUDE_DIRS \".\"" >> $LIBRARY/CMakeLists.txt -echo " REQUIRES \"arduino-esp32\"" >> $LIBRARY/CMakeLists.txt -echo " )" >> $LIBRARY/CMakeLists.txt +{ + echo "idf_component_register(SRCS $(echo "$FILES" | sed -e 's/ /" "/g' | sed -e 's/^/"/' -e 's/$/"/')" + echo " INCLUDE_DIRS \".\"" + echo " REQUIRES \"arduino-esp32\"" + echo " )" +} >> "$LIBRARY"/CMakeLists.txt diff --git a/tools/gen_esp32part.exe b/tools/gen_esp32part.exe index 51c1959ac74..5bd12c6360d 100644 Binary files a/tools/gen_esp32part.exe and b/tools/gen_esp32part.exe differ diff --git a/tools/gen_esp32part.py b/tools/gen_esp32part.py index 4ba0ee59517..ffa740a36e0 100755 --- a/tools/gen_esp32part.py +++ b/tools/gen_esp32part.py @@ -529,7 +529,7 @@ def to_binary(self): def to_csv(self, simple_formatting=False): def addr_format(a, include_sizes): if not simple_formatting and include_sizes: - for (val, suffix) in [(0x100000, "M"), (0x400, "K")]: + for val, suffix in [(0x100000, "M"), (0x400, "K")]: if a % val == 0: return "%d%s" % (a // val, suffix) return "0x%x" % a diff --git a/tools/get.exe b/tools/get.exe index ed5fabbb7b4..b56f2b98384 100644 Binary files a/tools/get.exe and b/tools/get.exe differ diff --git a/tools/get.py b/tools/get.py index 68b92e05da7..c791020b7e9 100755 --- a/tools/get.py +++ b/tools/get.py @@ -101,59 +101,83 @@ def verify_files(filename, destination, rename_to): t1 = time.time() if filename.endswith(".zip"): try: - with zipfile.ZipFile(filename, "r") as archive: - first_dir = archive.namelist()[0].split("/")[0] - total_files = len(archive.namelist()) - for i, zipped_file in enumerate(archive.namelist(), 1): - local_path = os.path.join(extracted_dir_path, zipped_file.replace(first_dir, rename_to, 1)) - if not os.path.exists(local_path): - print(f"\nMissing {zipped_file} on location: {extracted_dir_path}") - print(f"Verification failed; aborted in {format_time(time.time() - t1)}") - return False - print_verification_progress(total_files, i, t1) + archive = zipfile.ZipFile(filename, "r") + file_list = archive.namelist() except zipfile.BadZipFile: - print(f"Verification failed; aborted in {format_time(time.time() - t1)}") + if verbose: + print(f"Verification failed; aborted in {format_time(time.time() - t1)}") return False elif filename.endswith(".tar.gz"): try: - with tarfile.open(filename, "r:gz") as archive: - first_dir = archive.getnames()[0].split("/")[0] - total_files = len(archive.getnames()) - for i, zipped_file in enumerate(archive.getnames(), 1): - local_path = os.path.join(extracted_dir_path, zipped_file.replace(first_dir, rename_to, 1)) - if not os.path.exists(local_path): - print(f"\nMissing {zipped_file} on location: {extracted_dir_path}") - print(f"Verification failed; aborted in {format_time(time.time() - t1)}") - return False - print_verification_progress(total_files, i, t1) + archive = tarfile.open(filename, "r:gz") + file_list = archive.getnames() except tarfile.ReadError: - print(f"Verification failed; aborted in {format_time(time.time() - t1)}") + if verbose: + print(f"Verification failed; aborted in {format_time(time.time() - t1)}") return False elif filename.endswith(".tar.xz"): try: - with tarfile.open(filename, "r:xz") as archive: - first_dir = archive.getnames()[0].split("/")[0] - total_files = len(archive.getnames()) - for i, zipped_file in enumerate(archive.getnames(), 1): - local_path = os.path.join(extracted_dir_path, zipped_file.replace(first_dir, rename_to, 1)) - if not os.path.exists(local_path): - print(f"\nMissing {zipped_file} on location: {extracted_dir_path}") - print(f"Verification failed; aborted in {format_time(time.time() - t1)}") - return False - print_verification_progress(total_files, i, t1) + archive = tarfile.open(filename, "r:xz") + file_list = archive.getnames() except tarfile.ReadError: - print(f"Verification failed; aborted in {format_time(time.time() - t1)}") + if verbose: + print(f"Verification failed; aborted in {format_time(time.time() - t1)}") return False else: raise NotImplementedError("Unsupported archive type") + try: + first_dir = file_list[0].split("/")[0] + total_files = len(file_list) + for i, zipped_file in enumerate(file_list, 1): + local_path = os.path.join(extracted_dir_path, zipped_file.replace(first_dir, rename_to, 1)) + if not os.path.exists(local_path): + if verbose: + print(f"\nMissing {zipped_file} on location: {extracted_dir_path}") + print(f"Verification failed; aborted in {format_time(time.time() - t1)}") + return False + print_verification_progress(total_files, i, t1) + except Exception as e: + print(f"\nError: {e}") + return False + if verbose: print(f"\nVerification passed; completed in {format_time(time.time() - t1)}") return True -def unpack(filename, destination, force_extract): # noqa: C901 +def is_latest_version(destination, dirname, rename_to, cfile, checksum): + current_version = None + expected_version = None + + try: + expected_version = checksum + with open(os.path.join(destination, rename_to, ".package_checksum"), "r") as f: + current_version = f.read() + + if verbose: + print(f"\nTool: {rename_to}") + print(f"Current version: {current_version}") + print(f"Expected version: {expected_version}") + + if current_version and current_version == expected_version: + if verbose: + print("Latest version already installed. Skipping extraction") + return True + + if verbose: + print("New version detected") + + except Exception as e: + if verbose: + print(f"Failed to verify version for {rename_to}: {e}") + + return False + + +def unpack(filename, destination, force_extract, checksum): # noqa: C901 + sys_name = platform.system() dirname = "" cfile = None # Compressed file file_is_corrupted = False @@ -200,24 +224,30 @@ def unpack(filename, destination, force_extract): # noqa: C901 rename_to = re.match(r"^([a-z][^\-]*\-*)+", dirname).group(0).strip("-") if rename_to == dirname and dirname.startswith("esp32-arduino-libs-"): rename_to = "esp32-arduino-libs" + elif rename_to == dirname and dirname.startswith("esptool-"): + rename_to = "esptool" if not force_extract: - if verify_files(filename, destination, rename_to): - print(" Files ok. Skipping Extraction") - return True - else: - print(" Extracting archive...") + if is_latest_version(destination, dirname, rename_to, cfile, checksum): + if verify_files(filename, destination, rename_to): + print(" Files ok. Skipping Extraction") + return True + print(" Extracting archive...") else: print(" Forcing extraction") + if os.path.isdir(os.path.join(destination, rename_to)): + print("Removing existing {0} ...".format(rename_to)) + shutil.rmtree(os.path.join(destination, rename_to), ignore_errors=True) + if filename.endswith("tar.gz"): if not cfile: cfile = tarfile.open(filename, "r:gz") - cfile.extractall(destination) + cfile.extractall(destination, filter="tar") elif filename.endswith("tar.xz"): if not cfile: cfile = tarfile.open(filename, "r:xz") - cfile.extractall(destination) + cfile.extractall(destination, filter="tar") elif filename.endswith("zip"): if not cfile: cfile = zipfile.ZipFile(filename) @@ -227,11 +257,22 @@ def unpack(filename, destination, force_extract): # noqa: C901 if rename_to != dirname: print("Renaming {0} to {1} ...".format(dirname, rename_to)) - if os.path.isdir(rename_to): - shutil.rmtree(rename_to) shutil.move(dirname, rename_to) - return True + # Add execute permission to esptool on non-Windows platforms + if rename_to.startswith("esptool") and "CYGWIN_NT" not in sys_name and "Windows" not in sys_name: + st = os.stat(os.path.join(destination, rename_to, "esptool")) + os.chmod(os.path.join(destination, rename_to, "esptool"), st.st_mode | 0o111) + + with open(os.path.join(destination, rename_to, ".package_checksum"), "w") as f: + f.write(checksum) + + if verify_files(filename, destination, rename_to): + print(" Files extracted successfully.") + return True + else: + print(" Failed to extract files.") + return False def download_file_with_progress(url, filename, start_time): @@ -291,6 +332,7 @@ def get_tool(tool, force_download, force_extract): local_path = dist_dir + archive_name url = tool["url"] start_time = time.time() + print("") if not os.path.isfile(local_path) or force_download: if verbose: print("Downloading '" + archive_name + "' to '" + local_path + "'") @@ -324,17 +366,21 @@ def get_tool(tool, force_download, force_extract): print("Tool {0} already downloaded".format(archive_name)) sys.stdout.flush() - if "esp32-arduino-libs" not in archive_name and sha256sum(local_path) != checksum: + if sha256sum(local_path) != checksum: print("Checksum mismatch for {0}".format(archive_name)) return False - return unpack(local_path, ".", force_extract) + return unpack(local_path, ".", force_extract, checksum) def load_tools_list(filename, platform): tools_info = json.load(open(filename))["packages"][0]["tools"] tools_to_download = [] for t in tools_info: + if platform == "x86_64-mingw32": + if "i686-mingw32" not in [p["host"] for p in t["systems"]]: + raise Exception("Windows x64 requires both i686-mingw32 and x86_64-mingw32 tools") + tool_platform = [p for p in t["systems"] if p["host"] == platform] if len(tool_platform) == 0: # Fallback to x86 on Apple ARM @@ -348,6 +394,8 @@ def load_tools_list(filename, platform): if len(tool_platform) == 0: continue else: + if verbose: + print(f"Tool {t['name']} is not available for platform {platform}") continue tools_to_download.append(tool_platform[0]) return tools_to_download @@ -379,21 +427,17 @@ def identify_platform(): if __name__ == "__main__": parser = argparse.ArgumentParser(description="Download and extract tools") - parser.add_argument("-v", "--verbose", type=bool, default=False, required=False, help="Print verbose output") + parser.add_argument("-v", "--verbose", action="store_true", required=False, help="Print verbose output") - parser.add_argument( - "-d", "--force_download", type=bool, default=False, required=False, help="Force download of tools" - ) + parser.add_argument("-d", "--force_download", action="store_true", required=False, help="Force download of tools") - parser.add_argument( - "-e", "--force_extract", type=bool, default=False, required=False, help="Force extraction of tools" - ) + parser.add_argument("-e", "--force_extract", action="store_true", required=False, help="Force extraction of tools") parser.add_argument( - "-f", "--force_all", type=bool, default=False, required=False, help="Force download and extraction of tools" + "-f", "--force_all", action="store_true", required=False, help="Force download and extraction of tools" ) - parser.add_argument("-t", "--test", type=bool, default=False, required=False, help=argparse.SUPPRESS) + parser.add_argument("-t", "--test", action="store_true", required=False, help=argparse.SUPPRESS) args = parser.parse_args() @@ -403,6 +447,12 @@ def identify_platform(): force_all = args.force_all is_test = args.test + # Set current directory to the script location + if getattr(sys, "frozen", False): + os.chdir(os.path.dirname(sys.executable)) + else: + os.chdir(os.path.dirname(os.path.abspath(__file__))) + if is_test and (force_download or force_extract or force_all): print("Cannot combine test (-t) and forced execution (-d | -e | -f)") parser.print_help(sys.stderr) @@ -421,6 +471,9 @@ def identify_platform(): current_dir + "/../package/package_esp32_index.template.json", identified_platform ) mkdir_p(dist_dir) + + print("\nDownloading and extracting tools...") + for tool in tools_to_download: if is_test: print("Would install: {0}".format(tool["archiveFileName"])) @@ -432,4 +485,4 @@ def identify_platform(): print(f"Tool {tool['archiveFileName']} was corrupted, but re-downloading did not help!\n") sys.exit(1) - print("Platform Tools Installed") + print("\nPlatform Tools Installed") diff --git a/tools/partitions/default_32MB.csv b/tools/partitions/default_32MB.csv new file mode 100644 index 00000000000..dd07ac32185 --- /dev/null +++ b/tools/partitions/default_32MB.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0xC80000, +app1, app, ota_1, 0xC90000,0xC80000, +spiffs, data, spiffs, 0x1910000,0x6C0000, +coredump, data, coredump,0x1FF0000,0x10000, diff --git a/tools/partitions/max_app_4MB.csv b/tools/partitions/max_app_4MB.csv new file mode 100644 index 00000000000..ec30c10065b --- /dev/null +++ b/tools/partitions/max_app_4MB.csv @@ -0,0 +1,5 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, factory, 0x10000, 0x3E0000, +coredump, data, coredump,0x3F0000,0x10000, diff --git a/tools/partitions/ota_nofs_4MB.csv b/tools/partitions/ota_nofs_4MB.csv new file mode 100644 index 00000000000..04240badb49 --- /dev/null +++ b/tools/partitions/ota_nofs_4MB.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags + nvs, data, nvs, 0x9000, 0x5000, + otadata, data, ota, 0xE000, 0x2000, + app0, app, ota_0, 0x10000, 0x1F0000, + app1, app, ota_1, 0x200000, 0x1F0000, +coredump, data, coredump, 0x3F0000, 0x10000, diff --git a/tools/partitions/rainmaker.csv b/tools/partitions/rainmaker.csv index 7b05378ccf7..1eabd86b827 100644 --- a/tools/partitions/rainmaker.csv +++ b/tools/partitions/rainmaker.csv @@ -4,4 +4,4 @@ otadata, data, ota, 0xe000, 0x2000, ota_0, app, ota_0, 0x10000, 0x1E0000, ota_1, app, ota_1, 0x1F0000, 0x1E0000, fctry, data, nvs, 0x3D0000, 0x6000, -coredump, data, coredump, 0x3F0000, 0x10000, +coredump, data, coredump,0x3F0000, 0x10000, diff --git a/tools/partitions/rainmaker_4MB_no_ota.csv b/tools/partitions/rainmaker_4MB_no_ota.csv new file mode 100644 index 00000000000..ec10004d158 --- /dev/null +++ b/tools/partitions/rainmaker_4MB_no_ota.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +ota_0, app, ota_0, 0x10000, 0x3DA000, +fctry, data, nvs, 0x3EA000, 0x6000, +coredump, data, coredump,0x3F0000, 0x10000, diff --git a/tools/partitions/rainmaker_8MB.csv b/tools/partitions/rainmaker_8MB.csv new file mode 100644 index 00000000000..6d65333063f --- /dev/null +++ b/tools/partitions/rainmaker_8MB.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +ota_0, app, ota_0, 0x10000, 0x3ED000, +ota_1, app, ota_1, 0x3FD000, 0x3ED000, +fctry, data, nvs, 0x7EA000, 0x6000, +coredump, data, coredump,0x7F0000, 0x10000, diff --git a/tools/partitions/zigbee_2MB.csv b/tools/partitions/zigbee_2MB.csv new file mode 100644 index 00000000000..7034f9bd49b --- /dev/null +++ b/tools/partitions/zigbee_2MB.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +factory, app, factory, 0x10000, 0x140000, +spiffs, data, spiffs, 0x150000,0x9B000, +zb_storage, data, fat, 0x1EB000,0x4000, +zb_fct, data, fat, 0x1EF000,0x1000, +coredump, data, coredump,0x1F0000,0x10000, diff --git a/tools/partitions/zigbee_8MB.csv b/tools/partitions/zigbee_8MB.csv new file mode 100644 index 00000000000..fdf46fb59d1 --- /dev/null +++ b/tools/partitions/zigbee_8MB.csv @@ -0,0 +1,9 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x340000, +app1, app, ota_1, 0x350000,0x340000, +spiffs, data, spiffs, 0x690000,0x15B000, +zb_storage, data, fat, 0x7EB000,0x4000, +zb_fct, data, fat, 0x7EF000,0x1000, +coredump, data, coredump,0x7F0000,0x10000, diff --git a/tools/partitions/zigbee_zczr_2MB.csv b/tools/partitions/zigbee_zczr_2MB.csv new file mode 100644 index 00000000000..10484eeed87 --- /dev/null +++ b/tools/partitions/zigbee_zczr_2MB.csv @@ -0,0 +1,8 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +factory, app, factory, 0x10000, 0x140000, +spiffs, data, spiffs, 0x150000,0x9A000, +zb_storage, data, fat, 0x1EA000,0x4000, +zb_fct, data, fat, 0x1EE000,0x1000, +rcp_fw, data, spiffs, 0x1EF000,0x1000, +coredump, data, coredump,0x1F0000,0x10000, diff --git a/tools/partitions/zigbee_zczr_8MB.csv b/tools/partitions/zigbee_zczr_8MB.csv new file mode 100644 index 00000000000..70dd680dc1a --- /dev/null +++ b/tools/partitions/zigbee_zczr_8MB.csv @@ -0,0 +1,10 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x340000, +app1, app, ota_1, 0x350000,0x340000, +spiffs, data, spiffs, 0x690000,0x15A000, +zb_storage, data, fat, 0x7EA000,0x4000, +zb_fct, data, fat, 0x7EE000,0x1000, +rcp_fw, data, spiffs, 0x7EF000,0x1000, +coredump, data, coredump,0x7F0000,0x10000, diff --git a/tools/platformio-build.py b/tools/pioarduino-build.py similarity index 95% rename from tools/platformio-build.py rename to tools/pioarduino-build.py index 06b5dac2e1b..3335a716888 100644 --- a/tools/platformio-build.py +++ b/tools/pioarduino-build.py @@ -22,7 +22,7 @@ http://arduino.cc/en/Reference/HomePage """ -# Extends: https://github.com/platformio/platform-espressif32/blob/develop/builder/main.py +# Extends: https://github.com/pioarduino/platform-espressif32/blob/develop/builder/main.py from os.path import abspath, basename, isdir, isfile, join from copy import deepcopy @@ -160,10 +160,19 @@ def add_tinyuf2_extra_image(): join( FRAMEWORK_LIBS_DIR, build_mcu, - "platformio-build.py", + "pioarduino-build.py", ) ) +# +# Additional flags specific to Arduino core (not based on IDF) +# + +env.Append( + CFLAGS=["-Werror=return-type"], + CXXFLAGS=["-Werror=return-type"], +) + # # Target: Build Core Library # @@ -204,7 +213,7 @@ def add_tinyuf2_extra_image(): LIBSOURCE_DIRS=[join(FRAMEWORK_DIR, "libraries")], FLASH_EXTRA_IMAGES=[ ( - "0x1000" if build_mcu in ("esp32", "esp32s2") else "0x0000", + "0x1000" if build_mcu in ["esp32", "esp32s2"] else ("0x2000" if build_mcu in ["esp32p4"] else "0x0000"), get_bootloader_image(variants_dir), ), ("0x8000", join(env.subst("$BUILD_DIR"), "partitions.bin")), diff --git a/tools/pre-commit/requirements.txt b/tools/pre-commit/requirements.txt index 10db94a1393..aca4a61191f 100644 --- a/tools/pre-commit/requirements.txt +++ b/tools/pre-commit/requirements.txt @@ -1,2 +1,2 @@ -pre-commit==3.7.1 -docutils==0.21.2 +pre-commit==4.0.1 +docutils==0.16 diff --git a/variants/Bee_Data_Logger/pins_arduino.h b/variants/Bee_Data_Logger/pins_arduino.h index 9924e2eb38a..1114ff0bdd3 100644 --- a/variants/Bee_Data_Logger/pins_arduino.h +++ b/variants/Bee_Data_Logger/pins_arduino.h @@ -65,12 +65,12 @@ static const uint8_t LDO2 = 34; static const uint8_t RGB_DATA = 40; static const uint8_t RGB_PWR = 34; -#define PIN_NEOPIXEL RGB_DATA +#define PIN_RGB_LED RGB_DATA // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/Bee_Motion_S3/pins_arduino.h b/variants/Bee_Motion_S3/pins_arduino.h index a319f5ec161..45f73b56ba0 100644 --- a/variants/Bee_Motion_S3/pins_arduino.h +++ b/variants/Bee_Motion_S3/pins_arduino.h @@ -73,12 +73,12 @@ static const uint8_t LDO2 = 34; static const uint8_t RGB_DATA = 40; static const uint8_t RGB_PWR = 34; -#define PIN_NEOPIXEL RGB_DATA +#define PIN_RGB_LED RGB_DATA // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/Bee_S3/pins_arduino.h b/variants/Bee_S3/pins_arduino.h index b8bdd7f1d3b..9e76fff803e 100644 --- a/variants/Bee_S3/pins_arduino.h +++ b/variants/Bee_S3/pins_arduino.h @@ -62,12 +62,12 @@ static const uint8_t VBAT_VOLTAGE = 1; static const uint8_t RGB_DATA = 48; static const uint8_t RGB_PWR = 34; -#define PIN_NEOPIXEL RGB_DATA +#define PIN_RGB_LED RGB_DATA // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/BharatPi-A7672S-4G/pins_arduino.h b/variants/BharatPi-A7672S-4G/pins_arduino.h new file mode 100644 index 00000000000..bf1fab09ddc --- /dev/null +++ b/variants/BharatPi-A7672S-4G/pins_arduino.h @@ -0,0 +1,31 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +static const uint8_t LED_BUILTIN = 2; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t A0 = 14; +static const uint8_t A1 = 13; +static const uint8_t A2 = 12; +static const uint8_t A3 = 4; +static const uint8_t A4 = 2; +static const uint8_t A5 = 0; + +static const uint8_t TX = 1; +static const uint8_t RX = 3; + +static const uint8_t TX_4G = 17; +static const uint8_t RX_4G = 16; + +static const uint8_t SDA = 21; +static const uint8_t SCL = 22; + +static const uint8_t SS = 5; +static const uint8_t MOSI = 23; +static const uint8_t MISO = 19; +static const uint8_t SCK = 18; + +#endif /* Pins_Arduino_h */ diff --git a/variants/BharatPi-LoRa/pins_arduino.h b/variants/BharatPi-LoRa/pins_arduino.h new file mode 100644 index 00000000000..a42e5834a3a --- /dev/null +++ b/variants/BharatPi-LoRa/pins_arduino.h @@ -0,0 +1,35 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +static const uint8_t LED_BUILTIN = 2; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t A0 = 14; +static const uint8_t A1 = 13; +static const uint8_t A2 = 12; +static const uint8_t A3 = 4; +static const uint8_t A4 = 2; +static const uint8_t A5 = 0; + +static const uint8_t TX = 1; +static const uint8_t RX = 3; + +static const uint8_t TX2 = 17; +static const uint8_t RX2 = 16; + +static const uint8_t LORA_SS = 4; +static const uint8_t RST = 14; +static const uint8_t DIO0 = 2; + +static const uint8_t SDA = 21; +static const uint8_t SCL = 22; + +static const uint8_t SS = 5; +static const uint8_t MOSI = 23; +static const uint8_t MISO = 19; +static const uint8_t SCK = 18; + +#endif /* Pins_Arduino_h */ diff --git a/variants/BharatPi-Node-Wifi/pins_arduino.h b/variants/BharatPi-Node-Wifi/pins_arduino.h new file mode 100644 index 00000000000..3b151289f44 --- /dev/null +++ b/variants/BharatPi-Node-Wifi/pins_arduino.h @@ -0,0 +1,35 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +static const uint8_t LED_BUILTIN = 2; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t SAFFRON_LED = 12; +static const uint8_t WHITE_LED = 2; +static const uint8_t GREEN_LED = 13; + +static const uint8_t A0 = 14; +static const uint8_t A1 = 13; +static const uint8_t A2 = 12; +static const uint8_t A3 = 4; +static const uint8_t A4 = 2; +static const uint8_t A5 = 0; + +static const uint8_t TX = 1; +static const uint8_t RX = 3; + +static const uint8_t TX2 = 17; +static const uint8_t RX2 = 16; + +static const uint8_t SDA = 21; +static const uint8_t SCL = 22; + +static const uint8_t SS = 5; +static const uint8_t MOSI = 23; +static const uint8_t MISO = 19; +static const uint8_t SCK = 18; + +#endif /* Pins_Arduino_h */ diff --git a/variants/Geekble_ESP32C3/pins_arduino.h b/variants/Geekble_ESP32C3/pins_arduino.h index 4eec3aa2f68..660313ce849 100644 --- a/variants/Geekble_ESP32C3/pins_arduino.h +++ b/variants/Geekble_ESP32C3/pins_arduino.h @@ -27,6 +27,6 @@ static const uint8_t A1 = 1; static const uint8_t A2 = 2; static const uint8_t A3 = 3; static const uint8_t A4 = 4; -static const uint8_t A5 = 5; +//static const uint8_t A5 = 5; // ADC1 no longer supported #endif /* Pins_Arduino_h */ diff --git a/variants/Geekble_Nano_ESP32S3/pins_arduino.h b/variants/Geekble_Nano_ESP32S3/pins_arduino.h new file mode 100644 index 00000000000..657c0d5d51b --- /dev/null +++ b/variants/Geekble_Nano_ESP32S3/pins_arduino.h @@ -0,0 +1,74 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x82C5 +#define USB_MANUFACTURER "Geekble" +#define USB_PRODUCT "Geekble nano ESP32-S3" +#define USB_SERIAL "" // Empty string for MAC address + +static const uint8_t D0 = 44; // also RX +static const uint8_t D1 = 43; // also TX +static const uint8_t D2 = 5; +static const uint8_t D3 = 6; // also CTS +static const uint8_t D4 = 7; // also DSR +static const uint8_t D5 = 8; +static const uint8_t D6 = 9; +static const uint8_t D7 = 10; +static const uint8_t D8 = 17; +static const uint8_t D9 = 18; +static const uint8_t D10 = 21; // also SS +static const uint8_t D11 = 38; // also MOSI +static const uint8_t D12 = 47; // also MISO +static const uint8_t D13 = 48; // also SCK, LED_BUILTIN + +static const uint8_t A0 = 1; // also DTR +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 11; // also SDA +static const uint8_t A5 = 12; // also SCL +static const uint8_t A6 = 13; +static const uint8_t A7 = 14; + +// alternate pin functions + +static const uint8_t LED_BUILTIN = D13; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t SW_BUILTIN = 0; + +static const uint8_t TX = D1; +static const uint8_t RX = D0; +static const uint8_t RTS = 45; +static const uint8_t CTS = D3; +static const uint8_t DTR = A0; +static const uint8_t DSR = D4; + +static const uint8_t SS = D10; +static const uint8_t MOSI = D11; +static const uint8_t MISO = D12; +static const uint8_t SCK = D13; + +static const uint8_t SDA = A4; +static const uint8_t SCL = A5; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#define PIN_I2S_SCK D7 +#define PIN_I2S_FS D8 +#define PIN_I2S_SD D9 +#define PIN_I2S_SD_OUT D9 // same as bidir +#define PIN_I2S_SD_IN D10 + +#endif /* Pins_Arduino_h */ diff --git a/variants/Pcbcupid_GLYPH_C3/pins_arduino.h b/variants/Pcbcupid_GLYPH_C3/pins_arduino.h new file mode 100644 index 00000000000..653c2c48828 --- /dev/null +++ b/variants/Pcbcupid_GLYPH_C3/pins_arduino.h @@ -0,0 +1,43 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = 1; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +//MSR Used in on-board battery measurement +static const uint8_t BAT_MEASURE = 0; +#define MSR BAT_MEASURE + +static const uint8_t TX = 21; +static const uint8_t RX = 20; + +static const uint8_t SDA = 4; +static const uint8_t SCL = 5; + +static const uint8_t SS = 3; +static const uint8_t MOSI = 6; +static const uint8_t MISO = 7; +static const uint8_t SCK = 10; + +static const uint8_t A0 = 0; +static const uint8_t A1 = 1; +static const uint8_t A2 = 2; +static const uint8_t A3 = 3; + +static const uint8_t D0 = 0; +static const uint8_t D1 = 1; +static const uint8_t D2 = 2; +static const uint8_t D3 = 3; +static const uint8_t D4 = 4; +static const uint8_t D5 = 5; +static const uint8_t D6 = 6; +static const uint8_t D7 = 7; +static const uint8_t D8 = 8; +static const uint8_t D9 = 9; +static const uint8_t D10 = 10; + +#endif /* Pins_Arduino_h */ diff --git a/variants/Pcbcupid_GLYPH_C6/pins_arduino.h b/variants/Pcbcupid_GLYPH_C6/pins_arduino.h new file mode 100644 index 00000000000..f06fb151244 --- /dev/null +++ b/variants/Pcbcupid_GLYPH_C6/pins_arduino.h @@ -0,0 +1,52 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = 14; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +//MSR Used in on-board battery measurement +static const uint8_t BAT_MEASURE = 0; +#define MSR BAT_MEASURE + +static const uint8_t TX = 16; +static const uint8_t RX = 17; + +static const uint8_t SDA = 4; +static const uint8_t SCL = 5; + +static const uint8_t SS = 20; +static const uint8_t MOSI = 22; +static const uint8_t MISO = 23; +static const uint8_t SCK = 21; + +static const uint8_t A0 = 0; +static const uint8_t A1 = 1; +static const uint8_t A2 = 2; +static const uint8_t A3 = 3; + +static const uint8_t D0 = 0; +static const uint8_t D1 = 1; +static const uint8_t D2 = 2; +static const uint8_t D3 = 3; +static const uint8_t D4 = 4; +static const uint8_t D5 = 5; +static const uint8_t D6 = 6; +static const uint8_t D7 = 7; +static const uint8_t D8 = 8; +static const uint8_t D9 = 9; +static const uint8_t D14 = 14; +static const uint8_t D15 = 15; +static const uint8_t D16 = 16; +static const uint8_t D17 = 17; +static const uint8_t D18 = 18; +static const uint8_t D19 = 19; +static const uint8_t D20 = 20; +static const uint8_t D21 = 21; +static const uint8_t D22 = 22; +static const uint8_t D23 = 23; + +#endif /* Pins_Arduino_h */ diff --git a/variants/Pcbcupid_GLYPH_H2/pins_arduino.h b/variants/Pcbcupid_GLYPH_H2/pins_arduino.h new file mode 100644 index 00000000000..20a385a9817 --- /dev/null +++ b/variants/Pcbcupid_GLYPH_H2/pins_arduino.h @@ -0,0 +1,44 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = 0; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +//MSR Used in on-board battery measurement +static const uint8_t BAT_MEASURE = 1; +#define MSR BAT_MEASURE + +static const uint8_t TX = 24; +static const uint8_t RX = 23; + +static const uint8_t SDA = 4; +static const uint8_t SCL = 5; + +static const uint8_t SS = 3; +static const uint8_t MOSI = 22; +static const uint8_t MISO = 25; +static const uint8_t SCK = 11; + +static const uint8_t A1 = 1; +static const uint8_t A2 = 2; +static const uint8_t A3 = 3; + +static const uint8_t D0 = 0; +static const uint8_t D1 = 1; +static const uint8_t D2 = 2; +static const uint8_t D3 = 3; +static const uint8_t D4 = 4; +static const uint8_t D5 = 5; +static const uint8_t D8 = 8; +static const uint8_t D9 = 9; +static const uint8_t D10 = 10; +static const uint8_t D11 = 11; +static const uint8_t D12 = 12; +static const uint8_t D13 = 13; +static const uint8_t D14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/ViraLink-G0.1/pins_arduino.h b/variants/ViraLink-G0.1/pins_arduino.h new file mode 100644 index 00000000000..7e11a91ce18 --- /dev/null +++ b/variants/ViraLink-G0.1/pins_arduino.h @@ -0,0 +1,46 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +static const uint8_t LED_BUILTIN = 5; +#define BUILTIN_LED LED_BUILTIN +#define LED_BUILTIN LED_BUILTIN + +static const uint8_t RESET_KEY = 0; + +static const uint8_t RS485_TX = 32; +static const uint8_t RS485_RX = 35; + +static const uint8_t SDA = 4; +static const uint8_t SCL = 16; + +static const uint8_t BUZZER = 12; +static const uint8_t RELAY1_PIN = 2; +static const uint8_t RELAY2_PIN = 13; +static const uint8_t RELAY3_PIN = 14; +static const uint8_t RELAY4_PIN = 33; + +static const uint8_t Wiegand1_D0 = 15; +static const uint8_t Wiegand1_D1 = 34; + +static const uint8_t Wiegand2_D0 = 39; +static const uint8_t Wiegand2_D1 = 36; + +static const uint8_t ETH_CLK_OUT = 17; + +static const uint8_t EMAC_MDIO = 18; +static const uint8_t EMAC_TXD0 = 19; +static const uint8_t EMAC_TX_EN = 21; +static const uint8_t EMAC_TXD1 = 22; +static const uint8_t EMAC_MDC = 23; +static const uint8_t EMAC_RXD0 = 25; +static const uint8_t EMAC_RXD1 = 26; +static const uint8_t EMAC_RXD_DV = 27; + +static const uint8_t SS = -1; +static const uint8_t MOSI = -1; +static const uint8_t SCK = -1; +static const uint8_t MISO = -1; + +#endif /* Pins_Arduino_h */ diff --git a/variants/ViraLink-G1.1/pins_arduino.h b/variants/ViraLink-G1.1/pins_arduino.h new file mode 100644 index 00000000000..e509b0d0e79 --- /dev/null +++ b/variants/ViraLink-G1.1/pins_arduino.h @@ -0,0 +1,50 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +static const uint8_t RESET_KEY = 0; + +static const uint8_t RF433 = 5; + +static const uint8_t RS485_TX = 32; +static const uint8_t RS485_RX = 35; + +static const uint8_t GSM1_TX = 15; +static const uint8_t GSM1_RX = 34; + +static const uint8_t GSM2_TX = 32; +static const uint8_t GSM2_RX = 35; + +static const uint8_t GSM_PWR = 33; + +static const uint8_t SDA = 4; +static const uint8_t SCL = 16; + +static const uint8_t EXT1 = 12; +static const uint8_t EXT2 = 13; +static const uint8_t PCF1_INT = 14; + +static const uint8_t Wiegand1_D0 = 15; +static const uint8_t Wiegand1_D1 = 34; + +static const uint8_t Wiegand2_D0 = 39; +static const uint8_t Wiegand2_D1 = 36; + +static const uint8_t ETH_CLK_OUT = 17; + +static const uint8_t EMAC_MDIO = 18; +static const uint8_t EMAC_TXD0 = 19; +static const uint8_t EMAC_TX_EN = 21; +static const uint8_t EMAC_TXD1 = 22; +static const uint8_t EMAC_MDC = 23; +static const uint8_t EMAC_RXD0 = 25; +static const uint8_t EMAC_RXD1 = 26; +static const uint8_t EMAC_RXD_DV = 27; + +static const uint8_t SS = -1; +static const uint8_t MOSI = -1; +static const uint8_t SCK = -1; +static const uint8_t MISO = -1; + +#endif /* Pins_Arduino_h */ diff --git a/variants/XIAO_ESP32C3/pins_arduino.h b/variants/XIAO_ESP32C3/pins_arduino.h index ca89c5f557e..061e743f523 100644 --- a/variants/XIAO_ESP32C3/pins_arduino.h +++ b/variants/XIAO_ESP32C3/pins_arduino.h @@ -17,7 +17,6 @@ static const uint8_t SCK = 8; static const uint8_t A0 = 2; static const uint8_t A1 = 3; static const uint8_t A2 = 4; -static const uint8_t A3 = 5; static const uint8_t D0 = 2; static const uint8_t D1 = 3; diff --git a/variants/XIAO_ESP32C6/pins_arduino.h b/variants/XIAO_ESP32C6/pins_arduino.h index 4eb07fb2ac7..c90a3394237 100644 --- a/variants/XIAO_ESP32C6/pins_arduino.h +++ b/variants/XIAO_ESP32C6/pins_arduino.h @@ -41,4 +41,7 @@ static const uint8_t D8 = 19; static const uint8_t D9 = 20; static const uint8_t D10 = 18; +static const uint8_t WIFI_ENABLE = 3; +static const uint8_t WIFI_ANT_CONFIG = 14; + #endif /* Pins_Arduino_h */ diff --git a/variants/XIAO_ESP32C6/variant.cpp b/variants/XIAO_ESP32C6/variant.cpp new file mode 100644 index 00000000000..07bd8489c72 --- /dev/null +++ b/variants/XIAO_ESP32C6/variant.cpp @@ -0,0 +1,21 @@ +/* +*By setting the WIFI_ENABLE and WIFI_ANT_CONFIG pins, +* +*the XIAO_ESP32C6 will turn on the on-board antenna by default after power-on +* +*https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/ +*/ + +#include "esp32-hal-gpio.h" +#include "pins_arduino.h" + +extern "C" { + +void initVariant(void) { + pinMode(WIFI_ENABLE, OUTPUT); + digitalWrite(WIFI_ENABLE, LOW); //turn on this function + + pinMode(WIFI_ANT_CONFIG, OUTPUT); + digitalWrite(WIFI_ANT_CONFIG, LOW); //use built-in antenna, set HIGH to use external antenna +} +} diff --git a/variants/XIAO_ESP32S3_Plus/bootloader-tinyuf2.bin b/variants/XIAO_ESP32S3_Plus/bootloader-tinyuf2.bin new file mode 100644 index 00000000000..b11e5b236f0 Binary files /dev/null and b/variants/XIAO_ESP32S3_Plus/bootloader-tinyuf2.bin differ diff --git a/variants/XIAO_ESP32S3_Plus/partitions-8MB.csv b/variants/XIAO_ESP32S3_Plus/partitions-8MB.csv new file mode 100644 index 00000000000..4026378b6fb --- /dev/null +++ b/variants/XIAO_ESP32S3_Plus/partitions-8MB.csv @@ -0,0 +1,10 @@ +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +# bootloader.bin,, 0x1000, 32K +# partition table,, 0x8000, 4K +nvs, data, nvs, 0x9000, 20K, +otadata, data, ota, 0xe000, 8K, +ota_0, 0, ota_0, 0x10000, 2048K, +ota_1, 0, ota_1, 0x210000, 2048K, +uf2, app, factory,0x410000, 256K, +ffat, data, fat, 0x450000, 3776K, diff --git a/variants/XIAO_ESP32S3_Plus/pins_arduino.h b/variants/XIAO_ESP32S3_Plus/pins_arduino.h new file mode 100644 index 00000000000..fb887287e35 --- /dev/null +++ b/variants/XIAO_ESP32S3_Plus/pins_arduino.h @@ -0,0 +1,90 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x2886 +#define USB_PID 0x0056 + +static const uint8_t LED_BUILTIN = 21; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t TX1 = 42; +static const uint8_t RX1 = 41; + +static const uint8_t SDA = 5; +static const uint8_t SCL = 6; + +static const uint8_t SS = 44; +static const uint8_t MOSI = 9; +static const uint8_t MISO = 8; +static const uint8_t SCK = 7; + +static const uint8_t MOSI1 = 11; +static const uint8_t MISO1 = 12; +static const uint8_t SCK1 = 13; + +static const uint8_t I2S_SCK = 39; +static const uint8_t I2S_SD = 38; +static const uint8_t I2S_WS = 40; + +static const uint8_t MTCK = 39; +static const uint8_t MTDO = 40; +static const uint8_t MTDI = 41; +static const uint8_t MTMS = 42; + +static const uint8_t DVP_Y8 = 11; +static const uint8_t DVP_YP = 12; +static const uint8_t DVP_PCLK = 13; +static const uint8_t DVP_VSYNC = 38; +static const uint8_t CAM_SCL = 39; +static const uint8_t CAM_SDA = 40; +static const uint8_t XMCLK = 10; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A8 = 7; +static const uint8_t A9 = 8; +static const uint8_t A10 = 9; +static const uint8_t ADC_BAT = 10; + +static const uint8_t D0 = 1; +static const uint8_t D1 = 2; +static const uint8_t D2 = 3; +static const uint8_t D3 = 4; +static const uint8_t D4 = 5; +static const uint8_t D5 = 6; +static const uint8_t D6 = 43; +static const uint8_t D7 = 44; +static const uint8_t D8 = 7; +static const uint8_t D9 = 8; +static const uint8_t D10 = 9; +static const uint8_t D11 = 38; +static const uint8_t D12 = 39; +static const uint8_t D13 = 40; +static const uint8_t D14 = 41; +static const uint8_t D15 = 42; +static const uint8_t D16 = 10; +static const uint8_t D17 = 13; +static const uint8_t D18 = 12; +static const uint8_t D19 = 11; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; + +#endif /* Pins_Arduino_h */ diff --git a/variants/XIAO_ESP32S3_Plus/tinyuf2.bin b/variants/XIAO_ESP32S3_Plus/tinyuf2.bin new file mode 100644 index 00000000000..86d981f8019 Binary files /dev/null and b/variants/XIAO_ESP32S3_Plus/tinyuf2.bin differ diff --git a/variants/adafruit_camera_esp32s3/bootloader-tinyuf2.bin b/variants/adafruit_camera_esp32s3/bootloader-tinyuf2.bin index f0169612e13..ef4e3bf6fd1 100644 Binary files a/variants/adafruit_camera_esp32s3/bootloader-tinyuf2.bin and b/variants/adafruit_camera_esp32s3/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_camera_esp32s3/pins_arduino.h b/variants/adafruit_camera_esp32s3/pins_arduino.h index 8560b44f4fb..447204f7345 100644 --- a/variants/adafruit_camera_esp32s3/pins_arduino.h +++ b/variants/adafruit_camera_esp32s3/pins_arduino.h @@ -18,7 +18,7 @@ static const uint8_t NEOPIXEL_PIN = 1; static const uint8_t LED_BUILTIN = PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_camera_esp32s3/tinyuf2.bin b/variants/adafruit_camera_esp32s3/tinyuf2.bin index 0247a171331..5eb3429b516 100644 Binary files a/variants/adafruit_camera_esp32s3/tinyuf2.bin and b/variants/adafruit_camera_esp32s3/tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32_v2/pins_arduino.h b/variants/adafruit_feather_esp32_v2/pins_arduino.h index 89bd844e3b5..f4af72aa98b 100644 --- a/variants/adafruit_feather_esp32_v2/pins_arduino.h +++ b/variants/adafruit_feather_esp32_v2/pins_arduino.h @@ -46,7 +46,7 @@ static const uint8_t LED_BUILTIN = 13; // Neopixel #define PIN_NEOPIXEL 0 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_feather_esp32c6/pins_arduino.h b/variants/adafruit_feather_esp32c6/pins_arduino.h new file mode 100644 index 00000000000..c4ae4bab3fe --- /dev/null +++ b/variants/adafruit_feather_esp32c6/pins_arduino.h @@ -0,0 +1,38 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define PIN_NEOPIXEL 9 +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = 15; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() +#define RGB_BUILTIN (SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL) +#define RGB_BRIGHTNESS 64 + +#define NEOPIXEL_I2C_POWER 20 // I2C power pin +#define PIN_NEOPIXEL_I2C_POWER 20 // I2C power pin + +static const uint8_t TX = 16; +static const uint8_t RX = 17; + +static const uint8_t SDA = 19; +static const uint8_t SCL = 18; + +static const uint8_t SS = 0; +static const uint8_t MOSI = 22; +static const uint8_t MISO = 23; +static const uint8_t SCK = 21; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 4; +static const uint8_t A2 = 6; +static const uint8_t A3 = 5; +static const uint8_t A4 = 3; +static const uint8_t A5 = 2; +static const uint8_t A6 = 0; + +#endif /* Pins_Arduino_h */ diff --git a/variants/adafruit_feather_esp32c6/variant.cpp b/variants/adafruit_feather_esp32c6/variant.cpp new file mode 100644 index 00000000000..576afb6b228 --- /dev/null +++ b/variants/adafruit_feather_esp32c6/variant.cpp @@ -0,0 +1,37 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Ha Thach (tinyusb.org) for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "esp32-hal-gpio.h" +#include "pins_arduino.h" + +extern "C" { + +// Initialize variant/board, called before setup() +void initVariant(void) { + // This board has a power control pin, and we must set it to output and high + // in order to enable the NeoPixels & I2C + pinMode(NEOPIXEL_I2C_POWER, OUTPUT); + digitalWrite(NEOPIXEL_I2C_POWER, HIGH); +} +} diff --git a/variants/adafruit_feather_esp32s2/bootloader-tinyuf2.bin b/variants/adafruit_feather_esp32s2/bootloader-tinyuf2.bin index 6b885eb4e50..0c49080d571 100644 Binary files a/variants/adafruit_feather_esp32s2/bootloader-tinyuf2.bin and b/variants/adafruit_feather_esp32s2/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s2/pins_arduino.h b/variants/adafruit_feather_esp32s2/pins_arduino.h index 2e04e95e605..72ab65a8d33 100644 --- a/variants/adafruit_feather_esp32s2/pins_arduino.h +++ b/variants/adafruit_feather_esp32s2/pins_arduino.h @@ -16,7 +16,7 @@ // Neopixel #define PIN_NEOPIXEL 33 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_feather_esp32s2/tinyuf2.bin b/variants/adafruit_feather_esp32s2/tinyuf2.bin index 82b0d2aee8c..40a8f04f924 100644 Binary files a/variants/adafruit_feather_esp32s2/tinyuf2.bin and b/variants/adafruit_feather_esp32s2/tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s2_reversetft/bootloader-tinyuf2.bin b/variants/adafruit_feather_esp32s2_reversetft/bootloader-tinyuf2.bin index 12d2166aaa5..e4d6a498eb1 100644 Binary files a/variants/adafruit_feather_esp32s2_reversetft/bootloader-tinyuf2.bin and b/variants/adafruit_feather_esp32s2_reversetft/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s2_reversetft/pins_arduino.h b/variants/adafruit_feather_esp32s2_reversetft/pins_arduino.h index 22c9e938007..92902cc1622 100644 --- a/variants/adafruit_feather_esp32s2_reversetft/pins_arduino.h +++ b/variants/adafruit_feather_esp32s2_reversetft/pins_arduino.h @@ -16,7 +16,7 @@ // Neopixel #define PIN_NEOPIXEL 33 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_feather_esp32s2_reversetft/tinyuf2.bin b/variants/adafruit_feather_esp32s2_reversetft/tinyuf2.bin index b223d53f658..ff6eb115dba 100644 Binary files a/variants/adafruit_feather_esp32s2_reversetft/tinyuf2.bin and b/variants/adafruit_feather_esp32s2_reversetft/tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s2_tft/bootloader-tinyuf2.bin b/variants/adafruit_feather_esp32s2_tft/bootloader-tinyuf2.bin index 0c4e5968eab..aa7cb519661 100644 Binary files a/variants/adafruit_feather_esp32s2_tft/bootloader-tinyuf2.bin and b/variants/adafruit_feather_esp32s2_tft/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s2_tft/pins_arduino.h b/variants/adafruit_feather_esp32s2_tft/pins_arduino.h index 2717d441f7c..8c3059acb6e 100644 --- a/variants/adafruit_feather_esp32s2_tft/pins_arduino.h +++ b/variants/adafruit_feather_esp32s2_tft/pins_arduino.h @@ -16,7 +16,7 @@ // Neopixel #define PIN_NEOPIXEL 33 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_feather_esp32s2_tft/tinyuf2.bin b/variants/adafruit_feather_esp32s2_tft/tinyuf2.bin index 22fccd4926b..b8334f98220 100644 Binary files a/variants/adafruit_feather_esp32s2_tft/tinyuf2.bin and b/variants/adafruit_feather_esp32s2_tft/tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s3/bootloader-tinyuf2.bin b/variants/adafruit_feather_esp32s3/bootloader-tinyuf2.bin index 01e82101211..8a04549dad5 100644 Binary files a/variants/adafruit_feather_esp32s3/bootloader-tinyuf2.bin and b/variants/adafruit_feather_esp32s3/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s3/pins_arduino.h b/variants/adafruit_feather_esp32s3/pins_arduino.h index 679014b4df5..991a57c9eba 100644 --- a/variants/adafruit_feather_esp32s3/pins_arduino.h +++ b/variants/adafruit_feather_esp32s3/pins_arduino.h @@ -16,7 +16,7 @@ // Neopixel #define PIN_NEOPIXEL 33 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_feather_esp32s3/tinyuf2.bin b/variants/adafruit_feather_esp32s3/tinyuf2.bin index 5f9d486d3f9..d76bd75c297 100644 Binary files a/variants/adafruit_feather_esp32s3/tinyuf2.bin and b/variants/adafruit_feather_esp32s3/tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s3_nopsram/bootloader-tinyuf2.bin b/variants/adafruit_feather_esp32s3_nopsram/bootloader-tinyuf2.bin index cc6033500b6..9cca9d28a05 100644 Binary files a/variants/adafruit_feather_esp32s3_nopsram/bootloader-tinyuf2.bin and b/variants/adafruit_feather_esp32s3_nopsram/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s3_nopsram/pins_arduino.h b/variants/adafruit_feather_esp32s3_nopsram/pins_arduino.h index 0fd8b1e91ba..34fe2ebae2c 100644 --- a/variants/adafruit_feather_esp32s3_nopsram/pins_arduino.h +++ b/variants/adafruit_feather_esp32s3_nopsram/pins_arduino.h @@ -16,7 +16,7 @@ // Neopixel #define PIN_NEOPIXEL 33 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_feather_esp32s3_nopsram/tinyuf2.bin b/variants/adafruit_feather_esp32s3_nopsram/tinyuf2.bin index a5bab006bca..c345a5b8ce5 100644 Binary files a/variants/adafruit_feather_esp32s3_nopsram/tinyuf2.bin and b/variants/adafruit_feather_esp32s3_nopsram/tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s3_reversetft/bootloader-tinyuf2.bin b/variants/adafruit_feather_esp32s3_reversetft/bootloader-tinyuf2.bin index 57df9ed036f..4e92bba7a71 100644 Binary files a/variants/adafruit_feather_esp32s3_reversetft/bootloader-tinyuf2.bin and b/variants/adafruit_feather_esp32s3_reversetft/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s3_reversetft/pins_arduino.h b/variants/adafruit_feather_esp32s3_reversetft/pins_arduino.h index 4f76626a50b..ea955ff54f5 100644 --- a/variants/adafruit_feather_esp32s3_reversetft/pins_arduino.h +++ b/variants/adafruit_feather_esp32s3_reversetft/pins_arduino.h @@ -16,7 +16,7 @@ // Neopixel #define PIN_NEOPIXEL 33 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_feather_esp32s3_reversetft/tinyuf2.bin b/variants/adafruit_feather_esp32s3_reversetft/tinyuf2.bin index 7e852a31efd..70f80cf1dd3 100644 Binary files a/variants/adafruit_feather_esp32s3_reversetft/tinyuf2.bin and b/variants/adafruit_feather_esp32s3_reversetft/tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s3_tft/bootloader-tinyuf2.bin b/variants/adafruit_feather_esp32s3_tft/bootloader-tinyuf2.bin index 80c58ff2a7f..2babca98301 100644 Binary files a/variants/adafruit_feather_esp32s3_tft/bootloader-tinyuf2.bin and b/variants/adafruit_feather_esp32s3_tft/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_feather_esp32s3_tft/pins_arduino.h b/variants/adafruit_feather_esp32s3_tft/pins_arduino.h index 25cc9f785bc..3e007c7706d 100644 --- a/variants/adafruit_feather_esp32s3_tft/pins_arduino.h +++ b/variants/adafruit_feather_esp32s3_tft/pins_arduino.h @@ -16,7 +16,7 @@ // Neopixel #define PIN_NEOPIXEL 33 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_feather_esp32s3_tft/tinyuf2.bin b/variants/adafruit_feather_esp32s3_tft/tinyuf2.bin index fc895760a15..1f2b1d66157 100644 Binary files a/variants/adafruit_feather_esp32s3_tft/tinyuf2.bin and b/variants/adafruit_feather_esp32s3_tft/tinyuf2.bin differ diff --git a/variants/adafruit_funhouse_esp32s2/bootloader-tinyuf2.bin b/variants/adafruit_funhouse_esp32s2/bootloader-tinyuf2.bin index 2729f56c018..7e153e6b117 100644 Binary files a/variants/adafruit_funhouse_esp32s2/bootloader-tinyuf2.bin and b/variants/adafruit_funhouse_esp32s2/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_funhouse_esp32s2/tinyuf2.bin b/variants/adafruit_funhouse_esp32s2/tinyuf2.bin index 9e2422846d5..4cf847944f7 100644 Binary files a/variants/adafruit_funhouse_esp32s2/tinyuf2.bin and b/variants/adafruit_funhouse_esp32s2/tinyuf2.bin differ diff --git a/variants/adafruit_itsybitsy_esp32/pins_arduino.h b/variants/adafruit_itsybitsy_esp32/pins_arduino.h index bd7a09562e3..801dc15da57 100644 --- a/variants/adafruit_itsybitsy_esp32/pins_arduino.h +++ b/variants/adafruit_itsybitsy_esp32/pins_arduino.h @@ -11,7 +11,7 @@ static const uint8_t LED_BUILTIN = 13; // Neopixel static const uint8_t PIN_NEOPIXEL = 0; -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_magtag29_esp32s2/bootloader-tinyuf2.bin b/variants/adafruit_magtag29_esp32s2/bootloader-tinyuf2.bin index 43d83bd3710..eec06c84fa2 100644 Binary files a/variants/adafruit_magtag29_esp32s2/bootloader-tinyuf2.bin and b/variants/adafruit_magtag29_esp32s2/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_magtag29_esp32s2/pins_arduino.h b/variants/adafruit_magtag29_esp32s2/pins_arduino.h index 97977a0a6bc..197f2e4c1aa 100644 --- a/variants/adafruit_magtag29_esp32s2/pins_arduino.h +++ b/variants/adafruit_magtag29_esp32s2/pins_arduino.h @@ -16,7 +16,7 @@ // Neopixel #define PIN_NEOPIXEL 1 // D1 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_magtag29_esp32s2/tinyuf2.bin b/variants/adafruit_magtag29_esp32s2/tinyuf2.bin index 36b7a9bdfd1..7a70be3ef32 100644 Binary files a/variants/adafruit_magtag29_esp32s2/tinyuf2.bin and b/variants/adafruit_magtag29_esp32s2/tinyuf2.bin differ diff --git a/variants/adafruit_matrixportal_esp32s3/bootloader-tinyuf2.bin b/variants/adafruit_matrixportal_esp32s3/bootloader-tinyuf2.bin index dc5dc9e6e28..6f062fea2fe 100644 Binary files a/variants/adafruit_matrixportal_esp32s3/bootloader-tinyuf2.bin and b/variants/adafruit_matrixportal_esp32s3/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_matrixportal_esp32s3/pins_arduino.h b/variants/adafruit_matrixportal_esp32s3/pins_arduino.h index 9d5dd018b74..9843c54c1cd 100644 --- a/variants/adafruit_matrixportal_esp32s3/pins_arduino.h +++ b/variants/adafruit_matrixportal_esp32s3/pins_arduino.h @@ -16,7 +16,7 @@ #define PIN_NEOPIXEL 4 #define NEOPIXEL_PIN 4 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_matrixportal_esp32s3/tinyuf2.bin b/variants/adafruit_matrixportal_esp32s3/tinyuf2.bin index ac5b6e01899..16f7054546b 100644 Binary files a/variants/adafruit_matrixportal_esp32s3/tinyuf2.bin and b/variants/adafruit_matrixportal_esp32s3/tinyuf2.bin differ diff --git a/variants/adafruit_metro_esp32s2/bootloader-tinyuf2.bin b/variants/adafruit_metro_esp32s2/bootloader-tinyuf2.bin index 2646b979fb9..1a98daf73f7 100644 Binary files a/variants/adafruit_metro_esp32s2/bootloader-tinyuf2.bin and b/variants/adafruit_metro_esp32s2/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_metro_esp32s2/pins_arduino.h b/variants/adafruit_metro_esp32s2/pins_arduino.h index 89235f5ab15..cef937d3662 100644 --- a/variants/adafruit_metro_esp32s2/pins_arduino.h +++ b/variants/adafruit_metro_esp32s2/pins_arduino.h @@ -15,7 +15,7 @@ // Neopixel #define PIN_NEOPIXEL 45 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_metro_esp32s2/tinyuf2.bin b/variants/adafruit_metro_esp32s2/tinyuf2.bin index 2ada2351cd3..6763a41df29 100644 Binary files a/variants/adafruit_metro_esp32s2/tinyuf2.bin and b/variants/adafruit_metro_esp32s2/tinyuf2.bin differ diff --git a/variants/adafruit_metro_esp32s3/bootloader-tinyuf2.bin b/variants/adafruit_metro_esp32s3/bootloader-tinyuf2.bin index 2ed855b65a5..03cc2bfe4cf 100644 Binary files a/variants/adafruit_metro_esp32s3/bootloader-tinyuf2.bin and b/variants/adafruit_metro_esp32s3/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_metro_esp32s3/pins_arduino.h b/variants/adafruit_metro_esp32s3/pins_arduino.h index 80beb123e58..9e2cff7e651 100644 --- a/variants/adafruit_metro_esp32s3/pins_arduino.h +++ b/variants/adafruit_metro_esp32s3/pins_arduino.h @@ -15,7 +15,7 @@ // Neopixel #define PIN_NEOPIXEL 46 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking #define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_metro_esp32s3/tinyuf2.bin b/variants/adafruit_metro_esp32s3/tinyuf2.bin index 25a5ba66b1e..d0eaed3f7cf 100644 Binary files a/variants/adafruit_metro_esp32s3/tinyuf2.bin and b/variants/adafruit_metro_esp32s3/tinyuf2.bin differ diff --git a/variants/adafruit_qtpy_esp32/pins_arduino.h b/variants/adafruit_qtpy_esp32/pins_arduino.h index 6080527cdda..b422377d981 100644 --- a/variants/adafruit_qtpy_esp32/pins_arduino.h +++ b/variants/adafruit_qtpy_esp32/pins_arduino.h @@ -11,7 +11,7 @@ static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_qtpy_esp32c3/pins_arduino.h b/variants/adafruit_qtpy_esp32c3/pins_arduino.h index 71affaad7d7..92d2591a806 100644 --- a/variants/adafruit_qtpy_esp32c3/pins_arduino.h +++ b/variants/adafruit_qtpy_esp32c3/pins_arduino.h @@ -13,7 +13,7 @@ static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_qtpy_esp32s2/bootloader-tinyuf2.bin b/variants/adafruit_qtpy_esp32s2/bootloader-tinyuf2.bin index 2c985689ec5..f34e2710bd9 100644 Binary files a/variants/adafruit_qtpy_esp32s2/bootloader-tinyuf2.bin and b/variants/adafruit_qtpy_esp32s2/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_qtpy_esp32s2/pins_arduino.h b/variants/adafruit_qtpy_esp32s2/pins_arduino.h index 9eb04c70467..3baf0808db1 100644 --- a/variants/adafruit_qtpy_esp32s2/pins_arduino.h +++ b/variants/adafruit_qtpy_esp32s2/pins_arduino.h @@ -15,7 +15,7 @@ static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_qtpy_esp32s2/tinyuf2.bin b/variants/adafruit_qtpy_esp32s2/tinyuf2.bin index c4980536d35..008c8a1f9c4 100644 Binary files a/variants/adafruit_qtpy_esp32s2/tinyuf2.bin and b/variants/adafruit_qtpy_esp32s2/tinyuf2.bin differ diff --git a/variants/adafruit_qtpy_esp32s3_n4r2/bootloader-tinyuf2.bin b/variants/adafruit_qtpy_esp32s3_n4r2/bootloader-tinyuf2.bin index ec63e6aff59..301ccf6088c 100644 Binary files a/variants/adafruit_qtpy_esp32s3_n4r2/bootloader-tinyuf2.bin and b/variants/adafruit_qtpy_esp32s3_n4r2/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_qtpy_esp32s3_n4r2/pins_arduino.h b/variants/adafruit_qtpy_esp32s3_n4r2/pins_arduino.h index dc68c1f6998..1202ad1caca 100644 --- a/variants/adafruit_qtpy_esp32s3_n4r2/pins_arduino.h +++ b/variants/adafruit_qtpy_esp32s3_n4r2/pins_arduino.h @@ -18,7 +18,7 @@ static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_qtpy_esp32s3_n4r2/tinyuf2.bin b/variants/adafruit_qtpy_esp32s3_n4r2/tinyuf2.bin index 9df48efaa22..887fd31be65 100644 Binary files a/variants/adafruit_qtpy_esp32s3_n4r2/tinyuf2.bin and b/variants/adafruit_qtpy_esp32s3_n4r2/tinyuf2.bin differ diff --git a/variants/adafruit_qtpy_esp32s3_nopsram/bootloader-tinyuf2.bin b/variants/adafruit_qtpy_esp32s3_nopsram/bootloader-tinyuf2.bin index 70be41209c0..ff0868213e8 100644 Binary files a/variants/adafruit_qtpy_esp32s3_nopsram/bootloader-tinyuf2.bin and b/variants/adafruit_qtpy_esp32s3_nopsram/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_qtpy_esp32s3_nopsram/pins_arduino.h b/variants/adafruit_qtpy_esp32s3_nopsram/pins_arduino.h index 2c42f8c8db8..55b4f4355a9 100644 --- a/variants/adafruit_qtpy_esp32s3_nopsram/pins_arduino.h +++ b/variants/adafruit_qtpy_esp32s3_nopsram/pins_arduino.h @@ -18,7 +18,7 @@ static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/adafruit_qtpy_esp32s3_nopsram/tinyuf2.bin b/variants/adafruit_qtpy_esp32s3_nopsram/tinyuf2.bin index 983de1f1f0d..5dfee90e6e5 100644 Binary files a/variants/adafruit_qtpy_esp32s3_nopsram/tinyuf2.bin and b/variants/adafruit_qtpy_esp32s3_nopsram/tinyuf2.bin differ diff --git a/variants/adafruit_qualia_s3_rgb666/bootloader-tinyuf2.bin b/variants/adafruit_qualia_s3_rgb666/bootloader-tinyuf2.bin index e0b64a8f24a..0d437a3e3a3 100644 Binary files a/variants/adafruit_qualia_s3_rgb666/bootloader-tinyuf2.bin and b/variants/adafruit_qualia_s3_rgb666/bootloader-tinyuf2.bin differ diff --git a/variants/adafruit_qualia_s3_rgb666/tinyuf2.bin b/variants/adafruit_qualia_s3_rgb666/tinyuf2.bin index dd2ef92b724..ed8e9df4bcd 100644 Binary files a/variants/adafruit_qualia_s3_rgb666/tinyuf2.bin and b/variants/adafruit_qualia_s3_rgb666/tinyuf2.bin differ diff --git a/variants/adafruit_sparklemotion_esp32/pins_arduino.h b/variants/adafruit_sparklemotion_esp32/pins_arduino.h new file mode 100644 index 00000000000..99043a9758c --- /dev/null +++ b/variants/adafruit_sparklemotion_esp32/pins_arduino.h @@ -0,0 +1,42 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// User LED +static const uint8_t LED_BUILTIN = 4; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +// Neopixel +static const uint8_t PIN_NEOPIXEL = 2; +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking +#define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) +#define RGB_BRIGHTNESS 64 + +static const uint8_t TX = 9; +static const uint8_t RX = 10; + +#define TX1 TX +#define RX1 RX + +static const uint8_t SDA = 14; +static const uint8_t SCL = 13; + +static const uint8_t SS = 23; +static const uint8_t MOSI = 9; +static const uint8_t MISO = 10; +static const uint8_t SCK = 18; + +static const uint8_t A0 = 27; + +// internal switch +static const uint8_t BUTTON = 0; + +static const uint8_t T0 = 27; + +static const uint8_t DAC1 = 25; +static const uint8_t DAC2 = 26; + +#endif /* Pins_Arduino_h */ diff --git a/variants/adafruit_sparklemotionmini_esp32/pins_arduino.h b/variants/adafruit_sparklemotionmini_esp32/pins_arduino.h new file mode 100644 index 00000000000..2af307de209 --- /dev/null +++ b/variants/adafruit_sparklemotionmini_esp32/pins_arduino.h @@ -0,0 +1,42 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// User LED +static const uint8_t LED_BUILTIN = 12; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +// Neopixel +static const uint8_t PIN_NEOPIXEL = 18; +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking +#define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) +#define RGB_BRIGHTNESS 64 + +static const uint8_t TX = 25; +static const uint8_t RX = 26; + +#define TX1 TX +#define RX1 RX + +static const uint8_t SDA = 19; +static const uint8_t SCL = 22; + +static const uint8_t SS = 14; +static const uint8_t MOSI = 25; +static const uint8_t MISO = 26; +static const uint8_t SCK = 27; + +static const uint8_t A0 = 13; + +// internal switch +static const uint8_t BUTTON = 0; + +static const uint8_t T0 = 13; + +static const uint8_t DAC1 = 25; +static const uint8_t DAC2 = 26; + +#endif /* Pins_Arduino_h */ diff --git a/variants/alfredo-nou3/pins_arduino.h b/variants/alfredo-nou3/pins_arduino.h new file mode 100644 index 00000000000..8b5a7d51b9f --- /dev/null +++ b/variants/alfredo-nou3/pins_arduino.h @@ -0,0 +1,28 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#define USB_VID 0xAFD0 +#define USB_PID 0x0003 +#define USB_MANUFACTURER "Alfredo" +#define USB_PRODUCT "NoU3" +#define USB_SERIAL "" // Empty string for MAC address + +// User LED +#define LED_BUILTIN 45 +#define BUILTIN_LED LED_BUILTIN // backward compatibility + +//static const uint8_t TX = 39; +//static const uint8_t RX = 40; +//#define TX1 TX +//#define RX1 RX + +static const uint8_t SDA = -1; +static const uint8_t SCL = -1; + +static const uint8_t SS = -1; +static const uint8_t MOSI = -1; +static const uint8_t SCK = -1; +static const uint8_t MISO = -1; + +#endif /* Pins_Arduino_h */ diff --git a/variants/arduino_nano_nora/io_pin_remap.cpp b/variants/arduino_nano_nora/io_pin_remap.cpp index 5ed2b0efe89..f615f572905 100644 --- a/variants/arduino_nano_nora/io_pin_remap.cpp +++ b/variants/arduino_nano_nora/io_pin_remap.cpp @@ -10,7 +10,7 @@ // This board uses pin mapping but the build system has disabled it #warning The build system forces the Arduino API to use GPIO numbers on a board that has custom pin mapping. #elif defined(BOARD_USES_HW_GPIO_NUMBERS) -// The user has chosen to disable pin mappin. +// The user has chosen to disable pin mapping. #warning The Arduino API will use GPIO numbers for this build. #endif diff --git a/variants/atd35s3/pins_arduino.h b/variants/atd35s3/pins_arduino.h new file mode 100644 index 00000000000..c973693b71c --- /dev/null +++ b/variants/atd35s3/pins_arduino.h @@ -0,0 +1,78 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +// LCD pin +#define LCD_CS SS +#define LCD_SCK SCK +#define LCD_SDA MOSI +static const uint8_t LCD_DC = 21; +static const uint8_t LCD_RES = 14; +static const uint8_t LCD_BL = 3; + +// MicroSD Card pin +static const uint8_t SD_CS = 18; +static const uint8_t SD_CD = 17; + +static const uint8_t BTN_A = 4; +#define KEY_BUILTIN BTN_A + +static const uint8_t LED_BUILTIN = 5; + +// DAC pin +static const uint8_t DAC_DIN = 47; +static const uint8_t DAC_BCLK = 48; +static const uint8_t DAC_WS = 45; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/atmegazero_esp32s2/pins_arduino.h b/variants/atmegazero_esp32s2/pins_arduino.h index c28126dd397..dda442c20e2 100644 --- a/variants/atmegazero_esp32s2/pins_arduino.h +++ b/variants/atmegazero_esp32s2/pins_arduino.h @@ -10,12 +10,12 @@ #define USB_PRODUCT "ATMZ-ESP32S2" #define USB_SERIAL "" -static const uint8_t NEOPIXEL = 40; +static const uint8_t RGB_LED_PIN = 40; // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = (NEOPIXEL + SOC_GPIO_PIN_COUNT); +static const uint8_t LED_BUILTIN = (RGB_LED_PIN + SOC_GPIO_PIN_COUNT); #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/bpi-bit/pins_arduino.h b/variants/bpi-bit/pins_arduino.h index b6247c12ae9..42a820a0b26 100644 --- a/variants/bpi-bit/pins_arduino.h +++ b/variants/bpi-bit/pins_arduino.h @@ -9,13 +9,13 @@ static const uint8_t BUZZER = 25; static const uint8_t BUTTON_A = 35; static const uint8_t BUTTON_B = 27; -// NeoPixel Matrix 5 x 5 +// RGB LED Matrix 5 x 5 static const uint8_t RGB_LED = 4; // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino #define LED_BUILTIN (RGB_LED + SOC_GPIO_PIN_COUNT) // Just a single LED in the Matrix #define BUILTIN_LED LED_BUILTIN // backward compatibility -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 static const uint8_t LIGHT_SENSOR1 = 36; diff --git a/variants/bpi_leaf_s3/pins_arduino.h b/variants/bpi_leaf_s3/pins_arduino.h index 68083e2e1ea..3a22a46bfc1 100644 --- a/variants/bpi_leaf_s3/pins_arduino.h +++ b/variants/bpi_leaf_s3/pins_arduino.h @@ -13,12 +13,12 @@ // Some boards have too low voltage on this pin (board design bug) // Use different pin with 3V and connect with 48 // and change this setup for the chosen pin (for example 38) -#define PIN_NEOPIXEL 48 +#define PIN_RGB_LED 48 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 25 diff --git a/variants/cezerio_dev_esp32c6/pins_arduino.h b/variants/cezerio_dev_esp32c6/pins_arduino.h new file mode 100644 index 00000000000..3ffc59aee6f --- /dev/null +++ b/variants/cezerio_dev_esp32c6/pins_arduino.h @@ -0,0 +1,52 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define USB_VID 0x303A +#define USB_PID 0x1001 +#define USB_MANUFACTURER "RFtek Electronics" +#define USB_PRODUCT "cezerio dev ESP32C6" +#define USB_SERIAL "" + +#define PIN_RGB_LED 3 +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() +#define RGB_BUILTIN LED_BUILTIN +#define RGBLED LED_BUILTIN +#define RGB_BRIGHTNESS 64 + +static const uint8_t BUT_BUILTIN = 9; +#define BUILTIN_BUT BUT_BUILTIN // backward compatibility +#define BUT_BUILTIN BUT_BUILTIN // allow testing #ifdef BUT_BUILTIN +#define BOOT BUT_BUILTIN + +static const uint8_t TX = 16; +static const uint8_t RX = 17; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 7; + +static const uint8_t SS = 14; +static const uint8_t MOSI = 22; +static const uint8_t MISO = 23; +static const uint8_t SCK = 21; + +static const uint8_t A0 = 0; +static const uint8_t A1 = 1; +static const uint8_t A2 = 2; +static const uint8_t A3 = 3; +static const uint8_t A4 = 4; +static const uint8_t A5 = 5; +static const uint8_t A6 = 6; + +static const uint8_t MATRIX = 18; + +static const uint8_t IMUSD = 8; +static const uint8_t IMUSC = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/cezerio_mini_dev_esp32c6/pins_arduino.h b/variants/cezerio_mini_dev_esp32c6/pins_arduino.h new file mode 100644 index 00000000000..e7ef94e5a64 --- /dev/null +++ b/variants/cezerio_mini_dev_esp32c6/pins_arduino.h @@ -0,0 +1,47 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define USB_VID 0x303A +#define USB_PID 0x1001 +#define USB_MANUFACTURER "RFtek Electronics" +#define USB_PRODUCT "cezerio mini dev ESP32C6" +#define USB_SERIAL "" + +#define PIN_RGB_LED 20 +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() +#define RGB_BUILTIN LED_BUILTIN +#define RGBLED LED_BUILTIN +#define RGB_BRIGHTNESS 64 + +static const uint8_t BUT_BUILTIN = 9; +#define BUILTIN_BUT BUT_BUILTIN // backward compatibility +#define BUT_BUILTIN BUT_BUILTIN // allow testing #ifdef BUT_BUILTIN +#define BOOT BUT_BUILTIN + +static const uint8_t TX = 7; +static const uint8_t RX = 14; + +static const uint8_t SDA = 23; +static const uint8_t SCL = 22; + +static const uint8_t MOSI = 19; +static const uint8_t MISO = 21; +static const uint8_t SCK = 18; +static const uint8_t SS = 17; + +static const uint8_t A0 = 0; +static const uint8_t A1 = 1; +static const uint8_t A2 = 2; +static const uint8_t A3 = 3; +static const uint8_t A6 = 6; + +static const uint8_t MATRIX = 4; + +#endif /* Pins_Arduino_h */ diff --git a/variants/circuitart_zero_s3/bootloader_tinyuf2.bin b/variants/circuitart_zero_s3/bootloader_tinyuf2.bin new file mode 100644 index 00000000000..901005128d9 Binary files /dev/null and b/variants/circuitart_zero_s3/bootloader_tinyuf2.bin differ diff --git a/variants/circuitart_zero_s3/partitions_tinyuf2.csv b/variants/circuitart_zero_s3/partitions_tinyuf2.csv new file mode 100644 index 00000000000..55f6c2b8d76 --- /dev/null +++ b/variants/circuitart_zero_s3/partitions_tinyuf2.csv @@ -0,0 +1,10 @@ +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +# bootloader.bin,, 0x1000, 32K +# partition table,, 0x8000, 4K +nvs, data, nvs, 0x9000, 20K, +otadata, data, ota, 0xe000, 8K, +ota_0, app, ota_0, 0x10000, 2048K, +ota_1, app, ota_1, 0x210000, 2048K, +uf2, app, factory,0x410000, 256K, +ffat, data, fat, 0x450000, 11968K, diff --git a/variants/circuitart_zero_s3/pins_arduino.h b/variants/circuitart_zero_s3/pins_arduino.h new file mode 100644 index 00000000000..adf38ca672f --- /dev/null +++ b/variants/circuitart_zero_s3/pins_arduino.h @@ -0,0 +1,137 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303A +#define USB_PID 0x80DB +#define USB_MANUFACTURER "CircuitART" +#define USB_PRODUCT "ZeroS3" +#define USB_SERIAL "" // Empty string for MAC address + +// User LED +#define LED_BUILTIN 46 +#define BUILTIN_LED LED_BUILTIN // backward compatibility + +// RGB LED +#define PIN_RGB_LED 47 +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() and digitalWrite() for blinking +#define RGB_BUILTIN (PIN_RGB_LED + SOC_GPIO_PIN_COUNT) +#define RGB_BRIGHTNESS 64 +#define RGBLED_NUM 1 // number of RGB LEDs + +static const uint8_t KEY_BUILTIN = 0; + +static const uint8_t TFT_DC = 5; +static const uint8_t TFT_CS = 39; +static const uint8_t TFT_RST = 40; +static const uint8_t TFT_RESET = 40; + +static const uint8_t SD_CS = 42; +static const uint8_t SD_CHIP_SELECT = 42; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; +static const uint8_t TX0 = 43; +static const uint8_t RX0 = 44; + +static const uint8_t TX1 = 40; +static const uint8_t RX2 = 41; + +static const uint8_t SDA = 33; +static const uint8_t SCL = 34; + +static const uint8_t SS = 39; +static const uint8_t MOSI = 35; +static const uint8_t SCK = 36; +static const uint8_t MISO = 37; + +static const uint8_t DAC1 = 17; +static const uint8_t DAC2 = 18; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; +static const uint8_t T15 = 15; + +static const uint8_t D0 = 0; +static const uint8_t D1 = 1; +static const uint8_t D2 = 2; +static const uint8_t D3 = 3; +static const uint8_t D4 = 4; +static const uint8_t D5 = 5; +static const uint8_t D6 = 6; +static const uint8_t D7 = 7; +static const uint8_t D8 = 8; +static const uint8_t D9 = 9; +static const uint8_t D10 = 10; +static const uint8_t D11 = 11; +static const uint8_t D12 = 12; +static const uint8_t D13 = 13; +static const uint8_t D14 = 14; +static const uint8_t D15 = 15; +static const uint8_t D16 = 16; +static const uint8_t D17 = 17; +static const uint8_t D18 = 18; +static const uint8_t D33 = 33; +static const uint8_t D34 = 34; +static const uint8_t D35 = 35; +static const uint8_t D36 = 36; +static const uint8_t D37 = 37; +static const uint8_t D38 = 38; +static const uint8_t D39 = 39; +static const uint8_t D40 = 40; +static const uint8_t D41 = 41; + +// Camera +#define TFT_CAM_POWER 21 + +#define PWDN_GPIO_NUM -1 // connected through expander +#define RESET_GPIO_NUM -1 // connected through expander +#define XCLK_GPIO_NUM 15 +#define SIOD_GPIO_NUM SDA +#define SIOC_GPIO_NUM SCL + +#define Y9_GPIO_NUM 14 //16 +#define Y8_GPIO_NUM 13 //14 +#define Y7_GPIO_NUM 11 //13 +#define Y6_GPIO_NUM 10 +#define Y5_GPIO_NUM 9 //8 +#define Y4_GPIO_NUM 8 //6 +#define Y3_GPIO_NUM 7 +#define Y2_GPIO_NUM 6 //9 +#define VSYNC_GPIO_NUM 38 +#define HREF_GPIO_NUM 48 +#define PCLK_GPIO_NUM 16 //11 + +#endif /* Pins_Arduino_h */ diff --git a/variants/circuitart_zero_s3/tinyuf2.bin b/variants/circuitart_zero_s3/tinyuf2.bin new file mode 100644 index 00000000000..5c4db2984c7 Binary files /dev/null and b/variants/circuitart_zero_s3/tinyuf2.bin differ diff --git a/variants/codecell/pins_arduino.h b/variants/codecell/pins_arduino.h new file mode 100644 index 00000000000..b4b0f0bd2dd --- /dev/null +++ b/variants/codecell/pins_arduino.h @@ -0,0 +1,25 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +static const uint8_t TX = 21; +static const uint8_t RX = 20; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +static const uint8_t SS = 7; +static const uint8_t MOSI = 6; +static const uint8_t MISO = 5; +static const uint8_t SCK = 4; + +static const uint8_t A0 = 0; +static const uint8_t A1 = 1; +static const uint8_t A2 = 2; +static const uint8_t A3 = 3; +static const uint8_t A4 = 4; +static const uint8_t A5 = 5; + +#endif /* Pins_Arduino_h */ diff --git a/variants/cyobot_v2_esp32s3/pins_arduino.h b/variants/cyobot_v2_esp32s3/pins_arduino.h new file mode 100644 index 00000000000..45f0968ef2a --- /dev/null +++ b/variants/cyobot_v2_esp32s3/pins_arduino.h @@ -0,0 +1,52 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_MANUFACTURER "CYOBot" +#define USB_PRODUCT "CYOBrain ESP32S3" +#define USB_SERIAL "" // Empty string for MAC address + +static const uint8_t BUTTON0 = 4; +static const uint8_t BUTTON1 = 38; +static const uint8_t LED = 24; + +static const uint8_t BAT_MEAS = 6; +static const uint8_t CHAR_DET = 23; + +static const uint8_t NEO_BASE = 7; +static const uint8_t NEO_BRAIN = 15; + +static const uint8_t I2S0_MCLK = 16; +static const uint8_t I2S0_DSDIN = 8; +static const uint8_t I2S0_SCLK = 9; +static const uint8_t I2S0_LRCK = 45; + +static const uint8_t SDA = 17; +static const uint8_t SCL = 18; + +static const uint8_t SS = 5; +static const uint8_t MOSI = 2; +static const uint8_t MISO = 42; +static const uint8_t SCK = 41; + +static const uint8_t ENCODER1_A = 39; +static const uint8_t ENCODER1_B = 40; +static const uint8_t ENCODER2_B = 19; +static const uint8_t ENCODER2_A = 20; + +static const uint8_t UART1_RXD = 3; +static const uint8_t UART1_TXD = 1; + +static const uint8_t GPIO46 = 46; +static const uint8_t ESP_IO0 = 0; + +static const uint8_t SD_OUT = 10; +static const uint8_t SD_SPI_MOSI = 11; +static const uint8_t SD_SPI_CLK = 12; +static const uint8_t SD_SPI_MISO = 13; +static const uint8_t SD_SPI_CS = 14; + +static const uint8_t PA_CTRL = 25; + +#endif /* Pins_Arduino_h */ diff --git a/variants/cytron_maker_feather_aiot_s3/pins_arduino.h b/variants/cytron_maker_feather_aiot_s3/pins_arduino.h index 9f27ff8ecf7..9f7475294e8 100644 --- a/variants/cytron_maker_feather_aiot_s3/pins_arduino.h +++ b/variants/cytron_maker_feather_aiot_s3/pins_arduino.h @@ -19,7 +19,7 @@ static const uint8_t RGB_BUILTIN = SOC_GPIO_PIN_COUNT + 46; // RGB LED. #define LED LED_BUILTIN #define RGB RGB_BUILTIN -#define NEOPIXEL RGB_BUILTIN +#define RGB_LED_PIN RGB_BUILTIN #define RGB_BRIGHTNESS 65 #define VP_EN 11 // V Peripheral Enable. diff --git a/variants/department_of_alchemy_minimain_esp32s2/pins_arduino.h b/variants/department_of_alchemy_minimain_esp32s2/pins_arduino.h index c7ce982ff79..7f053b3f600 100644 --- a/variants/department_of_alchemy_minimain_esp32s2/pins_arduino.h +++ b/variants/department_of_alchemy_minimain_esp32s2/pins_arduino.h @@ -14,15 +14,15 @@ #define LED_BUILTIN 13 #define BUILTIN_LED LED_BUILTIN // backward compatibility -// Neopixel -#define PIN_NEOPIXEL 33 -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() and digitalWrite() for blinking -#define RGB_BUILTIN (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT) +// RGB LED +#define PIN_RGB_LED 33 +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWritee() for blinking +#define RGB_BUILTIN (PIN_RGB_LED + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 -#define NEOPIXEL_NUM 1 // number of neopixels -#define NEOPIXEL_POWER 21 // power pin -#define NEOPIXEL_POWER_ON HIGH // power pin state when on +#define RGBLED_NUM 1 // number of RGB LEDs +#define RGBLED_POWER 21 // power pin +#define RGBLED_POWER_ON HIGH // power pin state when on #define PIN_SERVO 2 // servo pin #define PIN_ISOLATED_INPUT 40 // optocoupled input diff --git a/variants/department_of_alchemy_minimain_esp32s2/variant.cpp b/variants/department_of_alchemy_minimain_esp32s2/variant.cpp index 7809ec26f46..ee4eaa8df2b 100644 --- a/variants/department_of_alchemy_minimain_esp32s2/variant.cpp +++ b/variants/department_of_alchemy_minimain_esp32s2/variant.cpp @@ -30,8 +30,8 @@ extern "C" { // Initialize variant/board, called before setup() void initVariant(void) { // This board has a power control pin, and we must set it to output and high - // in order to enable the NeoPixels. - pinMode(NEOPIXEL_POWER, OUTPUT); - digitalWrite(NEOPIXEL_POWER, HIGH); + // in order to enable the RGB LEDs. + pinMode(RGBLED_POWER, OUTPUT); + digitalWrite(RGBLED_POWER, HIGH); } } diff --git a/variants/elecrow_crowpanel_7/pins_arduino.h b/variants/elecrow_crowpanel_7/pins_arduino.h new file mode 100644 index 00000000000..6b55d35defd --- /dev/null +++ b/variants/elecrow_crowpanel_7/pins_arduino.h @@ -0,0 +1,65 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define USB_VID 0x1a86 +#define USB_PID 0x7523 + +// Some boards have too low voltage on this pin (board design bug) +// Use different pin with 3V and connect with 48 +// and change this setup for the chosen pin (for example 38) +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + 48; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN +#define RGB_BUILTIN LED_BUILTIN +#define RGB_BRIGHTNESS 64 + +static const uint8_t TX = 37; +static const uint8_t RX = 40; + +static const uint8_t TXD2 = 17; +static const uint8_t RXD2 = 18; + +static const uint8_t SDA = 19; +static const uint8_t SCL = 20; + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +static const uint8_t G0 = 0; +static const uint8_t G1 = 1; +static const uint8_t G2 = 2; +static const uint8_t G3 = 3; +static const uint8_t G4 = 4; +static const uint8_t G5 = 5; +static const uint8_t G6 = 6; +static const uint8_t G7 = 7; +static const uint8_t G8 = 8; +static const uint8_t G9 = 9; +static const uint8_t G11 = 11; +static const uint8_t G12 = 12; +static const uint8_t G13 = 13; +static const uint8_t G14 = 14; +static const uint8_t G17 = 17; +static const uint8_t G18 = 18; +static const uint8_t G19 = 19; +static const uint8_t G20 = 20; +static const uint8_t G21 = 21; +static const uint8_t G33 = 33; +static const uint8_t G34 = 34; +static const uint8_t G35 = 35; +static const uint8_t G36 = 36; +static const uint8_t G37 = 37; +static const uint8_t G38 = 38; +static const uint8_t G45 = 45; +static const uint8_t G46 = 46; +static const uint8_t G47 = 47; +static const uint8_t G48 = 48; + +static const uint8_t ADC = 38; + +#endif /* Pins_Arduino_h */ diff --git a/variants/esp32c3/pins_arduino.h b/variants/esp32c3/pins_arduino.h index 9ad2102955c..179ce636ea5 100644 --- a/variants/esp32c3/pins_arduino.h +++ b/variants/esp32c3/pins_arduino.h @@ -4,12 +4,12 @@ #include #include "soc/soc_caps.h" -#define PIN_NEOPIXEL 8 +#define PIN_RGB_LED 8 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/esp32c6/pins_arduino.h b/variants/esp32c6/pins_arduino.h index 705c2b4d9ce..348db9f907e 100644 --- a/variants/esp32c6/pins_arduino.h +++ b/variants/esp32c6/pins_arduino.h @@ -4,12 +4,12 @@ #include #include "soc/soc_caps.h" -#define PIN_NEOPIXEL 8 +#define PIN_RGB_LED 8 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 @@ -32,4 +32,9 @@ static const uint8_t A4 = 4; static const uint8_t A5 = 5; static const uint8_t A6 = 6; +// LP I2C Pins are fixed on ESP32-C6 +#define WIRE1_PIN_DEFINED +static const uint8_t SDA1 = 6; +static const uint8_t SCL1 = 7; + #endif /* Pins_Arduino_h */ diff --git a/variants/esp32h2-devkit-lipo/pins_arduino.h b/variants/esp32h2-devkit-lipo/pins_arduino.h index 534b6d64fe1..bb15be3e871 100644 --- a/variants/esp32h2-devkit-lipo/pins_arduino.h +++ b/variants/esp32h2-devkit-lipo/pins_arduino.h @@ -4,12 +4,12 @@ #include #include "soc/soc_caps.h" -#define PIN_NEOPIXEL 8 +#define PIN_RGB_LED 8 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/esp32h2/pins_arduino.h b/variants/esp32h2/pins_arduino.h index 99a6b1152c9..108d874699b 100644 --- a/variants/esp32h2/pins_arduino.h +++ b/variants/esp32h2/pins_arduino.h @@ -4,12 +4,12 @@ #include #include "soc/soc_caps.h" -#define PIN_NEOPIXEL 8 +#define PIN_RGB_LED 8 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/esp32p4/pins_arduino.h b/variants/esp32p4/pins_arduino.h new file mode 100644 index 00000000000..cbb1e871ae5 --- /dev/null +++ b/variants/esp32p4/pins_arduino.h @@ -0,0 +1,85 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BOOT_MODE 35 +// BOOT_MODE2 36 pullup + +static const uint8_t TX = 37; +static const uint8_t RX = 38; + +static const uint8_t SDA = 7; +static const uint8_t SCL = 8; + +// Use GPIOs 36 or lower on the P4 DevKit to avoid LDO power issues with high numbered GPIOs. +static const uint8_t SS = 26; +static const uint8_t MOSI = 32; +static const uint8_t MISO = 33; +static const uint8_t SCK = 36; + +static const uint8_t A0 = 16; +static const uint8_t A1 = 17; +static const uint8_t A2 = 18; +static const uint8_t A3 = 19; +static const uint8_t A4 = 20; +static const uint8_t A5 = 21; +static const uint8_t A6 = 22; +static const uint8_t A7 = 23; +static const uint8_t A8 = 49; +static const uint8_t A9 = 50; +static const uint8_t A10 = 51; +static const uint8_t A11 = 52; +static const uint8_t A12 = 53; +static const uint8_t A13 = 54; + +static const uint8_t T0 = 2; +static const uint8_t T1 = 3; +static const uint8_t T2 = 4; +static const uint8_t T3 = 5; +static const uint8_t T4 = 6; +static const uint8_t T5 = 7; +static const uint8_t T6 = 8; +static const uint8_t T7 = 9; +static const uint8_t T8 = 10; +static const uint8_t T9 = 11; +static const uint8_t T10 = 12; +static const uint8_t T11 = 13; +static const uint8_t T12 = 14; +static const uint8_t T13 = 15; + +/* ESP32-P4 EV Function board specific definitions */ +//ETH +#define ETH_PHY_TYPE ETH_PHY_TLK110 +#define ETH_PHY_ADDR 1 +#define ETH_PHY_MDC 31 +#define ETH_PHY_MDIO 52 +#define ETH_PHY_POWER 51 +#define ETH_RMII_TX_EN 49 +#define ETH_RMII_TX0 34 +#define ETH_RMII_TX1 35 +#define ETH_RMII_RX0 29 +#define ETH_RMII_RX1_EN 30 +#define ETH_RMII_CRS_DV 28 +#define ETH_RMII_CLK 50 +#define ETH_CLK_MODE EMAC_CLK_EXT_IN + +//SDMMC +#define BOARD_HAS_SDMMC +#define BOARD_SDMMC_SLOT 0 +#define BOARD_SDMMC_POWER_CHANNEL 4 +#define BOARD_SDMMC_POWER_PIN 45 +#define BOARD_SDMMC_POWER_ON_LEVEL LOW + +//WIFI - ESP32C6 +#define BOARD_HAS_SDIO_ESP_HOSTED +#define BOARD_SDIO_ESP_HOSTED_CLK 18 +#define BOARD_SDIO_ESP_HOSTED_CMD 19 +#define BOARD_SDIO_ESP_HOSTED_D0 14 +#define BOARD_SDIO_ESP_HOSTED_D1 15 +#define BOARD_SDIO_ESP_HOSTED_D2 16 +#define BOARD_SDIO_ESP_HOSTED_D3 17 +#define BOARD_SDIO_ESP_HOSTED_RESET 54 + +#endif /* Pins_Arduino_h */ diff --git a/variants/esp32s2-devkit-lipo-usb/pins_arduino.h b/variants/esp32s2-devkit-lipo-usb/pins_arduino.h index 3d5f92aa46f..6dba09dbe43 100644 --- a/variants/esp32s2-devkit-lipo-usb/pins_arduino.h +++ b/variants/esp32s2-devkit-lipo-usb/pins_arduino.h @@ -4,8 +4,8 @@ #include #include "soc/soc_caps.h" -#define PIN_NEOPIXEL 18 -#define RGB_BUILTIN PIN_NEOPIXEL +#define PIN_RGB_LED 18 +#define RGB_BUILTIN PIN_RGB_LED #define RGB_BRIGHTNESS 64 static const uint8_t BUT_BUILTIN = 0; diff --git a/variants/esp32s2-devkit-lipo/pins_arduino.h b/variants/esp32s2-devkit-lipo/pins_arduino.h index 04c89f4d5d6..98116754f5a 100644 --- a/variants/esp32s2-devkit-lipo/pins_arduino.h +++ b/variants/esp32s2-devkit-lipo/pins_arduino.h @@ -4,8 +4,8 @@ #include #include "soc/soc_caps.h" -#define PIN_NEOPIXEL 18 -#define RGB_BUILTIN PIN_NEOPIXEL +#define PIN_RGB_LED 18 +#define RGB_BUILTIN PIN_RGB_LED #define RGB_BRIGHTNESS 64 static const uint8_t BUT_BUILTIN = 0; diff --git a/variants/esp32s2/pins_arduino.h b/variants/esp32s2/pins_arduino.h index 95ece4649c8..27391ef22ab 100644 --- a/variants/esp32s2/pins_arduino.h +++ b/variants/esp32s2/pins_arduino.h @@ -5,14 +5,14 @@ #include "soc/soc_caps.h" // GPIO pin for Saola-1 & DevKitM-1 = 18 -#define PIN_NEOPIXEL 18 +#define PIN_RGB_LED 18 // GPIO pin for Kaluga = 45 -//#define PIN_NEOPIXEL 45 +//#define PIN_RGB_LED 45 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/esp32s3/pins_arduino.h b/variants/esp32s3/pins_arduino.h index de3a6f975ce..623d684e20f 100644 --- a/variants/esp32s3/pins_arduino.h +++ b/variants/esp32s3/pins_arduino.h @@ -10,12 +10,12 @@ // Some boards have too low voltage on this pin (board design bug) // Use different pin with 3V and connect with 48 // and change this setup for the chosen pin (for example 38) -#define PIN_NEOPIXEL 48 +#define PIN_RGB_LED 48 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/esp32s3usbotg/pins_arduino.h b/variants/esp32s3usbotg/pins_arduino.h index 004055cde49..5b873e2d2f1 100644 --- a/variants/esp32s3usbotg/pins_arduino.h +++ b/variants/esp32s3usbotg/pins_arduino.h @@ -2,6 +2,7 @@ #define Pins_Arduino_h #include +#include #define USB_VID 0x303a #define USB_PID 0x1001 diff --git a/variants/esp32thing_plus_c/pins_arduino.h b/variants/esp32thing_plus_c/pins_arduino.h index 6d154a402d6..ca7b6c65d45 100644 --- a/variants/esp32thing_plus_c/pins_arduino.h +++ b/variants/esp32thing_plus_c/pins_arduino.h @@ -8,7 +8,7 @@ static const uint8_t LED_BUILTIN = 13; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() static const uint8_t RGB_BUILTIN = SOC_GPIO_PIN_COUNT + 2; #define RGB_BUILTIN RGB_BUILTIN // necessary to make digitalWrite/digitalMode find it #define RGB_BRIGHTNESS 64 diff --git a/variants/franzininho_wifi_esp32s2/pins_arduino.h b/variants/franzininho_wifi_esp32s2/pins_arduino.h index 94d64aa18fb..b75fcc768d7 100644 --- a/variants/franzininho_wifi_esp32s2/pins_arduino.h +++ b/variants/franzininho_wifi_esp32s2/pins_arduino.h @@ -11,12 +11,12 @@ #define USB_SERIAL "0" #define USB_WEBUSB_ENABLED false -static const uint8_t PIN_NEOPIXEL = 18; +static const uint8_t PIN_RGB_LED = 18; // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT); +static const uint8_t LED_BUILTIN = (PIN_RGB_LED + SOC_GPIO_PIN_COUNT); #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/franzininho_wifi_msc_esp32s2/pins_arduino.h b/variants/franzininho_wifi_msc_esp32s2/pins_arduino.h index 5e301876c19..db213cb97d4 100644 --- a/variants/franzininho_wifi_msc_esp32s2/pins_arduino.h +++ b/variants/franzininho_wifi_msc_esp32s2/pins_arduino.h @@ -18,12 +18,12 @@ #define USB_FW_MSC_VOLUME_NAME "S2-Firmware" //max 11 chars #define USB_FW_MSC_SERIAL_NUMBER 0x00000000 -static const uint8_t PIN_NEOPIXEL = 18; +static const uint8_t PIN_RGB_LED = 18; // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT); +static const uint8_t LED_BUILTIN = (PIN_RGB_LED + SOC_GPIO_PIN_COUNT); #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/fri3d_2024_esp32s3/pins_arduino.h b/variants/fri3d_2024_esp32s3/pins_arduino.h new file mode 100644 index 00000000000..3cdba371f57 --- /dev/null +++ b/variants/fri3d_2024_esp32s3/pins_arduino.h @@ -0,0 +1,127 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +static const uint8_t LED_BUILTIN = 21; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 9; +static const uint8_t SCL = 18; + +static const uint8_t SS = 14; +static const uint8_t MOSI = 6; +static const uint8_t MISO = 8; +static const uint8_t SCK = 7; + +#define X_FRI3D_BADGE_2024 // General Define for use in sketches or lib files +#define X_WS2812_NUM_LEDS 5 // Number of RBG LEDs + +#define PIN_I2C_SDA SDA +#define PIN_I2C_SCL SCL +#define PIN_WS2812 12 +#define X_WS2812_NUM_LEDS 5 + +#define PIN_LED 21 +#define PIN_IR_RECEIVER 11 +#define PIN_BLASTER 10 +#define PIN_BUZZER 46 +#define PIN_BATTERY 13 + +#define PIN_SDCARD_CS SS + +#define PIN_JOY_X 1 +#define PIN_JOY_Y 3 + +#define PIN_A 39 +#define PIN_B 40 +#define PIN_X 38 +#define PIN_Y 41 +#define PIN_MENU 45 +#define PIN_START 0 + +#define PIN_AUX 42 // Fri3d Badge 2024 Aux Pwr + +#define CHANNEL_BUZZER 0 + +// Fri3d Badge 2024 Accelero Gyro +#define X_ACCELERO_GYRO 21 + +// I2S microphone on communicator addon +#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ONLY_LEFT +#define I2S_MIC_SERIAL_CLOCK 17 //serial clock SCLK: pin SCK +#define I2S_MIC_LEFT_RIGHT_CLOCK 47 //left/right clock LRCK: pin WS +#define I2S_MIC_SERIAL_DATA 15 //serial data DIN: pin SD + +// Fri3d Badge 2024 LCD +// For using display with TFT_eSPI library +#define USER_SETUP_LOADED +#define SPI_FREQUENCY 80000000 +#define ST7789_DRIVER +#define USE_HSPI_PORT + +#define TFT_RGB_ORDER TFT_BGR //# swap red and blue byte order +#define TFT_INVERSION_OFF +#define TFT_WIDTH 296 //;setting these will init the eSPI lib with correct dimensions +#define TFT_HEIGHT 240 //;setting these will init the eSPI lib with correct dimensions +#define TFT_MISO MISO +#define TFT_MOSI MOSI +#define TFT_SCLK SCK +#define TFT_CS 5 +#define TFT_DC 4 +#define TFT_RST 48 +#define LOAD_GLCD 1 +#define LOAD_FONT2 +#define LOAD_FONT4 +#define LOAD_FONT6 +#define LOAD_FONT7 +#define LOAD_FONT8 +#define LOAD_GFXFF +#define SMOOTH_FONT +#define SPI_FREQUENCY 80000000 + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/gpy/pins_arduino.h b/variants/gpy/pins_arduino.h index 02ee758e1a3..93d3e5bfa1d 100644 --- a/variants/gpy/pins_arduino.h +++ b/variants/gpy/pins_arduino.h @@ -15,12 +15,12 @@ #define LTE_WAKE 27 // GPIO27 - Sequans modem wake-up interrupt #define LTE_BAUD 921600 -// Neopixel -#define PIN_NEOPIXEL 0 // ->2812 RGB !!! -static const uint8_t LED_BUILTIN = PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT; +// RGB LED +#define PIN_RGB_LED 0 // ->2812 RGB !!! +static const uint8_t LED_BUILTIN = PIN_RGB_LED + SOC_GPIO_PIN_COUNT; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/heltec_vision_master_e290/pins_arduino.h b/variants/heltec_vision_master_e290/pins_arduino.h new file mode 100644 index 00000000000..7940cdde702 --- /dev/null +++ b/variants/heltec_vision_master_e290/pins_arduino.h @@ -0,0 +1,72 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define Vision_Master_E290 true +#define DISPLAY_HEIGHT 128 +#define DISPLAY_WIDTH 296 + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 39; +static const uint8_t SCL = 38; + +static const uint8_t SS = 8; +static const uint8_t MOSI = 10; +static const uint8_t MISO = 11; +static const uint8_t SCK = 9; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +static const uint8_t Vext = 18; +static const uint8_t Eink_SDI = 1; +static const uint8_t Eink_CLK = 2; +static const uint8_t Eink_CS = 3; +static const uint8_t Eink_DC = 4; +static const uint8_t Eink_RST = 5; +static const uint8_t Eink_BUSY = 6; + +static const uint8_t RST_LoRa = 12; +static const uint8_t BUSY_LoRa = 13; +static const uint8_t DIO0 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/heltec_vision_master_e_213/pins_arduino.h b/variants/heltec_vision_master_e_213/pins_arduino.h new file mode 100644 index 00000000000..003528f9cc0 --- /dev/null +++ b/variants/heltec_vision_master_e_213/pins_arduino.h @@ -0,0 +1,72 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define Vision_Master_E213 true +#define DISPLAY_HEIGHT 122 +#define DISPLAY_WIDTH 250 + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 39; +static const uint8_t SCL = 38; + +static const uint8_t SS = 8; +static const uint8_t MOSI = 10; +static const uint8_t MISO = 11; +static const uint8_t SCK = 9; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +static const uint8_t Vext = 18; +static const uint8_t Eink_BUSY = 1; +static const uint8_t Eink_DC = 2; +static const uint8_t Eink_RST = 3; +static const uint8_t Eink_CLK = 4; +static const uint8_t Eink_CS = 5; +static const uint8_t Eink_SDI = 6; + +static const uint8_t RST_LoRa = 12; +static const uint8_t BUSY_LoRa = 13; +static const uint8_t DIO0 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/heltec_vision_master_t190/pins_arduino.h b/variants/heltec_vision_master_t190/pins_arduino.h new file mode 100644 index 00000000000..6c5fbf907e1 --- /dev/null +++ b/variants/heltec_vision_master_t190/pins_arduino.h @@ -0,0 +1,71 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define Vision_Master_T190 true +#define DISPLAY_HEIGHT 170 +#define DISPLAY_WIDTH 320 + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 2; +static const uint8_t SCL = 1; + +static const uint8_t SS = 8; +static const uint8_t MOSI = 10; +static const uint8_t MISO = 11; +static const uint8_t SCK = 9; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +static const uint8_t Vext = 5; +static const uint8_t TFT_SCL = 38; +static const uint8_t TFT_CS = 39; +static const uint8_t TFT_RST = 40; +static const uint8_t TFT_RS = 47; +static const uint8_t TFT_SDA = 48; + +static const uint8_t RST_LoRa = 12; +static const uint8_t BUSY_LoRa = 13; +static const uint8_t DIO0 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/heltec_wifi_kit_32/pins_arduino.h b/variants/heltec_wifi_kit_32/pins_arduino.h index 5712e00a2e2..0bac8faf7d6 100644 --- a/variants/heltec_wifi_kit_32/pins_arduino.h +++ b/variants/heltec_wifi_kit_32/pins_arduino.h @@ -7,6 +7,8 @@ #define DISPLAY_HEIGHT 64 #define DISPLAY_WIDTH 128 +#define F_XTAL_MHZ 26 + static const uint8_t LED_BUILTIN = 25; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN diff --git a/variants/heltec_wifi_lora_32/pins_arduino.h b/variants/heltec_wifi_lora_32/pins_arduino.h index 5dc5c7aebb9..d4e78df4b23 100644 --- a/variants/heltec_wifi_lora_32/pins_arduino.h +++ b/variants/heltec_wifi_lora_32/pins_arduino.h @@ -7,6 +7,8 @@ #define DISPLAY_HEIGHT 64 #define DISPLAY_WIDTH 128 +#define F_XTAL_MHZ 26 + static const uint8_t LED_BUILTIN = 25; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN diff --git a/variants/huidu_hd_wf2/pins_arduino.h b/variants/huidu_hd_wf2/pins_arduino.h new file mode 100644 index 00000000000..6068e4d6371 --- /dev/null +++ b/variants/huidu_hd_wf2/pins_arduino.h @@ -0,0 +1,61 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +// Huidu HD-WF2 - esp32-s3 HUB75 driver board +// https://www.hdwell.com/Product/index46.html +// https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/discussions/667 + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +#define WF2_X1_R1_PIN 2 +#define WF2_X1_R2_PIN 3 +#define WF2_X1_G1_PIN 6 +#define WF2_X1_G2_PIN 7 +#define WF2_X1_B1_PIN 10 +#define WF2_X1_B2_PIN 11 +#define WF2_X1_E_PIN 21 + +#define WF2_X2_R1_PIN 4 +#define WF2_X2_R2_PIN 5 +#define WF2_X2_G1_PIN 8 +#define WF2_X2_G2_PIN 9 +#define WF2_X2_B1_PIN 12 +#define WF2_X2_B2_PIN 13 +#define WF2_X2_E_PIN -1 // Currently unknown, so X2 port will not work (yet) with 1/32 scan panels + +#define WF2_A_PIN 39 +#define WF2_B_PIN 38 +#define WF2_C_PIN 37 +#define WF2_D_PIN 36 +#define WF2_OE_PIN 35 +#define WF2_CLK_PIN 34 +#define WF2_LAT_PIN 33 + +#define WF2_BUTTON_TEST 17 // Test key button on PCB, 1=normal, 0=pressed +#define WF2_LED_RUN_PIN 40 // Status LED on PCB +#define WF2_BM8563_I2C_SDA 41 // RTC BM8563 I2C port +#define WF2_BM8563_I2C_SCL 42 +#define WF2_USB_DN_PIN 19 // USB D- +#define WF2_USB_DP_PIN 20 // USB D+ + +#define WF2_PCB1_PIN 45 // open pad on PCB +#define WF2_PCB2_PIN 46 // open pad on PCB + +#define LED_BUILTIN WF2_LED_RUN_PIN +#define BUILTIN_LED LED_BUILTIN // backward compatibility + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = WF2_BM8563_I2C_SDA; +static const uint8_t SCL = WF2_BM8563_I2C_SCL; + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +#endif /* Pins_Arduino_h */ diff --git a/variants/huidu_hd_wf4/pins_arduino.h b/variants/huidu_hd_wf4/pins_arduino.h new file mode 100644 index 00000000000..5b8667477bf --- /dev/null +++ b/variants/huidu_hd_wf4/pins_arduino.h @@ -0,0 +1,111 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +// Huidu HD-WF4 - esp32-s3 HUB75 driver board +// https://www.hdwell.com/Product/index46.html +// https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/discussions/667 + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +#define WF4_A_PIN 39 +#define WF4_B_PIN 38 +#define WF4_C_PIN 37 +#define WF4_D_PIN 36 +#define WF4_E_PIN 21 +#define WF4_OE_PIN 35 +#define WF4_CLK_PIN 34 +#define WF4_LAT_PIN 33 + +// X1 HUB75 +#define WF4_X1_R1_PIN 2 +#define WF4_X1_R2_PIN 3 +#define WF4_X1_G1_PIN 6 +#define WF4_X1_G2_PIN 7 +#define WF4_X1_B1_PIN 10 +#define WF4_X1_B2_PIN 11 +#define WF4_X1_CS_PIN 45 // CS gpio must be set HIGH to enable X1 output + +// X2 HUB75 +#define WF4_X2_R1_PIN 4 +#define WF4_X2_R2_PIN 5 +#define WF4_X2_G1_PIN 8 +#define WF4_X2_G2_PIN 9 +#define WF4_X2_B1_PIN 12 +#define WF4_X2_B2_PIN 13 +#define WF4_X2_CS_PIN WF4_X1_CS_PIN // CS gpio must be set HIGH to enable X2 output + +// X3 HUB75 +#define WF4_X3_R1_PIN 2 +#define WF4_X3_R2_PIN 3 +#define WF4_X3_G1_PIN 6 +#define WF4_X3_G2_PIN 7 +#define WF4_X3_B1_PIN 10 +#define WF4_X3_B2_PIN 11 +#define WF4_X3_CS_PIN 14 // CS gpio must be set HIGH to enable X3 output + +// X4 HUB75 +#define WF4_X4_R1_PIN 4 +#define WF4_X4_R2_PIN 5 +#define WF4_X4_G1_PIN 8 +#define WF4_X4_G2_PIN 9 +#define WF4_X4_B1_PIN 12 +#define WF4_X4_B2_PIN 13 +#define WF4_X4_CS_PIN WF4_X3_CS_PIN // CS gpio must be set HIGH to enable X4 output + +// P1 is a UART connector +#define WF4_P1_RX_PIN 44 +#define WF4_P1_TX_PIN 43 + +// P2: PCB holes gpio/gnd +#define WF4_P2_DATA_PIN 0 // GPIO0 boot + +// P5: temperature sensor connector +#define WF4_P5_DATA_PIN 16 + +// P7: VCC/GPIO holes on PCB +#define WF4_P7_DATA_PIN 1 + +// P11: IR connector +#define WF4_P11_DATA_PIN 15 + +// P12: two gpio's, Vcc, GND +#define WF4_P12_DATA1_PIN 47 +#define WF4_P12_DATA2_PIN 18 + +// S1 Button +#define WF4_S1_DATA_PIN 17 + +// S2-S3 PCB holes +#define WF4_S2_DATA_PIN 48 +#define WF4_S3_DATA_PIN 26 +#define WF4_S4_DATA_PIN 46 + +#define WF4_BUTTON_TEST WF4_S1_PIN // Test key button on PCB, 1=normal, 0=pressed +#define WF4_LED_RUN_PIN 40 // Status LED on PCB +#define WF4_BM8563_I2C_SDA 41 // RTC BM8563 I2C port +#define WF4_BM8563_I2C_SCL 42 +#define WF4_USB_DN_PIN 19 // USB-A D- +#define WF4_USB_DP_PIN 20 // USB-A D+ + +#define LED_BUILTIN WF4_LED_RUN_PIN +#define BUILTIN_LED LED_BUILTIN // backward compatibility + +static const uint8_t TX = WF4_P1_TX_PIN; +static const uint8_t RX = WF4_P1_RX_PIN; + +static const uint8_t SDA = WF4_BM8563_I2C_SDA; +static const uint8_t SCL = WF4_BM8563_I2C_SCL; + +// there is no dedicated SPI connector on board, but SPI could be accessed via PCB holes +static const uint8_t SS = WF4_S2_DATA_PIN; +static const uint8_t MOSI = WF4_S3_DATA_PIN; +static const uint8_t MISO = WF4_S4_DATA_PIN; +static const uint8_t SCK = WF4_P7_DATA_PIN; + +// touch pins are mostly busy with HUB75 ports +static const uint8_t T1 = WF4_P7_DATA_PIN; + +#endif /* Pins_Arduino_h */ diff --git a/variants/ioxesp32c6/pins_arduino.h b/variants/ioxesp32c6/pins_arduino.h new file mode 100644 index 00000000000..bcd20119514 --- /dev/null +++ b/variants/ioxesp32c6/pins_arduino.h @@ -0,0 +1,35 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define PIN_RGB_LED 8 +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() +#define RGB_BUILTIN LED_BUILTIN +#define RGB_BRIGHTNESS 64 + +static const uint8_t TX = 16; +static const uint8_t RX = 17; + +static const uint8_t SDA = 21; +static const uint8_t SCL = 22; + +static const uint8_t SS = 18; +static const uint8_t MOSI = 23; +static const uint8_t MISO = 20; +static const uint8_t SCK = 19; + +static const uint8_t A0 = 0; +static const uint8_t A1 = 1; +static const uint8_t A2 = 2; +static const uint8_t A3 = 3; +static const uint8_t A4 = 4; +static const uint8_t A5 = 5; +static const uint8_t A6 = 6; + +#endif /* Pins_Arduino_h */ diff --git a/variants/jczn_2432s028r/partitions_all_app_4MB.csv b/variants/jczn_2432s028r/partitions_all_app_4MB.csv new file mode 100644 index 00000000000..25eeb8c7d47 --- /dev/null +++ b/variants/jczn_2432s028r/partitions_all_app_4MB.csv @@ -0,0 +1,3 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +factory, app, factory, 0x10000, 0x3F0000, diff --git a/variants/jczn_2432s028r/partitions_otanofs_4MB.csv b/variants/jczn_2432s028r/partitions_otanofs_4MB.csv new file mode 100644 index 00000000000..04240badb49 --- /dev/null +++ b/variants/jczn_2432s028r/partitions_otanofs_4MB.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags + nvs, data, nvs, 0x9000, 0x5000, + otadata, data, ota, 0xE000, 0x2000, + app0, app, ota_0, 0x10000, 0x1F0000, + app1, app, ota_1, 0x200000, 0x1F0000, +coredump, data, coredump, 0x3F0000, 0x10000, diff --git a/variants/jczn_2432s028r/pins_arduino.h b/variants/jczn_2432s028r/pins_arduino.h new file mode 100644 index 00000000000..ba10d0f1fd4 --- /dev/null +++ b/variants/jczn_2432s028r/pins_arduino.h @@ -0,0 +1,91 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +static const uint8_t TX = 1; +static const uint8_t RX = 3; + +static const uint8_t D35 = 35; +static const uint8_t D22 = 22; +static const uint8_t D27 = 27; +static const uint8_t D21 = 21; + +static const uint8_t A6 = 34; +static const uint8_t A17 = 27; + +static const uint8_t T7 = 27; + +static const uint8_t SDA = 21; +static const uint8_t SCL = 22; + +static const uint8_t SS = 5; +static const uint8_t MOSI = 23; +static const uint8_t MISO = 19; +static const uint8_t SCK = 18; + +#define CYD_TP_IRQ 36 +#define CYD_TP_MOSI 32 +#define CYD_TP_MISO 39 +#define CYD_TP_CLK 25 +#define CYD_TP_CS 33 +#define CYD_TP_DIN CYD_TP_MOSI +#define CYD_TP_OUT CYD_TP_MOSI +#define CYD_TP_SPI_BUS VSPI + +#define CYD_TFT_DC 2 +#define CYD_TFT_MISO 12 +#define CYD_TFT_MOSI 13 +#define CYD_TFT_SCK 14 +#define CYD_TFT_CS 15 +#define CYD_TFT_RS CYD_TFT_DC +#define CYD_TFT_SDO CYD_TFT_MISO +#define CYD_TFT_SDI CYD_TFT_MOSI +#define CYD_TFT_SPI_BUS HSPI + +#define CYD_TFT_WIDTH 320 +#define CYD_TFT_HEIGHT 240 +#define CYD_SCREEN_WIDTH CYD_TFT_WIDTH +#define CYD_SCREEN_HEIGHT CYD_TFT_HEIGHT + +#define CYD_TFT_BL 21 +#define CYD_TFT_BL_ENABLE() ((pinMode(CYD_TFT_BL, OUTPUT))) +#define CYD_TFT_BL_OFF() (digitalWrite(CYD_TFT_BL, 0)) +#define CYD_TFT_BL_ON() (digitalWrite(CYD_TFT_BL, 1)) + +#define CYD_LED_RED 4 +#define CYD_LED_GREEN 16 +#define CYD_LED_BLUE 17 + +#define CYD_AUDIO_OUT 26 + +#define CYD_USER_BUTTON 0 + +#define CYD_SD_SS 5 +#define CYD_SD_MOSI 23 +#define CYD_SD_MISO 19 +#define CYD_SD_SCK 18 +#define CYD_SD_SPI_BUS VSPI + +#define CYD_LDR 34 + +#define CYD_LED_RED_OFF() (digitalWrite(CYD_LED_RED, 1)) +#define CYD_LED_RED_ON() (digitalWrite(CYD_LED_RED, 0)) +#define CYD_LED_GREEN_OFF() (digitalWrite(CYD_LED_GREEN, 1)) +#define CYD_LED_GREEN_ON() (digitalWrite(CYD_LED_GREEN, 0)) +#define CYD_LED_BLUE_OFF() (digitalWrite(CYD_LED_BLUE, 1)) +#define CYD_LED_BLUE_ON() (digitalWrite(CYD_LED_BLUE, 0)) +#define CYD_LED_RGB_OFF() \ + CYD_LED_RED_OFF(); \ + CYD_LED_GREEN_OFF(); \ + CYD_LED_BLUE_OFF() +#define CYD_LED_RGB_ON() \ + CYD_LED_RED_ON(); \ + CYD_LED_GREEN_ON(); \ + CYD_LED_BLUE_ON() +#define CYD_LED_WHITE_OFF() CYD_LED_RGB_OFF() +#define CYD_LED_WHITE_ON() CYD_LED_RGB_ON() + +#endif /* Pins_Arduino_h */ diff --git a/variants/jczn_2432s028r/variant.cpp b/variants/jczn_2432s028r/variant.cpp new file mode 100644 index 00000000000..a56fc4c190e --- /dev/null +++ b/variants/jczn_2432s028r/variant.cpp @@ -0,0 +1,13 @@ + +#include "esp32-hal-gpio.h" +#include "pins_arduino.h" + +extern "C" { +// Initialize variant/board, called before setup() +void initVariant(void) { + pinMode(CYD_LED_RED, OUTPUT); + pinMode(CYD_LED_GREEN, OUTPUT); + pinMode(CYD_LED_BLUE, OUTPUT); + CYD_LED_RGB_OFF(); +} +} diff --git a/variants/lilygo_t3_s3_lr1121/pins_arduino.h b/variants/lilygo_t3_s3_lr1121/pins_arduino.h new file mode 100644 index 00000000000..70fc3502dab --- /dev/null +++ b/variants/lilygo_t3_s3_lr1121/pins_arduino.h @@ -0,0 +1,67 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x820A + +static const uint8_t LED_BUILTIN = 37; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t BUTTON_1 = 0; +static const uint8_t BAT_VOLT = 1; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 18; +static const uint8_t SCL = 17; + +#define WIRE1_PIN_DEFINED //QWIIC +static const uint8_t SDA1 = 10; +static const uint8_t SCL1 = 21; + +// SD Card SPI +static const uint8_t SS = 13; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 2; +static const uint8_t SCK = 14; + +#define LORA_SCK 5 // LR1121 SCK +#define LORA_MISO 3 // LR1121 MISO +#define LORA_MOSI 6 // LR1121 MOSI +#define LORA_CS 7 // LR1121 CS +#define LORA_RST 8 // LR1121 RST + +#define LORA_DIO9 36 // LR1121 DIO9 +#define LORA_BUSY 34 // LR1121 BUSY +#define LORA_IRQ LORA_DIO9 + +// P1 +static const uint8_t PIN_42 = 45; +static const uint8_t PIN_46 = 46; +static const uint8_t PIN_45 = 45; +static const uint8_t PIN_41 = 41; +static const uint8_t PIN_40 = 40; +static const uint8_t PIN_39 = 39; +static const uint8_t PIN_43 = 43; +static const uint8_t PIN_44 = 44; +static const uint8_t PIN_38 = 38; + +// P2 +static const uint8_t PIN_37 = 37; +static const uint8_t PIN_36 = 36; +static const uint8_t PIN_0 = 0; +static const uint8_t PIN_35 = 35; +static const uint8_t PIN_34 = 34; +static const uint8_t PIN_33 = 33; +static const uint8_t PIN_47 = 47; +static const uint8_t PIN_48 = 48; +static const uint8_t PIN_12 = 12; +static const uint8_t PIN_8 = 8; +static const uint8_t PIN_15 = 15; +static const uint8_t PIN_16 = 16; + +#endif /* Pins_Arduino_h */ diff --git a/variants/lilygo_t3_s3_sx1262/pins_arduino.h b/variants/lilygo_t3_s3_sx1262/pins_arduino.h new file mode 100644 index 00000000000..8fbf0b31066 --- /dev/null +++ b/variants/lilygo_t3_s3_sx1262/pins_arduino.h @@ -0,0 +1,67 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x820A + +static const uint8_t LED_BUILTIN = 37; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t BUTTON_1 = 0; +static const uint8_t BAT_VOLT = 1; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 18; +static const uint8_t SCL = 17; + +#define WIRE1_PIN_DEFINED //QWIIC +static const uint8_t SDA1 = 10; +static const uint8_t SCL1 = 21; + +// SD Card SPI +static const uint8_t SS = 13; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 2; +static const uint8_t SCK = 14; + +#define LORA_SCK 5 // SX1262 SCK +#define LORA_MISO 3 // SX1262 MISO +#define LORA_MOSI 6 // SX1262 MOSI +#define LORA_CS 7 // SX1262 CS +#define LORA_RST 8 // SX1262 RST + +#define LORA_DIO1 33 //SX1262 DIO1 +#define LORA_BUSY 34 +#define LORA_IRQ LORA_DIO1 + +// P1 +static const uint8_t PIN_42 = 45; +static const uint8_t PIN_46 = 46; +static const uint8_t PIN_45 = 45; +static const uint8_t PIN_41 = 41; +static const uint8_t PIN_40 = 40; +static const uint8_t PIN_39 = 39; +static const uint8_t PIN_43 = 43; +static const uint8_t PIN_44 = 44; +static const uint8_t PIN_38 = 38; + +// P2 +static const uint8_t PIN_37 = 37; +static const uint8_t PIN_36 = 36; +static const uint8_t PIN_0 = 0; +static const uint8_t PIN_35 = 35; +static const uint8_t PIN_34 = 34; +static const uint8_t PIN_33 = 33; +static const uint8_t PIN_47 = 47; +static const uint8_t PIN_48 = 48; +static const uint8_t PIN_12 = 12; +static const uint8_t PIN_8 = 8; +static const uint8_t PIN_15 = 15; +static const uint8_t PIN_16 = 16; + +#endif /* Pins_Arduino_h */ diff --git a/variants/lilygo_t3_s3_sx127x/pins_arduino.h b/variants/lilygo_t3_s3_sx127x/pins_arduino.h new file mode 100644 index 00000000000..1b3e0a99239 --- /dev/null +++ b/variants/lilygo_t3_s3_sx127x/pins_arduino.h @@ -0,0 +1,74 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x820A + +static const uint8_t LED_BUILTIN = 37; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t BUTTON_1 = 0; +static const uint8_t BAT_VOLT = 1; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 18; +static const uint8_t SCL = 17; + +#define WIRE1_PIN_DEFINED //QWIIC +static const uint8_t SDA1 = 10; +static const uint8_t SCL1 = 21; + +// SD Card SPI +static const uint8_t SS = 13; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 2; +static const uint8_t SCK = 14; + +#define LORA_SCK 5 // SX1276/SX1278 SCK +#define LORA_MISO 3 // SX1276/SX1278 MISO +#define LORA_MOSI 6 // SX1276/SX1278 MOSI +#define LORA_CS 7 // SX1276/SX1278 CS +#define LORA_RST 8 // SX1276/SX1278 RST + +#define LORA_BUSY 33 +#define LORA_DIO0 9 //IRQ +#define LORA_DIO1 33 +#define LORA_DIO2 34 +#define LORA_DIO3 21 +#define LORA_DIO4 10 +#define LORA_DIO5 36 + +#define LORA_IRQ LORA_DIO0 +#define LORA_BUSY LORA_DIO1 + +// P1 +static const uint8_t PIN_42 = 45; +static const uint8_t PIN_46 = 46; +static const uint8_t PIN_45 = 45; +static const uint8_t PIN_41 = 41; +static const uint8_t PIN_40 = 40; +static const uint8_t PIN_39 = 39; +static const uint8_t PIN_43 = 43; +static const uint8_t PIN_44 = 44; +static const uint8_t PIN_38 = 38; + +// P2 +static const uint8_t PIN_37 = 37; +static const uint8_t PIN_36 = 36; +static const uint8_t PIN_0 = 0; +static const uint8_t PIN_35 = 35; +static const uint8_t PIN_34 = 34; +static const uint8_t PIN_33 = 33; +static const uint8_t PIN_47 = 47; +static const uint8_t PIN_48 = 48; +static const uint8_t PIN_12 = 12; +static const uint8_t PIN_8 = 8; +static const uint8_t PIN_15 = 15; +static const uint8_t PIN_16 = 16; + +#endif /* Pins_Arduino_h */ diff --git a/variants/lilygo_t3_s3_sx1280/pins_arduino.h b/variants/lilygo_t3_s3_sx1280/pins_arduino.h new file mode 100644 index 00000000000..ba342f3b8e9 --- /dev/null +++ b/variants/lilygo_t3_s3_sx1280/pins_arduino.h @@ -0,0 +1,67 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x820A + +static const uint8_t LED_BUILTIN = 37; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t BUTTON_1 = 0; +static const uint8_t BAT_VOLT = 1; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 18; +static const uint8_t SCL = 17; + +#define WIRE1_PIN_DEFINED //QWIIC +static const uint8_t SDA1 = 10; +static const uint8_t SCL1 = 21; + +// SD Card SPI +static const uint8_t SS = 13; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 2; +static const uint8_t SCK = 14; + +#define LORA_SCK 5 // SX1280 SCK +#define LORA_MISO 3 // SX1280 MISO +#define LORA_MOSI 6 // SX1280 MOSI +#define LORA_CS 7 // SX1280 CS +#define LORA_RST 8 // SX1280 RST + +#define LORA_DIO1 9 // SX1280 DIO1 +#define LORA_BUSY 36 // SX1280 BUSY +#define LORA_IRQ LORA_DIO1 + +// P1 +static const uint8_t PIN_42 = 45; +static const uint8_t PIN_46 = 46; +static const uint8_t PIN_45 = 45; +static const uint8_t PIN_41 = 41; +static const uint8_t PIN_40 = 40; +static const uint8_t PIN_39 = 39; +static const uint8_t PIN_43 = 43; +static const uint8_t PIN_44 = 44; +static const uint8_t PIN_38 = 38; + +// P2 +static const uint8_t PIN_37 = 37; +static const uint8_t PIN_36 = 36; +static const uint8_t PIN_0 = 0; +static const uint8_t PIN_35 = 35; +static const uint8_t PIN_34 = 34; +static const uint8_t PIN_33 = 33; +static const uint8_t PIN_47 = 47; +static const uint8_t PIN_48 = 48; +static const uint8_t PIN_12 = 12; +static const uint8_t PIN_8 = 8; +static const uint8_t PIN_15 = 15; +static const uint8_t PIN_16 = 16; + +#endif /* Pins_Arduino_h */ diff --git a/variants/lilygo_t3_s3_sx1280pa/pins_arduino.h b/variants/lilygo_t3_s3_sx1280pa/pins_arduino.h new file mode 100644 index 00000000000..03212754a69 --- /dev/null +++ b/variants/lilygo_t3_s3_sx1280pa/pins_arduino.h @@ -0,0 +1,66 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x820A + +static const uint8_t LED_BUILTIN = 37; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t BUTTON_1 = 0; +static const uint8_t BAT_VOLT = 1; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 18; +static const uint8_t SCL = 17; + +// SD Card SPI +static const uint8_t SS = 13; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 2; +static const uint8_t SCK = 14; + +#define LORA_SCK 5 // SX1280PA SCK +#define LORA_MISO 3 // SX1280PA MISO +#define LORA_MOSI 6 // SX1280PA MOSI +#define LORA_CS 7 // SX1280PA CS +#define LORA_RST 8 // SX1280PA RST + +#define LORA_DIO1 9 // SX1280 DIO1 +#define LORA_BUSY 36 // SX1280 BUSY +#define LORA_IRQ LORA_DIO1 + +#define LORA_RX 21 // SX1280PA RX SWITCH +#define LORA_TX 10 // SX1280PA TX SWITCH + +// P1 +static const uint8_t PIN_42 = 45; +static const uint8_t PIN_46 = 46; +static const uint8_t PIN_45 = 45; +static const uint8_t PIN_41 = 41; +static const uint8_t PIN_40 = 40; +static const uint8_t PIN_39 = 39; +static const uint8_t PIN_43 = 43; +static const uint8_t PIN_44 = 44; +static const uint8_t PIN_38 = 38; + +// P2 +static const uint8_t PIN_37 = 37; +static const uint8_t PIN_36 = 36; +static const uint8_t PIN_0 = 0; +static const uint8_t PIN_35 = 35; +static const uint8_t PIN_34 = 34; +static const uint8_t PIN_33 = 33; +static const uint8_t PIN_47 = 47; +static const uint8_t PIN_48 = 48; +static const uint8_t PIN_12 = 12; +static const uint8_t PIN_8 = 8; +static const uint8_t PIN_15 = 15; +static const uint8_t PIN_16 = 16; + +#endif /* Pins_Arduino_h */ diff --git a/variants/lilygo_t_eth_lite/pins_arduino.h b/variants/lilygo_t_eth_lite/pins_arduino.h new file mode 100644 index 00000000000..cb8fed779d9 --- /dev/null +++ b/variants/lilygo_t_eth_lite/pins_arduino.h @@ -0,0 +1,50 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 15; +static const uint8_t SCL = 16; + +static const uint8_t SS = 4; +static const uint8_t MISO = 5; +static const uint8_t MOSI = 6; +static const uint8_t SCK = 7; +static const uint8_t SD_SS = 42; + +// Analog +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; + +// Touch +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; + +// Ethernet +#define ETH_PHY_TYPE ETH_PHY_W5500 +#define ETH_PHY_ADDR 1 +#define ETH_PHY_CS 9 +#define ETH_PHY_IRQ 13 +#define ETH_PHY_RST 14 +#define ETH_PHY_SPI_HOST SPI2_HOST +#define ETH_PHY_SPI_SCK 10 +#define ETH_PHY_SPI_MISO 11 +#define ETH_PHY_SPI_MOSI 12 + +#endif /* Pins_Arduino_h */ diff --git a/variants/lilygo_tlora_pager/pins_arduino.h b/variants/lilygo_tlora_pager/pins_arduino.h new file mode 100644 index 00000000000..fb57b5d493f --- /dev/null +++ b/variants/lilygo_tlora_pager/pins_arduino.h @@ -0,0 +1,102 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#ifndef digitalPinToInterrupt +#define digitalPinToInterrupt(p) (((p) < 48) ? (p) : -1) +#endif + +#define USB_VID 0x303a +#define USB_PID 0x82D4 +#define USB_MANUFACTURER "LILYGO" +#define USB_PRODUCT "T-LoRa-Pager" + +// ST7796 +#define DISP_WIDTH (222) +#define DISP_HEIGHT (480) +#define SD_CS (21) + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// BHI260,PCF85063,BQ25896,DRV2605L,ES8311 share I2C Bus +static const uint8_t SDA = 3; +static const uint8_t SCL = 2; + +// Default sd cs pin +static const uint8_t SS = SD_CS; +static const uint8_t MOSI = 34; +static const uint8_t MISO = 33; +static const uint8_t SCK = 35; + +#define KB_INT (6) +#define KB_BACKLIGHT (46) + +// Rotary +#define ROTARY_A (40) +#define ROTARY_B (41) +#define ROTARY_C (7) + +// Interrupt IO port +#define RTC_INT (1) +#define NFC_INT (5) +#define SENSOR_INT (8) +#define NFC_CS (39) + +// ES8311 +#define I2S_WS (18) +#define I2S_SCK (11) +#define I2S_MCLK (10) +#define I2S_SDOUT (45) +#define I2S_SDIN (17) + +// GPS +#define GPS_TX (12) +#define GPS_RX (4) +#define GPS_PPS (13) + +// LoRa, SD, ST25R3916 card share SPI bus +#define LORA_SCK (SCK) // share spi bus +#define LORA_MISO (MISO) // share spi bus +#define LORA_MOSI (MOSI) // share spi bus +#define LORA_CS (36) +#define LORA_RST (47) +#define LORA_BUSY (48) +#define LORA_IRQ (14) + +// SPI interface display +#define DISP_MOSI (MOSI) +#define DISP_MISO (MISO) +#define DISP_SCK (SCK) +#define DISP_RST (-1) +#define DISP_CS (38) +#define DISP_DC (37) +#define DISP_BL (42) + +// External expansion chip IO definition +#define EXPANDS_DRV_EN (0) +#define EXPANDS_AMP_EN (1) +#define EXPANDS_KB_RST (2) +#define EXPANDS_LORA_EN (3) +#define EXPANDS_GPS_EN (4) +#define EXPANDS_NFC_EN (5) +#define EXPANDS_GPS_RST (7) +#define EXPANDS_KB_EN (8) +#define EXPANDS_GPIO_EN (9) +#define EXPANDS_SD_DET (10) +#define EXPANDS_SD_PULLEN (11) +#define EXPANDS_SD_EN (12) + +// Peripheral definition exists +#define USING_AUDIO_CODEC +#define USING_XL9555_EXPANDS +#define USING_PPM_MANAGE +#define USING_BQ_GAUGE +#define USING_INPUT_DEV_ROTARY +#define USING_INPUT_DEV_KEYBOARD +#define USING_ST25R3916 +#define USING_BHI260_SENSOR +#define HAS_SD_CARD_SOCKET + +#endif /* Pins_Arduino_h */ diff --git a/variants/lilygo_twatch_s3/pins_arduino.h b/variants/lilygo_twatch_s3/pins_arduino.h new file mode 100644 index 00000000000..05543de27c5 --- /dev/null +++ b/variants/lilygo_twatch_s3/pins_arduino.h @@ -0,0 +1,76 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x821B +#define USB_MANUFACTURER "LILYGO" +#define USB_PRODUCT "T-Watch-S3" + +#define DISP_WIDTH (240) +#define DISP_HEIGHT (240) + +#define DISP_MOSI (13) +#define DISP_MISO (-1) +#define DISP_SCK (18) +#define DISP_RST (-1) +#define DISP_CS (12) +#define DISP_DC (38) +#define DISP_BL (45) + +// touch screen +#define TP_INT (16) +#define TP_SDA (39) +#define TP_SCL (40) + +// Interrupt IO port +#define RTC_INT (17) +#define PMU_INT (21) +#define SENSOR_INT (14) + +// PDM microphone +#define MIC_SCK (44) +#define MIC_DAT (47) + +// MAX98357A +#define I2S_BCLK (48) +#define I2S_WCLK (15) +#define I2S_DOUT (46) + +#define IR_SEND (2) + +// TX, RX pin connected to GPS +static const uint8_t TX = 42; +static const uint8_t RX = 41; + +// BMA423,PCF8563,AXP2101,DRV2605L share I2C Bus +static const uint8_t SDA = 10; +static const uint8_t SCL = 11; + +// Default sd cs pin +static const uint8_t SS = 5; +static const uint8_t MOSI = 1; +static const uint8_t MISO = 4; +static const uint8_t SCK = 3; + +// LoRa and SD card share SPI bus +#define LORA_SCK (SCK) // share spi bus +#define LORA_MISO (MISO) // share spi bus +#define LORA_MOSI (MOSI) // share spi bus +#define LORA_CS (5) +#define LORA_RST (8) +#define LORA_BUSY (7) +#define LORA_IRQ (9) + +#define GPS_TX (TX) +#define GPS_RX (RX) + +// Peripheral definition exists +#define USING_PCM_AMPLIFIER +#define USING_PDM_MICROPHONE +#define USING_PMU_MANAGE +#define USING_INPUT_DEV_TOUCHPAD +#define USING_IR_REMOTE + +#endif /* Pins_Arduino_h */ diff --git a/variants/lilygo_twatch_ultra/pins_arduino.h b/variants/lilygo_twatch_ultra/pins_arduino.h new file mode 100644 index 00000000000..91797e687fa --- /dev/null +++ b/variants/lilygo_twatch_ultra/pins_arduino.h @@ -0,0 +1,93 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#ifndef digitalPinToInterrupt +#define digitalPinToInterrupt(p) (((p) < 48) ? (p) : -1) +#endif + +#define USB_VID 0x303a +#define USB_PID 0x8227 +#define USB_MANUFACTURER "LILYGO" +#define USB_PRODUCT "T-Watch-Ultra" + +#define DISP_WIDTH 502 +#define DISP_HEIGHT 410 + +// QSPI interface display +#define DISP_D0 (38) +#define DISP_D1 (39) +#define DISP_D2 (42) +#define DISP_D3 (45) +#define DISP_SCK (40) +#define DISP_CS (41) +#define DISP_RST (37) +#define DISP_TE (6) + +// Interrupt IO port +#define TP_INT (12) +#define RTC_INT (1) +#define PMU_INT (7) +#define NFC_INT (5) +#define SENSOR_INT (8) +#define NFC_CS (4) + +// PDM microphone +#define MIC_SCK (17) +#define MIC_DAT (18) + +// MAX98357A +#define I2S_BCLK (9) +#define I2S_WCLK (10) +#define I2S_DOUT (11) + +#define SD_CS (21) + +// TX, RX pin connected to GPS +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// BHI260,PCF85063,AXP2101,DRV2605L share I2C Bus +static const uint8_t SDA = 3; +static const uint8_t SCL = 2; + +// Default sd cs pin +static const uint8_t SS = SD_CS; +static const uint8_t MOSI = 34; +static const uint8_t MISO = 33; +static const uint8_t SCK = 35; + +#define GPS_TX (TX) +#define GPS_RX (RX) +#define GPS_PPS (13) + +#define TP_SDA (SDA) +#define TP_SCL (SCL) + +// LoRa and SD card share SPI bus +#define LORA_SCK (SCK) // share spi bus +#define LORA_MISO (MISO) // share spi bus +#define LORA_MOSI (MOSI) // share spi bus +#define LORA_CS (36) +#define LORA_RST (47) +#define LORA_BUSY (48) +#define LORA_IRQ (14) + +// External expansion chip IO definition +#define EXPANDS_DRV_EN (6) +#define EXPANDS_DISP_EN (7) +#define EXPANDS_TOUCH_RST (8) +#define EXPANDS_SD_DET (10) + +// Peripheral definition exists +#define USING_XL9555_EXPANDS +#define USING_PCM_AMPLIFIER +#define USING_PDM_MICROPHONE +#define USING_PMU_MANAGE +#define USING_INPUT_DEV_TOUCHPAD +#define USING_ST25R3916 +#define USING_BHI260_SENSOR +#define HAS_SD_CARD_SOCKET + +#endif /* Pins_Arduino_h */ diff --git a/variants/lolin_c3_mini/pins_arduino.h b/variants/lolin_c3_mini/pins_arduino.h index c7357975ac7..0236f02267d 100644 --- a/variants/lolin_c3_mini/pins_arduino.h +++ b/variants/lolin_c3_mini/pins_arduino.h @@ -2,10 +2,18 @@ #define Pins_Arduino_h #include +#include "soc/soc_caps.h" -static const uint8_t LED_BUILTIN = 7; +// based on https://www.wemos.cc/en/latest/c3/c3_mini.html +// WS2812 RGB LED on pin 7 +#define PIN_RGB_LED 7 +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() +#define RGB_BUILTIN LED_BUILTIN +#define RGB_BRIGHTNESS 64 static const uint8_t TX = 21; static const uint8_t RX = 20; diff --git a/variants/lolin_c3_pico/pins_arduino.h b/variants/lolin_c3_pico/pins_arduino.h index 8d4cfc5c4f0..45087c3f9fc 100644 --- a/variants/lolin_c3_pico/pins_arduino.h +++ b/variants/lolin_c3_pico/pins_arduino.h @@ -4,10 +4,18 @@ #define Pins_Arduino_h #include +#include "soc/soc_caps.h" -static const uint8_t LED_BUILTIN = 7; +// based on https://www.wemos.cc/en/latest/c3/c3_pico.html +// WS2812 RGB LED on pin 7 +#define PIN_RGB_LED 7 +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() +#define RGB_BUILTIN LED_BUILTIN +#define RGB_BRIGHTNESS 64 static const uint8_t TX = 21; static const uint8_t RX = 20; @@ -17,7 +25,7 @@ static const uint8_t SCL = 10; static const uint8_t VBAT = 3; -static const uint8_t SCK = 2; +static const uint8_t SCK = 1; static const uint8_t MISO = 0; static const uint8_t MOSI = 4; static const uint8_t SS = 5; diff --git a/variants/lolin_s3_mini/pins_arduino.h b/variants/lolin_s3_mini/pins_arduino.h index 346c7628b23..361d3238960 100644 --- a/variants/lolin_s3_mini/pins_arduino.h +++ b/variants/lolin_s3_mini/pins_arduino.h @@ -12,6 +12,9 @@ static const uint8_t LED_BUILTIN = 47 + SOC_GPIO_PIN_COUNT; #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 +// This board has a builtin RGB LED that works with a different signal color order +// Other order options can be found in https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp32-hal-rgb-led.h +#define RGB_BUILTIN_LED_COLOR_ORDER LED_COLOR_ORDER_RGB static const uint8_t TX = 43; static const uint8_t RX = 44; diff --git a/variants/lolin_s3_mini_pro/pins_arduino.h b/variants/lolin_s3_mini_pro/pins_arduino.h new file mode 100644 index 00000000000..1c5f6c26bd0 --- /dev/null +++ b/variants/lolin_s3_mini_pro/pins_arduino.h @@ -0,0 +1,77 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define USB_VID 0x303a +#define USB_PID 0x8216 + +static const uint8_t LED_BUILTIN = 8 + SOC_GPIO_PIN_COUNT; +; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN +#define RGB_BUILTIN LED_BUILTIN +#define RGB_BRIGHTNESS 5 +#define RGB_POWER 7 //RGB LED POWER PIN + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 12; +static const uint8_t SCL = 11; + +static const uint8_t SS = 37; +static const uint8_t MOSI = 38; +static const uint8_t MISO = 39; +static const uint8_t SCK = 40; + +//TFT +static const uint8_t TFT_BL = 33; +static const uint8_t TFT_DC = 36; +static const uint8_t TFT_CS = 35; +static const uint8_t TFT_RST = 34; + +//IR +static const uint8_t PIN_IR = 9; + +//BUTTON +static const uint8_t BUTTON_LEFT = 0; +static const uint8_t BUTTON_OK = 47; +static const uint8_t BUTTON_RIGHT = 48; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/lolin_s3_mini_pro/variant.cpp b/variants/lolin_s3_mini_pro/variant.cpp new file mode 100644 index 00000000000..72b340b27ad --- /dev/null +++ b/variants/lolin_s3_mini_pro/variant.cpp @@ -0,0 +1,31 @@ +/* + */ + +#include "esp32-hal-gpio.h" +#include "pins_arduino.h" + +extern "C" { + +// Initialize variant/board, called before setup() +void initVariant(void) { + // IR + pinMode(PIN_IR, OUTPUT); + digitalWrite(PIN_IR, LOW); + // RGB + pinMode(RGB_POWER, OUTPUT); + digitalWrite(RGB_POWER, LOW); + // BUTTON + pinMode(BUTTON_LEFT, INPUT_PULLUP); + pinMode(BUTTON_OK, INPUT_PULLUP); + pinMode(BUTTON_RIGHT, INPUT_PULLUP); + // TFT + pinMode(TFT_BL, OUTPUT); + digitalWrite(TFT_BL, LOW); + pinMode(TFT_CS, OUTPUT); + digitalWrite(TFT_CS, HIGH); + pinMode(TFT_RST, OUTPUT); + digitalWrite(TFT_RST, LOW); + delay(1); + digitalWrite(TFT_RST, HIGH); +} +} diff --git a/variants/lopy/pins_arduino.h b/variants/lopy/pins_arduino.h index a648c529c46..f7e2ee02476 100644 --- a/variants/lopy/pins_arduino.h +++ b/variants/lopy/pins_arduino.h @@ -15,12 +15,12 @@ #define LORA_IO1 LORA_IRQ // tied by diode to IO0 #define LORA_IO2 LORA_IRQ // tied by diode to IO0 -// Neopixel -#define PIN_NEOPIXEL 0 // ->2812 RGB !!! -static const uint8_t LED_BUILTIN = PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT; +// RGB LED +#define PIN_RGB_LED 0 // ->2812 RGB !!! +static const uint8_t LED_BUILTIN = PIN_RGB_LED + SOC_GPIO_PIN_COUNT; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/lopy4/pins_arduino.h b/variants/lopy4/pins_arduino.h index 4ac91267e69..eb36b3008e6 100644 --- a/variants/lopy4/pins_arduino.h +++ b/variants/lopy4/pins_arduino.h @@ -15,12 +15,12 @@ #define LORA_IO2 LORA_IRQ // tied by diode to IO0 #define LORA_RST NOT_A_PIN -// Neopixel -#define PIN_NEOPIXEL 0 // ->2812 RGB !!! -static const uint8_t LED_BUILTIN = PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT; +// RGB LED +#define PIN_RGB_LED 0 // ->2812 RGB !!! +static const uint8_t LED_BUILTIN = PIN_RGB_LED + SOC_GPIO_PIN_COUNT; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/m5stack_dinmeter/pins_arduino.h b/variants/m5stack_dinmeter/pins_arduino.h new file mode 100644 index 00000000000..2c50f97c262 --- /dev/null +++ b/variants/m5stack_dinmeter/pins_arduino.h @@ -0,0 +1,51 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t TXD2 = 1; +static const uint8_t RXD2 = 2; + +static const uint8_t SDA = 13; +static const uint8_t SCL = 15; + +static const uint8_t SS = 12; +static const uint8_t MOSI = 14; +static const uint8_t MISO = 39; +static const uint8_t SCK = 40; + +static const uint8_t G0 = 0; +static const uint8_t G1 = 1; +static const uint8_t G2 = 2; +static const uint8_t G3 = 3; +static const uint8_t G4 = 4; +static const uint8_t G5 = 5; +static const uint8_t G6 = 6; +static const uint8_t G7 = 7; +static const uint8_t G8 = 8; +static const uint8_t G9 = 9; +static const uint8_t G10 = 10; +static const uint8_t G11 = 11; +static const uint8_t G12 = 12; +static const uint8_t G13 = 13; +static const uint8_t G14 = 14; +static const uint8_t G15 = 15; +static const uint8_t G39 = 39; +static const uint8_t G40 = 40; +static const uint8_t G41 = 41; +static const uint8_t G42 = 42; +static const uint8_t G43 = 43; +static const uint8_t G44 = 44; +static const uint8_t G46 = 46; + +static const uint8_t ADC1 = 7; +static const uint8_t ADC2 = 8; + +#endif /* Pins_Arduino_h */ diff --git a/variants/m5stack_fire/pins_arduino.h b/variants/m5stack_fire/pins_arduino.h index 3759219d1bf..2202e6bb4bc 100644 --- a/variants/m5stack_fire/pins_arduino.h +++ b/variants/m5stack_fire/pins_arduino.h @@ -9,7 +9,7 @@ static const uint8_t RX = 3; static const uint8_t SDA = 21; static const uint8_t SCL = 22; -static const uint8_t SS = 5; +static const uint8_t SS = 4; static const uint8_t MOSI = 23; static const uint8_t MISO = 19; static const uint8_t SCK = 18; diff --git a/variants/m5stack_nanoc6/pins_arduino.h b/variants/m5stack_nanoc6/pins_arduino.h new file mode 100644 index 00000000000..8f16e0a2675 --- /dev/null +++ b/variants/m5stack_nanoc6/pins_arduino.h @@ -0,0 +1,45 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define USB_VID 0x303A +#define USB_PID 0x1001 +#define USB_MANUFACTURER "M5Stack" +#define USB_PRODUCT "NanoC6" +#define USB_SERIAL "" + +static const uint8_t LED_BUILTIN = 7; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t TX = 16; +static const uint8_t RX = 17; + +static const uint8_t SDA = 2; +static const uint8_t SCL = 1; + +static const uint8_t SS = 4; // Not connected +static const uint8_t MOSI = 5; // Not connected +static const uint8_t MISO = 6; // Not connected +static const uint8_t SCK = 8; // Not connected + +static const uint8_t A1 = 1; +static const uint8_t A2 = 2; +static const uint8_t A3 = 3; + +static const uint8_t D1 = 1; +static const uint8_t D2 = 2; +static const uint8_t D3 = 3; +static const uint8_t D4 = 7; +static const uint8_t D5 = 8; +static const uint8_t D6 = 9; + +static const uint8_t BLUE_LED_PIN = 7; +static const uint8_t BTN_PIN = 9; +static const uint8_t IR_TX_PIN = 3; +static const uint8_t RGB_LED_PWR_PIN = 19; +static const uint8_t RGB_LED_DATA_PIN = 20; + +#endif /* Pins_Arduino_h */ diff --git a/variants/m5stack_tough/pins_arduino.h b/variants/m5stack_tough/pins_arduino.h index a4bd6bb29a6..f9d5b8c1a72 100644 --- a/variants/m5stack_tough/pins_arduino.h +++ b/variants/m5stack_tough/pins_arduino.h @@ -3,9 +3,6 @@ #include -#define TX2 14 -#define RX2 13 - static const uint8_t TX = 1; static const uint8_t RX = 3; diff --git a/variants/micro_s2/pins_arduino.h b/variants/micro_s2/pins_arduino.h index 5b3d3964917..422799478fc 100644 --- a/variants/micro_s2/pins_arduino.h +++ b/variants/micro_s2/pins_arduino.h @@ -66,7 +66,7 @@ static const uint8_t LED_BUILTIN = 21; #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN static const uint8_t PIXEL_BUILTIN = 33; -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN (PIXEL_BUILTIN + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/sensebox_mcu_esp32s2/pins_arduino.h b/variants/sensebox_mcu_esp32s2/pins_arduino.h index c3d03784964..62acb6a13f4 100644 --- a/variants/sensebox_mcu_esp32s2/pins_arduino.h +++ b/variants/sensebox_mcu_esp32s2/pins_arduino.h @@ -16,9 +16,9 @@ #define USB_FW_MSC_VOLUME_NAME "senseBox" // max 11 chars #define USB_FW_MSC_SERIAL_NUMBER 0x00000000 -#define PIN_NEOPIXEL 1 // NeoPixel LED -#define NEOPIXEL_PIN 1 // NeoPixel LED -#define NEOPIXEL_NUM 1 // number of neopixels +#define PIN_RGB_LED 1 // RGB LED +#define RGBLED_PIN 1 // RGB LED +#define RGBLED_NUM 1 // number of RGB LEDs // Default I2C QWIIC-Ports static const uint8_t SDA = 39; diff --git a/variants/sensebox_mcu_esp32s2/variant.cpp b/variants/sensebox_mcu_esp32s2/variant.cpp index 59e187b2a7f..0c58ef2cbe2 100644 --- a/variants/sensebox_mcu_esp32s2/variant.cpp +++ b/variants/sensebox_mcu_esp32s2/variant.cpp @@ -34,8 +34,8 @@ void initVariant(void) { digitalWrite(IO_ENABLE, LOW); //reset RGB - pinMode(PIN_NEOPIXEL, OUTPUT); - digitalWrite(PIN_NEOPIXEL, LOW); + pinMode(PIN_RGB_LED, OUTPUT); + digitalWrite(PIN_RGB_LED, LOW); //enable XBEE by default pinMode(PIN_XB1_ENABLE, OUTPUT); diff --git a/variants/sparkfun_esp32_iot_redboard/pins_arduino.h b/variants/sparkfun_esp32_iot_redboard/pins_arduino.h index 3c84fa89da5..f6226fdf286 100644 --- a/variants/sparkfun_esp32_iot_redboard/pins_arduino.h +++ b/variants/sparkfun_esp32_iot_redboard/pins_arduino.h @@ -8,8 +8,8 @@ static const uint8_t LED_BUILTIN = 18; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -#define NEO_PIXEL 2 //WS2812 LED -static const uint8_t RGB_BUILTIN = (SOC_GPIO_PIN_COUNT + NEO_PIXEL); +#define RGB_LED_PIN 2 //WS2812 LED +static const uint8_t RGB_BUILTIN = (SOC_GPIO_PIN_COUNT + RGB_LED_PIN); #define RGB_BUILTIN RGB_BUILTIN // necessary to make digitalWrite/digitalMode find it #define RGB_BRIGHTNESS 64 diff --git a/variants/sparkfun_esp32c6_thing_plus/pins_arduino.h b/variants/sparkfun_esp32c6_thing_plus/pins_arduino.h index 53724f067f4..61c939a32a9 100644 --- a/variants/sparkfun_esp32c6_thing_plus/pins_arduino.h +++ b/variants/sparkfun_esp32c6_thing_plus/pins_arduino.h @@ -4,12 +4,12 @@ #include #include "soc/soc_caps.h" -#define PIN_NEOPIXEL 23 +#define PIN_RGB_LED 23 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/sparkfun_esp32s3_thing_plus/pins_arduino.h b/variants/sparkfun_esp32s3_thing_plus/pins_arduino.h new file mode 100644 index 00000000000..7c5e0c1f570 --- /dev/null +++ b/variants/sparkfun_esp32s3_thing_plus/pins_arduino.h @@ -0,0 +1,61 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +//#define USB_VID 0x303A +//#define USB_PID 0x1001 +//#define USB_MANUFACTURER "Sparkfun" +//#define USB_PRODUCT "ESP32-S3 Thing Plus" +#define USB_SERIAL "" + +#define LED_PIN 46 //Pin 46 on Thing Plus C S3 is connected to WS2812 LED +#define COLOR_ORDER GRB +#define CHIPSET WS2812 +#define NUM_LEDS 1 +#define BRIGHTNESS 25 +#define LED_BUILTIN LED_PIN +#define BUILTIN_LED LED_BUILTIN // backward compatibility + +static const uint8_t LED = LED_PIN; +static const uint8_t STAT_LED = 0; +static const uint8_t BTN = 0; +static const uint8_t Q_EN = 45; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SS = 10; +static const uint8_t MISO = 13; //POCI +static const uint8_t MOSI = 11; //PICO +static const uint8_t SCK = 12; + +static const uint8_t SCL = 9; +static const uint8_t SDA = 8; + +static const uint8_t A0 = 10; +static const uint8_t A1 = 14; +static const uint8_t A2 = 15; +static const uint8_t A3 = 16; +static const uint8_t A4 = 17; +static const uint8_t A5 = 18; + +static const uint8_t GPIO0 = 21; +static const uint8_t GPIO1 = 7; +static const uint8_t GPIO2 = 6; +static const uint8_t GPIO3 = 5; +static const uint8_t GPIO4 = 4; +static const uint8_t GPIO5 = 2; +static const uint8_t GPIO6 = 1; + +static const uint8_t FREEBIE = 42; + +static const uint8_t SDIO_DET = 48; +static const uint8_t SDIO0 = 39; +static const uint8_t SDIO1 = 40; +static const uint8_t SDIO2 = 47; +static const uint8_t SDIO3 = 33; +static const uint8_t SDIO_CLK = 38; +static const uint8_t SDIO_CMD = 34; + +#endif /* Pins_Arduino_h */ diff --git a/variants/thingpulse_epulse_feather_c6/pins_arduino.h b/variants/thingpulse_epulse_feather_c6/pins_arduino.h index 705c2b4d9ce..55afea91565 100644 --- a/variants/thingpulse_epulse_feather_c6/pins_arduino.h +++ b/variants/thingpulse_epulse_feather_c6/pins_arduino.h @@ -4,12 +4,12 @@ #include #include "soc/soc_caps.h" -#define PIN_NEOPIXEL 8 +#define PIN_RGB_LED 8 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL; +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/uPesy_esp32s3_basic/pins_arduino.h b/variants/uPesy_esp32s3_basic/pins_arduino.h index f2566444276..85d9c2ccb00 100644 --- a/variants/uPesy_esp32s3_basic/pins_arduino.h +++ b/variants/uPesy_esp32s3_basic/pins_arduino.h @@ -11,7 +11,7 @@ #define USB_SERIAL "" static const uint8_t RGB_DATA = 38; -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/um_bling/pins_arduino.h b/variants/um_bling/pins_arduino.h index bd5b4a07b38..590eec5efea 100644 --- a/variants/um_bling/pins_arduino.h +++ b/variants/um_bling/pins_arduino.h @@ -67,7 +67,7 @@ static const uint8_t I2S_AMP_WS = 1; static const uint8_t RTC_INT = 7; static const uint8_t RGB_DATA = 18; -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino diff --git a/variants/um_feathers2neo/pins_arduino.h b/variants/um_feathers2neo/pins_arduino.h index ff3398de910..92c9cd1a099 100644 --- a/variants/um_feathers2neo/pins_arduino.h +++ b/variants/um_feathers2neo/pins_arduino.h @@ -54,7 +54,7 @@ static const uint8_t NEOPIXEL_MATRIX_DATA = 21; static const uint8_t NEOPIXEL_MATRIX_PWR = 4; static const uint8_t NEOPIXEL_DATA = 40; -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN (NEOPIXEL_DATA + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino diff --git a/variants/um_feathers3/pins_arduino.h b/variants/um_feathers3/pins_arduino.h index 4d68148ac92..1c81339c88e 100644 --- a/variants/um_feathers3/pins_arduino.h +++ b/variants/um_feathers3/pins_arduino.h @@ -16,6 +16,10 @@ static const uint8_t RX = 44; static const uint8_t SDA = 8; static const uint8_t SCL = 9; +#define WIRE1_PIN_DEFINED 1 // See Wire.cpp at bool TwoWire::initPins(int sdaPin, int sclPin) +static const uint8_t SDA1 = 16; +static const uint8_t SCL1 = 15; + static const uint8_t SS = 5; static const uint8_t MOSI = 35; static const uint8_t MISO = 37; @@ -57,7 +61,7 @@ static const uint8_t VBUS_SENSE = 34; #define BUILTIN_LED LED_BUILTIN // backward compatibility static const uint8_t RGB_DATA = 40; -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/um_feathers3neo/pins_arduino.h b/variants/um_feathers3neo/pins_arduino.h index c0a1aae867e..94d546d22c2 100644 --- a/variants/um_feathers3neo/pins_arduino.h +++ b/variants/um_feathers3neo/pins_arduino.h @@ -57,7 +57,7 @@ static const uint8_t VBUS_SENSE = 15; #define BUILTIN_LED LED_BUILTIN // backward compatibility static const uint8_t RGB_DATA = 40; -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 diff --git a/variants/um_nanos3/pins_arduino.h b/variants/um_nanos3/pins_arduino.h index 0db14ebf792..66aef214c47 100644 --- a/variants/um_nanos3/pins_arduino.h +++ b/variants/um_nanos3/pins_arduino.h @@ -44,7 +44,7 @@ static const uint8_t T8 = 8; static const uint8_t T9 = 9; static const uint8_t RGB_DATA = 41; -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino diff --git a/variants/um_omgs3/bootloader_tinyuf2.bin b/variants/um_omgs3/bootloader_tinyuf2.bin new file mode 100644 index 00000000000..84bab25be27 Binary files /dev/null and b/variants/um_omgs3/bootloader_tinyuf2.bin differ diff --git a/variants/um_omgs3/partitions_tinyuf2.csv b/variants/um_omgs3/partitions_tinyuf2.csv new file mode 100644 index 00000000000..4026378b6fb --- /dev/null +++ b/variants/um_omgs3/partitions_tinyuf2.csv @@ -0,0 +1,10 @@ +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +# bootloader.bin,, 0x1000, 32K +# partition table,, 0x8000, 4K +nvs, data, nvs, 0x9000, 20K, +otadata, data, ota, 0xe000, 8K, +ota_0, 0, ota_0, 0x10000, 2048K, +ota_1, 0, ota_1, 0x210000, 2048K, +uf2, app, factory,0x410000, 256K, +ffat, data, fat, 0x450000, 3776K, diff --git a/variants/um_omgs3/pins_arduino.h b/variants/um_omgs3/pins_arduino.h new file mode 100644 index 00000000000..81164c48efe --- /dev/null +++ b/variants/um_omgs3/pins_arduino.h @@ -0,0 +1,59 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +#define USB_VID 0x303A +#define USB_PID 0x8224 +#define USB_MANUFACTURER "Unexpected Maker" +#define USB_PRODUCT "OMGS3" +#define USB_SERIAL "" + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +static const uint8_t SS = 3; +static const uint8_t MOSI = 6; +static const uint8_t MISO = 5; +static const uint8_t SDO = 6; +static const uint8_t SDI = 5; +static const uint8_t SCK = 4; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; + +static const uint8_t VBUS_SENSE = 33; + +static const uint8_t RGB_DATA = 35; +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() +#define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT) +#define RGB_BRIGHTNESS 64 +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = RGB_BUILTIN; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t RGB_PWR = 34; + +#endif /* Pins_Arduino_h */ diff --git a/variants/um_omgs3/tinyuf2.bin b/variants/um_omgs3/tinyuf2.bin new file mode 100644 index 00000000000..fccd2906393 Binary files /dev/null and b/variants/um_omgs3/tinyuf2.bin differ diff --git a/variants/um_pros3/pins_arduino.h b/variants/um_pros3/pins_arduino.h index 7a8921bacb7..4b9bc8de6aa 100644 --- a/variants/um_pros3/pins_arduino.h +++ b/variants/um_pros3/pins_arduino.h @@ -55,7 +55,7 @@ static const uint8_t VBAT_SENSE = 10; static const uint8_t VBUS_SENSE = 33; static const uint8_t RGB_DATA = 18; -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino diff --git a/variants/um_tinyc6/pins_arduino.h b/variants/um_tinyc6/pins_arduino.h index 1afb1d5cc17..6505e1ed50e 100644 --- a/variants/um_tinyc6/pins_arduino.h +++ b/variants/um_tinyc6/pins_arduino.h @@ -47,7 +47,7 @@ static const uint8_t VBAT_SENSE = 4; static const uint8_t VBUS_SENSE = 10; static const uint8_t RGB_DATA = 23; -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino diff --git a/variants/um_tinys2/pins_arduino.h b/variants/um_tinys2/pins_arduino.h index 1a725f58686..2a6e03aa078 100644 --- a/variants/um_tinys2/pins_arduino.h +++ b/variants/um_tinys2/pins_arduino.h @@ -66,7 +66,7 @@ static const uint8_t VBAT_SENSE = 3; static const uint8_t VBUS_SENSE = 21; static const uint8_t RGB_DATA = 1; -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino diff --git a/variants/um_tinys3/pins_arduino.h b/variants/um_tinys3/pins_arduino.h index 7168669caf9..24742781dce 100644 --- a/variants/um_tinys3/pins_arduino.h +++ b/variants/um_tinys3/pins_arduino.h @@ -47,7 +47,7 @@ static const uint8_t VBAT_SENSE = 10; static const uint8_t VBUS_SENSE = 33; static const uint8_t RGB_DATA = 18; -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT) #define RGB_BRIGHTNESS 64 // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino diff --git a/variants/walter/pins_arduino.h b/variants/walter/pins_arduino.h new file mode 100644 index 00000000000..53076e7b48e --- /dev/null +++ b/variants/walter/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 +#define USB_MANUFACTURER "DPTechnics" +#define USB_PRODUCT "Walter" +#define USB_SERIAL "" + +#define MODEM_TX 48 // Sequans modem UART0 TX +#define MODEM_RX 14 // Sequans modem UART0 RX +#define MODEM_CTS 47 // Sequans modem UART0 CTS +#define MODEM_RTS 19 // Sequans modem UART0 RTS +#define MODEM_RESET 45 // Sequans modem reset signal +#define MODEM_WAKE 46 // Sequans modem wake signal + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_lcd_146/pins_arduino.h b/variants/waveshare_esp32_s3_lcd_146/pins_arduino.h new file mode 100644 index 00000000000..2539f207bd0 --- /dev/null +++ b/variants/waveshare_esp32_s3_lcd_146/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8258 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-1.46" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 10; +static const uint8_t SDA = 11; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_lcd_147/pins_arduino.h b/variants/waveshare_esp32_s3_lcd_147/pins_arduino.h new file mode 100644 index 00000000000..b79a970c1ef --- /dev/null +++ b/variants/waveshare_esp32_s3_lcd_147/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x828A + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-LCD-1.47" +#define USB_SERIAL "" + +#define PIN_RGB_LED 38 + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_lcd_169/pins_arduino.h b/variants/waveshare_esp32_s3_lcd_169/pins_arduino.h new file mode 100644 index 00000000000..54663a6810a --- /dev/null +++ b/variants/waveshare_esp32_s3_lcd_169/pins_arduino.h @@ -0,0 +1,102 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8221 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-LCD-1.69" +#define USB_SERIAL "" + +// display for ST7789V2 +#define WS_LCD_DC 4 +#define WS_LCD_CS 5 +#define WS_LCD_SCL 6 +#define WS_LCD_SDA 7 +#define WS_LCD_RST 8 +#define WS_LCD_BL 15 + +// Onboard RTC for PCF85063 +#define WS_RTC_SCL 10 +#define WS_RTC_SDA 11 +#define WS_RTC_ADDRESS 0x51 +#define WS_RTC_INT 41 + +// Onboard QMI8658 IMU +#define WS_QMI8658_SDA 11 +#define WS_QMI8658_SCL 10 +#define WS_QMI8658_ADDRESS 0x6B +#define WS_QMI8658_INT1 38 + +// Onboard Electric buzzer & Custom buttons +// GPIO and PSRAM conflict, need to pay attention when using +#define WS_BUZZ 33 // Please pull down the level when using +#define WS_SYS_OUT 36 +#define WS_SYS_EN 35 + +// Partial voltage measurement method +#define WS_BAT_ADC 1 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 10; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_lcd_185/pins_arduino.h b/variants/waveshare_esp32_s3_lcd_185/pins_arduino.h new file mode 100644 index 00000000000..f8542f014e7 --- /dev/null +++ b/variants/waveshare_esp32_s3_lcd_185/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8290 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-LCD-1.85" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 10; +static const uint8_t SDA = 11; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_relay_6ch/pins_arduino.h b/variants/waveshare_esp32_s3_relay_6ch/pins_arduino.h new file mode 100644 index 00000000000..f389f5e1358 --- /dev/null +++ b/variants/waveshare_esp32_s3_relay_6ch/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8273 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Relay-6CH" +#define USB_SERIAL "" + +#define PIN_RGB_LED 38 + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_amoled_143/pins_arduino.h b/variants/waveshare_esp32_s3_touch_amoled_143/pins_arduino.h new file mode 100644 index 00000000000..ed6df1d3a2c --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_amoled_143/pins_arduino.h @@ -0,0 +1,49 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x824A + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-AMOLED-1.43" +#define USB_SERIAL "" + +// display QSPI SPI2 +#define QSPI_CS 9 +#define QSPI_SCK 10 +#define QSPI_D0 11 +#define QSPI_D1 12 +#define QSPI_D2 13 +#define QSPI_D3 14 +#define AMOLED_RESET 21 +#define AMOLED_TE -1 +#define AMOLED_PWR_EN -1 +// Touch I2C +#define TP_SCL 48 +#define TP_SDA 47 +#define TP_RST -1 +#define TP_INT -1 + +// RTC +#define RTC_INT 15 +// Partial voltage measurement method +#define BAT_ADC 4 +// Onboard QMI8658 IMU +#define QMI_INT1 8 + +static const uint8_t SDA = 47; +static const uint8_t SCL = 48; +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +//esp32s3-PSFlash SPI1/SPI0 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_amoled_164/pins_arduino.h b/variants/waveshare_esp32_s3_touch_amoled_164/pins_arduino.h new file mode 100644 index 00000000000..ce17a49972a --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_amoled_164/pins_arduino.h @@ -0,0 +1,55 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8249 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-AMOLED-1.64" +#define USB_SERIAL "" + +// display QSPI SPI2 +#define QSPI_CS 9 +#define QSPI_SCK 10 +#define QSPI_D0 11 +#define QSPI_D1 12 +#define QSPI_D2 13 +#define QSPI_D3 14 +#define AMOLED_RESET 21 +#define AMOLED_TE -1 +#define AMOLED_PWR_EN -1 + +// Touch I2C +#define TP_SCL 48 +#define TP_SDA 47 +#define TP_RST -1 +#define TP_INT -1 + +//key +#define KEY_0 0 +//ADC +#define BAT_ADC 4 + +//SD_CARD +#define SD_CS 38 +#define SD_MOSI 39 +#define SD_MISO 40 +#define SD_SCLK 41 + +static const uint8_t SDA = 47; +static const uint8_t SCL = 48; + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +//esp32s3-PSFlash SPI1/SPI0 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_amoled_18/pins_arduino.h b/variants/waveshare_esp32_s3_touch_amoled_18/pins_arduino.h new file mode 100644 index 00000000000..de8bcaec2d9 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_amoled_18/pins_arduino.h @@ -0,0 +1,87 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8255 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-AMOLED-1.8" +#define USB_SERIAL "" + +// display for SH8601 +#define WS_LCD_CS 12 +#define WS_QSPI_SIO0 4 +#define WS_QSPI_SI1 5 +#define WS_QSPI_SI2 6 +#define WS_QSPI_SI3 7 +#define WS_QSPI_SCL 11 + +// Touch for FT3168 +#define WS_TP_INT 21 + +// Onboard Electric buzzer & Custom buttons +// GPIO and PSRAM conflict, need to pay attention when using + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 14; +static const uint8_t SCL = 15; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_amoled_191/pins_arduino.h b/variants/waveshare_esp32_s3_touch_amoled_191/pins_arduino.h new file mode 100644 index 00000000000..7e882a7ef46 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_amoled_191/pins_arduino.h @@ -0,0 +1,57 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x824B + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-AMOLED-1.91" +#define USB_SERIAL "" + +// display QSPI SPI2 +#define QSPI_CS 6 +#define QSPI_SCK 47 +#define QSPI_D0 18 +#define QSPI_D1 7 +#define QSPI_D2 48 +#define QSPI_D3 5 +#define AMOLED_RESET 17 +#define AMOLED_TE -1 +#define AMOLED_PWR_EN -1 +// Touch I2C +#define TP_SCL 39 +#define TP_SDA 40 +#define TP_RST -1 +#define TP_INT -1 + +// Partial voltage measurement method +#define BAT_ADC 1 +// Onboard QMI8658 IMU +#define QMI_INT1 45 +#define QMI_INT1 46 + +//SD +#define SD_CS 9 +#define SD_MISO 8 +#define SD_MOSI 42 +#define SD_CLK 47 + +//i2c + +static const uint8_t SDA = 40; +static const uint8_t SCL = 39; + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +//esp32s3-PSFlash SPI1/SPI0 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_amoled_241/pins_arduino.h b/variants/waveshare_esp32_s3_touch_amoled_241/pins_arduino.h new file mode 100644 index 00000000000..cb6c5f40ac1 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_amoled_241/pins_arduino.h @@ -0,0 +1,60 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8242 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-AMOLED-2.41" +#define USB_SERIAL "" + +// display QSPI SPI2 +#define QSPI_CS 9 +#define QSPI_SCK 10 +#define QSPI_D0 11 +#define QSPI_D1 12 +#define QSPI_D2 13 +#define QSPI_D3 14 +#define AMOLED_RESET 21 +#define AMOLED_TE -1 +#define AMOLED_PWR_EN -1 + +// Touch I2C +#define TP_SCL 48 +#define TP_SDA 47 +#define TP_RST -1 +#define TP_INT -1 + +// Onboard RTC for PCF85063 +#define RTC_SCL 48 +#define RTC_SDA 47 +#define RTC_ADDRESS 0x51 +#define RTC_INT -1 + +// Onboard QMI8658 IMU +#define QMI8658_SDA 47 +#define QMI8658_SCL 48 +#define QMI8658_ADDRESS 0x6b +#define QMI8658_INT1 -1 + +// Partial voltage measurement method +#define BAT_ADC 17 + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 47; +static const uint8_t SCL = 48; + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +//esp32s3-PSFlash SPI1/SPI0 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_146/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_146/pins_arduino.h new file mode 100644 index 00000000000..1c14bfe6714 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_146/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8287 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-1.85-Box" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 10; +static const uint8_t SDA = 11; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_169/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_169/pins_arduino.h new file mode 100644 index 00000000000..8d1562f4cd7 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_169/pins_arduino.h @@ -0,0 +1,108 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x821e + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-1.69" +#define USB_SERIAL "" + +// display for ST7789V2 +#define WS_LCD_DC 4 +#define WS_LCD_CS 5 +#define WS_LCD_SCL 6 +#define WS_LCD_SDA 7 +#define WS_LCD_RST 8 +#define WS_LCD_BL 15 + +// Touch for CST816T +#define WS_TP_SCL 10 +#define WS_TP_SDA 11 +#define WS_TP_RST 13 +#define WS_TP_INT 14 + +// Onboard RTC for PCF85063 +#define WS_RTC_SCL 10 +#define WS_RTC_SDA 11 +#define WS_RTC_ADDRESS 0x51 +#define WS_RTC_INT 41 + +// Onboard QMI8658 IMU +#define WS_QMI8658_SDA 11 +#define WS_QMI8658_SCL 10 +#define WS_QMI8658_ADDRESS 0x6B +#define WS_QMI8658_INT1 38 + +// Onboard Electric buzzer & Custom buttons +// GPIO and PSRAM conflict, need to pay attention when using +#define WS_BUZZ 33 // Please pull down the level when using +#define WS_SYS_OUT 36 +#define WS_SYS_EN 35 + +// Partial voltage measurement method +#define WS_BAT_ADC 1 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 10; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_185/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_185/pins_arduino.h new file mode 100644 index 00000000000..863590e321a --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_185/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8290 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-1.85" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 10; +static const uint8_t SDA = 11; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_185_box/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_185_box/pins_arduino.h new file mode 100644 index 00000000000..438da04025a --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_185_box/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x825B + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-2.1" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 7; +static const uint8_t SDA = 15; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_21/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_21/pins_arduino.h new file mode 100644 index 00000000000..a6c76a7ff34 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_21/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x825E + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-2.8" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 10; +static const uint8_t SDA = 11; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_28/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_28/pins_arduino.h new file mode 100644 index 00000000000..a6c76a7ff34 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_28/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x825E + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-2.8" +#define USB_SERIAL "" + +// I2C pins +static const uint8_t SCL = 10; +static const uint8_t SDA = 11; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_4/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_4/pins_arduino.h new file mode 100644 index 00000000000..f4a08ea7945 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_4/pins_arduino.h @@ -0,0 +1,73 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x823D + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-4" +#define USB_SERIAL "" + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = -1; +static const uint8_t SCL = -1; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_43/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_43/pins_arduino.h new file mode 100644 index 00000000000..9b60b50e0c1 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_43/pins_arduino.h @@ -0,0 +1,116 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x822E + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-4.3" +#define USB_SERIAL "" + +// display for ST7262 +#define WS_LCD_B3 14 +#define WS_LCD_B4 38 +#define WS_LCD_B5 18 +#define WS_LCD_B6 17 +#define WS_LCD_B7 10 + +#define WS_LCD_G2 39 +#define WS_LCD_G3 0 +#define WS_LCD_G4 45 +#define WS_LCD_G5 48 +#define WS_LCD_G6 47 +#define WS_LCD_G7 21 + +#define WS_LCD_R3 1 +#define WS_LCD_R4 2 +#define WS_LCD_R5 42 +#define WS_LCD_R6 41 +#define WS_LCD_R7 40 + +#define WS_LCD_VSYNC 3 +#define WS_LCD_HSYNC 46 +#define WS_LCD_PCLK 7 +#define WS_LCD_DE 5 + +// Touch for gt911 +#define WS_TP_SDA 8 +#define WS_TP_SCL 9 +#define WS_TP_RST -1 +#define WS_TP_INT 4 + +//RS485 +#define WS_RS485_RXD 16 +#define WS_RS485_TXD 15 + +//CAN +#define WS_CAN_RXD 19 +#define WS_CAN_TXD 20 + +//Onboard CH422G IO expander +#define WS_CH422G_SDA 8 +#define WS_CH422G_SCL 9 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 10; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_43b/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_43b/pins_arduino.h new file mode 100644 index 00000000000..f3bcb406d4c --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_43b/pins_arduino.h @@ -0,0 +1,116 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8231 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-4.3B" +#define USB_SERIAL "" + +// display for ST7262 +#define WS_LCD_B3 14 +#define WS_LCD_B4 38 +#define WS_LCD_B5 18 +#define WS_LCD_B6 17 +#define WS_LCD_B7 10 + +#define WS_LCD_G2 39 +#define WS_LCD_G3 0 +#define WS_LCD_G4 45 +#define WS_LCD_G5 48 +#define WS_LCD_G6 47 +#define WS_LCD_G7 21 + +#define WS_LCD_R3 1 +#define WS_LCD_R4 2 +#define WS_LCD_R5 42 +#define WS_LCD_R6 41 +#define WS_LCD_R7 40 + +#define WS_LCD_VSYNC 3 +#define WS_LCD_HSYNC 46 +#define WS_LCD_PCLK 7 +#define WS_LCD_DE 5 + +// Touch for gt911 +#define WS_TP_SDA 8 +#define WS_TP_SCL 9 +#define WS_TP_RST -1 +#define WS_TP_INT 4 + +//RS485 +#define WS_RS485_RXD 43 +#define WS_RS485_TXD 44 + +//CAN +#define WS_CAN_RXD 15 +#define WS_CAN_TXD 16 + +//Onboard CH422G IO expander +#define WS_CH422G_SDA 8 +#define WS_CH422G_SCL 9 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 10; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_5/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_5/pins_arduino.h new file mode 100644 index 00000000000..135dc0d0895 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_5/pins_arduino.h @@ -0,0 +1,116 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8237 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-5" +#define USB_SERIAL "" + +// display for ST7262 +#define WS_LCD_B3 14 +#define WS_LCD_B4 38 +#define WS_LCD_B5 18 +#define WS_LCD_B6 17 +#define WS_LCD_B7 10 + +#define WS_LCD_G2 39 +#define WS_LCD_G3 0 +#define WS_LCD_G4 45 +#define WS_LCD_G5 48 +#define WS_LCD_G6 47 +#define WS_LCD_G7 21 + +#define WS_LCD_R3 1 +#define WS_LCD_R4 2 +#define WS_LCD_R5 42 +#define WS_LCD_R6 41 +#define WS_LCD_R7 40 + +#define WS_LCD_VSYNC 3 +#define WS_LCD_HSYNC 46 +#define WS_LCD_PCLK 7 +#define WS_LCD_DE 5 + +// Touch for gt911 +#define WS_TP_SDA 8 +#define WS_TP_SCL 9 +#define WS_TP_RST -1 +#define WS_TP_INT 4 + +//RS485 +#define WS_RS485_RXD 43 +#define WS_RS485_TXD 44 + +//CAN +#define WS_CAN_RXD 15 +#define WS_CAN_TXD 16 + +//Onboard CH422G IO expander +#define WS_CH422G_SDA 8 +#define WS_CH422G_SCL 9 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 10; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_5b/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_5b/pins_arduino.h new file mode 100644 index 00000000000..e8829608a26 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_5b/pins_arduino.h @@ -0,0 +1,116 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x823A + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-5B" +#define USB_SERIAL "" + +// display for ST7262 +#define WS_LCD_B3 14 +#define WS_LCD_B4 38 +#define WS_LCD_B5 18 +#define WS_LCD_B6 17 +#define WS_LCD_B7 10 + +#define WS_LCD_G2 39 +#define WS_LCD_G3 0 +#define WS_LCD_G4 45 +#define WS_LCD_G5 48 +#define WS_LCD_G6 47 +#define WS_LCD_G7 21 + +#define WS_LCD_R3 1 +#define WS_LCD_R4 2 +#define WS_LCD_R5 42 +#define WS_LCD_R6 41 +#define WS_LCD_R7 40 + +#define WS_LCD_VSYNC 3 +#define WS_LCD_HSYNC 46 +#define WS_LCD_PCLK 7 +#define WS_LCD_DE 5 + +// Touch for gt911 +#define WS_TP_SDA 8 +#define WS_TP_SCL 9 +#define WS_TP_RST -1 +#define WS_TP_INT 4 + +//RS485 +#define WS_RS485_RXD 43 +#define WS_RS485_TXD 44 + +//CAN +#define WS_CAN_RXD 15 +#define WS_CAN_TXD 16 + +//Onboard CH422G IO expander +#define WS_CH422G_SDA 8 +#define WS_CH422G_SCL 9 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 10; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_touch_lcd_7/pins_arduino.h b/variants/waveshare_esp32_s3_touch_lcd_7/pins_arduino.h new file mode 100644 index 00000000000..357edf78c34 --- /dev/null +++ b/variants/waveshare_esp32_s3_touch_lcd_7/pins_arduino.h @@ -0,0 +1,116 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x8234 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-LCD-7" +#define USB_SERIAL "" + +// display for ST7262 +#define WS_LCD_B3 14 +#define WS_LCD_B4 38 +#define WS_LCD_B5 18 +#define WS_LCD_B6 17 +#define WS_LCD_B7 10 + +#define WS_LCD_G2 39 +#define WS_LCD_G3 0 +#define WS_LCD_G4 45 +#define WS_LCD_G5 48 +#define WS_LCD_G6 47 +#define WS_LCD_G7 21 + +#define WS_LCD_R3 1 +#define WS_LCD_R4 2 +#define WS_LCD_R5 42 +#define WS_LCD_R6 41 +#define WS_LCD_R7 40 + +#define WS_LCD_VSYNC 3 +#define WS_LCD_HSYNC 46 +#define WS_LCD_PCLK 7 +#define WS_LCD_DE 5 + +// Touch for gt911 +#define WS_TP_SDA 8 +#define WS_TP_SCL 9 +#define WS_TP_RST -1 +#define WS_TP_INT 4 + +//RS485 +#define WS_RS485_RXD 16 +#define WS_RS485_TXD 15 + +//CAN +#define WS_CAN_RXD 19 +#define WS_CAN_TXD 20 + +//Onboard CH422G IO expander +#define WS_CH422G_SDA 8 +#define WS_CH422G_SCL 9 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 10; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO17 = 17; +static const uint8_t OUTPUT_IO18 = 18; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/waveshare_esp32_s3_zero/pins_arduino.h b/variants/waveshare_esp32_s3_zero/pins_arduino.h new file mode 100644 index 00000000000..0d73bee16d0 --- /dev/null +++ b/variants/waveshare_esp32_s3_zero/pins_arduino.h @@ -0,0 +1,81 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x822B +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Zero" +#define USB_SERIAL "" // Empty string for MAC address + +// Partial voltage measurement method +#define WS_RGB 21 + +// Mapping based on the ESP32S3 data sheet - alternate for OUTPUT +static const uint8_t OUTPUT_IO1 = 1; +static const uint8_t OUTPUT_IO2 = 2; +static const uint8_t OUTPUT_IO3 = 3; +static const uint8_t OUTPUT_IO4 = 4; +static const uint8_t OUTPUT_IO5 = 5; +static const uint8_t OUTPUT_IO6 = 6; +static const uint8_t OUTPUT_IO7 = 7; +static const uint8_t OUTPUT_IO8 = 8; +static const uint8_t OUTPUT_IO9 = 9; +static const uint8_t OUTPUT_IO10 = 10; +static const uint8_t OUTPUT_IO11 = 11; +static const uint8_t OUTPUT_IO12 = 12; +static const uint8_t OUTPUT_IO13 = 13; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = -1; +static const uint8_t SCL = -1; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/wipy3/pins_arduino.h b/variants/wipy3/pins_arduino.h index 54e565d862f..a9fda1ecaa3 100644 --- a/variants/wipy3/pins_arduino.h +++ b/variants/wipy3/pins_arduino.h @@ -4,13 +4,13 @@ #include #include "soc/soc_caps.h" -// Neopixel -#define PIN_NEOPIXEL 0 // ->2812 RGB !!! +// RGB LED +#define PIN_RGB_LED 0 // ->2812 RGB !!! // BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino -static const uint8_t LED_BUILTIN = (PIN_NEOPIXEL + SOC_GPIO_PIN_COUNT); +static const uint8_t LED_BUILTIN = (PIN_RGB_LED + SOC_GPIO_PIN_COUNT); #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN -// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() #define RGB_BUILTIN LED_BUILTIN #define RGB_BRIGHTNESS 64 diff --git a/variants/ws_esp32_s3_matrix/partitions_all_app_4MB.csv b/variants/ws_esp32_s3_matrix/partitions_all_app_4MB.csv new file mode 100755 index 00000000000..25eeb8c7d47 --- /dev/null +++ b/variants/ws_esp32_s3_matrix/partitions_all_app_4MB.csv @@ -0,0 +1,3 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +factory, app, factory, 0x10000, 0x3F0000, diff --git a/variants/ws_esp32_s3_matrix/partitions_otanofs_4MB.csv b/variants/ws_esp32_s3_matrix/partitions_otanofs_4MB.csv new file mode 100755 index 00000000000..04240badb49 --- /dev/null +++ b/variants/ws_esp32_s3_matrix/partitions_otanofs_4MB.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags + nvs, data, nvs, 0x9000, 0x5000, + otadata, data, ota, 0xE000, 0x2000, + app0, app, ota_0, 0x10000, 0x1F0000, + app1, app, ota_1, 0x200000, 0x1F0000, +coredump, data, coredump, 0x3F0000, 0x10000, diff --git a/variants/ws_esp32_s3_matrix/pins_arduino.h b/variants/ws_esp32_s3_matrix/pins_arduino.h new file mode 100644 index 00000000000..ab067055c8e --- /dev/null +++ b/variants/ws_esp32_s3_matrix/pins_arduino.h @@ -0,0 +1,77 @@ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BN: ESP32 Family Device +#define USB_VID 0x303a +#define USB_PID 0x1001 + +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Matrix" +#define USB_SERIAL "" + +// Onboard 8 x 8 Matrix panel +#define WS_MATRIX_DIN 14 + +// Onboard QMI8658 IMU +#define WS_IMU_SDA 11 +#define WS_IMU_SCL 12 +#define WS_IMU_ADDRESS 0x6B +#define WS_IMU_INT1 10 +#define WS_IMU_INT2 13 + +// UART0 pins +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// Def for I2C that shares the IMU I2C pins +static const uint8_t SDA = 11; +static const uint8_t SCL = 12; + +// Mapping based on the ESP32S3 data sheet - alternate for SPI2 +static const uint8_t SS = 34; // FSPICS0 +static const uint8_t MOSI = 35; // FSPID +static const uint8_t MISO = 37; // FSPIQ +static const uint8_t SCK = 36; // FSPICLK + +// Analog capable pins on the header +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; + +// GPIO capable pins on the header +static const uint8_t D0 = 7; +static const uint8_t D1 = 6; +static const uint8_t D2 = 5; +static const uint8_t D3 = 4; +static const uint8_t D4 = 3; +static const uint8_t D5 = 2; +static const uint8_t D6 = 1; +static const uint8_t D7 = 44; +static const uint8_t D8 = 43; +static const uint8_t D9 = 40; +static const uint8_t D10 = 39; +static const uint8_t D11 = 38; +static const uint8_t D12 = 37; +static const uint8_t D13 = 36; +static const uint8_t D14 = 35; +static const uint8_t D15 = 34; +static const uint8_t D16 = 33; + +// Touch input capable pins on the header +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; + +#endif /* Pins_Arduino_h */ diff --git a/variants/yb_esp32s3_amp_v2/pins_arduino.h b/variants/yb_esp32s3_amp_v2/pins_arduino.h new file mode 100644 index 00000000000..34d454f5f5e --- /dev/null +++ b/variants/yb_esp32s3_amp_v2/pins_arduino.h @@ -0,0 +1,57 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +static const uint8_t LED_BUILTIN = 47; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +//I2S for onboard MAX98357A only +static const uint8_t I2S_BCLK = 5; +static const uint8_t I2S_LRCLK = 6; +static const uint8_t I2S_DOUT = 7; + +// SPI for onboard microSD only +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +// SPI2 for public usage +static const uint8_t SS2 = 38; +static const uint8_t MOSI2 = 39; +static const uint8_t MISO2 = 41; +static const uint8_t SCK2 = 40; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 8; +static const uint8_t A5 = 9; +static const uint8_t A6 = 10; +static const uint8_t A7 = 14; +static const uint8_t A8 = 15; +static const uint8_t A9 = 16; +static const uint8_t A10 = 17; +static const uint8_t A11 = 18; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T14 = 14; + +#define PIN_DAC_MUTE 47 // only if solder bridge "DAC_MUTE" is closed + +#endif /* Pins_Arduino_h */ diff --git a/variants/yb_esp32s3_amp_v3/pins_arduino.h b/variants/yb_esp32s3_amp_v3/pins_arduino.h new file mode 100644 index 00000000000..0b6ff0f29a1 --- /dev/null +++ b/variants/yb_esp32s3_amp_v3/pins_arduino.h @@ -0,0 +1,60 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303A +#define USB_PID 0x1001 + +static const uint8_t LED_BUILTIN = 47; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +//I2S for onboard MAX98357A only +static const uint8_t I2S_BCLK = 5; +static const uint8_t I2S_LRCLK = 6; +static const uint8_t I2S_DOUT = 7; + +// SPI for onboard microSD only +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +// SPI2 for public usage +static const uint8_t SS2 = 38; +static const uint8_t MOSI2 = 39; +static const uint8_t MISO2 = 41; +static const uint8_t SCK2 = 40; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 8; +static const uint8_t A5 = 9; +static const uint8_t A6 = 10; +static const uint8_t A7 = 14; +static const uint8_t A8 = 15; +static const uint8_t A9 = 16; +static const uint8_t A10 = 17; +static const uint8_t A11 = 18; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T14 = 14; + +#define PIN_DAC_MUTE 47 // only if solder bridge "DAC_MUTE" is closed + +#endif /* Pins_Arduino_h */ diff --git a/variants/yb_esp32s3_eth/pins_arduino.h b/variants/yb_esp32s3_eth/pins_arduino.h new file mode 100644 index 00000000000..77fcf6923fc --- /dev/null +++ b/variants/yb_esp32s3_eth/pins_arduino.h @@ -0,0 +1,63 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303A +#define USB_PID 0x1001 + +static const uint8_t LED_BUILTIN = 47; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +// Definitions for onboard WIZnet W5500 ethernet controller chip +static const uint8_t W5500_SS = 14; // W5500 chip select +static const uint8_t W5500_INT = 18; // available only if solder bridge "INT" is closed (default open) +static const uint8_t W5500_RST = 21; // set GPIO21 to INPUT (high impedance) if RST signal is unused + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */