mirror of
https://github.com/0xFEEDC0DE64/arduino-esp32.git
synced 2025-06-26 10:21:34 +02:00
Compare commits
125 Commits
old_versio
...
2.0.0-alph
Author | SHA1 | Date | |
---|---|---|---|
5d9b98c9b0 | |||
11f89cddf6 | |||
01c8cae0dc | |||
57cf2fb9f5 | |||
41c372c143 | |||
223acb3511 | |||
f6c9faf4da | |||
89e7893b1a | |||
7a4e7066f9 | |||
f3dca15a6f | |||
9f1330c70c | |||
ec7aeb4903 | |||
9a518cd3d7 | |||
81b7c47203 | |||
e6ba8c7ac9 | |||
72eb3f32fe | |||
66b11ff2a4 | |||
404a31f445 | |||
371f382db7 | |||
425619dfea | |||
aeb4a13aad | |||
8645971981 | |||
5502879a5b | |||
46d5afb17f | |||
66746750a4 | |||
e7a2759b65 | |||
2ee66b54f0 | |||
2d3c57635d | |||
a299ddc99e | |||
93bcf5f250 | |||
bd41334265 | |||
9a0762ad2a | |||
a451c9ef0d | |||
d362e1ee1a | |||
33d9f4aa19 | |||
63c51d51fb | |||
5b845272ed | |||
5da4a47bdf | |||
3253de8792 | |||
a31f30529d | |||
35643bdd9b | |||
8dc70e0add | |||
b42739dfa4 | |||
93d5b8c672 | |||
f815a7c636 | |||
23f6e81d52 | |||
e8311b00ae | |||
4d95e3a7ea | |||
7dc769d81c | |||
4204d1e60a | |||
d7fda910fb | |||
f7fc8ab377 | |||
dd834b3372 | |||
0e55f775d3 | |||
22a488cf23 | |||
6e7cc5210d | |||
7a6900a1f2 | |||
0e0a7565e8 | |||
bd3addeb8e | |||
1cf1c8eb79 | |||
3fe7c2e8cd | |||
5d00b6eb16 | |||
419ba32432 | |||
a0ddd8a16e | |||
b8dab5ed1a | |||
2141313148 | |||
44aaf13225 | |||
560c0f45f5 | |||
4b3f5c8ed4 | |||
c282cd8f5f | |||
7e59971d2f | |||
f4b17b3033 | |||
1ab550f6f2 | |||
9be784f69b | |||
7cdfb8bc7c | |||
8134a42162 | |||
f13ff65691 | |||
e831680a41 | |||
d964873840 | |||
7e8993fc83 | |||
15bae92a72 | |||
6f23cd5988 | |||
ad4cf1461b | |||
5de03a3918 | |||
4b385690bc | |||
dd513df124 | |||
cee659563d | |||
55442a05a4 | |||
c9b3e512dd | |||
8d0e68db4f | |||
d2530850a3 | |||
7ecbb483da | |||
b0e896e9ae | |||
08f4665775 | |||
2452c1fb53 | |||
5f98370707 | |||
81b9130d8d | |||
434d02c49f | |||
15db297130 | |||
fe093a5e35 | |||
a0ef17a9dd | |||
be77bd4e27 | |||
ef99cd7fe7 | |||
b05bdf6904 | |||
442c63a4c6 | |||
d1a4b3b822 | |||
7d5bf9e385 | |||
aac26a4d1e | |||
804c221499 | |||
3236358ded | |||
82e71f9b50 | |||
2e12392721 | |||
6b0114366b | |||
18832bb418 | |||
97dcea2b99 | |||
dcff2e9774 | |||
6d256b6454 | |||
f6bf0f7aa2 | |||
a59eb5d51e | |||
cee7b4237c | |||
954df2fc3e | |||
cecef8e930 | |||
a8e99baeab | |||
7494c4e76d | |||
c1951670d1 |
32
.github/scripts/install-arduino-ide.sh
vendored
32
.github/scripts/install-arduino-ide.sh
vendored
@ -98,8 +98,8 @@ function build_sketch(){ # build_sketch <fqbn> <path-to-ino> [extra-options]
|
|||||||
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"
|
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"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
#echo ""
|
||||||
echo "Compiling '"$(basename "$sketch")"' ..."
|
#echo "Compiling '"$(basename "$sketch")"' ..."
|
||||||
mkdir -p "$ARDUINO_BUILD_DIR"
|
mkdir -p "$ARDUINO_BUILD_DIR"
|
||||||
mkdir -p "$ARDUINO_CACHE_DIR"
|
mkdir -p "$ARDUINO_CACHE_DIR"
|
||||||
$ARDUINO_IDE_PATH/arduino-builder -compile -logger=human -core-api-version=10810 \
|
$ARDUINO_IDE_PATH/arduino-builder -compile -logger=human -core-api-version=10810 \
|
||||||
@ -131,14 +131,14 @@ function count_sketches() # count_sketches <examples-path> <target-mcu>
|
|||||||
local sketchdir=$(dirname $sketch)
|
local sketchdir=$(dirname $sketch)
|
||||||
local sketchdirname=$(basename $sketchdir)
|
local sketchdirname=$(basename $sketchdir)
|
||||||
local sketchname=$(basename $sketch)
|
local sketchname=$(basename $sketch)
|
||||||
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
|
if [[ "$sketchdirname.ino" != "$sketchname" ]]; then
|
||||||
continue
|
continue
|
||||||
fi;
|
elif [[ -f "$sketchdir/.skip.$target" ]]; then
|
||||||
if [[ -f "$sketchdir/.skip.$target" ]]; then
|
|
||||||
continue
|
continue
|
||||||
fi
|
else
|
||||||
echo $sketch >> sketches.txt
|
echo $sketch >> sketches.txt
|
||||||
sketchnum=$(($sketchnum + 1))
|
sketchnum=$(($sketchnum + 1))
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
return $sketchnum
|
return $sketchnum
|
||||||
}
|
}
|
||||||
@ -168,13 +168,13 @@ function build_sketches() # build_sketches <fqbn> <target-mcu> <examples-path> <
|
|||||||
echo "ERROR: Chunks count must be positive number"
|
echo "ERROR: Chunks count must be positive number"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
if [ "$chunk_idex" -ge "$chunks_num" ]; then
|
if [ "$chunk_idex" -ge "$chunks_num" ] && [ "$chunks_num" -ge 2 ]; then
|
||||||
echo "ERROR: Chunk index must be less than chunks count"
|
echo "ERROR: Chunk index must be less than chunks count"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
set +e
|
set +e
|
||||||
count_sketches "$examples"
|
count_sketches "$examples" "$target"
|
||||||
local sketchcount=$?
|
local sketchcount=$?
|
||||||
set -e
|
set -e
|
||||||
local sketches=$(cat sketches.txt)
|
local sketches=$(cat sketches.txt)
|
||||||
@ -186,19 +186,27 @@ function build_sketches() # build_sketches <fqbn> <target-mcu> <examples-path> <
|
|||||||
chunk_size=$(( $chunk_size + 1 ))
|
chunk_size=$(( $chunk_size + 1 ))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local start_index=$(( $chunk_idex * $chunk_size ))
|
local start_index=0
|
||||||
|
local end_index=0
|
||||||
|
if [ "$chunk_idex" -ge "$chunks_num" ]; then
|
||||||
|
start_index=$chunk_idex
|
||||||
|
end_index=$sketchcount
|
||||||
|
else
|
||||||
|
start_index=$(( $chunk_idex * $chunk_size ))
|
||||||
if [ "$sketchcount" -le "$start_index" ]; then
|
if [ "$sketchcount" -le "$start_index" ]; then
|
||||||
echo "Skipping job"
|
echo "Skipping job"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
|
end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
|
||||||
if [ "$end_index" -gt "$sketchcount" ]; then
|
if [ "$end_index" -gt "$sketchcount" ]; then
|
||||||
end_index=$sketchcount
|
end_index=$sketchcount
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
local start_num=$(( $start_index + 1 ))
|
local start_num=$(( $start_index + 1 ))
|
||||||
echo "Found $sketchcount Sketches";
|
echo "Found $sketchcount Sketches for target '$target'";
|
||||||
|
echo "Chunk Index : $chunk_idex"
|
||||||
echo "Chunk Count : $chunks_num"
|
echo "Chunk Count : $chunks_num"
|
||||||
echo "Chunk Size : $chunk_size"
|
echo "Chunk Size : $chunk_size"
|
||||||
echo "Start Sketch: $start_num"
|
echo "Start Sketch: $start_num"
|
||||||
@ -218,6 +226,8 @@ function build_sketches() # build_sketches <fqbn> <target-mcu> <examples-path> <
|
|||||||
|| [ "$sketchnum" -gt "$end_index" ]; then
|
|| [ "$sketchnum" -gt "$end_index" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
echo ""
|
||||||
|
echo "Building Sketch Index $(($sketchnum - 1)) - $sketchdirname"
|
||||||
build_sketch "$fqbn" "$sketch" "$xtra_opts"
|
build_sketch "$fqbn" "$sketch" "$xtra_opts"
|
||||||
local result=$?
|
local result=$?
|
||||||
if [ $result -ne 0 ]; then
|
if [ $result -ne 0 ]; then
|
||||||
|
6
.github/scripts/on-pages.sh
vendored
6
.github/scripts/on-pages.sh
vendored
@ -87,9 +87,15 @@ function git_safe_upload_to_pages(){
|
|||||||
|
|
||||||
EVENT_JSON=`cat $GITHUB_EVENT_PATH`
|
EVENT_JSON=`cat $GITHUB_EVENT_PATH`
|
||||||
|
|
||||||
|
echo "GITHUB_EVENT_PATH: $GITHUB_EVENT_PATH"
|
||||||
|
echo "EVENT_JSON: $EVENT_JSON"
|
||||||
|
|
||||||
pages_added=`echo "$EVENT_JSON" | jq -r '.commits[].added[]'`
|
pages_added=`echo "$EVENT_JSON" | jq -r '.commits[].added[]'`
|
||||||
|
echo "added: $pages_added"
|
||||||
pages_modified=`echo "$EVENT_JSON" | jq -r '.commits[].modified[]'`
|
pages_modified=`echo "$EVENT_JSON" | jq -r '.commits[].modified[]'`
|
||||||
|
echo "modified: $pages_modified"
|
||||||
pages_removed=`echo "$EVENT_JSON" | jq -r '.commits[].removed[]'`
|
pages_removed=`echo "$EVENT_JSON" | jq -r '.commits[].removed[]'`
|
||||||
|
echo "removed: $pages_removed"
|
||||||
|
|
||||||
for page in $pages_added; do
|
for page in $pages_added; do
|
||||||
if [[ $page != "README.md" && $page != "docs/"* ]]; then
|
if [[ $page != "README.md" && $page != "docs/"* ]]; then
|
||||||
|
15
.github/scripts/on-push.sh
vendored
15
.github/scripts/on-push.sh
vendored
@ -24,7 +24,7 @@ BUILD_PIO=0
|
|||||||
if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then
|
if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then
|
||||||
CHUNK_INDEX=0
|
CHUNK_INDEX=0
|
||||||
CHUNKS_CNT=1
|
CHUNKS_CNT=1
|
||||||
elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ]; then
|
elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ] && [ "$CHUNKS_CNT" -ge 2 ]; then
|
||||||
CHUNK_INDEX=$CHUNKS_CNT
|
CHUNK_INDEX=$CHUNKS_CNT
|
||||||
elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then
|
elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then
|
||||||
BUILD_PIO=1
|
BUILD_PIO=1
|
||||||
@ -69,6 +69,19 @@ if [ "$BUILD_PIO" -eq 0 ]; then
|
|||||||
else
|
else
|
||||||
build_sketches "$FQBN" "$TARGET" "$ARDUINO_ESP32_PATH/libraries" "$CHUNK_INDEX" "$CHUNKS_CNT"
|
build_sketches "$FQBN" "$TARGET" "$ARDUINO_ESP32_PATH/libraries" "$CHUNK_INDEX" "$CHUNKS_CNT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ArduinoIDE ESP32C3 Test
|
||||||
|
TARGET="esp32c3"
|
||||||
|
FQBN="espressif:esp32:esp32c3:PartitionScheme=huge_app"
|
||||||
|
if [ "$OS_IS_WINDOWS" == "1" ]; then
|
||||||
|
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
|
||||||
|
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino"
|
||||||
|
elif [ "$OS_IS_MACOS" == "1" ]; then
|
||||||
|
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
|
||||||
|
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino"
|
||||||
|
else
|
||||||
|
build_sketches "$FQBN" "$TARGET" "$ARDUINO_ESP32_PATH/libraries" "$CHUNK_INDEX" "$CHUNKS_CNT"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
source ./.github/scripts/install-platformio-esp32.sh
|
source ./.github/scripts/install-platformio-esp32.sh
|
||||||
# PlatformIO ESP32 Test
|
# PlatformIO ESP32 Test
|
||||||
|
64
.github/scripts/on-release.sh
vendored
64
.github/scripts/on-release.sh
vendored
@ -183,6 +183,7 @@ cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.py" "$PKG_DIR/tools/"
|
|||||||
cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.exe" "$PKG_DIR/tools/"
|
cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.exe" "$PKG_DIR/tools/"
|
||||||
cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/"
|
cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/"
|
||||||
cp -Rf "$GITHUB_WORKSPACE/tools/sdk" "$PKG_DIR/tools/"
|
cp -Rf "$GITHUB_WORKSPACE/tools/sdk" "$PKG_DIR/tools/"
|
||||||
|
cp -f $GITHUB_WORKSPACE/tools/platformio-build*.py "$PKG_DIR/tools/"
|
||||||
|
|
||||||
# Remove unnecessary files in the package folder
|
# Remove unnecessary files in the package folder
|
||||||
echo "Cleaning up folders ..."
|
echo "Cleaning up folders ..."
|
||||||
@ -194,6 +195,7 @@ echo "Generating platform.txt..."
|
|||||||
cat "$GITHUB_WORKSPACE/platform.txt" | \
|
cat "$GITHUB_WORKSPACE/platform.txt" | \
|
||||||
sed "s/version=.*/version=$ver$extent/g" | \
|
sed "s/version=.*/version=$ver$extent/g" | \
|
||||||
sed 's/runtime.tools.xtensa-esp32-elf-gcc.path={runtime.platform.path}\/tools\/xtensa-esp32-elf//g' | \
|
sed 's/runtime.tools.xtensa-esp32-elf-gcc.path={runtime.platform.path}\/tools\/xtensa-esp32-elf//g' | \
|
||||||
|
sed 's/runtime.tools.xtensa-esp32s2-elf-gcc.path={runtime.platform.path}\/tools\/xtensa-esp32s2-elf//g' | \
|
||||||
sed 's/tools.esptool_py.path={runtime.platform.path}\/tools\/esptool/tools.esptool_py.path=\{runtime.tools.esptool_py.path\}/g' \
|
sed 's/tools.esptool_py.path={runtime.platform.path}\/tools\/esptool/tools.esptool_py.path=\{runtime.tools.esptool_py.path\}/g' \
|
||||||
> "$PKG_DIR/platform.txt"
|
> "$PKG_DIR/platform.txt"
|
||||||
|
|
||||||
@ -254,17 +256,30 @@ releasesJson=`curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.
|
|||||||
if [ $? -ne 0 ]; then echo "ERROR: Get Releases Failed! ($?)"; exit 1; fi
|
if [ $? -ne 0 ]; then echo "ERROR: Get Releases Failed! ($?)"; exit 1; fi
|
||||||
|
|
||||||
set +e
|
set +e
|
||||||
prev_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name')
|
prev_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false)) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
|
||||||
prev_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name')
|
prev_any_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false)) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
|
||||||
|
prev_branch_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false and .target_commitish == \"$RELEASE_BRANCH\")) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
|
||||||
|
prev_branch_any_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .target_commitish == \"$RELEASE_BRANCH\")) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
|
||||||
shopt -s nocasematch
|
shopt -s nocasematch
|
||||||
if [ "$prev_any_release" == "$RELEASE_TAG" ]; then
|
if [ "$prev_release" == "$RELEASE_TAG" ]; then
|
||||||
prev_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name')
|
prev_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false)) | sort_by(.published_at | - fromdateiso8601) | .[1].tag_name")
|
||||||
prev_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name')
|
fi
|
||||||
|
if [ "$prev_any_release" == "$RELEASE_TAG" ]; then
|
||||||
|
prev_any_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false)) | sort_by(.published_at | - fromdateiso8601) | .[1].tag_name")
|
||||||
|
fi
|
||||||
|
if [ "$prev_branch_release" == "$RELEASE_TAG" ]; then
|
||||||
|
prev_branch_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false and .target_commitish == \"$RELEASE_BRANCH\")) | sort_by(.published_at | - fromdateiso8601) | .[1].tag_name")
|
||||||
|
fi
|
||||||
|
if [ "$prev_branch_any_release" == "$RELEASE_TAG" ]; then
|
||||||
|
prev_branch_any_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .target_commitish == \"$RELEASE_BRANCH\")) | sort_by(.published_at | - fromdateiso8601) | .[1].tag_name")
|
||||||
fi
|
fi
|
||||||
COMMITS_SINCE_RELEASE="$prev_any_release"
|
|
||||||
shopt -u nocasematch
|
shopt -u nocasematch
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
echo "Previous Release: $prev_release"
|
||||||
|
echo "Previous (any)release: $prev_any_release"
|
||||||
|
echo
|
||||||
|
|
||||||
# Merge package JSONs with previous releases
|
# Merge package JSONs with previous releases
|
||||||
if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
|
if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
|
||||||
echo "Merging with JSON from $prev_any_release ..."
|
echo "Merging with JSON from $prev_any_release ..."
|
||||||
@ -272,17 +287,12 @@ if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$RELEASE_PRE" == "false" ]; then
|
if [ "$RELEASE_PRE" == "false" ]; then
|
||||||
COMMITS_SINCE_RELEASE="$prev_release"
|
|
||||||
if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then
|
if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then
|
||||||
echo "Merging with JSON from $prev_release ..."
|
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" "$OUTPUT_DIR/$PACKAGE_JSON_REL"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Previous Release: $prev_release"
|
|
||||||
echo "Previous (any)release: $prev_any_release"
|
|
||||||
echo
|
|
||||||
|
|
||||||
# Upload package JSONs
|
# Upload package JSONs
|
||||||
echo "Uploading $PACKAGE_JSON_DEV ..."
|
echo "Uploading $PACKAGE_JSON_DEV ..."
|
||||||
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
|
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
|
||||||
@ -327,21 +337,35 @@ if [ $arrLen > 3 ] && [ "${msgArray[0]:0:3}" == "tag" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Append Commit Messages
|
# Append Commit Messages
|
||||||
|
echo
|
||||||
|
echo "Previous Branch Release: $prev_branch_release"
|
||||||
|
echo "Previous Branch (any)release: $prev_branch_any_release"
|
||||||
|
echo
|
||||||
|
commitFile="$OUTPUT_DIR/commits.txt"
|
||||||
|
COMMITS_SINCE_RELEASE="$prev_branch_any_release"
|
||||||
|
if [ "$RELEASE_PRE" == "false" ]; then
|
||||||
|
COMMITS_SINCE_RELEASE="$prev_branch_release"
|
||||||
|
fi
|
||||||
if [ ! -z "$COMMITS_SINCE_RELEASE" ] && [ "$COMMITS_SINCE_RELEASE" != "null" ]; then
|
if [ ! -z "$COMMITS_SINCE_RELEASE" ] && [ "$COMMITS_SINCE_RELEASE" != "null" ]; then
|
||||||
echo "Getting commits since $COMMITS_SINCE_RELEASE ..."
|
echo "Getting commits since $COMMITS_SINCE_RELEASE ..."
|
||||||
commitFile=$OUTPUT_DIR/commits.txt
|
git -C "$GITHUB_WORKSPACE" log --oneline -n 500 "$COMMITS_SINCE_RELEASE..HEAD" > "$commitFile"
|
||||||
git -C "$GITHUB_WORKSPACE" log --oneline "$COMMITS_SINCE_RELEASE..HEAD" > "$OUTPUT_DIR/commits.txt"
|
elif [ "$RELEASE_BRANCH" != "master" ]; then
|
||||||
releaseNotes+=$'\r\n##### Commits\r\n'
|
echo "Getting all commits on branch '$RELEASE_BRANCH' ..."
|
||||||
IFS=$'\n'
|
git -C "$GITHUB_WORKSPACE" log --oneline -n 500 --cherry-pick --left-only --no-merges HEAD...origin/master > "$commitFile"
|
||||||
for next in `cat $commitFile`
|
else
|
||||||
do
|
echo "Getting all commits on master ..."
|
||||||
|
git -C "$GITHUB_WORKSPACE" log --oneline -n 500 --no-merges > "$commitFile"
|
||||||
|
fi
|
||||||
|
releaseNotes+=$'\r\n##### Commits\r\n'
|
||||||
|
IFS=$'\n'
|
||||||
|
for next in `cat $commitFile`
|
||||||
|
do
|
||||||
IFS=' ' read -r commitId commitMsg <<< "$next"
|
IFS=' ' read -r commitId commitMsg <<< "$next"
|
||||||
commitLine="- [$commitId](https://github.com/$GITHUB_REPOSITORY/commit/$commitId) $commitMsg"
|
commitLine="- [$commitId](https://github.com/$GITHUB_REPOSITORY/commit/$commitId) $commitMsg"
|
||||||
releaseNotes+="$commitLine"
|
releaseNotes+="$commitLine"
|
||||||
releaseNotes+=$'\r\n'
|
releaseNotes+=$'\r\n'
|
||||||
done
|
done
|
||||||
rm -f $commitFile
|
rm -f $commitFile
|
||||||
fi
|
|
||||||
|
|
||||||
# Prepend the original release body
|
# Prepend the original release body
|
||||||
if [ "${RELEASE_BODY: -1}" == $'\r' ]; then
|
if [ "${RELEASE_BODY: -1}" == $'\r' ]; then
|
||||||
|
11
.github/stale.yml
vendored
11
.github/stale.yml
vendored
@ -12,12 +12,9 @@ onlyLabels: []
|
|||||||
|
|
||||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||||
exemptLabels:
|
exemptLabels:
|
||||||
- pinned
|
- "Type: For reference"
|
||||||
- security
|
- "Type: To be implemented"
|
||||||
- "to be implemented"
|
- "Type: Feature request"
|
||||||
- "for reference"
|
|
||||||
- "move to PR"
|
|
||||||
- "enhancement"
|
|
||||||
|
|
||||||
# Set to true to ignore issues in a project (defaults to false)
|
# Set to true to ignore issues in a project (defaults to false)
|
||||||
exemptProjects: false
|
exemptProjects: false
|
||||||
@ -29,7 +26,7 @@ exemptMilestones: false
|
|||||||
exemptAssignees: false
|
exemptAssignees: false
|
||||||
|
|
||||||
# Label to use when marking as stale
|
# Label to use when marking as stale
|
||||||
staleLabel: stale
|
staleLabel: Status: Stale
|
||||||
|
|
||||||
# Comment to post when marking as stale. Set to `false` to disable
|
# Comment to post when marking as stale. Set to `false` to disable
|
||||||
markComment: >
|
markComment: >
|
||||||
|
3
.github/workflows/gh-pages.yml
vendored
3
.github/workflows/gh-pages.yml
vendored
@ -4,9 +4,12 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
- pages
|
||||||
paths:
|
paths:
|
||||||
- 'README.md'
|
- 'README.md'
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
|
- '.github/scripts/on-pages.sh'
|
||||||
|
- '.github/workflows/gh-pages.yml'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -11,6 +11,8 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@master
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
- uses: actions/setup-python@v1
|
- uses: actions/setup-python@v1
|
||||||
with:
|
with:
|
||||||
python-version: '3.x'
|
python-version: '3.x'
|
||||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,10 +1,11 @@
|
|||||||
tools/xtensa-esp32-elf
|
tools/xtensa-esp32-elf
|
||||||
tools/xtensa-esp32s2-elf
|
tools/xtensa-esp32s2-elf
|
||||||
|
tools/riscv32-esp-elf
|
||||||
tools/dist
|
tools/dist
|
||||||
tools/esptool
|
tools/esptool
|
||||||
tools/esptool.exe
|
tools/esptool.exe
|
||||||
tools/mkspiffs/mkspiffs
|
tools/mkspiffs
|
||||||
tools/mkspiffs/mkspiffs.exe
|
tools/mklittlefs
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
#Ignore files built by Visual Studio/Visual Micro
|
#Ignore files built by Visual Studio/Visual Micro
|
||||||
|
138
CMakeLists.txt
138
CMakeLists.txt
@ -1,43 +1,175 @@
|
|||||||
set(CORE_SRCS
|
set(CORE_SRCS
|
||||||
|
cores/esp32/base64.cpp
|
||||||
|
cores/esp32/cbuf.cpp
|
||||||
cores/esp32/esp32-hal-adc.c
|
cores/esp32/esp32-hal-adc.c
|
||||||
|
cores/esp32/esp32-hal-bt.c
|
||||||
cores/esp32/esp32-hal-cpu.c
|
cores/esp32/esp32-hal-cpu.c
|
||||||
cores/esp32/esp32-hal-dac.c
|
cores/esp32/esp32-hal-dac.c
|
||||||
cores/esp32/esp32-hal-gpio.c
|
cores/esp32/esp32-hal-gpio.c
|
||||||
cores/esp32/esp32-hal-i2c.c
|
cores/esp32/esp32-hal-i2c.c
|
||||||
|
cores/esp32/esp32-hal-log.c
|
||||||
cores/esp32/esp32-hal-ledc.c
|
cores/esp32/esp32-hal-ledc.c
|
||||||
cores/esp32/esp32-hal-matrix.c
|
cores/esp32/esp32-hal-matrix.c
|
||||||
cores/esp32/esp32-hal-misc.c
|
cores/esp32/esp32-hal-misc.c
|
||||||
cores/esp32/esp32-hal-psram.c
|
cores/esp32/esp32-hal-psram.c
|
||||||
cores/esp32/esp32-hal-sigmadelta.c
|
cores/esp32/esp32-hal-sigmadelta.c
|
||||||
cores/esp32/esp32-hal-spi.c
|
cores/esp32/esp32-hal-spi.c
|
||||||
|
cores/esp32/esp32-hal-time.c
|
||||||
|
cores/esp32/esp32-hal-timer.c
|
||||||
cores/esp32/esp32-hal-tinyusb.c
|
cores/esp32/esp32-hal-tinyusb.c
|
||||||
cores/esp32/esp32-hal-touch.c
|
cores/esp32/esp32-hal-touch.c
|
||||||
|
cores/esp32/esp32-hal-uart.c
|
||||||
cores/esp32/esp32-hal-rmt.c
|
cores/esp32/esp32-hal-rmt.c
|
||||||
|
cores/esp32/Esp.cpp
|
||||||
cores/esp32/FunctionalInterrupt.cpp
|
cores/esp32/FunctionalInterrupt.cpp
|
||||||
|
cores/esp32/HardwareSerial.cpp
|
||||||
|
cores/esp32/IPAddress.cpp
|
||||||
|
cores/esp32/IPv6Address.cpp
|
||||||
|
cores/esp32/libb64/cdecode.c
|
||||||
|
cores/esp32/libb64/cencode.c
|
||||||
|
cores/esp32/main.cpp
|
||||||
|
cores/esp32/MD5Builder.cpp
|
||||||
|
cores/esp32/Print.cpp
|
||||||
cores/esp32/stdlib_noniso.c
|
cores/esp32/stdlib_noniso.c
|
||||||
|
cores/esp32/Stream.cpp
|
||||||
|
cores/esp32/StreamString.cpp
|
||||||
cores/esp32/USB.cpp
|
cores/esp32/USB.cpp
|
||||||
cores/esp32/USBCDC.cpp
|
cores/esp32/USBCDC.cpp
|
||||||
cores/esp32/wiring_pulse.c
|
cores/esp32/wiring_pulse.c
|
||||||
cores/esp32/wiring_shift.c
|
cores/esp32/wiring_shift.c
|
||||||
cores/esp32/WMath.cpp
|
cores/esp32/WMath.cpp
|
||||||
|
cores/esp32/WString.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBRARY_SRCS
|
set(LIBRARY_SRCS
|
||||||
|
libraries/ArduinoOTA/src/ArduinoOTA.cpp
|
||||||
|
libraries/AsyncUDP/src/AsyncUDP.cpp
|
||||||
|
libraries/BluetoothSerial/src/BluetoothSerial.cpp
|
||||||
|
libraries/BluetoothSerial/src/BTAddress.cpp
|
||||||
|
libraries/BluetoothSerial/src/BTAdvertisedDeviceSet.cpp
|
||||||
|
libraries/BluetoothSerial/src/BTScanResultsSet.cpp
|
||||||
|
libraries/DNSServer/src/DNSServer.cpp
|
||||||
|
libraries/EEPROM/src/EEPROM.cpp
|
||||||
|
libraries/ESPmDNS/src/ESPmDNS.cpp
|
||||||
|
libraries/FFat/src/FFat.cpp
|
||||||
|
libraries/FS/src/FS.cpp
|
||||||
|
libraries/FS/src/vfs_api.cpp
|
||||||
|
libraries/HTTPClient/src/HTTPClient.cpp
|
||||||
|
libraries/HTTPUpdate/src/HTTPUpdate.cpp
|
||||||
|
libraries/LITTLEFS/src/LITTLEFS.cpp
|
||||||
|
libraries/NetBIOS/src/NetBIOS.cpp
|
||||||
|
libraries/Preferences/src/Preferences.cpp
|
||||||
|
libraries/RainMaker/src/RMaker.cpp
|
||||||
|
libraries/RainMaker/src/RMakerNode.cpp
|
||||||
|
libraries/RainMaker/src/RMakerParam.cpp
|
||||||
|
libraries/RainMaker/src/RMakerDevice.cpp
|
||||||
|
libraries/RainMaker/src/RMakerType.cpp
|
||||||
|
libraries/SD_MMC/src/SD_MMC.cpp
|
||||||
|
libraries/SD/src/SD.cpp
|
||||||
|
libraries/SD/src/sd_diskio.cpp
|
||||||
|
libraries/SD/src/sd_diskio_crc.c
|
||||||
|
libraries/SimpleBLE/src/SimpleBLE.cpp
|
||||||
|
libraries/SPIFFS/src/SPIFFS.cpp
|
||||||
libraries/SPI/src/SPI.cpp
|
libraries/SPI/src/SPI.cpp
|
||||||
|
libraries/Ticker/src/Ticker.cpp
|
||||||
|
libraries/Update/src/Updater.cpp
|
||||||
|
libraries/Update/src/HttpsOTAUpdate.cpp
|
||||||
|
libraries/WebServer/src/WebServer.cpp
|
||||||
|
libraries/WebServer/src/Parsing.cpp
|
||||||
|
libraries/WebServer/src/detail/mimetable.cpp
|
||||||
|
libraries/WiFiClientSecure/src/ssl_client.cpp
|
||||||
|
libraries/WiFiClientSecure/src/WiFiClientSecure.cpp
|
||||||
|
libraries/WiFi/src/ETH.cpp
|
||||||
|
libraries/WiFi/src/WiFiAP.cpp
|
||||||
|
libraries/WiFi/src/WiFiClient.cpp
|
||||||
|
libraries/WiFi/src/WiFi.cpp
|
||||||
|
libraries/WiFi/src/WiFiGeneric.cpp
|
||||||
|
libraries/WiFi/src/WiFiMulti.cpp
|
||||||
|
libraries/WiFi/src/WiFiScan.cpp
|
||||||
|
libraries/WiFi/src/WiFiServer.cpp
|
||||||
|
libraries/WiFi/src/WiFiSTA.cpp
|
||||||
|
libraries/WiFi/src/WiFiUdp.cpp
|
||||||
|
libraries/WiFiProv/src/WiFiProv.cpp
|
||||||
libraries/Wire/src/Wire.cpp
|
libraries/Wire/src/Wire.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(BLE_SRCS
|
||||||
|
libraries/BLE/src/BLE2902.cpp
|
||||||
|
libraries/BLE/src/BLE2904.cpp
|
||||||
|
libraries/BLE/src/BLEAddress.cpp
|
||||||
|
libraries/BLE/src/BLEAdvertisedDevice.cpp
|
||||||
|
libraries/BLE/src/BLEAdvertising.cpp
|
||||||
|
libraries/BLE/src/BLEBeacon.cpp
|
||||||
|
libraries/BLE/src/BLECharacteristic.cpp
|
||||||
|
libraries/BLE/src/BLECharacteristicMap.cpp
|
||||||
|
libraries/BLE/src/BLEClient.cpp
|
||||||
|
libraries/BLE/src/BLEDescriptor.cpp
|
||||||
|
libraries/BLE/src/BLEDescriptorMap.cpp
|
||||||
|
libraries/BLE/src/BLEDevice.cpp
|
||||||
|
libraries/BLE/src/BLEEddystoneTLM.cpp
|
||||||
|
libraries/BLE/src/BLEEddystoneURL.cpp
|
||||||
|
libraries/BLE/src/BLEExceptions.cpp
|
||||||
|
libraries/BLE/src/BLEHIDDevice.cpp
|
||||||
|
libraries/BLE/src/BLERemoteCharacteristic.cpp
|
||||||
|
libraries/BLE/src/BLERemoteDescriptor.cpp
|
||||||
|
libraries/BLE/src/BLERemoteService.cpp
|
||||||
|
libraries/BLE/src/BLEScan.cpp
|
||||||
|
libraries/BLE/src/BLESecurity.cpp
|
||||||
|
libraries/BLE/src/BLEServer.cpp
|
||||||
|
libraries/BLE/src/BLEService.cpp
|
||||||
|
libraries/BLE/src/BLEServiceMap.cpp
|
||||||
|
libraries/BLE/src/BLEUtils.cpp
|
||||||
|
libraries/BLE/src/BLEUUID.cpp
|
||||||
|
libraries/BLE/src/BLEValue.cpp
|
||||||
|
libraries/BLE/src/FreeRTOS.cpp
|
||||||
|
libraries/BLE/src/GeneralUtils.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
set(includedirs
|
set(includedirs
|
||||||
variants/esp32/
|
variants/${IDF_TARGET}/
|
||||||
cores/esp32/
|
cores/esp32/
|
||||||
|
libraries/ArduinoOTA/src
|
||||||
|
libraries/AsyncUDP/src
|
||||||
|
libraries/BLE/src
|
||||||
|
libraries/BluetoothSerial/src
|
||||||
|
libraries/DNSServer/src
|
||||||
|
libraries/EEPROM/src
|
||||||
|
libraries/ESP32/src
|
||||||
|
libraries/ESPmDNS/src
|
||||||
|
libraries/FFat/src
|
||||||
|
libraries/FS/src
|
||||||
|
libraries/HTTPClient/src
|
||||||
|
libraries/HTTPUpdate/src
|
||||||
|
libraries/LITTLEFS/src
|
||||||
|
libraries/NetBIOS/src
|
||||||
|
libraries/Preferences/src
|
||||||
|
libraries/RainMaker/src
|
||||||
|
libraries/SD_MMC/src
|
||||||
|
libraries/SD/src
|
||||||
|
libraries/SimpleBLE/src
|
||||||
|
libraries/SPIFFS/src
|
||||||
libraries/SPI/src
|
libraries/SPI/src
|
||||||
|
libraries/Ticker/src
|
||||||
|
libraries/Update/src
|
||||||
|
libraries/WebServer/src
|
||||||
|
libraries/WiFiClientSecure/src
|
||||||
|
libraries/WiFi/src
|
||||||
|
libraries/WiFiProv/src
|
||||||
libraries/Wire/src
|
libraries/Wire/src
|
||||||
)
|
)
|
||||||
|
|
||||||
set(srcs ${CORE_SRCS} ${LIBRARY_SRCS} ${BLE_SRCS})
|
set(srcs ${CORE_SRCS} ${LIBRARY_SRCS} ${BLE_SRCS})
|
||||||
set(requires spi_flash mbedtls esp_adc_cal wifi_provisioning)
|
set(priv_includes cores/esp32/libb64)
|
||||||
set(priv_requires nvs_flash bootloader_support tinyusb espcpputils fmt)
|
set(requires spi_flash mbedtls mdns esp_adc_cal)
|
||||||
|
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support openssl bt arduino_tinyusb main)
|
||||||
|
|
||||||
|
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ArduinoOTA)
|
||||||
|
list(APPEND priv_requires esp_https_ota)
|
||||||
|
endif()
|
||||||
|
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_LITTLEFS)
|
||||||
|
list(APPEND priv_requires esp_littlefs)
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})
|
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})
|
||||||
|
|
||||||
|
@ -9,6 +9,91 @@ config ENABLE_ARDUINO_DEPENDS
|
|||||||
select MEMMAP_SMP
|
select MEMMAP_SMP
|
||||||
default "y"
|
default "y"
|
||||||
|
|
||||||
|
config AUTOSTART_ARDUINO
|
||||||
|
bool "Autostart Arduino setup and loop on boot"
|
||||||
|
default "n"
|
||||||
|
help
|
||||||
|
Enabling this option will implement app_main and start Arduino.
|
||||||
|
All you need to implement in your main.cpp is setup() and loop()
|
||||||
|
and include Arduino.h
|
||||||
|
If disabled, you can call initArduino() to run any preparations
|
||||||
|
required by the framework
|
||||||
|
|
||||||
|
choice ARDUINO_RUNNING_CORE
|
||||||
|
bool "Core on which Arduino's setup() and loop() are running"
|
||||||
|
default ARDUINO_RUN_CORE1
|
||||||
|
help
|
||||||
|
Select on which core Arduino's setup() and loop() functions run
|
||||||
|
|
||||||
|
config ARDUINO_RUN_CORE0
|
||||||
|
bool "CORE 0"
|
||||||
|
config ARDUINO_RUN_CORE1
|
||||||
|
bool "CORE 1"
|
||||||
|
config ARDUINO_RUN_NO_AFFINITY
|
||||||
|
bool "BOTH"
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config ARDUINO_RUNNING_CORE
|
||||||
|
int
|
||||||
|
default 0 if ARDUINO_RUN_CORE0
|
||||||
|
default 1 if ARDUINO_RUN_CORE1
|
||||||
|
default -1 if ARDUINO_RUN_NO_AFFINITY
|
||||||
|
|
||||||
|
config ARDUINO_LOOP_STACK_SIZE
|
||||||
|
int "Loop thread stack size"
|
||||||
|
default 8192
|
||||||
|
help
|
||||||
|
Amount of stack available for the Arduino task.
|
||||||
|
|
||||||
|
choice ARDUINO_EVENT_RUNNING_CORE
|
||||||
|
bool "Core on which Arduino's event handler is running"
|
||||||
|
default ARDUINO_EVENT_RUN_CORE1
|
||||||
|
help
|
||||||
|
Select on which core Arduino's WiFi.onEvent() run
|
||||||
|
|
||||||
|
config ARDUINO_EVENT_RUN_CORE0
|
||||||
|
bool "CORE 0"
|
||||||
|
config ARDUINO_EVENT_RUN_CORE1
|
||||||
|
bool "CORE 1"
|
||||||
|
config ARDUINO_EVENT_RUN_NO_AFFINITY
|
||||||
|
bool "BOTH"
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config ARDUINO_EVENT_RUNNING_CORE
|
||||||
|
int
|
||||||
|
default 0 if ARDUINO_EVENT_RUN_CORE0
|
||||||
|
default 1 if ARDUINO_EVENT_RUN_CORE1
|
||||||
|
default -1 if ARDUINO_EVENT_RUN_NO_AFFINITY
|
||||||
|
|
||||||
|
choice ARDUINO_UDP_RUNNING_CORE
|
||||||
|
bool "Core on which Arduino's UDP is running"
|
||||||
|
default ARDUINO_UDP_RUN_CORE1
|
||||||
|
help
|
||||||
|
Select on which core Arduino's UDP run
|
||||||
|
|
||||||
|
config ARDUINO_UDP_RUN_CORE0
|
||||||
|
bool "CORE 0"
|
||||||
|
config ARDUINO_UDP_RUN_CORE1
|
||||||
|
bool "CORE 1"
|
||||||
|
config ARDUINO_UDP_RUN_NO_AFFINITY
|
||||||
|
bool "BOTH"
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config ARDUINO_UDP_TASK_PRIORITY
|
||||||
|
int "Priority of the UDP task"
|
||||||
|
default 3
|
||||||
|
help
|
||||||
|
Select at what priority you want the UDP task to run.
|
||||||
|
|
||||||
|
config ARDUINO_UDP_RUNNING_CORE
|
||||||
|
int
|
||||||
|
default 0 if ARDUINO_UDP_RUN_CORE0
|
||||||
|
default 1 if ARDUINO_UDP_RUN_CORE1
|
||||||
|
default -1 if ARDUINO_UDP_RUN_NO_AFFINITY
|
||||||
|
|
||||||
config ARDUINO_ISR_IRAM
|
config ARDUINO_ISR_IRAM
|
||||||
bool "Run interrupts in IRAM"
|
bool "Run interrupts in IRAM"
|
||||||
default "n"
|
default "n"
|
||||||
@ -78,15 +163,148 @@ config ARDUHAL_ESP_LOG
|
|||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
choice ARDUHAL_PARTITION_SCHEME
|
||||||
|
bool "Used partition scheme"
|
||||||
|
default ARDUHAL_PARTITION_SCHEME_DEFAULT
|
||||||
|
help
|
||||||
|
Specify which partition scheme to be used.
|
||||||
|
|
||||||
|
config ARDUHAL_PARTITION_SCHEME_DEFAULT
|
||||||
|
bool "Default"
|
||||||
|
config ARDUHAL_PARTITION_SCHEME_MINIMAL
|
||||||
|
bool "Minimal (for 2MB FLASH)"
|
||||||
|
config ARDUHAL_PARTITION_SCHEME_NO_OTA
|
||||||
|
bool "No OTA (for large apps)"
|
||||||
|
config ARDUHAL_PARTITION_SCHEME_HUGE_APP
|
||||||
|
bool "Huge App (for very large apps)"
|
||||||
|
config ARDUHAL_PARTITION_SCHEME_MIN_SPIFFS
|
||||||
|
bool "Minimal SPIFFS (for large apps with OTA)"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config ARDUHAL_PARTITION_SCHEME
|
||||||
|
string
|
||||||
|
default "default" if ARDUHAL_PARTITION_SCHEME_DEFAULT
|
||||||
|
default "minimal" if ARDUHAL_PARTITION_SCHEME_MINIMAL
|
||||||
|
default "no_ota" if ARDUHAL_PARTITION_SCHEME_NO_OTA
|
||||||
|
default "huge_app" if ARDUHAL_PARTITION_SCHEME_HUGE_APP
|
||||||
|
default "min_spiffs" if ARDUHAL_PARTITION_SCHEME_MIN_SPIFFS
|
||||||
|
|
||||||
|
|
||||||
|
config AUTOCONNECT_WIFI
|
||||||
|
bool "Autoconnect WiFi on boot"
|
||||||
|
default "n"
|
||||||
|
depends on AUTOSTART_ARDUINO
|
||||||
|
select ARDUINO_SELECTIVE_WiFi
|
||||||
|
help
|
||||||
|
If enabled, WiFi will connect to the last used SSID (if station was enabled),
|
||||||
|
else connection will be started only after calling WiFi.begin(ssid, password)
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_COMPILATION
|
config ARDUINO_SELECTIVE_COMPILATION
|
||||||
bool "Include only specific Arduino libraries"
|
bool "Include only specific Arduino libraries"
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_ArduinoOTA
|
||||||
|
bool "Enable ArduinoOTA"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
select ARDUINO_SELECTIVE_WiFi
|
||||||
|
select ARDUINO_SELECTIVE_ESPmDNS
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_AsyncUDP
|
||||||
|
bool "Enable AsyncUDP"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_AzureIoT
|
||||||
|
bool "Enable AzureIoT"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
select ARDUINO_SELECTIVE_HTTPClient
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_BLE
|
||||||
|
bool "Enable BLE"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_BluetoothSerial
|
||||||
|
bool "Enable BluetoothSerial"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_DNSServer
|
||||||
|
bool "Enable DNSServer"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
select ARDUINO_SELECTIVE_WiFi
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_EEPROM
|
||||||
|
bool "Enable EEPROM"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_ESP32
|
||||||
|
bool "Enable ESP32"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_ESPmDNS
|
||||||
|
bool "Enable ESPmDNS"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
select ARDUINO_SELECTIVE_WiFi
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_FFat
|
||||||
|
bool "Enable FFat"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
select ARDUINO_SELECTIVE_FS
|
||||||
|
default y
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_FS
|
config ARDUINO_SELECTIVE_FS
|
||||||
bool "Enable FS"
|
bool "Enable FS"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_HTTPClient
|
||||||
|
bool "Enable HTTPClient"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
select ARDUINO_SELECTIVE_WiFi
|
||||||
|
select ARDUINO_SELECTIVE_WiFiClientSecure
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_LITTLEFS
|
||||||
|
bool "Enable LITTLEFS"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
select ARDUINO_SELECTIVE_FS
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_NetBIOS
|
||||||
|
bool "Enable NetBIOS"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
select ARDUINO_SELECTIVE_WiFi
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_Preferences
|
||||||
|
bool "Enable Preferences"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_SD
|
||||||
|
bool "Enable SD"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
select ARDUINO_SELECTIVE_FS
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_SD_MMC
|
||||||
|
bool "Enable SD_MMC"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
select ARDUINO_SELECTIVE_FS
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_SimpleBLE
|
||||||
|
bool "Enable SimpleBLE"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_SPI
|
config ARDUINO_SELECTIVE_SPI
|
||||||
bool "Enable SPI"
|
bool "Enable SPI"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
@ -98,6 +316,39 @@ config ARDUINO_SELECTIVE_SPIFFS
|
|||||||
select ARDUINO_SELECTIVE_FS
|
select ARDUINO_SELECTIVE_FS
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_Ticker
|
||||||
|
bool "Enable Ticker"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_Update
|
||||||
|
bool "Enable Update"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_WebServer
|
||||||
|
bool "Enable WebServer"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
select ARDUINO_SELECTIVE_FS
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_WiFi
|
||||||
|
bool "Enable WiFi"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_WiFiClientSecure
|
||||||
|
bool "Enable WiFiClientSecure"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
select ARDUINO_SELECTIVE_WiFi
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_WiFiProv
|
||||||
|
bool "Enable WiFiProv"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
select ARDUINO_SELECTIVE_WiFi
|
||||||
|
default y
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_Wire
|
config ARDUINO_SELECTIVE_Wire
|
||||||
bool "Enable Wire"
|
bool "Enable Wire"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
@ -44,6 +44,8 @@ Finally, if you are sure no one else had the issue, follow the [ISSUE_TEMPLATE](
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
### Tip
|
### Tip
|
||||||
|
|
||||||
Sometimes to program ESP32 via serial you must keep GPIO0 LOW during the programming process
|
Sometimes to program ESP32 via serial you must keep GPIO0 LOW during the programming process
|
||||||
|
2023
boards.txt
2023
boards.txt
File diff suppressed because it is too large
Load Diff
190
cores/esp32/Arduino.h
Normal file
190
cores/esp32/Arduino.h
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
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 Arduino_h
|
||||||
|
#define Arduino_h
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "esp_arduino_version.h"
|
||||||
|
#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"
|
||||||
|
|
||||||
|
#include "stdlib_noniso.h"
|
||||||
|
#include "binary.h"
|
||||||
|
|
||||||
|
#define PI 3.1415926535897932384626433832795
|
||||||
|
#define HALF_PI 1.5707963267948966192313216916398
|
||||||
|
#define TWO_PI 6.283185307179586476925286766559
|
||||||
|
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||||
|
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||||
|
#define EULER 2.718281828459045235360287471352
|
||||||
|
|
||||||
|
#define SERIAL 0x0
|
||||||
|
#define DISPLAY 0x1
|
||||||
|
|
||||||
|
#define LSBFIRST 0
|
||||||
|
#define MSBFIRST 1
|
||||||
|
|
||||||
|
//Interrupt Modes
|
||||||
|
#define RISING 0x01
|
||||||
|
#define FALLING 0x02
|
||||||
|
#define CHANGE 0x03
|
||||||
|
#define ONLOW 0x04
|
||||||
|
#define ONHIGH 0x05
|
||||||
|
#define ONLOW_WE 0x0C
|
||||||
|
#define ONHIGH_WE 0x0D
|
||||||
|
|
||||||
|
#define DEFAULT 1
|
||||||
|
#define EXTERNAL 0
|
||||||
|
|
||||||
|
#ifndef __STRINGIFY
|
||||||
|
#define __STRINGIFY(a) #a
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
||||||
|
#define radians(deg) ((deg)*DEG_TO_RAD)
|
||||||
|
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
||||||
|
#define sq(x) ((x)*(x))
|
||||||
|
|
||||||
|
#define sei()
|
||||||
|
#define cli()
|
||||||
|
#define interrupts() sei()
|
||||||
|
#define noInterrupts() cli()
|
||||||
|
|
||||||
|
#define clockCyclesPerMicrosecond() ( (long int)getCpuFrequencyMhz() )
|
||||||
|
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
|
||||||
|
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
|
||||||
|
|
||||||
|
#define lowByte(w) ((uint8_t) ((w) & 0xff))
|
||||||
|
#define highByte(w) ((uint8_t) ((w) >> 8))
|
||||||
|
|
||||||
|
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||||
|
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
|
||||||
|
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||||
|
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
|
||||||
|
|
||||||
|
// avr-libc defines _NOP() since 1.6.2
|
||||||
|
#ifndef _NOP
|
||||||
|
#define _NOP() do { __asm__ volatile ("nop"); } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define bit(b) (1UL << (b))
|
||||||
|
#define _BV(b) (1UL << (b))
|
||||||
|
|
||||||
|
#define digitalPinToPort(pin) (((pin)>31)?1:0)
|
||||||
|
#define digitalPinToBitMask(pin) (1UL << (((pin)>31)?((pin)-32):(pin)))
|
||||||
|
#define digitalPinToTimer(pin) (0)
|
||||||
|
#define analogInPinToBit(P) (P)
|
||||||
|
#define portOutputRegister(port) ((volatile uint32_t*)((port)?GPIO_OUT1_REG:GPIO_OUT_REG))
|
||||||
|
#define portInputRegister(port) ((volatile uint32_t*)((port)?GPIO_IN1_REG:GPIO_IN_REG))
|
||||||
|
#define portModeRegister(port) ((volatile uint32_t*)((port)?GPIO_ENABLE1_REG:GPIO_ENABLE_REG))
|
||||||
|
|
||||||
|
#define NOT_A_PIN -1
|
||||||
|
#define NOT_A_PORT -1
|
||||||
|
#define NOT_AN_INTERRUPT -1
|
||||||
|
#define NOT_ON_TIMER 0
|
||||||
|
|
||||||
|
typedef bool boolean;
|
||||||
|
typedef uint8_t byte;
|
||||||
|
typedef unsigned int word;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
void setup(void);
|
||||||
|
void loop(void);
|
||||||
|
|
||||||
|
long random(long, long);
|
||||||
|
#endif
|
||||||
|
void randomSeed(unsigned long);
|
||||||
|
long map(long, long, long, long, long);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void init(void);
|
||||||
|
void initVariant(void);
|
||||||
|
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);
|
||||||
|
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "WCharacter.h"
|
||||||
|
#include "WString.h"
|
||||||
|
#include "Stream.h"
|
||||||
|
#include "Printable.h"
|
||||||
|
#include "Print.h"
|
||||||
|
#include "IPAddress.h"
|
||||||
|
#include "Client.h"
|
||||||
|
#include "Server.h"
|
||||||
|
#include "Udp.h"
|
||||||
|
#include "HardwareSerial.h"
|
||||||
|
#include "Esp.h"
|
||||||
|
|
||||||
|
using std::abs;
|
||||||
|
using std::isinf;
|
||||||
|
using std::isnan;
|
||||||
|
using std::max;
|
||||||
|
using std::min;
|
||||||
|
using ::round;
|
||||||
|
|
||||||
|
uint16_t makeWord(uint16_t w);
|
||||||
|
uint16_t makeWord(byte h, byte l);
|
||||||
|
|
||||||
|
#define word(...) makeWord(__VA_ARGS__)
|
||||||
|
|
||||||
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||||
|
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||||
|
|
||||||
|
extern "C" bool getLocalTime(struct tm * info, uint32_t ms = 5000);
|
||||||
|
extern "C" void configTime(long gmtOffset_sec, int daylightOffset_sec,
|
||||||
|
const char* server1, const char* server2 = nullptr, const char* server3 = nullptr);
|
||||||
|
extern "C" void configTzTime(const char* tz,
|
||||||
|
const char* server1, const char* server2 = nullptr, const char* server3 = nullptr);
|
||||||
|
|
||||||
|
// WMath prototypes
|
||||||
|
long random(long);
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#define _min(a,b) ((a)<(b)?(a):(b))
|
||||||
|
#define _max(a,b) ((a)>(b)?(a):(b))
|
||||||
|
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
#endif /* _ESP32_CORE_ARDUINO_H_ */
|
48
cores/esp32/Client.h
Normal file
48
cores/esp32/Client.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
Client.h - Base class that provides Client
|
||||||
|
Copyright (c) 2011 Adrian McEwen. 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 client_h
|
||||||
|
#define client_h
|
||||||
|
#include "Print.h"
|
||||||
|
#include "Stream.h"
|
||||||
|
#include "IPAddress.h"
|
||||||
|
|
||||||
|
class Client: public Stream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual int connect(IPAddress ip, uint16_t port) =0;
|
||||||
|
virtual int connect(const char *host, uint16_t port) =0;
|
||||||
|
virtual size_t write(uint8_t) =0;
|
||||||
|
virtual size_t write(const uint8_t *buf, size_t size) =0;
|
||||||
|
virtual int available() = 0;
|
||||||
|
virtual int read() = 0;
|
||||||
|
virtual int read(uint8_t *buf, size_t size) = 0;
|
||||||
|
virtual int peek() = 0;
|
||||||
|
virtual void flush() = 0;
|
||||||
|
virtual void stop() = 0;
|
||||||
|
virtual uint8_t connected() = 0;
|
||||||
|
virtual operator bool() = 0;
|
||||||
|
protected:
|
||||||
|
uint8_t* rawIPAddress(IPAddress& addr)
|
||||||
|
{
|
||||||
|
return addr.raw_address();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
395
cores/esp32/Esp.cpp
Normal file
395
cores/esp32/Esp.cpp
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
/*
|
||||||
|
Esp.cpp - ESP31B-specific APIs
|
||||||
|
Copyright (c) 2015 Ivan Grokhotkov. All rights 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "Esp.h"
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
#include "esp_spi_flash.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <soc/soc.h>
|
||||||
|
#include <esp_partition.h>
|
||||||
|
extern "C" {
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
#include "esp_image_format.h"
|
||||||
|
}
|
||||||
|
#include <MD5Builder.h>
|
||||||
|
|
||||||
|
#include "esp_system.h"
|
||||||
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "esp32/rom/spi_flash.h"
|
||||||
|
#include "soc/efuse_reg.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/spi_flash.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/rom/spi_flash.h"
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
|
#include "rom/spi_flash.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User-defined Literals
|
||||||
|
* usage:
|
||||||
|
*
|
||||||
|
* uint32_t = test = 10_MHz; // --> 10000000
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned long long operator"" _kHz(unsigned long long x)
|
||||||
|
{
|
||||||
|
return x * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _MHz(unsigned long long x)
|
||||||
|
{
|
||||||
|
return x * 1000 * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _GHz(unsigned long long x)
|
||||||
|
{
|
||||||
|
return x * 1000 * 1000 * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _kBit(unsigned long long x)
|
||||||
|
{
|
||||||
|
return x * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _MBit(unsigned long long x)
|
||||||
|
{
|
||||||
|
return x * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _GBit(unsigned long long x)
|
||||||
|
{
|
||||||
|
return x * 1024 * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _kB(unsigned long long x)
|
||||||
|
{
|
||||||
|
return x * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _MB(unsigned long long x)
|
||||||
|
{
|
||||||
|
return x * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long operator"" _GB(unsigned long long x)
|
||||||
|
{
|
||||||
|
return x * 1024 * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EspClass ESP;
|
||||||
|
|
||||||
|
void EspClass::deepSleep(uint32_t time_us)
|
||||||
|
{
|
||||||
|
esp_deep_sleep(time_us);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EspClass::restart(void)
|
||||||
|
{
|
||||||
|
esp_restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getHeapSize(void)
|
||||||
|
{
|
||||||
|
multi_heap_info_t info;
|
||||||
|
heap_caps_get_info(&info, MALLOC_CAP_INTERNAL);
|
||||||
|
return info.total_free_bytes + info.total_allocated_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getFreeHeap(void)
|
||||||
|
{
|
||||||
|
return heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getMinFreeHeap(void)
|
||||||
|
{
|
||||||
|
return heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getMaxAllocHeap(void)
|
||||||
|
{
|
||||||
|
return heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getPsramSize(void)
|
||||||
|
{
|
||||||
|
if(psramFound()){
|
||||||
|
multi_heap_info_t info;
|
||||||
|
heap_caps_get_info(&info, MALLOC_CAP_SPIRAM);
|
||||||
|
return info.total_free_bytes + info.total_allocated_bytes;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getFreePsram(void)
|
||||||
|
{
|
||||||
|
if(psramFound()){
|
||||||
|
return heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getMinFreePsram(void)
|
||||||
|
{
|
||||||
|
if(psramFound()){
|
||||||
|
return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getMaxAllocPsram(void)
|
||||||
|
{
|
||||||
|
if(psramFound()){
|
||||||
|
return heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t sketchSize(sketchSize_t response) {
|
||||||
|
esp_image_metadata_t data;
|
||||||
|
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||||
|
if (!running) return 0;
|
||||||
|
const esp_partition_pos_t running_pos = {
|
||||||
|
.offset = running->address,
|
||||||
|
.size = running->size,
|
||||||
|
};
|
||||||
|
data.start_addr = running_pos.offset;
|
||||||
|
esp_image_verify(ESP_IMAGE_VERIFY, &running_pos, &data);
|
||||||
|
if (response) {
|
||||||
|
return running_pos.size - data.image_len;
|
||||||
|
} else {
|
||||||
|
return data.image_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getSketchSize () {
|
||||||
|
return sketchSize(SKETCH_SIZE_TOTAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
String EspClass::getSketchMD5()
|
||||||
|
{
|
||||||
|
static String result;
|
||||||
|
if (result.length()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint32_t lengthLeft = getSketchSize();
|
||||||
|
|
||||||
|
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||||
|
if (!running) {
|
||||||
|
log_e("Partition could not be found");
|
||||||
|
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
const size_t bufSize = SPI_FLASH_SEC_SIZE;
|
||||||
|
std::unique_ptr<uint8_t[]> buf(new uint8_t[bufSize]);
|
||||||
|
uint32_t offset = 0;
|
||||||
|
if(!buf.get()) {
|
||||||
|
log_e("Not enough memory to allocate buffer");
|
||||||
|
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
MD5Builder md5;
|
||||||
|
md5.begin();
|
||||||
|
while( lengthLeft > 0) {
|
||||||
|
size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize;
|
||||||
|
if (!ESP.flashRead(running->address + offset, reinterpret_cast<uint32_t*>(buf.get()), (readBytes + 3) & ~3)) {
|
||||||
|
log_e("Could not read buffer from flash");
|
||||||
|
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
md5.add(buf.get(), readBytes);
|
||||||
|
lengthLeft -= readBytes;
|
||||||
|
offset += readBytes;
|
||||||
|
}
|
||||||
|
md5.calculate();
|
||||||
|
result = md5.toString();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getFreeSketchSpace () {
|
||||||
|
const esp_partition_t* _partition = esp_ota_get_next_update_partition(NULL);
|
||||||
|
if(!_partition){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _partition->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t EspClass::getChipRevision(void)
|
||||||
|
{
|
||||||
|
esp_chip_info_t chip_info;
|
||||||
|
esp_chip_info(&chip_info);
|
||||||
|
return chip_info.revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * EspClass::getChipModel(void)
|
||||||
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
|
||||||
|
uint32_t pkg_ver = chip_ver & 0x7;
|
||||||
|
switch (pkg_ver) {
|
||||||
|
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6 :
|
||||||
|
return "ESP32-D0WDQ6";
|
||||||
|
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5 :
|
||||||
|
return "ESP32-D0WDQ5";
|
||||||
|
case EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 :
|
||||||
|
return "ESP32-D2WDQ5";
|
||||||
|
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 :
|
||||||
|
return "ESP32-PICO-D2";
|
||||||
|
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4 :
|
||||||
|
return "ESP32-PICO-D4";
|
||||||
|
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302 :
|
||||||
|
return "ESP32-PICO-V3-02";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
return "ESP32-S2";
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
|
return "ESP32-S3";
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
return "ESP32-C3";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t EspClass::getChipCores(void)
|
||||||
|
{
|
||||||
|
esp_chip_info_t chip_info;
|
||||||
|
esp_chip_info(&chip_info);
|
||||||
|
return chip_info.cores;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * EspClass::getSdkVersion(void)
|
||||||
|
{
|
||||||
|
return esp_get_idf_version();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getFlashChipSize(void)
|
||||||
|
{
|
||||||
|
esp_image_header_t fhdr;
|
||||||
|
if(flashRead(0x1000, (uint32_t*)&fhdr, sizeof(esp_image_header_t)) && fhdr.magic != ESP_IMAGE_HEADER_MAGIC) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return magicFlashChipSize(fhdr.spi_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getFlashChipSpeed(void)
|
||||||
|
{
|
||||||
|
esp_image_header_t fhdr;
|
||||||
|
if(flashRead(0x1000, (uint32_t*)&fhdr, sizeof(esp_image_header_t)) && fhdr.magic != ESP_IMAGE_HEADER_MAGIC) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return magicFlashChipSpeed(fhdr.spi_speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
FlashMode_t EspClass::getFlashChipMode(void)
|
||||||
|
{
|
||||||
|
esp_image_header_t fhdr;
|
||||||
|
if(flashRead(0x1000, (uint32_t*)&fhdr, sizeof(esp_image_header_t)) && fhdr.magic != ESP_IMAGE_HEADER_MAGIC) {
|
||||||
|
return FM_UNKNOWN;
|
||||||
|
}
|
||||||
|
return magicFlashChipMode(fhdr.spi_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::magicFlashChipSize(uint8_t byte)
|
||||||
|
{
|
||||||
|
switch(byte & 0x0F) {
|
||||||
|
case 0x0: // 8 MBit (1MB)
|
||||||
|
return (1_MB);
|
||||||
|
case 0x1: // 16 MBit (2MB)
|
||||||
|
return (2_MB);
|
||||||
|
case 0x2: // 32 MBit (4MB)
|
||||||
|
return (4_MB);
|
||||||
|
case 0x3: // 64 MBit (8MB)
|
||||||
|
return (8_MB);
|
||||||
|
case 0x4: // 128 MBit (16MB)
|
||||||
|
return (16_MB);
|
||||||
|
default: // fail?
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::magicFlashChipSpeed(uint8_t byte)
|
||||||
|
{
|
||||||
|
switch(byte & 0x0F) {
|
||||||
|
case 0x0: // 40 MHz
|
||||||
|
return (40_MHz);
|
||||||
|
case 0x1: // 26 MHz
|
||||||
|
return (26_MHz);
|
||||||
|
case 0x2: // 20 MHz
|
||||||
|
return (20_MHz);
|
||||||
|
case 0xf: // 80 MHz
|
||||||
|
return (80_MHz);
|
||||||
|
default: // fail?
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FlashMode_t EspClass::magicFlashChipMode(uint8_t byte)
|
||||||
|
{
|
||||||
|
FlashMode_t mode = (FlashMode_t) byte;
|
||||||
|
if(mode > FM_SLOW_READ) {
|
||||||
|
mode = FM_UNKNOWN;
|
||||||
|
}
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EspClass::flashEraseSector(uint32_t sector)
|
||||||
|
{
|
||||||
|
return spi_flash_erase_sector(sector) == ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warning: These functions do not work with encrypted flash
|
||||||
|
bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size)
|
||||||
|
{
|
||||||
|
return spi_flash_write(offset, (uint32_t*) data, size) == ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size)
|
||||||
|
{
|
||||||
|
return spi_flash_read(offset, (uint32_t*) data, size) == ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EspClass::partitionEraseRange(const esp_partition_t *partition, uint32_t offset, size_t size)
|
||||||
|
{
|
||||||
|
return esp_partition_erase_range(partition, offset, size) == ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EspClass::partitionWrite(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size)
|
||||||
|
{
|
||||||
|
return esp_partition_write(partition, offset, data, size) == ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EspClass::partitionRead(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size)
|
||||||
|
{
|
||||||
|
return esp_partition_read(partition, offset, data, size) == ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t EspClass::getEfuseMac(void)
|
||||||
|
{
|
||||||
|
uint64_t _chipmacid = 0LL;
|
||||||
|
esp_efuse_mac_get_default((uint8_t*) (&_chipmacid));
|
||||||
|
return _chipmacid;
|
||||||
|
}
|
120
cores/esp32/Esp.h
Normal file
120
cores/esp32/Esp.h
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
Esp.h - ESP31B-specific APIs
|
||||||
|
Copyright (c) 2015 Ivan Grokhotkov. All rights 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 ESP_H
|
||||||
|
#define ESP_H
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <esp_partition.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AVR macros for WDT managment
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
WDTO_0MS = 0, //!< WDTO_0MS
|
||||||
|
WDTO_15MS = 15, //!< WDTO_15MS
|
||||||
|
WDTO_30MS = 30, //!< WDTO_30MS
|
||||||
|
WDTO_60MS = 60, //!< WDTO_60MS
|
||||||
|
WDTO_120MS = 120, //!< WDTO_120MS
|
||||||
|
WDTO_250MS = 250, //!< WDTO_250MS
|
||||||
|
WDTO_500MS = 500, //!< WDTO_500MS
|
||||||
|
WDTO_1S = 1000,//!< WDTO_1S
|
||||||
|
WDTO_2S = 2000,//!< WDTO_2S
|
||||||
|
WDTO_4S = 4000,//!< WDTO_4S
|
||||||
|
WDTO_8S = 8000 //!< WDTO_8S
|
||||||
|
} WDTO_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FM_QIO = 0x00,
|
||||||
|
FM_QOUT = 0x01,
|
||||||
|
FM_DIO = 0x02,
|
||||||
|
FM_DOUT = 0x03,
|
||||||
|
FM_FAST_READ = 0x04,
|
||||||
|
FM_SLOW_READ = 0x05,
|
||||||
|
FM_UNKNOWN = 0xff
|
||||||
|
} FlashMode_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SKETCH_SIZE_TOTAL = 0,
|
||||||
|
SKETCH_SIZE_FREE = 1
|
||||||
|
} sketchSize_t;
|
||||||
|
|
||||||
|
class EspClass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EspClass() {}
|
||||||
|
~EspClass() {}
|
||||||
|
void restart();
|
||||||
|
|
||||||
|
//Internal RAM
|
||||||
|
uint32_t getHeapSize(); //total heap size
|
||||||
|
uint32_t getFreeHeap(); //available heap
|
||||||
|
uint32_t getMinFreeHeap(); //lowest level of free heap since boot
|
||||||
|
uint32_t getMaxAllocHeap(); //largest block of heap that can be allocated at once
|
||||||
|
|
||||||
|
//SPI RAM
|
||||||
|
uint32_t getPsramSize();
|
||||||
|
uint32_t getFreePsram();
|
||||||
|
uint32_t getMinFreePsram();
|
||||||
|
uint32_t getMaxAllocPsram();
|
||||||
|
|
||||||
|
uint8_t getChipRevision();
|
||||||
|
const char * getChipModel();
|
||||||
|
uint8_t getChipCores();
|
||||||
|
uint32_t getCpuFreqMHz(){ return getCpuFrequencyMhz(); }
|
||||||
|
inline uint32_t getCycleCount() __attribute__((always_inline));
|
||||||
|
const char * getSdkVersion();
|
||||||
|
|
||||||
|
void deepSleep(uint32_t time_us);
|
||||||
|
|
||||||
|
uint32_t getFlashChipSize();
|
||||||
|
uint32_t getFlashChipSpeed();
|
||||||
|
FlashMode_t getFlashChipMode();
|
||||||
|
|
||||||
|
uint32_t magicFlashChipSize(uint8_t byte);
|
||||||
|
uint32_t magicFlashChipSpeed(uint8_t byte);
|
||||||
|
FlashMode_t magicFlashChipMode(uint8_t byte);
|
||||||
|
|
||||||
|
uint32_t getSketchSize();
|
||||||
|
String getSketchMD5();
|
||||||
|
uint32_t getFreeSketchSpace();
|
||||||
|
|
||||||
|
bool flashEraseSector(uint32_t sector);
|
||||||
|
bool flashWrite(uint32_t offset, uint32_t *data, size_t size);
|
||||||
|
bool flashRead(uint32_t offset, uint32_t *data, size_t size);
|
||||||
|
|
||||||
|
bool partitionEraseRange(const esp_partition_t *partition, uint32_t offset, size_t size);
|
||||||
|
bool partitionWrite(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size);
|
||||||
|
bool partitionRead(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size);
|
||||||
|
|
||||||
|
uint64_t getEfuseMac();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t ARDUINO_ISR_ATTR EspClass::getCycleCount()
|
||||||
|
{
|
||||||
|
uint32_t ccount;
|
||||||
|
__asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
|
||||||
|
return ccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern EspClass ESP;
|
||||||
|
|
||||||
|
#endif //ESP_H
|
@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "FunctionalInterrupt.h"
|
#include "FunctionalInterrupt.h"
|
||||||
#include "esp32-hal.h"
|
#include "Arduino.h"
|
||||||
|
|
||||||
typedef void (*voidFuncPtr)(void);
|
typedef void (*voidFuncPtr)(void);
|
||||||
typedef void (*voidFuncPtrArg)(void*);
|
typedef void (*voidFuncPtrArg)(void*);
|
||||||
|
221
cores/esp32/HardwareSerial.cpp
Normal file
221
cores/esp32/HardwareSerial.cpp
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
#include "HardwareSerial.h"
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
|
||||||
|
#ifndef RX1
|
||||||
|
#define RX1 9
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TX1
|
||||||
|
#define TX1 10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RX2
|
||||||
|
#define RX2 16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TX2
|
||||||
|
#define TX2 17
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef RX1
|
||||||
|
#define RX1 18
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TX1
|
||||||
|
#define TX1 17
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
||||||
|
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
||||||
|
HardwareSerial Serial0(0);
|
||||||
|
#else
|
||||||
|
HardwareSerial Serial(0);
|
||||||
|
#endif
|
||||||
|
HardwareSerial Serial1(1);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
HardwareSerial Serial2(2);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL) {}
|
||||||
|
|
||||||
|
void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms, uint8_t rxfifo_full_thrhd)
|
||||||
|
{
|
||||||
|
if(0 > _uart_nr || _uart_nr > 2) {
|
||||||
|
log_e("Serial number is invalid, please use 0, 1 or 2");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(_uart) {
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
if(_uart_nr == 0 && rxPin < 0 && txPin < 0) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
rxPin = 3;
|
||||||
|
txPin = 1;
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
rxPin = 44;
|
||||||
|
txPin = 43;
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
rxPin = 20;
|
||||||
|
txPin = 21;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if(_uart_nr == 1 && rxPin < 0 && txPin < 0) {
|
||||||
|
rxPin = RX1;
|
||||||
|
txPin = TX1;
|
||||||
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
if(_uart_nr == 2 && rxPin < 0 && txPin < 0) {
|
||||||
|
rxPin = RX2;
|
||||||
|
txPin = TX2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert, rxfifo_full_thrhd);
|
||||||
|
_tx_pin = txPin;
|
||||||
|
_rx_pin = rxPin;
|
||||||
|
|
||||||
|
if(!baud) {
|
||||||
|
uartStartDetectBaudrate(_uart);
|
||||||
|
time_t startMillis = millis();
|
||||||
|
unsigned long detectedBaudRate = 0;
|
||||||
|
while(millis() - startMillis < timeout_ms && !(detectedBaudRate = uartDetectBaudrate(_uart))) {
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
end();
|
||||||
|
|
||||||
|
if(detectedBaudRate) {
|
||||||
|
delay(100); // Give some time...
|
||||||
|
_uart = uartBegin(_uart_nr, detectedBaudRate, config, rxPin, txPin, 256, invert, rxfifo_full_thrhd);
|
||||||
|
} else {
|
||||||
|
log_e("Could not detect baudrate. Serial data at the port must be present within the timeout for detection to be possible");
|
||||||
|
_uart = NULL;
|
||||||
|
_tx_pin = 255;
|
||||||
|
_rx_pin = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::updateBaudRate(unsigned long baud)
|
||||||
|
{
|
||||||
|
uartSetBaudRate(_uart, baud);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::end()
|
||||||
|
{
|
||||||
|
if(uartGetDebug() == _uart_nr) {
|
||||||
|
uartSetDebug(0);
|
||||||
|
}
|
||||||
|
delay(10);
|
||||||
|
log_v("pins %d %d",_tx_pin, _rx_pin);
|
||||||
|
uartEnd(_uart, _tx_pin, _rx_pin);
|
||||||
|
_uart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t HardwareSerial::setRxBufferSize(size_t new_size) {
|
||||||
|
return uartResizeRxBuffer(_uart, new_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::setDebugOutput(bool en)
|
||||||
|
{
|
||||||
|
if(_uart == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(en) {
|
||||||
|
uartSetDebug(_uart);
|
||||||
|
} else {
|
||||||
|
if(uartGetDebug() == _uart_nr) {
|
||||||
|
uartSetDebug(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int HardwareSerial::available(void)
|
||||||
|
{
|
||||||
|
return uartAvailable(_uart);
|
||||||
|
}
|
||||||
|
int HardwareSerial::availableForWrite(void)
|
||||||
|
{
|
||||||
|
return uartAvailableForWrite(_uart);
|
||||||
|
}
|
||||||
|
|
||||||
|
int HardwareSerial::peek(void)
|
||||||
|
{
|
||||||
|
if (available()) {
|
||||||
|
return uartPeek(_uart);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HardwareSerial::read(void)
|
||||||
|
{
|
||||||
|
if(available()) {
|
||||||
|
return uartRead(_uart);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read characters into buffer
|
||||||
|
// terminates if size characters have been read, or no further are pending
|
||||||
|
// returns the number of characters placed in the buffer
|
||||||
|
// the buffer is NOT null terminated.
|
||||||
|
size_t HardwareSerial::read(uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
size_t avail = available();
|
||||||
|
if (size < avail) {
|
||||||
|
avail = size;
|
||||||
|
}
|
||||||
|
size_t count = 0;
|
||||||
|
while(count < avail) {
|
||||||
|
*buffer++ = uartRead(_uart);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::flush(void)
|
||||||
|
{
|
||||||
|
uartFlush(_uart);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::flush(bool txOnly)
|
||||||
|
{
|
||||||
|
uartFlushTxOnly(_uart, txOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t HardwareSerial::write(uint8_t c)
|
||||||
|
{
|
||||||
|
uartWrite(_uart, c);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t HardwareSerial::write(const uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
uartWriteBuf(_uart, buffer, size);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
uint32_t HardwareSerial::baudRate()
|
||||||
|
|
||||||
|
{
|
||||||
|
return uartGetBaudRate(_uart);
|
||||||
|
}
|
||||||
|
HardwareSerial::operator bool() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::setRxInvert(bool invert)
|
||||||
|
{
|
||||||
|
uartSetRxInvert(_uart, invert);
|
||||||
|
}
|
132
cores/esp32/HardwareSerial.h
Normal file
132
cores/esp32/HardwareSerial.h
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
HardwareSerial.h - Hardware serial library for Wiring
|
||||||
|
Copyright (c) 2006 Nicholas Zambetti. 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
|
||||||
|
|
||||||
|
Modified 28 September 2010 by Mark Sproul
|
||||||
|
Modified 14 August 2012 by Alarus
|
||||||
|
Modified 3 December 2013 by Matthijs Kooijman
|
||||||
|
Modified 18 December 2014 by Ivan Grokhotkov (esp8266 platform support)
|
||||||
|
Modified 31 March 2015 by Markus Sattler (rewrite the code for UART0 + UART1 support in ESP8266)
|
||||||
|
Modified 25 April 2015 by Thomas Flayols (add configuration different from 8N1 in ESP8266)
|
||||||
|
Modified 13 October 2018 by Jeroen Döll (add baudrate detection)
|
||||||
|
Baudrate detection example usage (detection on Serial1):
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(100);
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
Serial1.begin(0, SERIAL_8N1, -1, -1, true, 11000UL); // Passing 0 for baudrate to detect it, the last parameter is a timeout in ms
|
||||||
|
|
||||||
|
unsigned long detectedBaudRate = Serial1.baudRate();
|
||||||
|
if(detectedBaudRate) {
|
||||||
|
Serial.printf("Detected baudrate is %lu\n", detectedBaudRate);
|
||||||
|
} else {
|
||||||
|
Serial.println("No baudrate detected, Serial1 will not work!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pay attention: the baudrate returned by baudRate() may be rounded, eg 115200 returns 115201
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HardwareSerial_h
|
||||||
|
#define HardwareSerial_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "Stream.h"
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
|
||||||
|
class HardwareSerial: public Stream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HardwareSerial(int uart_nr);
|
||||||
|
|
||||||
|
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);
|
||||||
|
void end();
|
||||||
|
void updateBaudRate(unsigned long baud);
|
||||||
|
int available(void);
|
||||||
|
int availableForWrite(void);
|
||||||
|
int peek(void);
|
||||||
|
int read(void);
|
||||||
|
size_t read(uint8_t *buffer, size_t size);
|
||||||
|
inline size_t read(char * buffer, size_t size)
|
||||||
|
{
|
||||||
|
return read((uint8_t*) buffer, size);
|
||||||
|
}
|
||||||
|
void flush(void);
|
||||||
|
void flush( bool txOnly);
|
||||||
|
size_t write(uint8_t);
|
||||||
|
size_t write(const uint8_t *buffer, size_t size);
|
||||||
|
inline size_t write(const char * buffer, size_t size)
|
||||||
|
{
|
||||||
|
return write((uint8_t*) buffer, size);
|
||||||
|
}
|
||||||
|
inline size_t write(const char * s)
|
||||||
|
{
|
||||||
|
return write((uint8_t*) s, strlen(s));
|
||||||
|
}
|
||||||
|
inline size_t write(unsigned long n)
|
||||||
|
{
|
||||||
|
return write((uint8_t) n);
|
||||||
|
}
|
||||||
|
inline size_t write(long n)
|
||||||
|
{
|
||||||
|
return write((uint8_t) n);
|
||||||
|
}
|
||||||
|
inline size_t write(unsigned int n)
|
||||||
|
{
|
||||||
|
return write((uint8_t) n);
|
||||||
|
}
|
||||||
|
inline size_t write(int n)
|
||||||
|
{
|
||||||
|
return write((uint8_t) n);
|
||||||
|
}
|
||||||
|
uint32_t baudRate();
|
||||||
|
operator bool() const;
|
||||||
|
|
||||||
|
size_t setRxBufferSize(size_t);
|
||||||
|
void setDebugOutput(bool);
|
||||||
|
|
||||||
|
void setRxInvert(bool);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int _uart_nr;
|
||||||
|
uart_t* _uart;
|
||||||
|
uint8_t _tx_pin;
|
||||||
|
uint8_t _rx_pin;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void serialEventRun(void) __attribute__((weak));
|
||||||
|
|
||||||
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
||||||
|
#ifndef ARDUINO_SERIAL_PORT
|
||||||
|
#define ARDUINO_SERIAL_PORT 0
|
||||||
|
#endif
|
||||||
|
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
||||||
|
#include "USB.h"
|
||||||
|
#include "USBCDC.h"
|
||||||
|
extern HardwareSerial Serial0;
|
||||||
|
#else
|
||||||
|
extern HardwareSerial Serial;
|
||||||
|
#endif
|
||||||
|
extern HardwareSerial Serial1;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
extern HardwareSerial Serial2;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // HardwareSerial_h
|
122
cores/esp32/IPAddress.cpp
Normal file
122
cores/esp32/IPAddress.cpp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
IPAddress.cpp - Base class that provides IPAddress
|
||||||
|
Copyright (c) 2011 Adrian McEwen. 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <IPAddress.h>
|
||||||
|
#include <Print.h>
|
||||||
|
|
||||||
|
IPAddress::IPAddress()
|
||||||
|
{
|
||||||
|
_address.dword = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
|
||||||
|
{
|
||||||
|
_address.bytes[0] = first_octet;
|
||||||
|
_address.bytes[1] = second_octet;
|
||||||
|
_address.bytes[2] = third_octet;
|
||||||
|
_address.bytes[3] = fourth_octet;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress::IPAddress(uint32_t address)
|
||||||
|
{
|
||||||
|
_address.dword = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress::IPAddress(const uint8_t *address)
|
||||||
|
{
|
||||||
|
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress& IPAddress::operator=(const uint8_t *address)
|
||||||
|
{
|
||||||
|
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress& IPAddress::operator=(uint32_t address)
|
||||||
|
{
|
||||||
|
_address.dword = address;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPAddress::operator==(const uint8_t* addr) const
|
||||||
|
{
|
||||||
|
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t IPAddress::printTo(Print& p) const
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
for(int i = 0; i < 3; i++) {
|
||||||
|
n += p.print(_address.bytes[i], DEC);
|
||||||
|
n += p.print('.');
|
||||||
|
}
|
||||||
|
n += p.print(_address.bytes[3], DEC);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
String IPAddress::toString() const
|
||||||
|
{
|
||||||
|
char szRet[16];
|
||||||
|
sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3]);
|
||||||
|
return String(szRet);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPAddress::fromString(const char *address)
|
||||||
|
{
|
||||||
|
// TODO: add support for "a", "a.b", "a.b.c" formats
|
||||||
|
|
||||||
|
uint16_t acc = 0; // Accumulator
|
||||||
|
uint8_t dots = 0;
|
||||||
|
|
||||||
|
while (*address)
|
||||||
|
{
|
||||||
|
char c = *address++;
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
{
|
||||||
|
acc = acc * 10 + (c - '0');
|
||||||
|
if (acc > 255) {
|
||||||
|
// Value out of [0..255] range
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '.')
|
||||||
|
{
|
||||||
|
if (dots == 3) {
|
||||||
|
// Too much dots (there must be 3 dots)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_address.bytes[dots++] = acc;
|
||||||
|
acc = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Invalid char
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dots != 3) {
|
||||||
|
// Too few dots (there must be 3 dots)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_address.bytes[3] = acc;
|
||||||
|
return true;
|
||||||
|
}
|
96
cores/esp32/IPAddress.h
Normal file
96
cores/esp32/IPAddress.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
IPAddress.h - Base class that provides IPAddress
|
||||||
|
Copyright (c) 2011 Adrian McEwen. 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 IPAddress_h
|
||||||
|
#define IPAddress_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <WString.h>
|
||||||
|
#include <Printable.h>
|
||||||
|
|
||||||
|
// A class to make it easier to handle and pass around IP addresses
|
||||||
|
|
||||||
|
class IPAddress: public Printable
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
union {
|
||||||
|
uint8_t bytes[4]; // IPv4 address
|
||||||
|
uint32_t dword;
|
||||||
|
} _address;
|
||||||
|
|
||||||
|
// Access the raw byte array containing the address. Because this returns a pointer
|
||||||
|
// to the internal structure rather than a copy of the address this function should only
|
||||||
|
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||||
|
// stored.
|
||||||
|
uint8_t* raw_address()
|
||||||
|
{
|
||||||
|
return _address.bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructors
|
||||||
|
IPAddress();
|
||||||
|
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
||||||
|
IPAddress(uint32_t address);
|
||||||
|
IPAddress(const uint8_t *address);
|
||||||
|
virtual ~IPAddress() {}
|
||||||
|
|
||||||
|
bool fromString(const char *address);
|
||||||
|
bool fromString(const String &address) { return fromString(address.c_str()); }
|
||||||
|
|
||||||
|
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
|
||||||
|
// to a four-byte uint8_t array is expected
|
||||||
|
operator uint32_t() const
|
||||||
|
{
|
||||||
|
return _address.dword;
|
||||||
|
}
|
||||||
|
bool operator==(const IPAddress& addr) const
|
||||||
|
{
|
||||||
|
return _address.dword == addr._address.dword;
|
||||||
|
}
|
||||||
|
bool operator==(const uint8_t* addr) const;
|
||||||
|
|
||||||
|
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||||
|
uint8_t operator[](int index) const
|
||||||
|
{
|
||||||
|
return _address.bytes[index];
|
||||||
|
}
|
||||||
|
uint8_t& operator[](int index)
|
||||||
|
{
|
||||||
|
return _address.bytes[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
|
||||||
|
IPAddress& operator=(const uint8_t *address);
|
||||||
|
IPAddress& operator=(uint32_t address);
|
||||||
|
|
||||||
|
virtual size_t printTo(Print& p) const;
|
||||||
|
String toString() const;
|
||||||
|
|
||||||
|
friend class EthernetClass;
|
||||||
|
friend class UDP;
|
||||||
|
friend class Client;
|
||||||
|
friend class Server;
|
||||||
|
friend class DhcpClass;
|
||||||
|
friend class DNSClient;
|
||||||
|
};
|
||||||
|
|
||||||
|
const IPAddress INADDR_NONE(0, 0, 0, 0);
|
||||||
|
|
||||||
|
#endif
|
90
cores/esp32/IPv6Address.cpp
Normal file
90
cores/esp32/IPv6Address.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
IPv6Address.cpp - Base class that provides IPv6Address
|
||||||
|
Copyright (c) 2011 Adrian McEwen. 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <IPv6Address.h>
|
||||||
|
#include <Print.h>
|
||||||
|
|
||||||
|
IPv6Address::IPv6Address()
|
||||||
|
{
|
||||||
|
memset(_address.bytes, 0, sizeof(_address.bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPv6Address::IPv6Address(const uint8_t *address)
|
||||||
|
{
|
||||||
|
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPv6Address::IPv6Address(const uint32_t *address)
|
||||||
|
{
|
||||||
|
memcpy(_address.bytes, (const uint8_t *)address, sizeof(_address.bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPv6Address& IPv6Address::operator=(const uint8_t *address)
|
||||||
|
{
|
||||||
|
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPv6Address::operator==(const uint8_t* addr) const
|
||||||
|
{
|
||||||
|
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t IPv6Address::printTo(Print& p) const
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
for(int i = 0; i < 16; i+=2) {
|
||||||
|
if(i){
|
||||||
|
n += p.print(':');
|
||||||
|
}
|
||||||
|
n += p.printf("%02x", _address.bytes[i]);
|
||||||
|
n += p.printf("%02x", _address.bytes[i+1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
String IPv6Address::toString() const
|
||||||
|
{
|
||||||
|
char szRet[40];
|
||||||
|
sprintf(szRet,"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
||||||
|
_address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3],
|
||||||
|
_address.bytes[4], _address.bytes[5], _address.bytes[6], _address.bytes[7],
|
||||||
|
_address.bytes[8], _address.bytes[9], _address.bytes[10], _address.bytes[11],
|
||||||
|
_address.bytes[12], _address.bytes[13], _address.bytes[14], _address.bytes[15]);
|
||||||
|
return String(szRet);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPv6Address::fromString(const char *address)
|
||||||
|
{
|
||||||
|
//format 0011:2233:4455:6677:8899:aabb:ccdd:eeff
|
||||||
|
if(strlen(address) != 39){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char * pos = (char *)address;
|
||||||
|
size_t i = 0;
|
||||||
|
for(i = 0; i < 16; i+=2) {
|
||||||
|
if(!sscanf(pos, "%2hhx", &_address.bytes[i]) || !sscanf(pos+2, "%2hhx", &_address.bytes[i+1])){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pos += 5;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
94
cores/esp32/IPv6Address.h
Normal file
94
cores/esp32/IPv6Address.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
IPv6Address.h - Base class that provides IPv6Address
|
||||||
|
Copyright (c) 2011 Adrian McEwen. 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 IPv6Address_h
|
||||||
|
#define IPv6Address_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <WString.h>
|
||||||
|
#include <Printable.h>
|
||||||
|
|
||||||
|
// A class to make it easier to handle and pass around IP addresses
|
||||||
|
|
||||||
|
class IPv6Address: public Printable
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
union {
|
||||||
|
uint8_t bytes[16]; // IPv4 address
|
||||||
|
uint32_t dword[4];
|
||||||
|
} _address;
|
||||||
|
|
||||||
|
// Access the raw byte array containing the address. Because this returns a pointer
|
||||||
|
// to the internal structure rather than a copy of the address this function should only
|
||||||
|
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||||
|
// stored.
|
||||||
|
uint8_t* raw_address()
|
||||||
|
{
|
||||||
|
return _address.bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructors
|
||||||
|
IPv6Address();
|
||||||
|
IPv6Address(const uint8_t *address);
|
||||||
|
IPv6Address(const uint32_t *address);
|
||||||
|
virtual ~IPv6Address() {}
|
||||||
|
|
||||||
|
bool fromString(const char *address);
|
||||||
|
bool fromString(const String &address) { return fromString(address.c_str()); }
|
||||||
|
|
||||||
|
operator const uint8_t*() const
|
||||||
|
{
|
||||||
|
return _address.bytes;
|
||||||
|
}
|
||||||
|
operator const uint32_t*() const
|
||||||
|
{
|
||||||
|
return _address.dword;
|
||||||
|
}
|
||||||
|
bool operator==(const IPv6Address& addr) const
|
||||||
|
{
|
||||||
|
return (_address.dword[0] == addr._address.dword[0])
|
||||||
|
&& (_address.dword[1] == addr._address.dword[1])
|
||||||
|
&& (_address.dword[2] == addr._address.dword[2])
|
||||||
|
&& (_address.dword[3] == addr._address.dword[3]);
|
||||||
|
}
|
||||||
|
bool operator==(const uint8_t* addr) const;
|
||||||
|
|
||||||
|
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||||
|
uint8_t operator[](int index) const
|
||||||
|
{
|
||||||
|
return _address.bytes[index];
|
||||||
|
}
|
||||||
|
uint8_t& operator[](int index)
|
||||||
|
{
|
||||||
|
return _address.bytes[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overloaded copy operators to allow initialisation of IPv6Address objects from other types
|
||||||
|
IPv6Address& operator=(const uint8_t *address);
|
||||||
|
|
||||||
|
virtual size_t printTo(Print& p) const;
|
||||||
|
String toString() const;
|
||||||
|
|
||||||
|
friend class UDP;
|
||||||
|
friend class Client;
|
||||||
|
friend class Server;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
117
cores/esp32/MD5Builder.cpp
Normal file
117
cores/esp32/MD5Builder.cpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <MD5Builder.h>
|
||||||
|
|
||||||
|
uint8_t hex_char_to_byte(uint8_t c)
|
||||||
|
{
|
||||||
|
return (c >= 'a' && c <= 'f') ? (c - ((uint8_t)'a' - 0xa)) :
|
||||||
|
(c >= 'A' && c <= 'F') ? (c - ((uint8_t)'A' - 0xA)) :
|
||||||
|
(c >= '0' && c<= '9') ? (c - (uint8_t)'0') : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MD5Builder::begin(void)
|
||||||
|
{
|
||||||
|
memset(_buf, 0x00, 16);
|
||||||
|
MD5Init(&_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MD5Builder::add(uint8_t * data, uint16_t len)
|
||||||
|
{
|
||||||
|
MD5Update(&_ctx, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MD5Builder::addHexString(const char * data)
|
||||||
|
{
|
||||||
|
uint16_t i, len = strlen(data);
|
||||||
|
uint8_t * tmp = (uint8_t*)malloc(len/2);
|
||||||
|
if(tmp == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(i=0; i<len; i+=2) {
|
||||||
|
uint8_t high = hex_char_to_byte(data[i]);
|
||||||
|
uint8_t low = hex_char_to_byte(data[i+1]);
|
||||||
|
tmp[i/2] = (high & 0x0F) << 4 | (low & 0x0F);
|
||||||
|
}
|
||||||
|
add(tmp, len/2);
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MD5Builder::addStream(Stream & stream, const size_t maxLen)
|
||||||
|
{
|
||||||
|
const int buf_size = 512;
|
||||||
|
int maxLengthLeft = maxLen;
|
||||||
|
uint8_t * buf = (uint8_t*) malloc(buf_size);
|
||||||
|
|
||||||
|
if(!buf) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bytesAvailable = stream.available();
|
||||||
|
while((bytesAvailable > 0) && (maxLengthLeft > 0)) {
|
||||||
|
|
||||||
|
// determine number of bytes to read
|
||||||
|
int readBytes = bytesAvailable;
|
||||||
|
if(readBytes > maxLengthLeft) {
|
||||||
|
readBytes = maxLengthLeft ; // read only until max_len
|
||||||
|
}
|
||||||
|
if(readBytes > buf_size) {
|
||||||
|
readBytes = buf_size; // not read more the buffer can handle
|
||||||
|
}
|
||||||
|
|
||||||
|
// read data and check if we got something
|
||||||
|
int numBytesRead = stream.readBytes(buf, readBytes);
|
||||||
|
if(numBytesRead< 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update MD5 with buffer payload
|
||||||
|
MD5Update(&_ctx, buf, numBytesRead);
|
||||||
|
|
||||||
|
// update available number of bytes
|
||||||
|
maxLengthLeft -= numBytesRead;
|
||||||
|
bytesAvailable = stream.available();
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MD5Builder::calculate(void)
|
||||||
|
{
|
||||||
|
MD5Final(_buf, &_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MD5Builder::getBytes(uint8_t * output)
|
||||||
|
{
|
||||||
|
memcpy(output, _buf, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MD5Builder::getChars(char * output)
|
||||||
|
{
|
||||||
|
for(uint8_t i = 0; i < 16; i++) {
|
||||||
|
sprintf(output + (i * 2), "%02x", _buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String MD5Builder::toString(void)
|
||||||
|
{
|
||||||
|
char out[33];
|
||||||
|
getChars(out);
|
||||||
|
return String(out);
|
||||||
|
}
|
77
cores/esp32/MD5Builder.h
Normal file
77
cores/esp32/MD5Builder.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
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 __ESP8266_MD5_BUILDER__
|
||||||
|
#define __ESP8266_MD5_BUILDER__
|
||||||
|
|
||||||
|
#include <WString.h>
|
||||||
|
#include <Stream.h>
|
||||||
|
|
||||||
|
#include "esp_system.h"
|
||||||
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "esp32/rom/md5_hash.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/md5_hash.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/rom/md5_hash.h"
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
|
#include "rom/md5_hash.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class MD5Builder
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct MD5Context _ctx;
|
||||||
|
uint8_t _buf[16];
|
||||||
|
public:
|
||||||
|
void begin(void);
|
||||||
|
void add(uint8_t * data, uint16_t len);
|
||||||
|
void add(const char * data)
|
||||||
|
{
|
||||||
|
add((uint8_t*)data, strlen(data));
|
||||||
|
}
|
||||||
|
void add(char * data)
|
||||||
|
{
|
||||||
|
add((const char*)data);
|
||||||
|
}
|
||||||
|
void add(String data)
|
||||||
|
{
|
||||||
|
add(data.c_str());
|
||||||
|
}
|
||||||
|
void addHexString(const char * data);
|
||||||
|
void addHexString(char * data)
|
||||||
|
{
|
||||||
|
addHexString((const char*)data);
|
||||||
|
}
|
||||||
|
void addHexString(String data)
|
||||||
|
{
|
||||||
|
addHexString(data.c_str());
|
||||||
|
}
|
||||||
|
bool addStream(Stream & stream, const size_t maxLen);
|
||||||
|
void calculate(void);
|
||||||
|
void getBytes(uint8_t * output);
|
||||||
|
void getChars(char * output);
|
||||||
|
String toString(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
374
cores/esp32/Print.cpp
Normal file
374
cores/esp32/Print.cpp
Normal file
@ -0,0 +1,374 @@
|
|||||||
|
/*
|
||||||
|
Print.cpp - Base class that provides print() and println()
|
||||||
|
Copyright (c) 2008 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 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
|
||||||
|
|
||||||
|
Modified 23 November 2006 by David A. Mellis
|
||||||
|
Modified December 2014 by Ivan Grokhotkov
|
||||||
|
Modified May 2015 by Michael C. Miller - ESP31B progmem support
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#include "Print.h"
|
||||||
|
extern "C" {
|
||||||
|
#include "time.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public Methods //////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/* default implementation: may be overridden */
|
||||||
|
size_t Print::write(const uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
while(size--) {
|
||||||
|
n += write(*buffer++);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::printf(const char *format, ...)
|
||||||
|
{
|
||||||
|
char loc_buf[64];
|
||||||
|
char * temp = loc_buf;
|
||||||
|
va_list arg;
|
||||||
|
va_list copy;
|
||||||
|
va_start(arg, format);
|
||||||
|
va_copy(copy, arg);
|
||||||
|
int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
|
||||||
|
va_end(copy);
|
||||||
|
if(len < 0) {
|
||||||
|
va_end(arg);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
if(len >= sizeof(loc_buf)){
|
||||||
|
temp = (char*) malloc(len+1);
|
||||||
|
if(temp == NULL) {
|
||||||
|
va_end(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
len = vsnprintf(temp, len+1, format, arg);
|
||||||
|
}
|
||||||
|
va_end(arg);
|
||||||
|
len = write((uint8_t*)temp, len);
|
||||||
|
if(temp != loc_buf){
|
||||||
|
free(temp);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(const __FlashStringHelper *ifsh)
|
||||||
|
{
|
||||||
|
return print(reinterpret_cast<const char *>(ifsh));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(const String &s)
|
||||||
|
{
|
||||||
|
return write(s.c_str(), s.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(const char str[])
|
||||||
|
{
|
||||||
|
return write(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(char c)
|
||||||
|
{
|
||||||
|
return write(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(unsigned char b, int base)
|
||||||
|
{
|
||||||
|
return print((unsigned long) b, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(int n, int base)
|
||||||
|
{
|
||||||
|
return print((long) n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(unsigned int n, int base)
|
||||||
|
{
|
||||||
|
return print((unsigned long) n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(long n, int base)
|
||||||
|
{
|
||||||
|
int t = 0;
|
||||||
|
if (base == 10 && n < 0) {
|
||||||
|
t = print('-');
|
||||||
|
n = -n;
|
||||||
|
}
|
||||||
|
return printNumber(static_cast<unsigned long>(n), base) + t;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(unsigned long n, int base)
|
||||||
|
{
|
||||||
|
if(base == 0) {
|
||||||
|
return write(n);
|
||||||
|
} else {
|
||||||
|
return printNumber(n, base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(long long n, int base)
|
||||||
|
{
|
||||||
|
int t = 0;
|
||||||
|
if (base == 10 && n < 0) {
|
||||||
|
t = print('-');
|
||||||
|
n = -n;
|
||||||
|
}
|
||||||
|
return printNumber(static_cast<unsigned long long>(n), base) + t;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(unsigned long long n, int base)
|
||||||
|
{
|
||||||
|
if (base == 0) {
|
||||||
|
return write(n);
|
||||||
|
} else {
|
||||||
|
return printNumber(n, base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(double n, int digits)
|
||||||
|
{
|
||||||
|
return printFloat(n, digits);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(const __FlashStringHelper *ifsh)
|
||||||
|
{
|
||||||
|
size_t n = print(ifsh);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(const Printable& x)
|
||||||
|
{
|
||||||
|
return x.printTo(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(struct tm * timeinfo, const char * format)
|
||||||
|
{
|
||||||
|
const char * f = format;
|
||||||
|
if(!f){
|
||||||
|
f = "%c";
|
||||||
|
}
|
||||||
|
char buf[64];
|
||||||
|
size_t written = strftime(buf, 64, f, timeinfo);
|
||||||
|
if(written == 0){
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
return print(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(void)
|
||||||
|
{
|
||||||
|
return print("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(const String &s)
|
||||||
|
{
|
||||||
|
size_t n = print(s);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(const char c[])
|
||||||
|
{
|
||||||
|
size_t n = print(c);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(char c)
|
||||||
|
{
|
||||||
|
size_t n = print(c);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(unsigned char b, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(b, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(int num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(unsigned int num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(long num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(unsigned long num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(long long num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(unsigned long long num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(double num, int digits)
|
||||||
|
{
|
||||||
|
size_t n = print(num, digits);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(const Printable& x)
|
||||||
|
{
|
||||||
|
size_t n = print(x);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(struct tm * timeinfo, const char * format)
|
||||||
|
{
|
||||||
|
size_t n = print(timeinfo, format);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private Methods /////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
size_t Print::printNumber(unsigned long n, uint8_t base)
|
||||||
|
{
|
||||||
|
char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||||
|
char *str = &buf[sizeof(buf) - 1];
|
||||||
|
|
||||||
|
*str = '\0';
|
||||||
|
|
||||||
|
// prevent crash if called with base == 1
|
||||||
|
if(base < 2) {
|
||||||
|
base = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
char c = n % base;
|
||||||
|
n /= base;
|
||||||
|
|
||||||
|
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||||
|
} while (n);
|
||||||
|
|
||||||
|
return write(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::printNumber(unsigned long long n, uint8_t base)
|
||||||
|
{
|
||||||
|
char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||||
|
char* str = &buf[sizeof(buf) - 1];
|
||||||
|
|
||||||
|
*str = '\0';
|
||||||
|
|
||||||
|
// prevent crash if called with base == 1
|
||||||
|
if (base < 2) {
|
||||||
|
base = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
auto m = n;
|
||||||
|
n /= base;
|
||||||
|
char c = m - base * n;
|
||||||
|
|
||||||
|
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||||
|
} while (n);
|
||||||
|
|
||||||
|
return write(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::printFloat(double number, uint8_t digits)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
if(isnan(number)) {
|
||||||
|
return print("nan");
|
||||||
|
}
|
||||||
|
if(isinf(number)) {
|
||||||
|
return print("inf");
|
||||||
|
}
|
||||||
|
if(number > 4294967040.0) {
|
||||||
|
return print("ovf"); // constant determined empirically
|
||||||
|
}
|
||||||
|
if(number < -4294967040.0) {
|
||||||
|
return print("ovf"); // constant determined empirically
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle negative numbers
|
||||||
|
if(number < 0.0) {
|
||||||
|
n += print('-');
|
||||||
|
number = -number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||||
|
double rounding = 0.5;
|
||||||
|
for(uint8_t i = 0; i < digits; ++i) {
|
||||||
|
rounding /= 10.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
number += rounding;
|
||||||
|
|
||||||
|
// Extract the integer part of the number and print it
|
||||||
|
unsigned long int_part = (unsigned long) number;
|
||||||
|
double remainder = number - (double) int_part;
|
||||||
|
n += print(int_part);
|
||||||
|
|
||||||
|
// Print the decimal point, but only if there are digits beyond
|
||||||
|
if(digits > 0) {
|
||||||
|
n += print(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract digits from the remainder one at a time
|
||||||
|
while(digits-- > 0) {
|
||||||
|
remainder *= 10.0;
|
||||||
|
int toPrint = int(remainder);
|
||||||
|
n += print(toPrint);
|
||||||
|
remainder -= toPrint;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
113
cores/esp32/Print.h
Normal file
113
cores/esp32/Print.h
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
Print.h - Base class that provides print() and println()
|
||||||
|
Copyright (c) 2008 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 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 Print_h
|
||||||
|
#define Print_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "WString.h"
|
||||||
|
#include "Printable.h"
|
||||||
|
|
||||||
|
#define DEC 10
|
||||||
|
#define HEX 16
|
||||||
|
#define OCT 8
|
||||||
|
#define BIN 2
|
||||||
|
|
||||||
|
class Print
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int write_error;
|
||||||
|
size_t printNumber(unsigned long, uint8_t);
|
||||||
|
size_t printNumber(unsigned long long, uint8_t);
|
||||||
|
size_t printFloat(double, uint8_t);
|
||||||
|
protected:
|
||||||
|
void setWriteError(int err = 1)
|
||||||
|
{
|
||||||
|
write_error = err;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
Print() :
|
||||||
|
write_error(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual ~Print() {}
|
||||||
|
int getWriteError()
|
||||||
|
{
|
||||||
|
return write_error;
|
||||||
|
}
|
||||||
|
void clearWriteError()
|
||||||
|
{
|
||||||
|
setWriteError(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t write(uint8_t) = 0;
|
||||||
|
size_t write(const char *str)
|
||||||
|
{
|
||||||
|
if(str == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return write((const uint8_t *) str, strlen(str));
|
||||||
|
}
|
||||||
|
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||||
|
size_t write(const char *buffer, size_t size)
|
||||||
|
{
|
||||||
|
return write((const uint8_t *) buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
|
|
||||||
|
// add availableForWrite to make compatible with Arduino Print.h
|
||||||
|
// default to zero, meaning "a single write may block"
|
||||||
|
// should be overriden by subclasses with buffering
|
||||||
|
virtual int availableForWrite() { return 0; }
|
||||||
|
size_t print(const __FlashStringHelper *);
|
||||||
|
size_t print(const String &);
|
||||||
|
size_t print(const char[]);
|
||||||
|
size_t print(char);
|
||||||
|
size_t print(unsigned char, int = DEC);
|
||||||
|
size_t print(int, int = DEC);
|
||||||
|
size_t print(unsigned int, int = DEC);
|
||||||
|
size_t print(long, int = DEC);
|
||||||
|
size_t print(unsigned long, int = DEC);
|
||||||
|
size_t print(long long, int = DEC);
|
||||||
|
size_t print(unsigned long long, int = DEC);
|
||||||
|
size_t print(double, int = 2);
|
||||||
|
size_t print(const Printable&);
|
||||||
|
size_t print(struct tm * timeinfo, const char * format = NULL);
|
||||||
|
|
||||||
|
size_t println(const __FlashStringHelper *);
|
||||||
|
size_t println(const String &s);
|
||||||
|
size_t println(const char[]);
|
||||||
|
size_t println(char);
|
||||||
|
size_t println(unsigned char, int = DEC);
|
||||||
|
size_t println(int, int = DEC);
|
||||||
|
size_t println(unsigned int, int = DEC);
|
||||||
|
size_t println(long, int = DEC);
|
||||||
|
size_t println(unsigned long, int = DEC);
|
||||||
|
size_t println(long long, int = DEC);
|
||||||
|
size_t println(unsigned long long, int = DEC);
|
||||||
|
size_t println(double, int = 2);
|
||||||
|
size_t println(const Printable&);
|
||||||
|
size_t println(struct tm * timeinfo, const char * format = NULL);
|
||||||
|
size_t println(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
41
cores/esp32/Printable.h
Normal file
41
cores/esp32/Printable.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
Printable.h - Interface class that allows printing of complex types
|
||||||
|
Copyright (c) 2011 Adrian McEwen. 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 Printable_h
|
||||||
|
#define Printable_h
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
class Print;
|
||||||
|
|
||||||
|
/** The Printable class provides a way for new classes to allow themselves to be printed.
|
||||||
|
By deriving from Printable and implementing the printTo method, it will then be possible
|
||||||
|
for users to print out instances of this class by passing them into the usual
|
||||||
|
Print::print and Print::println methods.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Printable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Printable() {}
|
||||||
|
virtual size_t printTo(Print& p) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
31
cores/esp32/Server.h
Normal file
31
cores/esp32/Server.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
Server.h - Base class that provides Server
|
||||||
|
Copyright (c) 2011 Adrian McEwen. 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 server_h
|
||||||
|
#define server_h
|
||||||
|
|
||||||
|
#include "Print.h"
|
||||||
|
|
||||||
|
class Server: public Print
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void begin(uint16_t port=0) =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
337
cores/esp32/Stream.cpp
Normal file
337
cores/esp32/Stream.cpp
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
/*
|
||||||
|
Stream.cpp - adds parsing methods to Stream class
|
||||||
|
Copyright (c) 2008 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 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
|
||||||
|
|
||||||
|
Created July 2011
|
||||||
|
parsing functions based on TextFinder library by Michael Margolis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
_startMillis = millis();
|
||||||
|
do {
|
||||||
|
c = read();
|
||||||
|
if(c >= 0) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
} while(millis() - _startMillis < _timeout);
|
||||||
|
return -1; // -1 indicates timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
// private method to peek stream with timeout
|
||||||
|
int Stream::timedPeek()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
_startMillis = millis();
|
||||||
|
do {
|
||||||
|
c = peek();
|
||||||
|
if(c >= 0) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
} while(millis() - _startMillis < _timeout);
|
||||||
|
return -1; // -1 indicates timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns peek of the next digit in the stream or -1 if timeout
|
||||||
|
// discards non-numeric characters
|
||||||
|
int Stream::peekNextDigit()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
while(1) {
|
||||||
|
c = timedPeek();
|
||||||
|
if(c < 0) {
|
||||||
|
return c; // timeout
|
||||||
|
}
|
||||||
|
if(c == '-') {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
if(c >= '0' && c <= '9') {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
read(); // discard non-numeric
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public Methods
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
|
||||||
|
{
|
||||||
|
_timeout = timeout;
|
||||||
|
}
|
||||||
|
unsigned long Stream::getTimeout(void) {
|
||||||
|
return _timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find returns true if the target string is found
|
||||||
|
bool Stream::find(const char *target)
|
||||||
|
{
|
||||||
|
return findUntil(target, strlen(target), NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads data from the stream until the target string of given length is found
|
||||||
|
// returns true if target string is found, false if timed out
|
||||||
|
bool Stream::find(const char *target, size_t length)
|
||||||
|
{
|
||||||
|
return findUntil(target, length, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// as find but search ends if the terminator string is found
|
||||||
|
bool Stream::findUntil(const char *target, const char *terminator)
|
||||||
|
{
|
||||||
|
return findUntil(target, strlen(target), terminator, strlen(terminator));
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads data from the stream until the target string of the given length is found
|
||||||
|
// search terminated if the terminator string is found
|
||||||
|
// returns true if target string is found, false if terminated or timed out
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
|
||||||
|
return findMulti(t, 2) == 0 ? true : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
long value = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
c = peekNextDigit();
|
||||||
|
// ignore non numeric leading characters
|
||||||
|
if(c < 0) {
|
||||||
|
return 0; // zero returned if timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(c == skipChar) {
|
||||||
|
} // ignore this charactor
|
||||||
|
else if(c == '-') {
|
||||||
|
isNegative = true;
|
||||||
|
} else if(c >= '0' && c <= '9') { // is c a digit?
|
||||||
|
value = value * 10 + c - '0';
|
||||||
|
}
|
||||||
|
read(); // consume the character we got with peek
|
||||||
|
c = timedPeek();
|
||||||
|
} while((c >= '0' && c <= '9') || c == skipChar);
|
||||||
|
|
||||||
|
if(isNegative) {
|
||||||
|
value = -value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
int c;
|
||||||
|
float fraction = 1.0;
|
||||||
|
|
||||||
|
c = peekNextDigit();
|
||||||
|
// ignore non numeric leading characters
|
||||||
|
if(c < 0) {
|
||||||
|
return 0; // zero returned if timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(c == skipChar) {
|
||||||
|
} // 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.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
read(); // consume the character we got with peek
|
||||||
|
c = timedPeek();
|
||||||
|
} while((c >= '0' && c <= '9') || c == '.' || c == skipChar);
|
||||||
|
|
||||||
|
if(isNegative) {
|
||||||
|
value = -value;
|
||||||
|
}
|
||||||
|
if(isFraction) {
|
||||||
|
return value * fraction;
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read characters from stream into buffer
|
||||||
|
// terminates if length characters have been read, or timeout (see setTimeout)
|
||||||
|
// returns the number of characters placed in the buffer
|
||||||
|
// the buffer is NOT null terminated.
|
||||||
|
//
|
||||||
|
size_t Stream::readBytes(char *buffer, size_t length)
|
||||||
|
{
|
||||||
|
size_t count = 0;
|
||||||
|
while(count < length) {
|
||||||
|
int c = timedRead();
|
||||||
|
if(c < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*buffer++ = (char) c;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// as readBytes with terminator character
|
||||||
|
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||||
|
// 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) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*buffer++ = (char) c;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return index; // return number of characters, not including null terminator
|
||||||
|
}
|
||||||
|
|
||||||
|
String Stream::readString()
|
||||||
|
{
|
||||||
|
String ret;
|
||||||
|
int c = timedRead();
|
||||||
|
while(c >= 0) {
|
||||||
|
ret += (char) c;
|
||||||
|
c = timedRead();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
String Stream::readStringUntil(char terminator)
|
||||||
|
{
|
||||||
|
String ret;
|
||||||
|
int c = timedRead();
|
||||||
|
while(c >= 0 && c != terminator) {
|
||||||
|
ret += (char) c;
|
||||||
|
c = timedRead();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
140
cores/esp32/Stream.h
Normal file
140
cores/esp32/Stream.h
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
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 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
|
||||||
|
|
||||||
|
parsing functions based on TextFinder library by Michael Margolis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Stream_h
|
||||||
|
#define Stream_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "Print.h"
|
||||||
|
|
||||||
|
// compatability 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)
|
||||||
|
*/
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual int available() = 0;
|
||||||
|
virtual int read() = 0;
|
||||||
|
virtual int peek() = 0;
|
||||||
|
virtual void flush() = 0;
|
||||||
|
|
||||||
|
Stream():_startMillis(0)
|
||||||
|
{
|
||||||
|
_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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
// returns true if target string is found, false if timed out
|
||||||
|
|
||||||
|
bool find(char target)
|
||||||
|
{
|
||||||
|
return find (&target, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
float parseFloat(); // 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)
|
||||||
|
{
|
||||||
|
return readBytes((char *) buffer, length);
|
||||||
|
}
|
||||||
|
// terminates if length characters have been read or timeout (see setTimeout)
|
||||||
|
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||||
|
|
||||||
|
size_t readBytesUntil(char terminator, char *buffer, size_t length); // as readBytes with terminator character
|
||||||
|
size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length)
|
||||||
|
{
|
||||||
|
return readBytesUntil(terminator, (char *) buffer, length);
|
||||||
|
}
|
||||||
|
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||||
|
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||||
|
|
||||||
|
// Arduino String functions to be added here
|
||||||
|
virtual String readString();
|
||||||
|
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
|
||||||
|
|
||||||
|
struct MultiTarget {
|
||||||
|
const char *str; // string you're searching for
|
||||||
|
size_t len; // length of string you're searching for
|
||||||
|
size_t index; // index used by the search routine.
|
||||||
|
};
|
||||||
|
|
||||||
|
// This allows you to search for an arbitrary number of strings.
|
||||||
|
// Returns index of the target that is found first or -1 if timeout occurs.
|
||||||
|
int findMulti(struct MultiTarget *targets, int tCount);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
67
cores/esp32/StreamString.cpp
Normal file
67
cores/esp32/StreamString.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
StreamString.cpp
|
||||||
|
|
||||||
|
Copyright (c) 2015 Markus Sattler. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "StreamString.h"
|
||||||
|
|
||||||
|
size_t StreamString::write(const uint8_t *data, size_t size) {
|
||||||
|
if(size && data) {
|
||||||
|
const unsigned int newlen = length() + size;
|
||||||
|
if(reserve(newlen + 1)) {
|
||||||
|
memcpy((void *) (wbuffer() + len()), (const void *) data, size);
|
||||||
|
setLen(newlen);
|
||||||
|
*(wbuffer() + newlen) = 0x00; // add null for string end
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t StreamString::write(uint8_t data) {
|
||||||
|
return concat((char) data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StreamString::available() {
|
||||||
|
return length();
|
||||||
|
}
|
||||||
|
|
||||||
|
int StreamString::read() {
|
||||||
|
if(length()) {
|
||||||
|
char c = charAt(0);
|
||||||
|
remove(0, 1);
|
||||||
|
return c;
|
||||||
|
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StreamString::peek() {
|
||||||
|
if(length()) {
|
||||||
|
char c = charAt(0);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamString::flush() {
|
||||||
|
}
|
||||||
|
|
39
cores/esp32/StreamString.h
Normal file
39
cores/esp32/StreamString.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
StreamString.h
|
||||||
|
|
||||||
|
Copyright (c) 2015 Markus Sattler. All rights 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 STREAMSTRING_H_
|
||||||
|
#define STREAMSTRING_H_
|
||||||
|
|
||||||
|
|
||||||
|
class StreamString: public Stream, public String
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
size_t write(const uint8_t *buffer, size_t size) override;
|
||||||
|
size_t write(uint8_t data) override;
|
||||||
|
|
||||||
|
int available() override;
|
||||||
|
int read() override;
|
||||||
|
int peek() override;
|
||||||
|
void flush() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* STREAMSTRING_H_ */
|
@ -14,7 +14,7 @@
|
|||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
#include "esp32-hal-tinyusb.h"
|
#include "esp32-hal-tinyusb.h"
|
||||||
#include "USB.h"
|
#include "USB.h"
|
||||||
#if CONFIG_USB_ENABLED
|
#if CONFIG_TINYUSB_ENABLED
|
||||||
|
|
||||||
#ifndef USB_VID
|
#ifndef USB_VID
|
||||||
#define USB_VID USB_ESPRESSIF_VID
|
#define USB_VID USB_ESPRESSIF_VID
|
||||||
@ -32,11 +32,7 @@
|
|||||||
#define USB_SERIAL "0"
|
#define USB_SERIAL "0"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
#if CFG_TUD_DFU_RUNTIME
|
||||||
#include "tinyusb.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CFG_TUD_DFU_RT
|
|
||||||
static uint16_t load_dfu_descriptor(uint8_t * dst, uint8_t * itf)
|
static uint16_t load_dfu_descriptor(uint8_t * dst, uint8_t * itf)
|
||||||
{
|
{
|
||||||
#define DFU_ATTR_CAN_DOWNLOAD 1
|
#define DFU_ATTR_CAN_DOWNLOAD 1
|
||||||
@ -59,7 +55,7 @@ void tud_dfu_rt_reboot_to_dfu(void)
|
|||||||
{
|
{
|
||||||
usb_persist_restart(RESTART_BOOTLOADER_DFU);
|
usb_persist_restart(RESTART_BOOTLOADER_DFU);
|
||||||
}
|
}
|
||||||
#endif /* CFG_TUD_DFU_RT */
|
#endif /* CFG_TUD_DFU_RUNTIME */
|
||||||
|
|
||||||
ESP_EVENT_DEFINE_BASE(ARDUINO_USB_EVENTS);
|
ESP_EVENT_DEFINE_BASE(ARDUINO_USB_EVENTS);
|
||||||
|
|
||||||
@ -187,9 +183,9 @@ ESPUSB::operator bool() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ESPUSB::enableDFU(){
|
bool ESPUSB::enableDFU(){
|
||||||
#if CFG_TUD_DFU_RT
|
#if CFG_TUD_DFU_RUNTIME
|
||||||
return tinyusb_enable_interface(USB_INTERFACE_DFU, TUD_DFU_RT_DESC_LEN, load_dfu_descriptor) == ESP_OK;
|
return tinyusb_enable_interface(USB_INTERFACE_DFU, TUD_DFU_RT_DESC_LEN, load_dfu_descriptor) == ESP_OK;
|
||||||
#endif /* CFG_TUD_DFU_RT */
|
#endif /* CFG_TUD_DFU_RUNTIME */
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,4 +331,4 @@ const char * ESPUSB::webUSBURL(void){
|
|||||||
|
|
||||||
ESPUSB USB;
|
ESPUSB USB;
|
||||||
|
|
||||||
#endif /* CONFIG_USB_ENABLED */
|
#endif /* CONFIG_TINYUSB_ENABLED */
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if CONFIG_USB_ENABLED
|
#if CONFIG_TINYUSB_ENABLED
|
||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "USBCDC.h"
|
#include "USBCDC.h"
|
||||||
@ -115,4 +115,4 @@ class ESPUSB {
|
|||||||
|
|
||||||
extern ESPUSB USB;
|
extern ESPUSB USB;
|
||||||
|
|
||||||
#endif /* CONFIG_USB_ENABLED */
|
#endif /* CONFIG_TINYUSB_ENABLED */
|
||||||
|
@ -15,16 +15,12 @@
|
|||||||
#include "esp32-hal-tinyusb.h"
|
#include "esp32-hal-tinyusb.h"
|
||||||
#include "USB.h"
|
#include "USB.h"
|
||||||
#include "USBCDC.h"
|
#include "USBCDC.h"
|
||||||
#if CONFIG_USB_ENABLED
|
#if CONFIG_TINYUSB_ENABLED
|
||||||
|
|
||||||
ESP_EVENT_DEFINE_BASE(ARDUINO_USB_CDC_EVENTS);
|
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_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);
|
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);
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "tinyusb.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CFG_TUD_CDC
|
#if CFG_TUD_CDC
|
||||||
#define MAX_USB_CDC_DEVICES 2
|
#define MAX_USB_CDC_DEVICES 2
|
||||||
USBCDC * devices[MAX_USB_CDC_DEVICES] = {NULL, NULL};
|
USBCDC * devices[MAX_USB_CDC_DEVICES] = {NULL, NULL};
|
||||||
@ -75,7 +71,7 @@ static size_t tinyusb_cdc_write(uint8_t itf, const uint8_t *buffer, size_t size)
|
|||||||
while(tosend){
|
while(tosend){
|
||||||
uint32_t space = tud_cdc_n_write_available(itf);
|
uint32_t space = tud_cdc_n_write_available(itf);
|
||||||
if(!space){
|
if(!space){
|
||||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
delay(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(tosend < space){
|
if(tosend < space){
|
||||||
@ -202,6 +198,9 @@ void USBCDC::_onLineState(bool _dtr, bool _rts){
|
|||||||
|
|
||||||
void USBCDC::_onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _parity, uint8_t _data_bits){
|
void USBCDC::_onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _parity, uint8_t _data_bits){
|
||||||
if(bit_rate != _bit_rate || data_bits != _data_bits || stop_bits != _stop_bits || parity != _parity){
|
if(bit_rate != _bit_rate || data_bits != _data_bits || stop_bits != _stop_bits || parity != _parity){
|
||||||
|
if(bit_rate == 9600 && _bit_rate == 1200){
|
||||||
|
usb_persist_restart(RESTART_BOOTLOADER);
|
||||||
|
} else {
|
||||||
bit_rate = _bit_rate;
|
bit_rate = _bit_rate;
|
||||||
data_bits = _data_bits;
|
data_bits = _data_bits;
|
||||||
stop_bits = _stop_bits;
|
stop_bits = _stop_bits;
|
||||||
@ -213,11 +212,12 @@ void USBCDC::_onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _pari
|
|||||||
p.line_coding.parity = parity;
|
p.line_coding.parity = parity;
|
||||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_LINE_CODING_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_LINE_CODING_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void USBCDC::_onRX(){
|
void USBCDC::_onRX(){
|
||||||
uint8_t buf[CONFIG_USB_CDC_RX_BUFSIZE+1];
|
uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE+1];
|
||||||
uint32_t count = tud_cdc_n_read(itf, buf, CONFIG_USB_CDC_RX_BUFSIZE);
|
uint32_t count = tud_cdc_n_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE);
|
||||||
for(uint32_t i=0; i<count; i++){
|
for(uint32_t i=0; i<count; i++){
|
||||||
if(rx_queue == NULL || !xQueueSend(rx_queue, buf+i, 0)){
|
if(rx_queue == NULL || !xQueueSend(rx_queue, buf+i, 0)){
|
||||||
return;
|
return;
|
||||||
@ -333,6 +333,6 @@ USBCDC::operator bool() const
|
|||||||
USBCDC Serial(0);
|
USBCDC Serial(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* CONFIG_USB_CDC_ENABLED */
|
#endif /* CONFIG_TINYUSB_CDC_ENABLED */
|
||||||
|
|
||||||
#endif /* CONFIG_USB_ENABLED */
|
#endif /* CONFIG_TINYUSB_ENABLED */
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "Stream.h"
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
#if CONFIG_USB_CDC_ENABLED
|
#if CONFIG_TINYUSB_CDC_ENABLED
|
||||||
|
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ typedef union {
|
|||||||
} rx;
|
} rx;
|
||||||
} arduino_usb_cdc_event_data_t;
|
} arduino_usb_cdc_event_data_t;
|
||||||
|
|
||||||
class USBCDC
|
class USBCDC: public Stream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
USBCDC(uint8_t itf=0);
|
USBCDC(uint8_t itf=0);
|
||||||
@ -129,4 +130,4 @@ protected:
|
|||||||
extern USBCDC Serial;
|
extern USBCDC Serial;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* CONFIG_USB_CDC_ENABLED */
|
#endif /* CONFIG_TINYUSB_CDC_ENABLED */
|
||||||
|
93
cores/esp32/Udp.h
Normal file
93
cores/esp32/Udp.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Udp.cpp: Library to send/receive UDP packets.
|
||||||
|
*
|
||||||
|
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
|
||||||
|
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
|
||||||
|
* might not happen often in practice, but in larger network topologies, a UDP
|
||||||
|
* packet can be received out of sequence.
|
||||||
|
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
|
||||||
|
* aware of it. Again, this may not be a concern in practice on small local networks.
|
||||||
|
* For more information, see http://www.cafeaulait.org/course/week12/35.html
|
||||||
|
*
|
||||||
|
* MIT License:
|
||||||
|
* Copyright (c) 2008 Bjoern Hartmann
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* bjoern@cs.stanford.edu 12/30/2008
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef udp_h
|
||||||
|
#define udp_h
|
||||||
|
|
||||||
|
#include <Stream.h>
|
||||||
|
#include <IPAddress.h>
|
||||||
|
|
||||||
|
class UDP: public Stream
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
|
||||||
|
virtual uint8_t beginMulticast(IPAddress, uint16_t) { return 0; } // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 on failure
|
||||||
|
virtual void stop() =0; // Finish with the UDP socket
|
||||||
|
|
||||||
|
// Sending UDP packets
|
||||||
|
|
||||||
|
// Start building up a packet to send to the remote host specific in ip and port
|
||||||
|
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||||
|
virtual int beginPacket(IPAddress ip, uint16_t port) =0;
|
||||||
|
// Start building up a packet to send to the remote host specific in host and port
|
||||||
|
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
|
||||||
|
virtual int beginPacket(const char *host, uint16_t port) =0;
|
||||||
|
// Finish off this packet and send it
|
||||||
|
// Returns 1 if the packet was sent successfully, 0 if there was an error
|
||||||
|
virtual int endPacket() =0;
|
||||||
|
// Write a single byte into the packet
|
||||||
|
virtual size_t write(uint8_t) =0;
|
||||||
|
// Write size bytes from buffer into the packet
|
||||||
|
virtual size_t write(const uint8_t *buffer, size_t size) =0;
|
||||||
|
|
||||||
|
// Start processing the next available incoming packet
|
||||||
|
// Returns the size of the packet in bytes, or 0 if no packets are available
|
||||||
|
virtual int parsePacket() =0;
|
||||||
|
// Number of bytes remaining in the current packet
|
||||||
|
virtual int available() =0;
|
||||||
|
// Read a single byte from the current packet
|
||||||
|
virtual int read() =0;
|
||||||
|
// Read up to len bytes from the current packet and place them into buffer
|
||||||
|
// Returns the number of bytes read, or 0 if none are available
|
||||||
|
virtual int read(unsigned char* buffer, size_t len) =0;
|
||||||
|
// Read up to len characters from the current packet and place them into buffer
|
||||||
|
// Returns the number of characters read, or 0 if none are available
|
||||||
|
virtual int read(char* buffer, size_t len) =0;
|
||||||
|
// Return the next byte from the current packet without moving on to the next byte
|
||||||
|
virtual int peek() =0;
|
||||||
|
virtual void flush() =0; // Finish reading the current packet
|
||||||
|
|
||||||
|
// Return the IP address of the host who sent the current incoming packet
|
||||||
|
virtual IPAddress remoteIP() =0;
|
||||||
|
// Return the port of the host who sent the current incoming packet
|
||||||
|
virtual uint16_t remotePort() =0;
|
||||||
|
protected:
|
||||||
|
uint8_t* rawIPAddress(IPAddress& addr)
|
||||||
|
{
|
||||||
|
return addr.raw_address();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -25,83 +25,83 @@
|
|||||||
#define toascii(__c) ((__c)&0177)
|
#define toascii(__c) ((__c)&0177)
|
||||||
|
|
||||||
// WCharacter.h prototypes
|
// WCharacter.h prototypes
|
||||||
inline bool isAlphaNumeric(int c) __attribute__((always_inline));
|
inline boolean isAlphaNumeric(int c) __attribute__((always_inline));
|
||||||
inline bool isAlpha(int c) __attribute__((always_inline));
|
inline boolean isAlpha(int c) __attribute__((always_inline));
|
||||||
inline bool isAscii(int c) __attribute__((always_inline));
|
inline boolean isAscii(int c) __attribute__((always_inline));
|
||||||
inline bool isWhitespace(int c) __attribute__((always_inline));
|
inline boolean isWhitespace(int c) __attribute__((always_inline));
|
||||||
inline bool isControl(int c) __attribute__((always_inline));
|
inline boolean isControl(int c) __attribute__((always_inline));
|
||||||
inline bool isDigit(int c) __attribute__((always_inline));
|
inline boolean isDigit(int c) __attribute__((always_inline));
|
||||||
inline bool isGraph(int c) __attribute__((always_inline));
|
inline boolean isGraph(int c) __attribute__((always_inline));
|
||||||
inline bool isLowerCase(int c) __attribute__((always_inline));
|
inline boolean isLowerCase(int c) __attribute__((always_inline));
|
||||||
inline bool isPrintable(int c) __attribute__((always_inline));
|
inline boolean isPrintable(int c) __attribute__((always_inline));
|
||||||
inline bool isPunct(int c) __attribute__((always_inline));
|
inline boolean isPunct(int c) __attribute__((always_inline));
|
||||||
inline bool isSpace(int c) __attribute__((always_inline));
|
inline boolean isSpace(int c) __attribute__((always_inline));
|
||||||
inline bool isUpperCase(int c) __attribute__((always_inline));
|
inline boolean isUpperCase(int c) __attribute__((always_inline));
|
||||||
inline bool isHexadecimalDigit(int c) __attribute__((always_inline));
|
inline boolean isHexadecimalDigit(int c) __attribute__((always_inline));
|
||||||
inline int toAscii(int c) __attribute__((always_inline));
|
inline int toAscii(int c) __attribute__((always_inline));
|
||||||
inline int toLowerCase(int c) __attribute__((always_inline));
|
inline int toLowerCase(int c) __attribute__((always_inline));
|
||||||
inline int toUpperCase(int c) __attribute__((always_inline));
|
inline int toUpperCase(int c) __attribute__((always_inline));
|
||||||
|
|
||||||
// Checks for an alphanumeric character.
|
// Checks for an alphanumeric character.
|
||||||
// It is equivalent to (isalpha(c) || isdigit(c)).
|
// It is equivalent to (isalpha(c) || isdigit(c)).
|
||||||
inline bool isAlphaNumeric(int c)
|
inline boolean isAlphaNumeric(int c)
|
||||||
{
|
{
|
||||||
return (isalnum(c) == 0 ? false : true);
|
return (isalnum(c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks for an alphabetic character.
|
// Checks for an alphabetic character.
|
||||||
// It is equivalent to (isupper(c) || islower(c)).
|
// It is equivalent to (isupper(c) || islower(c)).
|
||||||
inline bool isAlpha(int c)
|
inline boolean isAlpha(int c)
|
||||||
{
|
{
|
||||||
return (isalpha(c) == 0 ? false : true);
|
return (isalpha(c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks whether c is a 7-bit unsigned char value
|
// Checks whether c is a 7-bit unsigned char value
|
||||||
// that fits into the ASCII character set.
|
// that fits into the ASCII character set.
|
||||||
inline bool isAscii(int c)
|
inline boolean isAscii(int c)
|
||||||
{
|
{
|
||||||
return ( isascii (c) == 0 ? false : true);
|
return ( isascii (c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks for a blank character, that is, a space or a tab.
|
// Checks for a blank character, that is, a space or a tab.
|
||||||
inline bool isWhitespace(int c)
|
inline boolean isWhitespace(int c)
|
||||||
{
|
{
|
||||||
return (isblank(c) == 0 ? false : true);
|
return (isblank(c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks for a control character.
|
// Checks for a control character.
|
||||||
inline bool isControl(int c)
|
inline boolean isControl(int c)
|
||||||
{
|
{
|
||||||
return (iscntrl(c) == 0 ? false : true);
|
return (iscntrl(c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks for a digit (0 through 9).
|
// Checks for a digit (0 through 9).
|
||||||
inline bool isDigit(int c)
|
inline boolean isDigit(int c)
|
||||||
{
|
{
|
||||||
return (isdigit(c) == 0 ? false : true);
|
return (isdigit(c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks for any printable character except space.
|
// Checks for any printable character except space.
|
||||||
inline bool isGraph(int c)
|
inline boolean isGraph(int c)
|
||||||
{
|
{
|
||||||
return (isgraph(c) == 0 ? false : true);
|
return (isgraph(c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks for a lower-case character.
|
// Checks for a lower-case character.
|
||||||
inline bool isLowerCase(int c)
|
inline boolean isLowerCase(int c)
|
||||||
{
|
{
|
||||||
return (islower(c) == 0 ? false : true);
|
return (islower(c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks for any printable character including space.
|
// Checks for any printable character including space.
|
||||||
inline bool isPrintable(int c)
|
inline boolean isPrintable(int c)
|
||||||
{
|
{
|
||||||
return (isprint(c) == 0 ? false : true);
|
return (isprint(c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks for any printable character which is not a space
|
// Checks for any printable character which is not a space
|
||||||
// or an alphanumeric character.
|
// or an alphanumeric character.
|
||||||
inline bool isPunct(int c)
|
inline boolean isPunct(int c)
|
||||||
{
|
{
|
||||||
return (ispunct(c) == 0 ? false : true);
|
return (ispunct(c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
@ -109,20 +109,20 @@ inline bool isPunct(int c)
|
|||||||
// Checks for white-space characters. For the avr-libc library,
|
// Checks for white-space characters. For the avr-libc library,
|
||||||
// these are: space, formfeed ('\f'), newline ('\n'), carriage
|
// these are: space, formfeed ('\f'), newline ('\n'), carriage
|
||||||
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
|
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
|
||||||
inline bool isSpace(int c)
|
inline boolean isSpace(int c)
|
||||||
{
|
{
|
||||||
return (isspace(c) == 0 ? false : true);
|
return (isspace(c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks for an uppercase letter.
|
// Checks for an uppercase letter.
|
||||||
inline bool isUpperCase(int c)
|
inline boolean isUpperCase(int c)
|
||||||
{
|
{
|
||||||
return (isupper(c) == 0 ? false : true);
|
return (isupper(c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
|
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
|
||||||
// 8 9 a b c d e f A B C D E F.
|
// 8 9 a b c d e f A B C D E F.
|
||||||
inline bool isHexadecimalDigit(int c)
|
inline boolean isHexadecimalDigit(int c)
|
||||||
{
|
{
|
||||||
return (isxdigit(c) == 0 ? false : true);
|
return (isxdigit(c) == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
@ -24,23 +24,65 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
#include <stdlib.h>
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
}
|
}
|
||||||
|
#include "esp32-hal-log.h"
|
||||||
|
|
||||||
//long map(long x, long in_min, long in_max, long out_min, long out_max) {
|
void randomSeed(unsigned long seed)
|
||||||
// const long dividend = out_max - out_min;
|
{
|
||||||
// const long divisor = in_max - in_min;
|
if(seed != 0) {
|
||||||
// const long delta = x - in_min;
|
srand(seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// return (delta * dividend + (divisor / 2)) / divisor + out_min;
|
long random(long howbig)
|
||||||
//}
|
{
|
||||||
|
uint32_t x = esp_random();
|
||||||
|
uint64_t m = uint64_t(x) * uint64_t(howbig);
|
||||||
|
uint32_t l = uint32_t(m);
|
||||||
|
if (l < howbig) {
|
||||||
|
uint32_t t = -howbig;
|
||||||
|
if (t >= howbig) {
|
||||||
|
t -= howbig;
|
||||||
|
if (t >= howbig)
|
||||||
|
t %= howbig;
|
||||||
|
}
|
||||||
|
while (l < t) {
|
||||||
|
x = esp_random();
|
||||||
|
m = uint64_t(x) * uint64_t(howbig);
|
||||||
|
l = uint32_t(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m >> 32;
|
||||||
|
}
|
||||||
|
|
||||||
//unsigned int makeWord(unsigned int w)
|
long random(long howsmall, long howbig)
|
||||||
//{
|
{
|
||||||
// return w;
|
if(howsmall >= howbig) {
|
||||||
//}
|
return howsmall;
|
||||||
|
}
|
||||||
|
long diff = howbig - howsmall;
|
||||||
|
return random(diff) + howsmall;
|
||||||
|
}
|
||||||
|
|
||||||
//unsigned int makeWord(unsigned char h, unsigned char l)
|
long map(long x, long in_min, long in_max, long out_min, long out_max) {
|
||||||
//{
|
const long dividend = out_max - out_min;
|
||||||
// return (h << 8) | l;
|
const long divisor = in_max - in_min;
|
||||||
//}
|
const long delta = x - in_min;
|
||||||
|
if(divisor == 0){
|
||||||
|
log_e("Invalid map input range, min == max");
|
||||||
|
return -1; //AVR returns -1, SAM returns 0
|
||||||
|
}
|
||||||
|
return (delta * dividend + (divisor / 2)) / divisor + out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int makeWord(unsigned int w)
|
||||||
|
{
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int makeWord(unsigned char h, unsigned char l)
|
||||||
|
{
|
||||||
|
return (h << 8) | l;
|
||||||
|
}
|
||||||
|
863
cores/esp32/WString.cpp
Normal file
863
cores/esp32/WString.cpp
Normal file
@ -0,0 +1,863 @@
|
|||||||
|
/*
|
||||||
|
WString.cpp - String library for Wiring & Arduino
|
||||||
|
...mostly rewritten by Paul Stoffregen...
|
||||||
|
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
|
||||||
|
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||||
|
Modified by Ivan Grokhotkov, 2014 - esp8266 support
|
||||||
|
Modified by Michael C. Miller, 2015 - esp8266 progmem support
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "WString.h"
|
||||||
|
#include "stdlib_noniso.h"
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Constructors */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
String::String(const char *cstr) {
|
||||||
|
init();
|
||||||
|
if (cstr)
|
||||||
|
copy(cstr, strlen(cstr));
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(const String &value) {
|
||||||
|
init();
|
||||||
|
*this = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(const __FlashStringHelper *pstr) {
|
||||||
|
init();
|
||||||
|
*this = pstr; // see operator =
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
String::String(String &&rval) {
|
||||||
|
init();
|
||||||
|
move(rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(StringSumHelper &&rval) {
|
||||||
|
init();
|
||||||
|
move(rval);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String::String(char c) {
|
||||||
|
init();
|
||||||
|
char buf[2];
|
||||||
|
buf[0] = c;
|
||||||
|
buf[1] = 0;
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(unsigned char value, unsigned char base) {
|
||||||
|
init();
|
||||||
|
char buf[1 + 8 * sizeof(unsigned char)];
|
||||||
|
utoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(int value, unsigned char base) {
|
||||||
|
init();
|
||||||
|
char buf[2 + 8 * sizeof(int)];
|
||||||
|
if (base == 10) {
|
||||||
|
sprintf(buf, "%d", value);
|
||||||
|
} else {
|
||||||
|
itoa(value, buf, base);
|
||||||
|
}
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(unsigned int value, unsigned char base) {
|
||||||
|
init();
|
||||||
|
char buf[1 + 8 * sizeof(unsigned int)];
|
||||||
|
utoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(long value, unsigned char base) {
|
||||||
|
init();
|
||||||
|
char buf[2 + 8 * sizeof(long)];
|
||||||
|
if (base==10) {
|
||||||
|
sprintf(buf, "%ld", value);
|
||||||
|
} else {
|
||||||
|
ltoa(value, buf, base);
|
||||||
|
}
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(unsigned long value, unsigned char base) {
|
||||||
|
init();
|
||||||
|
char buf[1 + 8 * sizeof(unsigned long)];
|
||||||
|
ultoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(float value, unsigned char decimalPlaces) {
|
||||||
|
init();
|
||||||
|
char buf[33];
|
||||||
|
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(double value, unsigned char decimalPlaces) {
|
||||||
|
init();
|
||||||
|
char buf[33];
|
||||||
|
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
String::~String() {
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// /*********************************************/
|
||||||
|
// /* Memory Management */
|
||||||
|
// /*********************************************/
|
||||||
|
|
||||||
|
inline void String::init(void) {
|
||||||
|
setSSO(false);
|
||||||
|
setBuffer(nullptr);
|
||||||
|
setCapacity(0);
|
||||||
|
setLen(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::invalidate(void) {
|
||||||
|
if(!isSSO() && wbuffer())
|
||||||
|
free(wbuffer());
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::reserve(unsigned int size) {
|
||||||
|
if(buffer() && capacity() >= size)
|
||||||
|
return 1;
|
||||||
|
if(changeBuffer(size)) {
|
||||||
|
if(len() == 0)
|
||||||
|
wbuffer()[0] = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::changeBuffer(unsigned int maxStrLen) {
|
||||||
|
// Can we use SSO here to avoid allocation?
|
||||||
|
if (maxStrLen < sizeof(sso.buff) - 1) {
|
||||||
|
if (isSSO() || !buffer()) {
|
||||||
|
// Already using SSO, nothing to do
|
||||||
|
uint16_t oldLen = len();
|
||||||
|
setSSO(true);
|
||||||
|
setLen(oldLen);
|
||||||
|
return 1;
|
||||||
|
} else { // if bufptr && !isSSO()
|
||||||
|
// Using bufptr, need to shrink into sso.buff
|
||||||
|
char temp[sizeof(sso.buff)];
|
||||||
|
memcpy(temp, buffer(), maxStrLen);
|
||||||
|
free(wbuffer());
|
||||||
|
uint16_t oldLen = len();
|
||||||
|
setSSO(true);
|
||||||
|
memcpy(wbuffer(), temp, maxStrLen);
|
||||||
|
setLen(oldLen);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fallthrough to normal allocator
|
||||||
|
size_t newSize = (maxStrLen + 16) & (~0xf);
|
||||||
|
// Make sure we can fit newsize in the buffer
|
||||||
|
if (newSize > CAPACITY_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint16_t oldLen = len();
|
||||||
|
char *newbuffer = (char *) realloc(isSSO() ? nullptr : wbuffer(), newSize);
|
||||||
|
if (newbuffer) {
|
||||||
|
size_t oldSize = capacity() + 1; // include NULL.
|
||||||
|
if (isSSO()) {
|
||||||
|
// Copy the SSO buffer into allocated space
|
||||||
|
memmove(newbuffer, sso.buff, sizeof(sso.buff));
|
||||||
|
}
|
||||||
|
if (newSize > oldSize)
|
||||||
|
{
|
||||||
|
memset(newbuffer + oldSize, 0, newSize - oldSize);
|
||||||
|
}
|
||||||
|
setSSO(false);
|
||||||
|
setCapacity(newSize - 1);
|
||||||
|
setBuffer(newbuffer);
|
||||||
|
setLen(oldLen); // Needed in case of SSO where len() never existed
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /*********************************************/
|
||||||
|
// /* Copy and Move */
|
||||||
|
// /*********************************************/
|
||||||
|
|
||||||
|
String & String::copy(const char *cstr, unsigned int length) {
|
||||||
|
if(!reserve(length)) {
|
||||||
|
invalidate();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
memmove(wbuffer(), cstr, length + 1);
|
||||||
|
setLen(length);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String & String::copy(const __FlashStringHelper *pstr, unsigned int length) {
|
||||||
|
if (!reserve(length)) {
|
||||||
|
invalidate();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
memcpy_P(wbuffer(), (PGM_P)pstr, length + 1); // We know wbuffer() cannot ever be in PROGMEM, so memcpy safe here
|
||||||
|
setLen(length);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
void String::move(String &rhs) {
|
||||||
|
if(buffer()) {
|
||||||
|
if(capacity() >= rhs.len()) {
|
||||||
|
memmove(wbuffer(), rhs.buffer(), rhs.length() + 1);
|
||||||
|
setLen(rhs.len());
|
||||||
|
rhs.invalidate();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (!isSSO()) {
|
||||||
|
free(wbuffer());
|
||||||
|
setBuffer(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rhs.isSSO()) {
|
||||||
|
setSSO(true);
|
||||||
|
memmove(sso.buff, rhs.sso.buff, sizeof(sso.buff));
|
||||||
|
} else {
|
||||||
|
setSSO(false);
|
||||||
|
setBuffer(rhs.wbuffer());
|
||||||
|
}
|
||||||
|
setCapacity(rhs.capacity());
|
||||||
|
setLen(rhs.len());
|
||||||
|
rhs.setSSO(false);
|
||||||
|
rhs.setCapacity(0);
|
||||||
|
rhs.setBuffer(nullptr);
|
||||||
|
rhs.setLen(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String & String::operator =(const String &rhs) {
|
||||||
|
if(this == &rhs)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
if(rhs.buffer())
|
||||||
|
copy(rhs.buffer(), rhs.len());
|
||||||
|
else
|
||||||
|
invalidate();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
String & String::operator =(String &&rval) {
|
||||||
|
if(this != &rval)
|
||||||
|
move(rval);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String & String::operator =(StringSumHelper &&rval) {
|
||||||
|
if(this != &rval)
|
||||||
|
move(rval);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String & String::operator =(const char *cstr) {
|
||||||
|
if(cstr)
|
||||||
|
copy(cstr, strlen(cstr));
|
||||||
|
else
|
||||||
|
invalidate();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String & String::operator = (const __FlashStringHelper *pstr)
|
||||||
|
{
|
||||||
|
if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
|
||||||
|
else invalidate();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /*********************************************/
|
||||||
|
// /* concat */
|
||||||
|
// /*********************************************/
|
||||||
|
|
||||||
|
unsigned char 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 0;
|
||||||
|
if (s.len() == 0)
|
||||||
|
return 1;
|
||||||
|
if (!reserve(newlen))
|
||||||
|
return 0;
|
||||||
|
memmove(wbuffer() + len(), buffer(), len());
|
||||||
|
setLen(newlen);
|
||||||
|
wbuffer()[len()] = 0;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return concat(s.buffer(), s.len());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(const char *cstr, unsigned int length) {
|
||||||
|
unsigned int newlen = len() + length;
|
||||||
|
if(!cstr)
|
||||||
|
return 0;
|
||||||
|
if(length == 0)
|
||||||
|
return 1;
|
||||||
|
if(!reserve(newlen))
|
||||||
|
return 0;
|
||||||
|
if (cstr >= wbuffer() && cstr < wbuffer() + len())
|
||||||
|
// compatible with SSO in ram #6155 (case "x += x.c_str()")
|
||||||
|
memmove(wbuffer() + len(), cstr, length + 1);
|
||||||
|
else
|
||||||
|
// compatible with source in flash #6367
|
||||||
|
memcpy_P(wbuffer() + len(), cstr, length + 1);
|
||||||
|
setLen(newlen);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(const char *cstr) {
|
||||||
|
if(!cstr)
|
||||||
|
return 0;
|
||||||
|
return concat(cstr, strlen(cstr));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(char c) {
|
||||||
|
char buf[2];
|
||||||
|
buf[0] = c;
|
||||||
|
buf[1] = 0;
|
||||||
|
return concat(buf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(unsigned char num) {
|
||||||
|
char buf[1 + 3 * sizeof(unsigned char)];
|
||||||
|
sprintf(buf, "%d", num);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(int num) {
|
||||||
|
char buf[2 + 3 * sizeof(int)];
|
||||||
|
sprintf(buf, "%d", num);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(unsigned int num) {
|
||||||
|
char buf[1 + 3 * sizeof(unsigned int)];
|
||||||
|
utoa(num, buf, 10);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(long num) {
|
||||||
|
char buf[2 + 3 * sizeof(long)];
|
||||||
|
sprintf(buf, "%ld", num);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(unsigned long num) {
|
||||||
|
char buf[1 + 3 * sizeof(unsigned long)];
|
||||||
|
ultoa(num, buf, 10);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(float num) {
|
||||||
|
char buf[20];
|
||||||
|
char* string = dtostrf(num, 4, 2, buf);
|
||||||
|
return concat(string, strlen(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(double num) {
|
||||||
|
char buf[20];
|
||||||
|
char* string = dtostrf(num, 4, 2, buf);
|
||||||
|
return concat(string, strlen(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(const __FlashStringHelper * str) {
|
||||||
|
if (!str) return 0;
|
||||||
|
int length = strlen_P((PGM_P)str);
|
||||||
|
if (length == 0) return 1;
|
||||||
|
unsigned int newlen = len() + length;
|
||||||
|
if (!reserve(newlen)) return 0;
|
||||||
|
memcpy_P(wbuffer() + len(), (PGM_P)str, length + 1);
|
||||||
|
setLen(newlen);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Concatenate */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs) {
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if(!a.concat(rhs.buffer(), rhs.len()))
|
||||||
|
a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr) {
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if(!cstr || !a.concat(cstr, strlen(cstr)))
|
||||||
|
a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator +(const StringSumHelper &lhs, char c) {
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if(!a.concat(c))
|
||||||
|
a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num) {
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if(!a.concat(num))
|
||||||
|
a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator +(const StringSumHelper &lhs, int num) {
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if(!a.concat(num))
|
||||||
|
a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num) {
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if(!a.concat(num))
|
||||||
|
a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator +(const StringSumHelper &lhs, long num) {
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if(!a.concat(num))
|
||||||
|
a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num) {
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if(!a.concat(num))
|
||||||
|
a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator +(const StringSumHelper &lhs, float num) {
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if(!a.concat(num))
|
||||||
|
a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator +(const StringSumHelper &lhs, double num) {
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if(!a.concat(num))
|
||||||
|
a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(rhs))
|
||||||
|
a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /*********************************************/
|
||||||
|
// /* Comparison */
|
||||||
|
// /*********************************************/
|
||||||
|
|
||||||
|
int String::compareTo(const String &s) const {
|
||||||
|
if(!buffer() || !s.buffer()) {
|
||||||
|
if(s.buffer() && s.len() > 0)
|
||||||
|
return 0 - *(unsigned char *) s.buffer();
|
||||||
|
if(buffer() && len() > 0)
|
||||||
|
return *(unsigned char *) buffer();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return strcmp(buffer(), s.buffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::equals(const String &s2) const {
|
||||||
|
return (len() == s2.len() && compareTo(s2) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::equals(const char *cstr) const {
|
||||||
|
if(len() == 0)
|
||||||
|
return (cstr == NULL || *cstr == 0);
|
||||||
|
if(cstr == NULL)
|
||||||
|
return buffer()[0] == 0;
|
||||||
|
return strcmp(buffer(), cstr) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::operator<(const String &rhs) const {
|
||||||
|
return compareTo(rhs) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::operator>(const String &rhs) const {
|
||||||
|
return compareTo(rhs) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::operator<=(const String &rhs) const {
|
||||||
|
return compareTo(rhs) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::operator>=(const String &rhs) const {
|
||||||
|
return compareTo(rhs) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::equalsIgnoreCase(const String &s2) const {
|
||||||
|
if(this == &s2)
|
||||||
|
return 1;
|
||||||
|
if(len() != s2.len())
|
||||||
|
return 0;
|
||||||
|
if(len() == 0)
|
||||||
|
return 1;
|
||||||
|
const char *p1 = buffer();
|
||||||
|
const char *p2 = s2.buffer();
|
||||||
|
while(*p1) {
|
||||||
|
if(tolower(*p1++) != tolower(*p2++))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::equalsConstantTime(const String &s2) const {
|
||||||
|
// To avoid possible time-based attacks present function
|
||||||
|
// compares given strings in a constant time.
|
||||||
|
if(len() != s2.len())
|
||||||
|
return 0;
|
||||||
|
//at this point lengths are the same
|
||||||
|
if(len() == 0)
|
||||||
|
return 1;
|
||||||
|
//at this point lenghts are the same and non-zero
|
||||||
|
const char *p1 = buffer();
|
||||||
|
const char *p2 = s2.buffer();
|
||||||
|
unsigned int equalchars = 0;
|
||||||
|
unsigned int diffchars = 0;
|
||||||
|
while(*p1) {
|
||||||
|
if(*p1 == *p2)
|
||||||
|
++equalchars;
|
||||||
|
else
|
||||||
|
++diffchars;
|
||||||
|
++p1;
|
||||||
|
++p2;
|
||||||
|
}
|
||||||
|
//the following should force a constant time eval of the condition without a compiler "logical shortcut"
|
||||||
|
unsigned char equalcond = (equalchars == len());
|
||||||
|
unsigned char diffcond = (diffchars == 0);
|
||||||
|
return (equalcond & diffcond); //bitwise AND
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::startsWith(const String &s2) const {
|
||||||
|
if(len() < s2.len())
|
||||||
|
return 0;
|
||||||
|
return startsWith(s2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::startsWith(const String &s2, unsigned int offset) const {
|
||||||
|
if(offset > (unsigned)(len() - s2.len()) || !buffer() || !s2.buffer())
|
||||||
|
return 0;
|
||||||
|
return strncmp(&buffer()[offset], s2.buffer(), s2.len()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::endsWith(const String &s2) const {
|
||||||
|
if(len() < s2.len() || !buffer() || !s2.buffer())
|
||||||
|
return 0;
|
||||||
|
return strcmp(&buffer()[len() - s2.len()], s2.buffer()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /*********************************************/
|
||||||
|
// /* Character Access */
|
||||||
|
// /*********************************************/
|
||||||
|
|
||||||
|
char String::charAt(unsigned int loc) const {
|
||||||
|
return operator[](loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::setCharAt(unsigned int loc, char c) {
|
||||||
|
if(loc < len())
|
||||||
|
wbuffer()[loc] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
char & String::operator[](unsigned int index) {
|
||||||
|
static char dummy_writable_char;
|
||||||
|
if(index >= len() || !buffer()) {
|
||||||
|
dummy_writable_char = 0;
|
||||||
|
return dummy_writable_char;
|
||||||
|
}
|
||||||
|
return wbuffer()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
char String::operator[](unsigned int index) const {
|
||||||
|
if(index >= len() || !buffer())
|
||||||
|
return 0;
|
||||||
|
return buffer()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const {
|
||||||
|
if(!bufsize || !buf)
|
||||||
|
return;
|
||||||
|
if(index >= len()) {
|
||||||
|
buf[0] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsigned int n = bufsize - 1;
|
||||||
|
if(n > len() - index)
|
||||||
|
n = len() - index;
|
||||||
|
strncpy((char *) buf, buffer() + index, n);
|
||||||
|
buf[n] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /*********************************************/
|
||||||
|
// /* Search */
|
||||||
|
// /*********************************************/
|
||||||
|
|
||||||
|
int String::indexOf(char c) const {
|
||||||
|
return indexOf(c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf(char ch, unsigned int fromIndex) const {
|
||||||
|
if(fromIndex >= len())
|
||||||
|
return -1;
|
||||||
|
const char* temp = strchr(buffer() + fromIndex, ch);
|
||||||
|
if(temp == NULL)
|
||||||
|
return -1;
|
||||||
|
return temp - buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf(const String &s2) const {
|
||||||
|
return indexOf(s2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf(const String &s2, unsigned int fromIndex) const {
|
||||||
|
if(fromIndex >= len())
|
||||||
|
return -1;
|
||||||
|
const char *found = strstr(buffer() + fromIndex, s2.buffer());
|
||||||
|
if(found == NULL)
|
||||||
|
return -1;
|
||||||
|
return found - buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf(char theChar) const {
|
||||||
|
return lastIndexOf(theChar, len() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf(char ch, unsigned int fromIndex) const {
|
||||||
|
if(fromIndex >= len())
|
||||||
|
return -1;
|
||||||
|
char tempchar = buffer()[fromIndex + 1];
|
||||||
|
wbuffer()[fromIndex + 1] = '\0';
|
||||||
|
char* temp = strrchr(wbuffer(), ch);
|
||||||
|
wbuffer()[fromIndex + 1] = tempchar;
|
||||||
|
if(temp == NULL)
|
||||||
|
return -1;
|
||||||
|
return temp - buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf(const String &s2) const {
|
||||||
|
return lastIndexOf(s2, len() - s2.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const {
|
||||||
|
if(s2.len() == 0 || len() == 0 || s2.len() > len())
|
||||||
|
return -1;
|
||||||
|
if(fromIndex >= len())
|
||||||
|
fromIndex = len() - 1;
|
||||||
|
int found = -1;
|
||||||
|
for(char *p = wbuffer(); p <= wbuffer() + fromIndex; p++) {
|
||||||
|
p = strstr(p, s2.buffer());
|
||||||
|
if(!p)
|
||||||
|
break;
|
||||||
|
if((unsigned int) (p - wbuffer()) <= fromIndex)
|
||||||
|
found = p - buffer();
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
String String::substring(unsigned int left, unsigned int right) const {
|
||||||
|
if(left > right) {
|
||||||
|
unsigned int temp = right;
|
||||||
|
right = left;
|
||||||
|
left = temp;
|
||||||
|
}
|
||||||
|
String out;
|
||||||
|
if(left >= len())
|
||||||
|
return out;
|
||||||
|
if(right > len())
|
||||||
|
right = len();
|
||||||
|
char temp = buffer()[right]; // save the replaced character
|
||||||
|
wbuffer()[right] = '\0';
|
||||||
|
out = wbuffer() + left; // pointer arithmetic
|
||||||
|
wbuffer()[right] = temp; //restore character
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /*********************************************/
|
||||||
|
// /* Modification */
|
||||||
|
// /*********************************************/
|
||||||
|
|
||||||
|
void String::replace(char find, char replace) {
|
||||||
|
if(!buffer())
|
||||||
|
return;
|
||||||
|
for(char *p = wbuffer(); *p; p++) {
|
||||||
|
if(*p == find)
|
||||||
|
*p = replace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::replace(const String& find, const String& replace) {
|
||||||
|
if(len() == 0 || find.len() == 0)
|
||||||
|
return;
|
||||||
|
int diff = replace.len() - find.len();
|
||||||
|
char *readFrom = wbuffer();
|
||||||
|
char *foundAt;
|
||||||
|
if(diff == 0) {
|
||||||
|
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
|
||||||
|
memmove(foundAt, replace.buffer(), replace.len());
|
||||||
|
readFrom = foundAt + replace.len();
|
||||||
|
}
|
||||||
|
} else if(diff < 0) {
|
||||||
|
char *writeTo = wbuffer();
|
||||||
|
unsigned int l = len();
|
||||||
|
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
|
||||||
|
unsigned int n = foundAt - readFrom;
|
||||||
|
memmove(writeTo, readFrom, n);
|
||||||
|
writeTo += n;
|
||||||
|
memmove(writeTo, replace.buffer(), replace.len());
|
||||||
|
writeTo += replace.len();
|
||||||
|
readFrom = foundAt + find.len();
|
||||||
|
l += diff;
|
||||||
|
}
|
||||||
|
memmove(writeTo, readFrom, strlen(readFrom)+1);
|
||||||
|
setLen(l);
|
||||||
|
} else {
|
||||||
|
unsigned int size = len(); // compute size needed for result
|
||||||
|
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
|
||||||
|
readFrom = foundAt + find.len();
|
||||||
|
size += diff;
|
||||||
|
}
|
||||||
|
if(size == len())
|
||||||
|
return;
|
||||||
|
if(size > capacity() && !changeBuffer(size))
|
||||||
|
return; // XXX: tell user!
|
||||||
|
int index = len() - 1;
|
||||||
|
while(index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
|
||||||
|
readFrom = wbuffer() + index + find.len();
|
||||||
|
memmove(readFrom + diff, readFrom, len() - (readFrom - buffer()));
|
||||||
|
int newLen = len() + diff;
|
||||||
|
memmove(wbuffer() + index, replace.buffer(), replace.len());
|
||||||
|
setLen(newLen);
|
||||||
|
wbuffer()[newLen] = 0;
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::remove(unsigned int index) {
|
||||||
|
// Pass the biggest integer as the count. The remove method
|
||||||
|
// below will take care of truncating it at the end of the
|
||||||
|
// string.
|
||||||
|
remove(index, (unsigned int) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::remove(unsigned int index, unsigned int count) {
|
||||||
|
if(index >= len()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(count <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(count > len() - index) {
|
||||||
|
count = len() - index;
|
||||||
|
}
|
||||||
|
char *writeTo = wbuffer() + index;
|
||||||
|
unsigned int newlen = len() - count;
|
||||||
|
memmove(writeTo, wbuffer() + index + count, newlen - index);
|
||||||
|
setLen(newlen);
|
||||||
|
wbuffer()[newlen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::toLowerCase(void) {
|
||||||
|
if(!buffer())
|
||||||
|
return;
|
||||||
|
for(char *p = wbuffer(); *p; p++) {
|
||||||
|
*p = tolower(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::toUpperCase(void) {
|
||||||
|
if(!buffer())
|
||||||
|
return;
|
||||||
|
for(char *p = wbuffer(); *p; p++) {
|
||||||
|
*p = toupper(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::trim(void) {
|
||||||
|
if(!buffer() || len() == 0)
|
||||||
|
return;
|
||||||
|
char *begin = wbuffer();
|
||||||
|
while(isspace(*begin))
|
||||||
|
begin++;
|
||||||
|
char *end = wbuffer() + len() - 1;
|
||||||
|
while(isspace(*end) && end >= begin)
|
||||||
|
end--;
|
||||||
|
unsigned int newlen = end + 1 - begin;
|
||||||
|
if(begin > buffer())
|
||||||
|
memmove(wbuffer(), begin, newlen);
|
||||||
|
setLen(newlen);
|
||||||
|
wbuffer()[newlen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /*********************************************/
|
||||||
|
// /* Parsing / Conversion */
|
||||||
|
// /*********************************************/
|
||||||
|
|
||||||
|
long String::toInt(void) const {
|
||||||
|
if (buffer())
|
||||||
|
return atol(buffer());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float String::toFloat(void) const {
|
||||||
|
if (buffer())
|
||||||
|
return atof(buffer());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double String::toDouble(void) const
|
||||||
|
{
|
||||||
|
if (buffer())
|
||||||
|
return atof(buffer());
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// global empty string to allow returning const String& with nothing
|
||||||
|
|
||||||
|
const String emptyString;
|
376
cores/esp32/WString.h
Normal file
376
cores/esp32/WString.h
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
/*
|
||||||
|
WString.h - String library for Wiring & Arduino
|
||||||
|
...mostly rewritten by Paul Stoffregen...
|
||||||
|
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
|
||||||
|
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||||
|
|
||||||
|
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 String_class_h
|
||||||
|
#define String_class_h
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <pgmspace.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// An inherited class for holding the result of a concatenation. These
|
||||||
|
// result objects are assumed to be writable by subsequent concatenations.
|
||||||
|
class StringSumHelper;
|
||||||
|
|
||||||
|
// an abstract class used as a means to proide a unique pointer type
|
||||||
|
// but really has no body
|
||||||
|
class __FlashStringHelper;
|
||||||
|
#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
|
||||||
|
#define F(string_literal) (FPSTR(PSTR(string_literal)))
|
||||||
|
|
||||||
|
// The string class
|
||||||
|
class String {
|
||||||
|
// use a function pointer to allow for "if (s)" without the
|
||||||
|
// complications of an operator bool(). for more information, see:
|
||||||
|
// http://www.artima.com/cppsource/safebool.html
|
||||||
|
typedef void (String::*StringIfHelperType)() const;
|
||||||
|
void StringIfHelper() const {
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
// creates a copy of the initial value.
|
||||||
|
// if the initial value is null or invalid, or if memory allocation
|
||||||
|
// fails, the string will be marked as invalid (i.e. "if (s)" will
|
||||||
|
// be false).
|
||||||
|
String(const char *cstr = "");
|
||||||
|
String(const String &str);
|
||||||
|
String(const __FlashStringHelper *str);
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
String(String &&rval);
|
||||||
|
String(StringSumHelper &&rval);
|
||||||
|
#endif
|
||||||
|
explicit String(char c);
|
||||||
|
explicit String(unsigned char, unsigned char base = 10);
|
||||||
|
explicit String(int, unsigned char base = 10);
|
||||||
|
explicit String(unsigned int, unsigned char base = 10);
|
||||||
|
explicit String(long, unsigned char base = 10);
|
||||||
|
explicit String(unsigned long, unsigned char base = 10);
|
||||||
|
explicit String(float, unsigned char decimalPlaces = 2);
|
||||||
|
explicit String(double, unsigned char decimalPlaces = 2);
|
||||||
|
~String(void);
|
||||||
|
|
||||||
|
// memory management
|
||||||
|
// return true on success, false on failure (in which case, the string
|
||||||
|
// is left unchanged). reserve(0), if successful, will validate an
|
||||||
|
// invalid string (i.e., "if (s)" will be true afterwards)
|
||||||
|
unsigned char reserve(unsigned int size);
|
||||||
|
inline unsigned int length(void) const {
|
||||||
|
if(buffer()) {
|
||||||
|
return len();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void clear(void) {
|
||||||
|
setLen(0);
|
||||||
|
}
|
||||||
|
inline bool isEmpty(void) const {
|
||||||
|
return length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates a copy of the assigned value. if the value is null or
|
||||||
|
// invalid, or if the memory allocation fails, the string will be
|
||||||
|
// marked as invalid ("if (s)" will be false).
|
||||||
|
String & operator =(const String &rhs);
|
||||||
|
String & operator =(const char *cstr);
|
||||||
|
String & operator = (const __FlashStringHelper *str);
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
String & operator =(String &&rval);
|
||||||
|
String & operator =(StringSumHelper &&rval);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// concatenate (works w/ built-in types)
|
||||||
|
|
||||||
|
// returns true on success, false on failure (in which case, the string
|
||||||
|
// is left unchanged). if the argument is null or invalid, the
|
||||||
|
// concatenation is considered unsuccessful.
|
||||||
|
unsigned char concat(const String &str);
|
||||||
|
unsigned char concat(const char *cstr);
|
||||||
|
unsigned char concat(char c);
|
||||||
|
unsigned char concat(unsigned char c);
|
||||||
|
unsigned char concat(int num);
|
||||||
|
unsigned char concat(unsigned int num);
|
||||||
|
unsigned char concat(long num);
|
||||||
|
unsigned char concat(unsigned long num);
|
||||||
|
unsigned char concat(float num);
|
||||||
|
unsigned char concat(double num);
|
||||||
|
unsigned char concat(const __FlashStringHelper * str);
|
||||||
|
|
||||||
|
// if there's not enough memory for the concatenated value, the string
|
||||||
|
// will be left unchanged (but this isn't signalled in any way)
|
||||||
|
String & operator +=(const String &rhs) {
|
||||||
|
concat(rhs);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
String & operator +=(const char *cstr) {
|
||||||
|
concat(cstr);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
String & operator +=(char c) {
|
||||||
|
concat(c);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
String & operator +=(unsigned char num) {
|
||||||
|
concat(num);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
String & operator +=(int num) {
|
||||||
|
concat(num);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
String & operator +=(unsigned int num) {
|
||||||
|
concat(num);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
String & operator +=(long num) {
|
||||||
|
concat(num);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
String & operator +=(unsigned long num) {
|
||||||
|
concat(num);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
String & operator +=(float num) {
|
||||||
|
concat(num);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
String & operator +=(double num) {
|
||||||
|
concat(num);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
String & operator += (const __FlashStringHelper *str){
|
||||||
|
concat(str);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs);
|
||||||
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr);
|
||||||
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, char c);
|
||||||
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num);
|
||||||
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, int num);
|
||||||
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num);
|
||||||
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, long num);
|
||||||
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num);
|
||||||
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, float num);
|
||||||
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, double num);
|
||||||
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, const __FlashStringHelper *rhs);
|
||||||
|
|
||||||
|
// comparison (only works w/ Strings and "strings")
|
||||||
|
operator StringIfHelperType() const {
|
||||||
|
return buffer() ? &String::StringIfHelper : 0;
|
||||||
|
}
|
||||||
|
int compareTo(const String &s) const;
|
||||||
|
unsigned char equals(const String &s) const;
|
||||||
|
unsigned char equals(const char *cstr) const;
|
||||||
|
unsigned char operator ==(const String &rhs) const {
|
||||||
|
return equals(rhs);
|
||||||
|
}
|
||||||
|
unsigned char operator ==(const char *cstr) const {
|
||||||
|
return equals(cstr);
|
||||||
|
}
|
||||||
|
unsigned char operator !=(const String &rhs) const {
|
||||||
|
return !equals(rhs);
|
||||||
|
}
|
||||||
|
unsigned char operator !=(const char *cstr) const {
|
||||||
|
return !equals(cstr);
|
||||||
|
}
|
||||||
|
unsigned char operator <(const String &rhs) const;
|
||||||
|
unsigned char operator >(const String &rhs) const;
|
||||||
|
unsigned char operator <=(const String &rhs) const;
|
||||||
|
unsigned char operator >=(const String &rhs) const;
|
||||||
|
unsigned char equalsIgnoreCase(const String &s) const;
|
||||||
|
unsigned char equalsConstantTime(const String &s) const;
|
||||||
|
unsigned char startsWith(const String &prefix) const;
|
||||||
|
unsigned char startsWith(const char *prefix) const {
|
||||||
|
return this->startsWith(String(prefix));
|
||||||
|
}
|
||||||
|
unsigned char startsWith(const __FlashStringHelper *prefix) const {
|
||||||
|
return this->startsWith(String(prefix));
|
||||||
|
}
|
||||||
|
unsigned char startsWith(const String &prefix, unsigned int offset) const;
|
||||||
|
unsigned char endsWith(const String &suffix) const;
|
||||||
|
unsigned char endsWith(const char *suffix) const {
|
||||||
|
return this->endsWith(String(suffix));
|
||||||
|
}
|
||||||
|
unsigned char endsWith(const __FlashStringHelper * suffix) const {
|
||||||
|
return this->endsWith(String(suffix));
|
||||||
|
}
|
||||||
|
|
||||||
|
// character access
|
||||||
|
char charAt(unsigned int index) const;
|
||||||
|
void setCharAt(unsigned int index, char c);
|
||||||
|
char operator [](unsigned int index) const;
|
||||||
|
char& operator [](unsigned int index);
|
||||||
|
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index = 0) const;
|
||||||
|
void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const {
|
||||||
|
getBytes((unsigned char *) buf, bufsize, index);
|
||||||
|
}
|
||||||
|
const char* c_str() const { return buffer(); }
|
||||||
|
char* begin() { return wbuffer(); }
|
||||||
|
char* end() { return wbuffer() + length(); }
|
||||||
|
const char* begin() const { return c_str(); }
|
||||||
|
const char* end() const { return c_str() + length(); }
|
||||||
|
|
||||||
|
// search
|
||||||
|
int indexOf(char ch) const;
|
||||||
|
int indexOf(char ch, unsigned int fromIndex) const;
|
||||||
|
int indexOf(const String &str) const;
|
||||||
|
int indexOf(const String &str, unsigned int fromIndex) const;
|
||||||
|
int lastIndexOf(char ch) const;
|
||||||
|
int lastIndexOf(char ch, unsigned int fromIndex) const;
|
||||||
|
int lastIndexOf(const String &str) const;
|
||||||
|
int lastIndexOf(const String &str, unsigned int fromIndex) const;
|
||||||
|
String substring(unsigned int beginIndex) const {
|
||||||
|
return substring(beginIndex, len());
|
||||||
|
}
|
||||||
|
;
|
||||||
|
String substring(unsigned int beginIndex, unsigned int endIndex) const;
|
||||||
|
|
||||||
|
// modification
|
||||||
|
void replace(char find, char replace);
|
||||||
|
void replace(const String &find, const String &replace);
|
||||||
|
void replace(const char *find, const String &replace) {
|
||||||
|
this->replace(String(find), replace);
|
||||||
|
}
|
||||||
|
void replace(const __FlashStringHelper *find, const String &replace) {
|
||||||
|
this->replace(String(find), replace);
|
||||||
|
}
|
||||||
|
void replace(const char *find, const char *replace) {
|
||||||
|
this->replace(String(find), String(replace));
|
||||||
|
}
|
||||||
|
void replace(const __FlashStringHelper *find, const char *replace) {
|
||||||
|
this->replace(String(find), String(replace));
|
||||||
|
}
|
||||||
|
void replace(const __FlashStringHelper *find, const __FlashStringHelper *replace) {
|
||||||
|
this->replace(String(find), String(replace));
|
||||||
|
}
|
||||||
|
void remove(unsigned int index);
|
||||||
|
void remove(unsigned int index, unsigned int count);
|
||||||
|
void toLowerCase(void);
|
||||||
|
void toUpperCase(void);
|
||||||
|
void trim(void);
|
||||||
|
|
||||||
|
// parsing/conversion
|
||||||
|
long toInt(void) const;
|
||||||
|
float toFloat(void) const;
|
||||||
|
double toDouble(void) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Contains the string info when we're not in SSO mode
|
||||||
|
struct _ptr {
|
||||||
|
char * buff;
|
||||||
|
uint32_t cap;
|
||||||
|
uint32_t len;
|
||||||
|
};
|
||||||
|
// This allows strings up up to 11 (10 + \0 termination) without any extra space.
|
||||||
|
enum { SSOSIZE = sizeof(struct _ptr) + 4 - 1 }; // Characters to allocate space for SSO, must be 12 or more
|
||||||
|
struct _sso {
|
||||||
|
char buff[SSOSIZE];
|
||||||
|
unsigned char len : 7; // Ensure only one byte is allocated by GCC for the bitfields
|
||||||
|
unsigned char isSSO : 1;
|
||||||
|
} __attribute__((packed)); // Ensure that GCC doesn't expand the flag byte to a 32-bit word for alignment issues
|
||||||
|
#ifdef BOARD_HAS_PSRAM
|
||||||
|
enum { CAPACITY_MAX = 3145728 };
|
||||||
|
#else
|
||||||
|
enum { CAPACITY_MAX = 65535 };
|
||||||
|
#endif
|
||||||
|
union {
|
||||||
|
struct _ptr ptr;
|
||||||
|
struct _sso sso;
|
||||||
|
};
|
||||||
|
// Accessor functions
|
||||||
|
inline bool isSSO() const { return sso.isSSO; }
|
||||||
|
inline unsigned int len() const { return isSSO() ? sso.len : ptr.len; }
|
||||||
|
inline unsigned int capacity() const { return isSSO() ? (unsigned int)SSOSIZE - 1 : ptr.cap; } // Size of max string not including terminal NUL
|
||||||
|
inline void setSSO(bool set) { sso.isSSO = set; }
|
||||||
|
inline void setLen(int len) {
|
||||||
|
if (isSSO()) {
|
||||||
|
sso.len = len;
|
||||||
|
sso.buff[len] = 0;
|
||||||
|
} else {
|
||||||
|
ptr.len = len;
|
||||||
|
if (ptr.buff) {
|
||||||
|
ptr.buff[len] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void setCapacity(int cap) { if (!isSSO()) ptr.cap = cap; }
|
||||||
|
inline void setBuffer(char *buff) { if (!isSSO()) ptr.buff = buff; }
|
||||||
|
// Buffer accessor functions
|
||||||
|
inline const char *buffer() const { return (const char *)(isSSO() ? sso.buff : ptr.buff); }
|
||||||
|
inline char *wbuffer() const { return isSSO() ? const_cast<char *>(sso.buff) : ptr.buff; } // Writable version of buffer
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void init(void);
|
||||||
|
void invalidate(void);
|
||||||
|
unsigned char changeBuffer(unsigned int maxStrLen);
|
||||||
|
unsigned char concat(const char *cstr, unsigned int length);
|
||||||
|
|
||||||
|
// copy and move
|
||||||
|
String & copy(const char *cstr, unsigned int length);
|
||||||
|
String & copy(const __FlashStringHelper *pstr, unsigned int length);
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
void move(String &rhs);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
class StringSumHelper: public String {
|
||||||
|
public:
|
||||||
|
StringSumHelper(const String &s) :
|
||||||
|
String(s) {
|
||||||
|
}
|
||||||
|
StringSumHelper(const char *p) :
|
||||||
|
String(p) {
|
||||||
|
}
|
||||||
|
StringSumHelper(char c) :
|
||||||
|
String(c) {
|
||||||
|
}
|
||||||
|
StringSumHelper(unsigned char num) :
|
||||||
|
String(num) {
|
||||||
|
}
|
||||||
|
StringSumHelper(int num) :
|
||||||
|
String(num) {
|
||||||
|
}
|
||||||
|
StringSumHelper(unsigned int num) :
|
||||||
|
String(num) {
|
||||||
|
}
|
||||||
|
StringSumHelper(long num) :
|
||||||
|
String(num) {
|
||||||
|
}
|
||||||
|
StringSumHelper(unsigned long num) :
|
||||||
|
String(num) {
|
||||||
|
}
|
||||||
|
StringSumHelper(float num) :
|
||||||
|
String(num) {
|
||||||
|
}
|
||||||
|
StringSumHelper(double num) :
|
||||||
|
String(num) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const String emptyString;
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
#endif // String_class_h
|
1
cores/esp32/apps/sntp/sntp.h
Normal file
1
cores/esp32/apps/sntp/sntp.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "lwip/apps/sntp.h"
|
64
cores/esp32/base64.cpp
Normal file
64
cores/esp32/base64.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* base64.cpp
|
||||||
|
*
|
||||||
|
* Created on: 09.12.2015
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Markus Sattler. All rights reserved.
|
||||||
|
* This file is part of the ESP31B core for Arduino.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
extern "C" {
|
||||||
|
#include "libb64/cdecode.h"
|
||||||
|
#include "libb64/cencode.h"
|
||||||
|
}
|
||||||
|
#include "base64.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert input data to base64
|
||||||
|
* @param data const uint8_t *
|
||||||
|
* @param length size_t
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
String base64::encode(const uint8_t * data, size_t length)
|
||||||
|
{
|
||||||
|
size_t size = base64_encode_expected_len(length) + 1;
|
||||||
|
char * buffer = (char *) malloc(size);
|
||||||
|
if(buffer) {
|
||||||
|
base64_encodestate _state;
|
||||||
|
base64_init_encodestate(&_state);
|
||||||
|
int len = base64_encode_block((const char *) &data[0], length, &buffer[0], &_state);
|
||||||
|
len = base64_encode_blockend((buffer + len), &_state);
|
||||||
|
|
||||||
|
String base64 = String(buffer);
|
||||||
|
free(buffer);
|
||||||
|
return base64;
|
||||||
|
}
|
||||||
|
return String("-FAIL-");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert input data to base64
|
||||||
|
* @param text const String&
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
String base64::encode(const String& text)
|
||||||
|
{
|
||||||
|
return base64::encode((uint8_t *) text.c_str(), text.length());
|
||||||
|
}
|
||||||
|
|
13
cores/esp32/base64.h
Normal file
13
cores/esp32/base64.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef CORE_BASE64_H_
|
||||||
|
#define CORE_BASE64_H_
|
||||||
|
|
||||||
|
class base64
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static String encode(const uint8_t * data, size_t length);
|
||||||
|
static String encode(const String& text);
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CORE_BASE64_H_ */
|
534
cores/esp32/binary.h
Normal file
534
cores/esp32/binary.h
Normal file
@ -0,0 +1,534 @@
|
|||||||
|
/*
|
||||||
|
binary.h - Definitions for binary constants
|
||||||
|
Copyright (c) 2006 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 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 Binary_h
|
||||||
|
#define Binary_h
|
||||||
|
|
||||||
|
#define B0 0
|
||||||
|
#define B00 0
|
||||||
|
#define B000 0
|
||||||
|
#define B0000 0
|
||||||
|
#define B00000 0
|
||||||
|
#define B000000 0
|
||||||
|
#define B0000000 0
|
||||||
|
#define B00000000 0
|
||||||
|
#define B1 1
|
||||||
|
#define B01 1
|
||||||
|
#define B001 1
|
||||||
|
#define B0001 1
|
||||||
|
#define B00001 1
|
||||||
|
#define B000001 1
|
||||||
|
#define B0000001 1
|
||||||
|
#define B00000001 1
|
||||||
|
#define B10 2
|
||||||
|
#define B010 2
|
||||||
|
#define B0010 2
|
||||||
|
#define B00010 2
|
||||||
|
#define B000010 2
|
||||||
|
#define B0000010 2
|
||||||
|
#define B00000010 2
|
||||||
|
#define B11 3
|
||||||
|
#define B011 3
|
||||||
|
#define B0011 3
|
||||||
|
#define B00011 3
|
||||||
|
#define B000011 3
|
||||||
|
#define B0000011 3
|
||||||
|
#define B00000011 3
|
||||||
|
#define B100 4
|
||||||
|
#define B0100 4
|
||||||
|
#define B00100 4
|
||||||
|
#define B000100 4
|
||||||
|
#define B0000100 4
|
||||||
|
#define B00000100 4
|
||||||
|
#define B101 5
|
||||||
|
#define B0101 5
|
||||||
|
#define B00101 5
|
||||||
|
#define B000101 5
|
||||||
|
#define B0000101 5
|
||||||
|
#define B00000101 5
|
||||||
|
#define B110 6
|
||||||
|
#define B0110 6
|
||||||
|
#define B00110 6
|
||||||
|
#define B000110 6
|
||||||
|
#define B0000110 6
|
||||||
|
#define B00000110 6
|
||||||
|
#define B111 7
|
||||||
|
#define B0111 7
|
||||||
|
#define B00111 7
|
||||||
|
#define B000111 7
|
||||||
|
#define B0000111 7
|
||||||
|
#define B00000111 7
|
||||||
|
#define B1000 8
|
||||||
|
#define B01000 8
|
||||||
|
#define B001000 8
|
||||||
|
#define B0001000 8
|
||||||
|
#define B00001000 8
|
||||||
|
#define B1001 9
|
||||||
|
#define B01001 9
|
||||||
|
#define B001001 9
|
||||||
|
#define B0001001 9
|
||||||
|
#define B00001001 9
|
||||||
|
#define B1010 10
|
||||||
|
#define B01010 10
|
||||||
|
#define B001010 10
|
||||||
|
#define B0001010 10
|
||||||
|
#define B00001010 10
|
||||||
|
#define B1011 11
|
||||||
|
#define B01011 11
|
||||||
|
#define B001011 11
|
||||||
|
#define B0001011 11
|
||||||
|
#define B00001011 11
|
||||||
|
#define B1100 12
|
||||||
|
#define B01100 12
|
||||||
|
#define B001100 12
|
||||||
|
#define B0001100 12
|
||||||
|
#define B00001100 12
|
||||||
|
#define B1101 13
|
||||||
|
#define B01101 13
|
||||||
|
#define B001101 13
|
||||||
|
#define B0001101 13
|
||||||
|
#define B00001101 13
|
||||||
|
#define B1110 14
|
||||||
|
#define B01110 14
|
||||||
|
#define B001110 14
|
||||||
|
#define B0001110 14
|
||||||
|
#define B00001110 14
|
||||||
|
#define B1111 15
|
||||||
|
#define B01111 15
|
||||||
|
#define B001111 15
|
||||||
|
#define B0001111 15
|
||||||
|
#define B00001111 15
|
||||||
|
#define B10000 16
|
||||||
|
#define B010000 16
|
||||||
|
#define B0010000 16
|
||||||
|
#define B00010000 16
|
||||||
|
#define B10001 17
|
||||||
|
#define B010001 17
|
||||||
|
#define B0010001 17
|
||||||
|
#define B00010001 17
|
||||||
|
#define B10010 18
|
||||||
|
#define B010010 18
|
||||||
|
#define B0010010 18
|
||||||
|
#define B00010010 18
|
||||||
|
#define B10011 19
|
||||||
|
#define B010011 19
|
||||||
|
#define B0010011 19
|
||||||
|
#define B00010011 19
|
||||||
|
#define B10100 20
|
||||||
|
#define B010100 20
|
||||||
|
#define B0010100 20
|
||||||
|
#define B00010100 20
|
||||||
|
#define B10101 21
|
||||||
|
#define B010101 21
|
||||||
|
#define B0010101 21
|
||||||
|
#define B00010101 21
|
||||||
|
#define B10110 22
|
||||||
|
#define B010110 22
|
||||||
|
#define B0010110 22
|
||||||
|
#define B00010110 22
|
||||||
|
#define B10111 23
|
||||||
|
#define B010111 23
|
||||||
|
#define B0010111 23
|
||||||
|
#define B00010111 23
|
||||||
|
#define B11000 24
|
||||||
|
#define B011000 24
|
||||||
|
#define B0011000 24
|
||||||
|
#define B00011000 24
|
||||||
|
#define B11001 25
|
||||||
|
#define B011001 25
|
||||||
|
#define B0011001 25
|
||||||
|
#define B00011001 25
|
||||||
|
#define B11010 26
|
||||||
|
#define B011010 26
|
||||||
|
#define B0011010 26
|
||||||
|
#define B00011010 26
|
||||||
|
#define B11011 27
|
||||||
|
#define B011011 27
|
||||||
|
#define B0011011 27
|
||||||
|
#define B00011011 27
|
||||||
|
#define B11100 28
|
||||||
|
#define B011100 28
|
||||||
|
#define B0011100 28
|
||||||
|
#define B00011100 28
|
||||||
|
#define B11101 29
|
||||||
|
#define B011101 29
|
||||||
|
#define B0011101 29
|
||||||
|
#define B00011101 29
|
||||||
|
#define B11110 30
|
||||||
|
#define B011110 30
|
||||||
|
#define B0011110 30
|
||||||
|
#define B00011110 30
|
||||||
|
#define B11111 31
|
||||||
|
#define B011111 31
|
||||||
|
#define B0011111 31
|
||||||
|
#define B00011111 31
|
||||||
|
#define B100000 32
|
||||||
|
#define B0100000 32
|
||||||
|
#define B00100000 32
|
||||||
|
#define B100001 33
|
||||||
|
#define B0100001 33
|
||||||
|
#define B00100001 33
|
||||||
|
#define B100010 34
|
||||||
|
#define B0100010 34
|
||||||
|
#define B00100010 34
|
||||||
|
#define B100011 35
|
||||||
|
#define B0100011 35
|
||||||
|
#define B00100011 35
|
||||||
|
#define B100100 36
|
||||||
|
#define B0100100 36
|
||||||
|
#define B00100100 36
|
||||||
|
#define B100101 37
|
||||||
|
#define B0100101 37
|
||||||
|
#define B00100101 37
|
||||||
|
#define B100110 38
|
||||||
|
#define B0100110 38
|
||||||
|
#define B00100110 38
|
||||||
|
#define B100111 39
|
||||||
|
#define B0100111 39
|
||||||
|
#define B00100111 39
|
||||||
|
#define B101000 40
|
||||||
|
#define B0101000 40
|
||||||
|
#define B00101000 40
|
||||||
|
#define B101001 41
|
||||||
|
#define B0101001 41
|
||||||
|
#define B00101001 41
|
||||||
|
#define B101010 42
|
||||||
|
#define B0101010 42
|
||||||
|
#define B00101010 42
|
||||||
|
#define B101011 43
|
||||||
|
#define B0101011 43
|
||||||
|
#define B00101011 43
|
||||||
|
#define B101100 44
|
||||||
|
#define B0101100 44
|
||||||
|
#define B00101100 44
|
||||||
|
#define B101101 45
|
||||||
|
#define B0101101 45
|
||||||
|
#define B00101101 45
|
||||||
|
#define B101110 46
|
||||||
|
#define B0101110 46
|
||||||
|
#define B00101110 46
|
||||||
|
#define B101111 47
|
||||||
|
#define B0101111 47
|
||||||
|
#define B00101111 47
|
||||||
|
#define B110000 48
|
||||||
|
#define B0110000 48
|
||||||
|
#define B00110000 48
|
||||||
|
#define B110001 49
|
||||||
|
#define B0110001 49
|
||||||
|
#define B00110001 49
|
||||||
|
#define B110010 50
|
||||||
|
#define B0110010 50
|
||||||
|
#define B00110010 50
|
||||||
|
#define B110011 51
|
||||||
|
#define B0110011 51
|
||||||
|
#define B00110011 51
|
||||||
|
#define B110100 52
|
||||||
|
#define B0110100 52
|
||||||
|
#define B00110100 52
|
||||||
|
#define B110101 53
|
||||||
|
#define B0110101 53
|
||||||
|
#define B00110101 53
|
||||||
|
#define B110110 54
|
||||||
|
#define B0110110 54
|
||||||
|
#define B00110110 54
|
||||||
|
#define B110111 55
|
||||||
|
#define B0110111 55
|
||||||
|
#define B00110111 55
|
||||||
|
#define B111000 56
|
||||||
|
#define B0111000 56
|
||||||
|
#define B00111000 56
|
||||||
|
#define B111001 57
|
||||||
|
#define B0111001 57
|
||||||
|
#define B00111001 57
|
||||||
|
#define B111010 58
|
||||||
|
#define B0111010 58
|
||||||
|
#define B00111010 58
|
||||||
|
#define B111011 59
|
||||||
|
#define B0111011 59
|
||||||
|
#define B00111011 59
|
||||||
|
#define B111100 60
|
||||||
|
#define B0111100 60
|
||||||
|
#define B00111100 60
|
||||||
|
#define B111101 61
|
||||||
|
#define B0111101 61
|
||||||
|
#define B00111101 61
|
||||||
|
#define B111110 62
|
||||||
|
#define B0111110 62
|
||||||
|
#define B00111110 62
|
||||||
|
#define B111111 63
|
||||||
|
#define B0111111 63
|
||||||
|
#define B00111111 63
|
||||||
|
#define B1000000 64
|
||||||
|
#define B01000000 64
|
||||||
|
#define B1000001 65
|
||||||
|
#define B01000001 65
|
||||||
|
#define B1000010 66
|
||||||
|
#define B01000010 66
|
||||||
|
#define B1000011 67
|
||||||
|
#define B01000011 67
|
||||||
|
#define B1000100 68
|
||||||
|
#define B01000100 68
|
||||||
|
#define B1000101 69
|
||||||
|
#define B01000101 69
|
||||||
|
#define B1000110 70
|
||||||
|
#define B01000110 70
|
||||||
|
#define B1000111 71
|
||||||
|
#define B01000111 71
|
||||||
|
#define B1001000 72
|
||||||
|
#define B01001000 72
|
||||||
|
#define B1001001 73
|
||||||
|
#define B01001001 73
|
||||||
|
#define B1001010 74
|
||||||
|
#define B01001010 74
|
||||||
|
#define B1001011 75
|
||||||
|
#define B01001011 75
|
||||||
|
#define B1001100 76
|
||||||
|
#define B01001100 76
|
||||||
|
#define B1001101 77
|
||||||
|
#define B01001101 77
|
||||||
|
#define B1001110 78
|
||||||
|
#define B01001110 78
|
||||||
|
#define B1001111 79
|
||||||
|
#define B01001111 79
|
||||||
|
#define B1010000 80
|
||||||
|
#define B01010000 80
|
||||||
|
#define B1010001 81
|
||||||
|
#define B01010001 81
|
||||||
|
#define B1010010 82
|
||||||
|
#define B01010010 82
|
||||||
|
#define B1010011 83
|
||||||
|
#define B01010011 83
|
||||||
|
#define B1010100 84
|
||||||
|
#define B01010100 84
|
||||||
|
#define B1010101 85
|
||||||
|
#define B01010101 85
|
||||||
|
#define B1010110 86
|
||||||
|
#define B01010110 86
|
||||||
|
#define B1010111 87
|
||||||
|
#define B01010111 87
|
||||||
|
#define B1011000 88
|
||||||
|
#define B01011000 88
|
||||||
|
#define B1011001 89
|
||||||
|
#define B01011001 89
|
||||||
|
#define B1011010 90
|
||||||
|
#define B01011010 90
|
||||||
|
#define B1011011 91
|
||||||
|
#define B01011011 91
|
||||||
|
#define B1011100 92
|
||||||
|
#define B01011100 92
|
||||||
|
#define B1011101 93
|
||||||
|
#define B01011101 93
|
||||||
|
#define B1011110 94
|
||||||
|
#define B01011110 94
|
||||||
|
#define B1011111 95
|
||||||
|
#define B01011111 95
|
||||||
|
#define B1100000 96
|
||||||
|
#define B01100000 96
|
||||||
|
#define B1100001 97
|
||||||
|
#define B01100001 97
|
||||||
|
#define B1100010 98
|
||||||
|
#define B01100010 98
|
||||||
|
#define B1100011 99
|
||||||
|
#define B01100011 99
|
||||||
|
#define B1100100 100
|
||||||
|
#define B01100100 100
|
||||||
|
#define B1100101 101
|
||||||
|
#define B01100101 101
|
||||||
|
#define B1100110 102
|
||||||
|
#define B01100110 102
|
||||||
|
#define B1100111 103
|
||||||
|
#define B01100111 103
|
||||||
|
#define B1101000 104
|
||||||
|
#define B01101000 104
|
||||||
|
#define B1101001 105
|
||||||
|
#define B01101001 105
|
||||||
|
#define B1101010 106
|
||||||
|
#define B01101010 106
|
||||||
|
#define B1101011 107
|
||||||
|
#define B01101011 107
|
||||||
|
#define B1101100 108
|
||||||
|
#define B01101100 108
|
||||||
|
#define B1101101 109
|
||||||
|
#define B01101101 109
|
||||||
|
#define B1101110 110
|
||||||
|
#define B01101110 110
|
||||||
|
#define B1101111 111
|
||||||
|
#define B01101111 111
|
||||||
|
#define B1110000 112
|
||||||
|
#define B01110000 112
|
||||||
|
#define B1110001 113
|
||||||
|
#define B01110001 113
|
||||||
|
#define B1110010 114
|
||||||
|
#define B01110010 114
|
||||||
|
#define B1110011 115
|
||||||
|
#define B01110011 115
|
||||||
|
#define B1110100 116
|
||||||
|
#define B01110100 116
|
||||||
|
#define B1110101 117
|
||||||
|
#define B01110101 117
|
||||||
|
#define B1110110 118
|
||||||
|
#define B01110110 118
|
||||||
|
#define B1110111 119
|
||||||
|
#define B01110111 119
|
||||||
|
#define B1111000 120
|
||||||
|
#define B01111000 120
|
||||||
|
#define B1111001 121
|
||||||
|
#define B01111001 121
|
||||||
|
#define B1111010 122
|
||||||
|
#define B01111010 122
|
||||||
|
#define B1111011 123
|
||||||
|
#define B01111011 123
|
||||||
|
#define B1111100 124
|
||||||
|
#define B01111100 124
|
||||||
|
#define B1111101 125
|
||||||
|
#define B01111101 125
|
||||||
|
#define B1111110 126
|
||||||
|
#define B01111110 126
|
||||||
|
#define B1111111 127
|
||||||
|
#define B01111111 127
|
||||||
|
#define B10000000 128
|
||||||
|
#define B10000001 129
|
||||||
|
#define B10000010 130
|
||||||
|
#define B10000011 131
|
||||||
|
#define B10000100 132
|
||||||
|
#define B10000101 133
|
||||||
|
#define B10000110 134
|
||||||
|
#define B10000111 135
|
||||||
|
#define B10001000 136
|
||||||
|
#define B10001001 137
|
||||||
|
#define B10001010 138
|
||||||
|
#define B10001011 139
|
||||||
|
#define B10001100 140
|
||||||
|
#define B10001101 141
|
||||||
|
#define B10001110 142
|
||||||
|
#define B10001111 143
|
||||||
|
#define B10010000 144
|
||||||
|
#define B10010001 145
|
||||||
|
#define B10010010 146
|
||||||
|
#define B10010011 147
|
||||||
|
#define B10010100 148
|
||||||
|
#define B10010101 149
|
||||||
|
#define B10010110 150
|
||||||
|
#define B10010111 151
|
||||||
|
#define B10011000 152
|
||||||
|
#define B10011001 153
|
||||||
|
#define B10011010 154
|
||||||
|
#define B10011011 155
|
||||||
|
#define B10011100 156
|
||||||
|
#define B10011101 157
|
||||||
|
#define B10011110 158
|
||||||
|
#define B10011111 159
|
||||||
|
#define B10100000 160
|
||||||
|
#define B10100001 161
|
||||||
|
#define B10100010 162
|
||||||
|
#define B10100011 163
|
||||||
|
#define B10100100 164
|
||||||
|
#define B10100101 165
|
||||||
|
#define B10100110 166
|
||||||
|
#define B10100111 167
|
||||||
|
#define B10101000 168
|
||||||
|
#define B10101001 169
|
||||||
|
#define B10101010 170
|
||||||
|
#define B10101011 171
|
||||||
|
#define B10101100 172
|
||||||
|
#define B10101101 173
|
||||||
|
#define B10101110 174
|
||||||
|
#define B10101111 175
|
||||||
|
#define B10110000 176
|
||||||
|
#define B10110001 177
|
||||||
|
#define B10110010 178
|
||||||
|
#define B10110011 179
|
||||||
|
#define B10110100 180
|
||||||
|
#define B10110101 181
|
||||||
|
#define B10110110 182
|
||||||
|
#define B10110111 183
|
||||||
|
#define B10111000 184
|
||||||
|
#define B10111001 185
|
||||||
|
#define B10111010 186
|
||||||
|
#define B10111011 187
|
||||||
|
#define B10111100 188
|
||||||
|
#define B10111101 189
|
||||||
|
#define B10111110 190
|
||||||
|
#define B10111111 191
|
||||||
|
#define B11000000 192
|
||||||
|
#define B11000001 193
|
||||||
|
#define B11000010 194
|
||||||
|
#define B11000011 195
|
||||||
|
#define B11000100 196
|
||||||
|
#define B11000101 197
|
||||||
|
#define B11000110 198
|
||||||
|
#define B11000111 199
|
||||||
|
#define B11001000 200
|
||||||
|
#define B11001001 201
|
||||||
|
#define B11001010 202
|
||||||
|
#define B11001011 203
|
||||||
|
#define B11001100 204
|
||||||
|
#define B11001101 205
|
||||||
|
#define B11001110 206
|
||||||
|
#define B11001111 207
|
||||||
|
#define B11010000 208
|
||||||
|
#define B11010001 209
|
||||||
|
#define B11010010 210
|
||||||
|
#define B11010011 211
|
||||||
|
#define B11010100 212
|
||||||
|
#define B11010101 213
|
||||||
|
#define B11010110 214
|
||||||
|
#define B11010111 215
|
||||||
|
#define B11011000 216
|
||||||
|
#define B11011001 217
|
||||||
|
#define B11011010 218
|
||||||
|
#define B11011011 219
|
||||||
|
#define B11011100 220
|
||||||
|
#define B11011101 221
|
||||||
|
#define B11011110 222
|
||||||
|
#define B11011111 223
|
||||||
|
#define B11100000 224
|
||||||
|
#define B11100001 225
|
||||||
|
#define B11100010 226
|
||||||
|
#define B11100011 227
|
||||||
|
#define B11100100 228
|
||||||
|
#define B11100101 229
|
||||||
|
#define B11100110 230
|
||||||
|
#define B11100111 231
|
||||||
|
#define B11101000 232
|
||||||
|
#define B11101001 233
|
||||||
|
#define B11101010 234
|
||||||
|
#define B11101011 235
|
||||||
|
#define B11101100 236
|
||||||
|
#define B11101101 237
|
||||||
|
#define B11101110 238
|
||||||
|
#define B11101111 239
|
||||||
|
#define B11110000 240
|
||||||
|
#define B11110001 241
|
||||||
|
#define B11110010 242
|
||||||
|
#define B11110011 243
|
||||||
|
#define B11110100 244
|
||||||
|
#define B11110101 245
|
||||||
|
#define B11110110 246
|
||||||
|
#define B11110111 247
|
||||||
|
#define B11111000 248
|
||||||
|
#define B11111001 249
|
||||||
|
#define B11111010 250
|
||||||
|
#define B11111011 251
|
||||||
|
#define B11111100 252
|
||||||
|
#define B11111101 253
|
||||||
|
#define B11111110 254
|
||||||
|
#define B11111111 255
|
||||||
|
|
||||||
|
#endif
|
196
cores/esp32/cbuf.cpp
Normal file
196
cores/esp32/cbuf.cpp
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
cbuf.cpp - Circular buffer implementation
|
||||||
|
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cbuf.h"
|
||||||
|
|
||||||
|
cbuf::cbuf(size_t size) :
|
||||||
|
next(NULL), _size(size+1), _buf(new char[size+1]), _bufend(_buf + size + 1), _begin(_buf), _end(_begin)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
cbuf::~cbuf()
|
||||||
|
{
|
||||||
|
delete[] _buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cbuf::resizeAdd(size_t addSize)
|
||||||
|
{
|
||||||
|
return resize(_size + addSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cbuf::resize(size_t newSize)
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t bytes_available = available();
|
||||||
|
newSize += 1;
|
||||||
|
// not lose any data
|
||||||
|
// if data can be lost use remove or flush before resize
|
||||||
|
if((newSize < bytes_available) || (newSize == _size)) {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *newbuf = new char[newSize];
|
||||||
|
char *oldbuf = _buf;
|
||||||
|
|
||||||
|
if(!newbuf) {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_buf) {
|
||||||
|
read(newbuf, bytes_available);
|
||||||
|
memset((newbuf + bytes_available), 0x00, (newSize - bytes_available));
|
||||||
|
}
|
||||||
|
|
||||||
|
_begin = newbuf;
|
||||||
|
_end = newbuf + bytes_available;
|
||||||
|
_bufend = newbuf + newSize;
|
||||||
|
_size = newSize;
|
||||||
|
|
||||||
|
_buf = newbuf;
|
||||||
|
delete[] oldbuf;
|
||||||
|
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cbuf::available() const
|
||||||
|
{
|
||||||
|
if(_end >= _begin) {
|
||||||
|
return _end - _begin;
|
||||||
|
}
|
||||||
|
return _size - (_begin - _end);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cbuf::size()
|
||||||
|
{
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cbuf::room() const
|
||||||
|
{
|
||||||
|
if(_end >= _begin) {
|
||||||
|
return _size - (_end - _begin) - 1;
|
||||||
|
}
|
||||||
|
return _begin - _end - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cbuf::peek()
|
||||||
|
{
|
||||||
|
if(empty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<int>(*_begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cbuf::peek(char *dst, size_t size)
|
||||||
|
{
|
||||||
|
size_t bytes_available = available();
|
||||||
|
size_t size_to_read = (size < bytes_available) ? size : bytes_available;
|
||||||
|
size_t size_read = size_to_read;
|
||||||
|
char * begin = _begin;
|
||||||
|
if(_end < _begin && size_to_read > (size_t) (_bufend - _begin)) {
|
||||||
|
size_t top_size = _bufend - _begin;
|
||||||
|
memcpy(dst, _begin, top_size);
|
||||||
|
begin = _buf;
|
||||||
|
size_to_read -= top_size;
|
||||||
|
dst += top_size;
|
||||||
|
}
|
||||||
|
memcpy(dst, begin, size_to_read);
|
||||||
|
return size_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cbuf::read()
|
||||||
|
{
|
||||||
|
if(empty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char result = *_begin;
|
||||||
|
_begin = wrap_if_bufend(_begin + 1);
|
||||||
|
return static_cast<int>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cbuf::read(char* dst, size_t size)
|
||||||
|
{
|
||||||
|
size_t bytes_available = available();
|
||||||
|
size_t size_to_read = (size < bytes_available) ? size : bytes_available;
|
||||||
|
size_t size_read = size_to_read;
|
||||||
|
if(_end < _begin && size_to_read > (size_t) (_bufend - _begin)) {
|
||||||
|
size_t top_size = _bufend - _begin;
|
||||||
|
memcpy(dst, _begin, top_size);
|
||||||
|
_begin = _buf;
|
||||||
|
size_to_read -= top_size;
|
||||||
|
dst += top_size;
|
||||||
|
}
|
||||||
|
memcpy(dst, _begin, size_to_read);
|
||||||
|
_begin = wrap_if_bufend(_begin + size_to_read);
|
||||||
|
return size_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cbuf::write(char c)
|
||||||
|
{
|
||||||
|
if(full()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_end = c;
|
||||||
|
_end = wrap_if_bufend(_end + 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cbuf::write(const char* src, size_t size)
|
||||||
|
{
|
||||||
|
size_t bytes_available = room();
|
||||||
|
size_t size_to_write = (size < bytes_available) ? size : bytes_available;
|
||||||
|
size_t size_written = size_to_write;
|
||||||
|
if(_end >= _begin && size_to_write > (size_t) (_bufend - _end)) {
|
||||||
|
size_t top_size = _bufend - _end;
|
||||||
|
memcpy(_end, src, top_size);
|
||||||
|
_end = _buf;
|
||||||
|
size_to_write -= top_size;
|
||||||
|
src += top_size;
|
||||||
|
}
|
||||||
|
memcpy(_end, src, size_to_write);
|
||||||
|
_end = wrap_if_bufend(_end + size_to_write);
|
||||||
|
return size_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cbuf::flush()
|
||||||
|
{
|
||||||
|
_begin = _buf;
|
||||||
|
_end = _buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cbuf::remove(size_t size)
|
||||||
|
{
|
||||||
|
size_t bytes_available = available();
|
||||||
|
if(size >= bytes_available) {
|
||||||
|
flush();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t size_to_remove = (size < bytes_available) ? size : bytes_available;
|
||||||
|
if(_end < _begin && size_to_remove > (size_t) (_bufend - _begin)) {
|
||||||
|
size_t top_size = _bufend - _begin;
|
||||||
|
_begin = _buf;
|
||||||
|
size_to_remove -= top_size;
|
||||||
|
}
|
||||||
|
_begin = wrap_if_bufend(_begin + size_to_remove);
|
||||||
|
return available();
|
||||||
|
}
|
79
cores/esp32/cbuf.h
Normal file
79
cores/esp32/cbuf.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
cbuf.h - Circular buffer implementation
|
||||||
|
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
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 __cbuf_h
|
||||||
|
#define __cbuf_h
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
class cbuf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cbuf(size_t size);
|
||||||
|
~cbuf();
|
||||||
|
|
||||||
|
size_t resizeAdd(size_t addSize);
|
||||||
|
size_t resize(size_t newSize);
|
||||||
|
size_t available() const;
|
||||||
|
size_t size();
|
||||||
|
|
||||||
|
size_t room() const;
|
||||||
|
|
||||||
|
inline bool empty() const
|
||||||
|
{
|
||||||
|
return _begin == _end;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool full() const
|
||||||
|
{
|
||||||
|
return wrap_if_bufend(_end + 1) == _begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
int peek();
|
||||||
|
size_t peek(char *dst, size_t size);
|
||||||
|
|
||||||
|
int read();
|
||||||
|
size_t read(char* dst, size_t size);
|
||||||
|
|
||||||
|
size_t write(char c);
|
||||||
|
size_t write(const char* src, size_t size);
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
size_t remove(size_t size);
|
||||||
|
|
||||||
|
cbuf *next;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline char* wrap_if_bufend(char* ptr) const
|
||||||
|
{
|
||||||
|
return (ptr == _bufend) ? _buf : ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t _size;
|
||||||
|
char* _buf;
|
||||||
|
const char* _bufend;
|
||||||
|
char* _begin;
|
||||||
|
char* _end;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif//__cbuf_h
|
@ -13,20 +13,18 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "esp32-hal-adc.h"
|
#include "esp32-hal-adc.h"
|
||||||
#include "esp32-hal-log.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "soc/rtc_io_reg.h"
|
|
||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#include "soc/sens_reg.h"
|
|
||||||
|
|
||||||
#include "driver/adc.h"
|
#include "driver/adc.h"
|
||||||
|
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
#include "esp_adc_cal.h"
|
#include "esp_adc_cal.h"
|
||||||
|
#include "soc/sens_reg.h"
|
||||||
|
#include "soc/rtc_io_reg.h"
|
||||||
#include "esp32/rom/ets_sys.h"
|
#include "esp32/rom/ets_sys.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
#define DEFAULT_VREF 1100
|
#define DEFAULT_VREF 1100
|
||||||
@ -35,6 +33,10 @@ static uint16_t __analogVRef = 0;
|
|||||||
static uint8_t __analogVRefPin = 0;
|
static uint8_t __analogVRefPin = 0;
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
#include "esp32s2/rom/ets_sys.h"
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
|
#include "soc/sens_reg.h"
|
||||||
|
#include "soc/rtc_io_reg.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/rom/ets_sys.h"
|
||||||
#else
|
#else
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
#endif
|
#endif
|
||||||
@ -42,7 +44,6 @@ static uint8_t __analogVRefPin = 0;
|
|||||||
#include "rom/ets_sys.h"
|
#include "rom/ets_sys.h"
|
||||||
#include "esp_intr.h"
|
#include "esp_intr.h"
|
||||||
#endif
|
#endif
|
||||||
#include "esp32-hal-gpio.h"
|
|
||||||
|
|
||||||
static uint8_t __analogAttenuation = 3;//11db
|
static uint8_t __analogAttenuation = 3;//11db
|
||||||
static uint8_t __analogWidth = 3;//12 bits
|
static uint8_t __analogWidth = 3;//12 bits
|
||||||
@ -53,7 +54,9 @@ void __analogSetClockDiv(uint8_t clockDiv){
|
|||||||
clockDiv = 1;
|
clockDiv = 1;
|
||||||
}
|
}
|
||||||
__analogClockDiv = clockDiv;
|
__analogClockDiv = clockDiv;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||||
adc_set_clk_div(__analogClockDiv);
|
adc_set_clk_div(__analogClockDiv);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void __analogSetAttenuation(adc_attenuation_t attenuation)
|
void __analogSetAttenuation(adc_attenuation_t attenuation)
|
||||||
@ -116,11 +119,14 @@ bool __adcAttachPin(uint8_t pin){
|
|||||||
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, touch);
|
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, touch);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else if(pin == 25){
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
else if(pin == 25){
|
||||||
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);//stop dac1
|
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);//stop dac1
|
||||||
} else if(pin == 26){
|
} else if(pin == 26){
|
||||||
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE);//stop dac2
|
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE);//stop dac2
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
pinMode(pin, ANALOG);
|
pinMode(pin, ANALOG);
|
||||||
__analogSetPinAttenuation(pin, __analogAttenuation);
|
__analogSetPinAttenuation(pin, __analogAttenuation);
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "esp32-hal.h"
|
||||||
#include <stdbool.h>
|
|
||||||
//#include "esp32-hal.h"
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ADC_0db,
|
ADC_0db,
|
||||||
|
100
cores/esp32/esp32-hal-bt.c
Normal file
100
cores/esp32/esp32-hal-bt.c
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// Copyright 2015-2016 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-bt.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
|
||||||
|
bool btInUse(){ return true; }
|
||||||
|
|
||||||
|
#include "esp_bt.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_BTDM_CONTROLLER_MODE_BTDM
|
||||||
|
#define BT_MODE ESP_BT_MODE_BTDM
|
||||||
|
#elif defined(CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY)
|
||||||
|
#define BT_MODE ESP_BT_MODE_CLASSIC_BT
|
||||||
|
#else
|
||||||
|
#define BT_MODE ESP_BT_MODE_BLE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool btStarted(){
|
||||||
|
return (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool btStart(){
|
||||||
|
esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||||
|
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE){
|
||||||
|
esp_bt_controller_init(&cfg);
|
||||||
|
while(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE){}
|
||||||
|
}
|
||||||
|
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED){
|
||||||
|
if (esp_bt_controller_enable(BT_MODE)) {
|
||||||
|
log_e("BT Enable failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
log_e("BT Start failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool btStop(){
|
||||||
|
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED){
|
||||||
|
if (esp_bt_controller_disable()) {
|
||||||
|
log_e("BT Disable failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED);
|
||||||
|
}
|
||||||
|
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED){
|
||||||
|
if (esp_bt_controller_deinit()) {
|
||||||
|
log_e("BT deint failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
vTaskDelay(1);
|
||||||
|
if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
log_e("BT Stop failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // CONFIG_BT_ENABLED
|
||||||
|
bool btStarted()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool btStart()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool btStop()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_BT_ENABLED
|
||||||
|
|
32
cores/esp32/esp32-hal-bt.h
Normal file
32
cores/esp32/esp32-hal-bt.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2015-2016 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 _ESP32_ESP32_HAL_BT_H_
|
||||||
|
#define _ESP32_ESP32_HAL_BT_H_
|
||||||
|
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool btStarted();
|
||||||
|
bool btStart();
|
||||||
|
bool btStop();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _ESP32_ESP32_HAL_BT_H_ */
|
@ -16,7 +16,6 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/xtensa_timer.h"
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
@ -25,14 +24,17 @@
|
|||||||
#include "soc/efuse_reg.h"
|
#include "soc/efuse_reg.h"
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
#include "esp32-hal-cpu.h"
|
#include "esp32-hal-cpu.h"
|
||||||
#include "esp32-hal-log.h"
|
|
||||||
|
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "freertos/xtensa_timer.h"
|
||||||
#include "esp32/rom/rtc.h"
|
#include "esp32/rom/rtc.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "freertos/xtensa_timer.h"
|
||||||
#include "esp32s2/rom/rtc.h"
|
#include "esp32s2/rom/rtc.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/rom/rtc.h"
|
||||||
#else
|
#else
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
#endif
|
#endif
|
||||||
@ -49,7 +51,7 @@ typedef struct apb_change_cb_s {
|
|||||||
|
|
||||||
|
|
||||||
static apb_change_t * apb_change_callbacks = NULL;
|
static apb_change_t * apb_change_callbacks = NULL;
|
||||||
static SemaphoreHandle_t apb_change_lock = NULL;
|
static xSemaphoreHandle apb_change_lock = NULL;
|
||||||
|
|
||||||
static void initApbChangeCallback(){
|
static void initApbChangeCallback(){
|
||||||
static volatile bool initialized = false;
|
static volatile bool initialized = false;
|
||||||
@ -102,7 +104,7 @@ bool addApbChangeCallback(void * arg, apb_change_cb_t cb){
|
|||||||
// look for duplicate callbacks
|
// look for duplicate callbacks
|
||||||
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
|
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
|
||||||
if (r) {
|
if (r) {
|
||||||
log_e("duplicate func=%08X arg=%08X",(unsigned int)c->cb,(unsigned int)c->arg);
|
log_e("duplicate func=%08X arg=%08X",c->cb,c->arg);
|
||||||
free(c);
|
free(c);
|
||||||
xSemaphoreGive(apb_change_lock);
|
xSemaphoreGive(apb_change_lock);
|
||||||
return false;
|
return false;
|
||||||
@ -124,7 +126,7 @@ bool removeApbChangeCallback(void * arg, apb_change_cb_t cb){
|
|||||||
// look for matching callback
|
// look for matching callback
|
||||||
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
|
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
|
||||||
if ( r == NULL ) {
|
if ( r == NULL ) {
|
||||||
log_e("not found func=%08X arg=%08X",(unsigned int)cb,(unsigned int)arg);
|
log_e("not found func=%08X arg=%08X",cb,arg);
|
||||||
xSemaphoreGive(apb_change_lock);
|
xSemaphoreGive(apb_change_lock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -142,10 +144,14 @@ bool removeApbChangeCallback(void * arg, apb_change_cb_t cb){
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t calculateApb(rtc_cpu_freq_config_t * conf){
|
static uint32_t calculateApb(rtc_cpu_freq_config_t * conf){
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
return APB_CLK_FREQ;
|
||||||
|
#else
|
||||||
if(conf->freq_mhz >= 80){
|
if(conf->freq_mhz >= 80){
|
||||||
return 80 * MHZ;
|
return 80 * MHZ;
|
||||||
}
|
}
|
||||||
return (conf->source_freq_mhz * MHZ) / conf->div;
|
return (conf->source_freq_mhz * MHZ) / conf->div;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us); //private in IDF
|
void esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us); //private in IDF
|
||||||
@ -220,8 +226,12 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
|
|||||||
esp_timer_impl_update_apb_freq(apb / MHZ);
|
esp_timer_impl_update_apb_freq(apb / MHZ);
|
||||||
}
|
}
|
||||||
//Update FreeRTOS Tick Divisor
|
//Update FreeRTOS Tick Divisor
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
|
||||||
|
#else
|
||||||
uint32_t fcpu = (conf.freq_mhz >= 80)?(conf.freq_mhz * MHZ):(apb);
|
uint32_t fcpu = (conf.freq_mhz >= 80)?(conf.freq_mhz * MHZ):(apb);
|
||||||
_xt_tick_divisor = fcpu / XT_TICK_PER_SEC;
|
_xt_tick_divisor = fcpu / XT_TICK_PER_SEC;
|
||||||
|
#endif
|
||||||
//Call peripheral functions after the APB change
|
//Call peripheral functions after the APB change
|
||||||
if(apb_change_callbacks){
|
if(apb_change_callbacks){
|
||||||
triggerApbChangeCallback(APB_AFTER_CHANGE, capb, apb);
|
triggerApbChangeCallback(APB_AFTER_CHANGE, capb, apb);
|
||||||
|
@ -45,16 +45,4 @@ uint32_t getApbFrequency(); // In Hz
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef F_CPU
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
|
||||||
#define F_CPU (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000U)
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
||||||
#define F_CPU (CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ * 1000000U)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define clockCyclesPerMicrosecond() ( (long int)getCpuFrequencyMhz() )
|
|
||||||
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
|
|
||||||
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
|
|
||||||
|
|
||||||
#endif /* _ESP32_HAL_CPU_H_ */
|
#endif /* _ESP32_HAL_CPU_H_ */
|
||||||
|
@ -13,24 +13,28 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
#include "esp_attr.h"
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
#include "soc/rtc_io_reg.h"
|
#include "soc/rtc_io_reg.h"
|
||||||
|
#define DAC1 25
|
||||||
|
#define DAC2 26
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "soc/rtc_io_reg.h"
|
||||||
|
#define DAC1 17
|
||||||
|
#define DAC2 18
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#define NODAC
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NODAC
|
||||||
|
#include "esp_attr.h"
|
||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#include "soc/rtc_io_periph.h"
|
#include "soc/rtc_io_periph.h"
|
||||||
#include "soc/sens_reg.h"
|
#include "soc/sens_reg.h"
|
||||||
#include "soc/sens_struct.h"
|
#include "soc/sens_struct.h"
|
||||||
#include "driver/dac.h"
|
#include "driver/dac.h"
|
||||||
#include "esp32-hal-gpio.h"
|
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
#define DAC1 25
|
|
||||||
#define DAC2 26
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
||||||
#define DAC1 17
|
|
||||||
#define DAC2 18
|
|
||||||
#else
|
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ARDUINO_ISR_ATTR __dacWrite(uint8_t pin, uint8_t value)
|
void ARDUINO_ISR_ATTR __dacWrite(uint8_t pin, uint8_t value)
|
||||||
{
|
{
|
||||||
@ -55,3 +59,5 @@ void ARDUINO_ISR_ATTR __dacWrite(uint8_t pin, uint8_t value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern void dacWrite(uint8_t pin, uint8_t value) __attribute__ ((weak, alias("__dacWrite")));
|
extern void dacWrite(uint8_t pin, uint8_t value) __attribute__ ((weak, alias("__dacWrite")));
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
|
||||||
void dacWrite(uint8_t pin, uint8_t value);
|
void dacWrite(uint8_t pin, uint8_t value);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "esp32-hal.h"
|
|
||||||
#include "esp32-hal-gpio.h"
|
#include "esp32-hal-gpio.h"
|
||||||
#include "pins_arduino.h"
|
#include "pins_arduino.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
@ -21,24 +20,25 @@
|
|||||||
#include "soc/gpio_reg.h"
|
#include "soc/gpio_reg.h"
|
||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
#include "soc/gpio_struct.h"
|
#include "soc/gpio_struct.h"
|
||||||
#include "soc/rtc_io_reg.h"
|
#include "driver/gpio.h"
|
||||||
#include "soc/rtc_io_periph.h"
|
|
||||||
|
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
|
|
||||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
#include "esp32/rom/ets_sys.h"
|
#include "esp32/rom/ets_sys.h"
|
||||||
#include "esp32/rom/gpio.h"
|
#include "esp32/rom/gpio.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
|
#include "soc/rtc_io_reg.h"
|
||||||
#define GPIO_FUNC 2
|
#define GPIO_FUNC 2
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
#include "esp32s2/rom/ets_sys.h"
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
#include "esp32s2/rom/gpio.h"
|
#include "esp32s2/rom/gpio.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
#include "soc/periph_defs.h"
|
#include "soc/periph_defs.h"
|
||||||
|
#include "soc/rtc_io_reg.h"
|
||||||
#define GPIO_FUNC 1
|
#define GPIO_FUNC 1
|
||||||
#else
|
#else
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
#define USE_ESP_IDF_GPIO 1
|
||||||
#endif
|
#endif
|
||||||
#else // ESP32 Before IDF 4.0
|
#else // ESP32 Before IDF 4.0
|
||||||
#include "rom/ets_sys.h"
|
#include "rom/ets_sys.h"
|
||||||
@ -159,7 +159,45 @@ static InterruptHandle_t __pinInterruptHandlers[SOC_GPIO_PIN_COUNT] = {0,};
|
|||||||
|
|
||||||
extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode)
|
extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode)
|
||||||
{
|
{
|
||||||
|
#if USE_ESP_IDF_GPIO
|
||||||
|
if (!GPIO_IS_VALID_GPIO(pin)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gpio_config_t conf = {
|
||||||
|
.pin_bit_mask = (1ULL<<pin), /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
|
||||||
|
.mode = GPIO_MODE_DISABLE, /*!< GPIO mode: set input/output mode */
|
||||||
|
.pull_up_en = GPIO_PULLUP_DISABLE, /*!< GPIO pull-up */
|
||||||
|
.pull_down_en = GPIO_PULLDOWN_DISABLE, /*!< GPIO pull-down */
|
||||||
|
.intr_type = GPIO_INTR_DISABLE /*!< GPIO interrupt type */
|
||||||
|
};
|
||||||
|
if (mode < 0x20) {//io
|
||||||
|
conf.mode = mode & (INPUT | OUTPUT);
|
||||||
|
if (mode & OPEN_DRAIN) {
|
||||||
|
conf.mode |= GPIO_MODE_DEF_OD;
|
||||||
|
}
|
||||||
|
if (mode & PULLUP) {
|
||||||
|
conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||||
|
}
|
||||||
|
if (mode & PULLDOWN) {
|
||||||
|
conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gpio_config(&conf);
|
||||||
|
|
||||||
|
if(mode == SPECIAL){
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pin], (uint32_t)(((pin)==RX||(pin)==TX)?0:1));
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pin], (uint32_t)(((pin)==RX||(pin)==TX)?0:2));
|
||||||
|
#endif
|
||||||
|
} else if(mode == ANALOG){
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
//adc_gpio_init(ADC_UNIT_1, ADC_CHANNEL_0);
|
||||||
|
#endif
|
||||||
|
} else if(mode >= 0x20 && mode < ANALOG) {//function
|
||||||
|
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pin], mode >> 5);
|
||||||
|
}
|
||||||
|
#else
|
||||||
if(!digitalPinIsValid(pin)) {
|
if(!digitalPinIsValid(pin)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -230,11 +268,7 @@ extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode)
|
|||||||
pinFunction |= FUN_IE;//input enable but required for output as well?
|
pinFunction |= FUN_IE;//input enable but required for output as well?
|
||||||
|
|
||||||
if(mode & (INPUT | OUTPUT)) {
|
if(mode & (INPUT | OUTPUT)) {
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
pinFunction |= ((uint32_t)PIN_FUNC_GPIO << MCU_SEL_S);
|
||||||
pinFunction |= ((uint32_t)2 << MCU_SEL_S);
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
||||||
pinFunction |= ((uint32_t)1 << MCU_SEL_S);
|
|
||||||
#endif
|
|
||||||
} else if(mode == SPECIAL) {
|
} else if(mode == SPECIAL) {
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
pinFunction |= ((uint32_t)(((pin)==RX||(pin)==TX)?0:1) << MCU_SEL_S);
|
pinFunction |= ((uint32_t)(((pin)==RX||(pin)==TX)?0:1) << MCU_SEL_S);
|
||||||
@ -252,10 +286,20 @@ extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GPIO.pin[pin].val = pinControl;
|
GPIO.pin[pin].val = pinControl;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val)
|
extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val)
|
||||||
{
|
{
|
||||||
|
#if USE_ESP_IDF_GPIO
|
||||||
|
gpio_set_level((gpio_num_t)pin, val);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
if (val) {
|
||||||
|
GPIO.out_w1ts.out_w1ts = (1 << pin);
|
||||||
|
} else {
|
||||||
|
GPIO.out_w1tc.out_w1tc = (1 << pin);
|
||||||
|
}
|
||||||
|
#else
|
||||||
if(val) {
|
if(val) {
|
||||||
if(pin < 32) {
|
if(pin < 32) {
|
||||||
GPIO.out_w1ts = ((uint32_t)1 << pin);
|
GPIO.out_w1ts = ((uint32_t)1 << pin);
|
||||||
@ -269,18 +313,37 @@ extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val)
|
|||||||
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int ARDUINO_ISR_ATTR __digitalRead(uint8_t pin)
|
extern int ARDUINO_ISR_ATTR __digitalRead(uint8_t pin)
|
||||||
{
|
{
|
||||||
|
#if USE_ESP_IDF_GPIO
|
||||||
|
return gpio_get_level((gpio_num_t)pin);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
return (GPIO.in.data >> pin) & 0x1;
|
||||||
|
#else
|
||||||
if(pin < 32) {
|
if(pin < 32) {
|
||||||
return (GPIO.in >> pin) & 0x1;
|
return (GPIO.in >> pin) & 0x1;
|
||||||
} else if(pin < GPIO_PIN_COUNT) {
|
} else if(pin < GPIO_PIN_COUNT) {
|
||||||
return (GPIO.in1.val >> (pin - 32)) & 0x1;
|
return (GPIO.in1.val >> (pin - 32)) & 0x1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_ESP_IDF_GPIO
|
||||||
|
static void ARDUINO_ISR_ATTR __onPinInterrupt(void * arg) {
|
||||||
|
InterruptHandle_t * isr = (InterruptHandle_t*)arg;
|
||||||
|
if(isr->fn) {
|
||||||
|
if(isr->arg){
|
||||||
|
((voidFuncPtrArg)isr->fn)(isr->arg);
|
||||||
|
} else {
|
||||||
|
isr->fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
static intr_handle_t gpio_intr_handle = NULL;
|
static intr_handle_t gpio_intr_handle = NULL;
|
||||||
|
|
||||||
static void ARDUINO_ISR_ATTR __onPinInterrupt()
|
static void ARDUINO_ISR_ATTR __onPinInterrupt()
|
||||||
@ -322,6 +385,7 @@ static void ARDUINO_ISR_ATTR __onPinInterrupt()
|
|||||||
} while(++pin<GPIO_PIN_COUNT);
|
} while(++pin<GPIO_PIN_COUNT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
extern void cleanupFunctional(void* arg);
|
extern void cleanupFunctional(void* arg);
|
||||||
|
|
||||||
@ -330,8 +394,17 @@ extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc,
|
|||||||
static bool interrupt_initialized = false;
|
static bool interrupt_initialized = false;
|
||||||
|
|
||||||
if(!interrupt_initialized) {
|
if(!interrupt_initialized) {
|
||||||
|
#if USE_ESP_IDF_GPIO
|
||||||
|
esp_err_t err = gpio_install_isr_service((int)ARDUINO_ISR_FLAG);
|
||||||
|
interrupt_initialized = (err == ESP_OK) || (err == ESP_ERR_INVALID_STATE);
|
||||||
|
#else
|
||||||
interrupt_initialized = true;
|
interrupt_initialized = true;
|
||||||
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, __onPinInterrupt, NULL, &gpio_intr_handle);
|
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, __onPinInterrupt, NULL, &gpio_intr_handle);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if(!interrupt_initialized) {
|
||||||
|
log_e("GPIO ISR Service Failed To Start");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if new attach without detach remove old info
|
// if new attach without detach remove old info
|
||||||
@ -343,6 +416,14 @@ extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc,
|
|||||||
__pinInterruptHandlers[pin].arg = arg;
|
__pinInterruptHandlers[pin].arg = arg;
|
||||||
__pinInterruptHandlers[pin].functional = functional;
|
__pinInterruptHandlers[pin].functional = functional;
|
||||||
|
|
||||||
|
#if USE_ESP_IDF_GPIO
|
||||||
|
gpio_set_intr_type((gpio_num_t)pin, (gpio_int_type_t)(intr_type & 0x7));
|
||||||
|
if(intr_type & 0x8){
|
||||||
|
gpio_wakeup_enable((gpio_num_t)pin, (gpio_int_type_t)(intr_type & 0x7));
|
||||||
|
}
|
||||||
|
gpio_isr_handler_add((gpio_num_t)pin, __onPinInterrupt, &__pinInterruptHandlers[pin]);
|
||||||
|
gpio_intr_enable((gpio_num_t)pin);
|
||||||
|
#else
|
||||||
esp_intr_disable(gpio_intr_handle);
|
esp_intr_disable(gpio_intr_handle);
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU
|
if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU
|
||||||
@ -355,6 +436,7 @@ extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc,
|
|||||||
#endif
|
#endif
|
||||||
GPIO.pin[pin].int_type = intr_type;
|
GPIO.pin[pin].int_type = intr_type;
|
||||||
esp_intr_enable(gpio_intr_handle);
|
esp_intr_enable(gpio_intr_handle);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type)
|
extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type)
|
||||||
@ -368,7 +450,13 @@ extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int intr_type)
|
|||||||
|
|
||||||
extern void __detachInterrupt(uint8_t pin)
|
extern void __detachInterrupt(uint8_t pin)
|
||||||
{
|
{
|
||||||
|
#if USE_ESP_IDF_GPIO
|
||||||
|
gpio_intr_disable((gpio_num_t)pin);
|
||||||
|
gpio_isr_handler_remove((gpio_num_t)pin);
|
||||||
|
gpio_wakeup_disable((gpio_num_t)pin);
|
||||||
|
#else
|
||||||
esp_intr_disable(gpio_intr_handle);
|
esp_intr_disable(gpio_intr_handle);
|
||||||
|
#endif
|
||||||
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg)
|
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg)
|
||||||
{
|
{
|
||||||
cleanupFunctional(__pinInterruptHandlers[pin].arg);
|
cleanupFunctional(__pinInterruptHandlers[pin].arg);
|
||||||
@ -377,9 +465,13 @@ extern void __detachInterrupt(uint8_t pin)
|
|||||||
__pinInterruptHandlers[pin].arg = NULL;
|
__pinInterruptHandlers[pin].arg = NULL;
|
||||||
__pinInterruptHandlers[pin].functional = false;
|
__pinInterruptHandlers[pin].functional = false;
|
||||||
|
|
||||||
|
#if USE_ESP_IDF_GPIO
|
||||||
|
gpio_set_intr_type((gpio_num_t)pin, GPIO_INTR_DISABLE);
|
||||||
|
#else
|
||||||
GPIO.pin[pin].int_ena = 0;
|
GPIO.pin[pin].int_ena = 0;
|
||||||
GPIO.pin[pin].int_type = 0;
|
GPIO.pin[pin].int_type = 0;
|
||||||
esp_intr_enable(gpio_intr_handle);
|
esp_intr_enable(gpio_intr_handle);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,11 +24,11 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "stdint.h"
|
#include "esp32-hal.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
|
|
||||||
#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||||
#define NUM_OUPUT_PINS 45
|
#define NUM_OUPUT_PINS 46
|
||||||
#define PIN_DAC1 17
|
#define PIN_DAC1 17
|
||||||
#define PIN_DAC2 18
|
#define PIN_DAC2 18
|
||||||
#else
|
#else
|
||||||
|
@ -12,38 +12,34 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "esp32-hal-i2c.h"
|
#include "esp32-hal-i2c.h"
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "freertos/event_groups.h"
|
#include "freertos/event_groups.h"
|
||||||
#include "esp_private/periph_ctrl.h"
|
#include "driver/periph_ctrl.h"
|
||||||
#include "soc/i2c_reg.h"
|
#include "soc/i2c_reg.h"
|
||||||
#include "soc/i2c_struct.h"
|
#include "soc/i2c_struct.h"
|
||||||
#include "soc/dport_reg.h"
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp32-hal-cpu.h" // cpu clock change support 31DEC2018
|
#include "esp32-hal-cpu.h" // cpu clock change support 31DEC2018
|
||||||
#include "esp32-hal-log.h"
|
|
||||||
#include "esp32-hal-gpio.h"
|
|
||||||
#include "esp32-hal-matrix.h"
|
|
||||||
#include "esp32-hal-misc.h"
|
|
||||||
|
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "soc/dport_reg.h"
|
||||||
#include "esp32/rom/ets_sys.h"
|
#include "esp32/rom/ets_sys.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "soc/dport_reg.h"
|
||||||
#include "esp32s2/rom/ets_sys.h"
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/rom/ets_sys.h"
|
||||||
#else
|
#else
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
#endif
|
#endif
|
||||||
#else // ESP32 Before IDF 4.0
|
#else // ESP32 Before IDF 4.0
|
||||||
#include "rom/ets_sys.h"
|
#include "rom/ets_sys.h"
|
||||||
#endif
|
#endif
|
||||||
#include "driver/gpio.h"
|
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
@ -191,7 +187,7 @@ typedef struct {
|
|||||||
struct i2c_struct_t {
|
struct i2c_struct_t {
|
||||||
i2c_dev_t * dev;
|
i2c_dev_t * dev;
|
||||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||||
SemaphoreHandle_t lock;
|
xSemaphoreHandle lock;
|
||||||
#endif
|
#endif
|
||||||
uint8_t num;
|
uint8_t num;
|
||||||
int8_t sda;
|
int8_t sda;
|
||||||
@ -338,7 +334,7 @@ static void i2cDumpDqData(i2c_t * i2c)
|
|||||||
static void i2cDumpI2c(i2c_t * i2c)
|
static void i2cDumpI2c(i2c_t * i2c)
|
||||||
{
|
{
|
||||||
log_e("i2c=%p",i2c);
|
log_e("i2c=%p",i2c);
|
||||||
log_i("dev=%p date=%u",i2c->dev,i2c->dev->date);
|
log_i("dev=%p date=%p",i2c->dev,i2c->dev->date);
|
||||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||||
log_i("lock=%p",i2c->lock);
|
log_i("lock=%p",i2c->lock);
|
||||||
#endif
|
#endif
|
||||||
@ -1152,7 +1148,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
|
|||||||
if(multiMaster){// try to let the bus clear by its self
|
if(multiMaster){// try to let the bus clear by its self
|
||||||
uint32_t timeOutTick = millis();
|
uint32_t timeOutTick = millis();
|
||||||
while((i2c->dev->status_reg.bus_busy)&&(millis()-timeOutTick<timeOutMillis())){
|
while((i2c->dev->status_reg.bus_busy)&&(millis()-timeOutTick<timeOutMillis())){
|
||||||
vTaskDelay(2 / portTICK_PERIOD_MS); // allow task switch
|
delay(2); // allow task switch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(i2c->dev->status_reg.bus_busy){ // still busy, so die
|
if(i2c->dev->status_reg.bus_busy){ // still busy, so die
|
||||||
@ -1296,7 +1292,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
|
|||||||
// how many ticks should it take to transfer totalBytes through the I2C hardware,
|
// how many ticks should it take to transfer totalBytes through the I2C hardware,
|
||||||
// add user supplied timeOutMillis to Calculated Value
|
// add user supplied timeOutMillis to Calculated Value
|
||||||
|
|
||||||
TickType_t ticksTimeOut = ((totalBytes*10*1000)/(i2cGetFrequency(i2c))+timeOutMillis)/portTICK_PERIOD_MS;
|
portTickType ticksTimeOut = ((totalBytes*10*1000)/(i2cGetFrequency(i2c))+timeOutMillis)/portTICK_PERIOD_MS;
|
||||||
|
|
||||||
i2c->dev->ctr.trans_start=1; // go for it
|
i2c->dev->ctr.trans_start=1; // go for it
|
||||||
|
|
||||||
@ -1802,7 +1798,7 @@ struct i2c_struct_t {
|
|||||||
static i2c_t * i2c_ports[2] = {NULL, NULL};
|
static i2c_t * i2c_ports[2] = {NULL, NULL};
|
||||||
|
|
||||||
i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t clk_speed){
|
i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t clk_speed){
|
||||||
if(i2c_num >= 2){
|
if(i2c_num >= SOC_I2C_NUM){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(!clk_speed){
|
if(!clk_speed){
|
||||||
@ -1823,7 +1819,7 @@ i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t clk_speed){
|
|||||||
i2c_driver_delete((i2c_port_t)i2c_num);
|
i2c_driver_delete((i2c_port_t)i2c_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_config_t conf;
|
i2c_config_t conf = { };
|
||||||
conf.mode = I2C_MODE_MASTER;
|
conf.mode = I2C_MODE_MASTER;
|
||||||
conf.scl_io_num = (gpio_num_t)scl;
|
conf.scl_io_num = (gpio_num_t)scl;
|
||||||
conf.sda_io_num = (gpio_num_t)sda;
|
conf.sda_io_num = (gpio_num_t)sda;
|
||||||
|
@ -17,23 +17,25 @@
|
|||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "esp32-hal-matrix.h"
|
#include "esp32-hal-matrix.h"
|
||||||
#include "esp32-hal-log.h"
|
|
||||||
#include "soc/dport_reg.h"
|
|
||||||
#include "soc/ledc_reg.h"
|
#include "soc/ledc_reg.h"
|
||||||
#include "soc/ledc_struct.h"
|
#include "soc/ledc_struct.h"
|
||||||
#include "esp32-hal-cpu.h"
|
#include "driver/periph_ctrl.h"
|
||||||
#include "esp32-hal-gpio.h"
|
|
||||||
#include "esp32-hal-ledc.h"
|
|
||||||
|
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "soc/dport_reg.h"
|
||||||
#include "esp32/rom/ets_sys.h"
|
#include "esp32/rom/ets_sys.h"
|
||||||
#define LAST_CHAN (15)
|
#define LAST_CHAN (15)
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "soc/dport_reg.h"
|
||||||
#include "esp32s2/rom/ets_sys.h"
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
#define LAST_CHAN (7)
|
#define LAST_CHAN (7)
|
||||||
#define LEDC_DIV_NUM_HSTIMER0_V LEDC_CLK_DIV_LSTIMER0_V
|
#define LEDC_DIV_NUM_HSTIMER0_V LEDC_CLK_DIV_LSTIMER0_V
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/rom/ets_sys.h"
|
||||||
|
#define LAST_CHAN (7)
|
||||||
|
#define LEDC_DIV_NUM_HSTIMER0_V LEDC_CLK_DIV_LSTIMER0_V
|
||||||
#else
|
#else
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
#endif
|
#endif
|
||||||
@ -47,7 +49,7 @@
|
|||||||
#else
|
#else
|
||||||
#define LEDC_MUTEX_LOCK() do {} while (xSemaphoreTake(_ledc_sys_lock, portMAX_DELAY) != pdPASS)
|
#define LEDC_MUTEX_LOCK() do {} while (xSemaphoreTake(_ledc_sys_lock, portMAX_DELAY) != pdPASS)
|
||||||
#define LEDC_MUTEX_UNLOCK() xSemaphoreGive(_ledc_sys_lock)
|
#define LEDC_MUTEX_UNLOCK() xSemaphoreGive(_ledc_sys_lock)
|
||||||
SemaphoreHandle_t _ledc_sys_lock = NULL;
|
xSemaphoreHandle _ledc_sys_lock = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -115,8 +117,7 @@ static void _ledcSetupTimer(uint8_t chan, uint32_t div_num, uint8_t bit_num, boo
|
|||||||
static uint16_t _activeChannels = 0;
|
static uint16_t _activeChannels = 0;
|
||||||
if(!tHasStarted) {
|
if(!tHasStarted) {
|
||||||
tHasStarted = true;
|
tHasStarted = true;
|
||||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN);
|
periph_module_enable(PERIPH_LEDC_MODULE);
|
||||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST);
|
|
||||||
LEDC.conf.apb_clk_sel = 1;//LS use apb clock
|
LEDC.conf.apb_clk_sel = 1;//LS use apb clock
|
||||||
addApbChangeCallback((void*)&_activeChannels, _on_apb_change);
|
addApbChangeCallback((void*)&_activeChannels, _on_apb_change);
|
||||||
|
|
||||||
@ -306,7 +307,7 @@ void ledcAttachPin(uint8_t pin, uint8_t chan)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pinMode(pin, OUTPUT);
|
pinMode(pin, OUTPUT);
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
pinMatrixOutAttach(pin, LEDC_LS_SIG_OUT0_IDX + chan, false, false);
|
pinMatrixOutAttach(pin, LEDC_LS_SIG_OUT0_IDX + chan, false, false);
|
||||||
#else
|
#else
|
||||||
pinMatrixOutAttach(pin, ((chan/8)?LEDC_LS_SIG_OUT0_IDX:LEDC_HS_SIG_OUT0_IDX) + (chan%8), false, false);
|
pinMatrixOutAttach(pin, ((chan/8)?LEDC_LS_SIG_OUT0_IDX:LEDC_HS_SIG_OUT0_IDX) + (chan%8), false, false);
|
||||||
@ -317,3 +318,12 @@ void ledcDetachPin(uint8_t pin)
|
|||||||
{
|
{
|
||||||
pinMatrixOutDetach(pin, false, false);
|
pinMatrixOutDetach(pin, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double ledcChangeFrequency(uint8_t chan, double freq, uint8_t bit_num)
|
||||||
|
{
|
||||||
|
if (chan > 15) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
double res_freq = _ledcSetupTimerFreq(chan, freq, bit_num);
|
||||||
|
return res_freq;
|
||||||
|
}
|
||||||
|
@ -35,6 +35,7 @@ uint32_t ledcRead(uint8_t channel);
|
|||||||
double ledcReadFreq(uint8_t channel);
|
double ledcReadFreq(uint8_t channel);
|
||||||
void ledcAttachPin(uint8_t pin, uint8_t channel);
|
void ledcAttachPin(uint8_t pin, uint8_t channel);
|
||||||
void ledcDetachPin(uint8_t pin);
|
void ledcDetachPin(uint8_t pin);
|
||||||
|
double ledcChangeFrequency(uint8_t channel, double freq, uint8_t resolution_bits);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
19
cores/esp32/esp32-hal-log.c
Normal file
19
cores/esp32/esp32-hal-log.c
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef __MY_LOG__
|
||||||
|
#define __MY_LOG__
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "esp32-hal-log.h"
|
||||||
|
void log_to_esp(char* tag, esp_log_level_t level, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list va_args;
|
||||||
|
va_start(va_args, format);
|
||||||
|
|
||||||
|
char log_buffer[512];
|
||||||
|
int len = vsnprintf(log_buffer, sizeof(log_buffer), format, va_args);
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
ESP_LOG_LEVEL_LOCAL(level, tag, "%s", log_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(va_args);
|
||||||
|
}
|
||||||
|
#endif
|
@ -21,7 +21,6 @@ extern "C"
|
|||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "esp_log.h"
|
|
||||||
|
|
||||||
#define ARDUHAL_LOG_LEVEL_NONE (0)
|
#define ARDUHAL_LOG_LEVEL_NONE (0)
|
||||||
#define ARDUHAL_LOG_LEVEL_ERROR (1)
|
#define ARDUHAL_LOG_LEVEL_ERROR (1)
|
||||||
@ -38,6 +37,9 @@ extern "C"
|
|||||||
#define ARDUHAL_LOG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL
|
#define ARDUHAL_LOG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL
|
||||||
#else
|
#else
|
||||||
#define ARDUHAL_LOG_LEVEL CORE_DEBUG_LEVEL
|
#define ARDUHAL_LOG_LEVEL CORE_DEBUG_LEVEL
|
||||||
|
#ifdef USE_ESP_IDF_LOG
|
||||||
|
#define LOG_LOCAL_LEVEL CORE_DEBUG_LEVEL
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_ARDUHAL_LOG_COLORS
|
#ifndef CONFIG_ARDUHAL_LOG_COLORS
|
||||||
@ -73,62 +75,126 @@ extern "C"
|
|||||||
#define ARDUHAL_LOG_RESET_COLOR
|
#define ARDUHAL_LOG_RESET_COLOR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_LOG_LOCATION
|
|
||||||
#define ARDUHAL_LOG_FORMAT(letter, format) format
|
|
||||||
#else
|
|
||||||
#define ARDUHAL_LOG_FORMAT(letter, format) "[%s:%u] %s(): " format, (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__), __LINE__, __FUNCTION__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ARDUHAL_LOG_TAG "ARDUINO"
|
|
||||||
|
const char * pathToFileName(const char * path);
|
||||||
|
int log_printf(const char *fmt, ...);
|
||||||
|
|
||||||
|
#define ARDUHAL_SHORT_LOG_FORMAT(letter, format) ARDUHAL_LOG_COLOR_ ## letter format ARDUHAL_LOG_RESET_COLOR "\r\n"
|
||||||
|
#define ARDUHAL_LOG_FORMAT(letter, format) ARDUHAL_LOG_COLOR_ ## letter "[%6u][" #letter "][%s:%u] %s(): " format ARDUHAL_LOG_RESET_COLOR "\r\n", (unsigned long) (esp_timer_get_time() / 1000ULL), pathToFileName(__FILE__), __LINE__, __FUNCTION__
|
||||||
|
|
||||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
|
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
|
||||||
#define log_v(format, ...) ESP_LOGV(ARDUHAL_LOG_TAG, ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
|
#ifndef USE_ESP_IDF_LOG
|
||||||
#define isr_log_v(format, ...) ESP_LOGV(ARDUHAL_LOG_TAG, ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
|
#define log_v(format, ...) log_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
|
||||||
|
#define isr_log_v(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define log_v(format, ...) do {log_to_esp(TAG, ESP_LOG_VERBOSE, format, ##__VA_ARGS__);}while(0)
|
||||||
|
#define isr_log_v(format, ...) do {ets_printf(LOG_FORMAT(V, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define log_v(format, ...)
|
#define log_v(format, ...)
|
||||||
#define isr_log_v(format, ...)
|
#define isr_log_v(format, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
|
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
|
||||||
#define log_d(format, ...) ESP_LOGD(ARDUHAL_LOG_TAG, ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__)
|
#ifndef USE_ESP_IDF_LOG
|
||||||
#define isr_log_d(format, ...) ESP_LOGD(ARDUHAL_LOG_TAG, ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__)
|
#define log_d(format, ...) log_printf(ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__)
|
||||||
|
#define isr_log_d(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define log_d(format, ...) do {log_to_esp(TAG, ESP_LOG_DEBUG, format, ##__VA_ARGS__);}while(0)
|
||||||
|
#define isr_log_d(format, ...) do {ets_printf(LOG_FORMAT(D, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define log_d(format, ...)
|
#define log_d(format, ...)
|
||||||
#define isr_log_d(format, ...)
|
#define isr_log_d(format, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
|
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
|
||||||
#define log_i(format, ...) ESP_LOGI(ARDUHAL_LOG_TAG, ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__)
|
#ifndef USE_ESP_IDF_LOG
|
||||||
#define isr_log_i(format, ...) ESP_LOGI(ARDUHAL_LOG_TAG, ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__)
|
#define log_i(format, ...) log_printf(ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__)
|
||||||
|
#define isr_log_i(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define log_i(format, ...) do {log_to_esp(TAG, ESP_LOG_INFO, format, ##__VA_ARGS__);}while(0)
|
||||||
|
#define isr_log_i(format, ...) do {ets_printf(LOG_FORMAT(I, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define log_i(format, ...)
|
#define log_i(format, ...)
|
||||||
#define isr_log_i(format, ...)
|
#define isr_log_i(format, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_WARN
|
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_WARN
|
||||||
#define log_w(format, ...) ESP_LOGW(ARDUHAL_LOG_TAG, ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__)
|
#ifndef USE_ESP_IDF_LOG
|
||||||
#define isr_log_w(format, ...) ESP_LOGW(ARDUHAL_LOG_TAG, ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__)
|
#define log_w(format, ...) log_printf(ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__)
|
||||||
|
#define isr_log_w(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define log_w(format, ...) do {log_to_esp(TAG, ESP_LOG_WARN, format, ##__VA_ARGS__);}while(0)
|
||||||
|
#define isr_log_w(format, ...) do {ets_printf(LOG_FORMAT(W, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define log_w(format, ...)
|
#define log_w(format, ...)
|
||||||
#define isr_log_w(format, ...)
|
#define isr_log_w(format, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
|
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
|
||||||
#define log_e(format, ...) ESP_LOGE(ARDUHAL_LOG_TAG, ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
|
#ifndef USE_ESP_IDF_LOG
|
||||||
#define isr_log_e(format, ...) ESP_LOGE(ARDUHAL_LOG_TAG, ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
|
#define log_e(format, ...) log_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
|
||||||
|
#define isr_log_e(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define log_e(format, ...) do {log_to_esp(TAG, ESP_LOG_ERROR, format, ##__VA_ARGS__);}while(0)
|
||||||
|
#define isr_log_e(format, ...) do {ets_printf(LOG_FORMAT(E, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define log_e(format, ...)
|
#define log_e(format, ...)
|
||||||
#define isr_log_e(format, ...)
|
#define isr_log_e(format, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_NONE
|
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_NONE
|
||||||
#define log_n(format, ...) ESP_LOGE(ARDUHAL_LOG_TAG, ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
|
#ifndef USE_ESP_IDF_LOG
|
||||||
#define isr_log_n(format, ...) ESP_LOGE(ARDUHAL_LOG_TAG, ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
|
#define log_n(format, ...) log_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
|
||||||
|
#define isr_log_n(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define log_n(format, ...) do {log_to_esp(TAG, ESP_LOG_ERROR, format, ##__VA_ARGS__);}while(0)
|
||||||
|
#define isr_log_n(format, ...) do {ets_printf(LOG_FORMAT(E, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define log_n(format, ...)
|
#define log_n(format, ...)
|
||||||
#define isr_log_n(format, ...)
|
#define isr_log_n(format, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
#ifdef USE_ESP_IDF_LOG
|
||||||
|
#ifndef TAG
|
||||||
|
#define TAG "ARDUINO"
|
||||||
|
#endif
|
||||||
|
void log_to_esp(char* tag, esp_log_level_t level, const char* format, ...);
|
||||||
|
//#define log_n(format, ...) myLog(ESP_LOG_NONE, format, ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#ifdef CONFIG_ARDUHAL_ESP_LOG
|
||||||
|
#undef ESP_LOGE
|
||||||
|
#undef ESP_LOGW
|
||||||
|
#undef ESP_LOGI
|
||||||
|
#undef ESP_LOGD
|
||||||
|
#undef ESP_LOGV
|
||||||
|
#undef ESP_EARLY_LOGE
|
||||||
|
#undef ESP_EARLY_LOGW
|
||||||
|
#undef ESP_EARLY_LOGI
|
||||||
|
#undef ESP_EARLY_LOGD
|
||||||
|
#undef ESP_EARLY_LOGV
|
||||||
|
|
||||||
|
#define ESP_LOGE(tag, ...) log_e(__VA_ARGS__)
|
||||||
|
#define ESP_LOGW(tag, ...) log_w(__VA_ARGS__)
|
||||||
|
#define ESP_LOGI(tag, ...) log_i(__VA_ARGS__)
|
||||||
|
#define ESP_LOGD(tag, ...) log_d(__VA_ARGS__)
|
||||||
|
#define ESP_LOGV(tag, ...) log_v(__VA_ARGS__)
|
||||||
|
#define ESP_EARLY_LOGE(tag, ...) isr_log_e(__VA_ARGS__)
|
||||||
|
#define ESP_EARLY_LOGW(tag, ...) isr_log_w(__VA_ARGS__)
|
||||||
|
#define ESP_EARLY_LOGI(tag, ...) isr_log_i(__VA_ARGS__)
|
||||||
|
#define ESP_EARLY_LOGD(tag, ...) isr_log_d(__VA_ARGS__)
|
||||||
|
#define ESP_EARLY_LOGV(tag, ...) isr_log_v(__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
#include "esp32-hal-matrix.h"
|
#include "esp32-hal-matrix.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp32-hal.h"
|
|
||||||
|
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
@ -22,6 +21,8 @@
|
|||||||
#include "esp32/rom/gpio.h"
|
#include "esp32/rom/gpio.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
#include "esp32s2/rom/gpio.h"
|
#include "esp32s2/rom/gpio.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/rom/gpio.h"
|
||||||
#else
|
#else
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,8 +20,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "esp32-hal.h"
|
||||||
#include <stdbool.h>
|
|
||||||
#include "soc/gpio_sig_map.h"
|
#include "soc/gpio_sig_map.h"
|
||||||
|
|
||||||
void pinMatrixOutAttach(uint8_t pin, uint8_t function, bool invertOut, bool invertEnable);
|
void pinMatrixOutAttach(uint8_t pin, uint8_t function, bool invertOut, bool invertEnable);
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp32-hal-misc.h"
|
|
||||||
#include "esp32-hal.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
@ -23,6 +21,9 @@
|
|||||||
#include "esp_partition.h"
|
#include "esp_partition.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
|
#ifdef CONFIG_APP_ROLLBACK_ENABLE
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
#endif //CONFIG_APP_ROLLBACK_ENABLE
|
||||||
#ifdef CONFIG_BT_ENABLED
|
#ifdef CONFIG_BT_ENABLED
|
||||||
#include "esp_bt.h"
|
#include "esp_bt.h"
|
||||||
#endif //CONFIG_BT_ENABLED
|
#endif //CONFIG_BT_ENABLED
|
||||||
@ -31,6 +32,7 @@
|
|||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#include "soc/apb_ctrl_reg.h"
|
#include "soc/apb_ctrl_reg.h"
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
@ -38,6 +40,10 @@
|
|||||||
#include "esp32/rom/rtc.h"
|
#include "esp32/rom/rtc.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
#include "esp32s2/rom/rtc.h"
|
#include "esp32s2/rom/rtc.h"
|
||||||
|
#include "driver/temp_sensor.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/rom/rtc.h"
|
||||||
|
#include "driver/temp_sensor.h"
|
||||||
#else
|
#else
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
#endif
|
#endif
|
||||||
@ -47,12 +53,25 @@
|
|||||||
|
|
||||||
//Undocumented!!! Get chip temperature in Farenheit
|
//Undocumented!!! Get chip temperature in Farenheit
|
||||||
//Source: https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/ESP32_int_temp_sensor/ESP32_int_temp_sensor.ino
|
//Source: https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/ESP32_int_temp_sensor/ESP32_int_temp_sensor.ino
|
||||||
|
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||||
uint8_t temprature_sens_read();
|
uint8_t temprature_sens_read();
|
||||||
|
|
||||||
float temperatureRead()
|
float temperatureRead()
|
||||||
{
|
{
|
||||||
return (temprature_sens_read() - 32) / 1.8;
|
return (temprature_sens_read() - 32) / 1.8;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
float temperatureRead()
|
||||||
|
{
|
||||||
|
float result = NAN;
|
||||||
|
temp_sensor_config_t tsens = TSENS_CONFIG_DEFAULT();
|
||||||
|
temp_sensor_set_config(tsens);
|
||||||
|
temp_sensor_start();
|
||||||
|
temp_sensor_read_celsius(&result);
|
||||||
|
temp_sensor_stop();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void __yield()
|
void __yield()
|
||||||
{
|
{
|
||||||
@ -61,24 +80,194 @@ void __yield()
|
|||||||
|
|
||||||
void yield() __attribute__ ((weak, alias("__yield")));
|
void yield() __attribute__ ((weak, alias("__yield")));
|
||||||
|
|
||||||
|
#if CONFIG_AUTOSTART_ARDUINO
|
||||||
|
|
||||||
|
extern TaskHandle_t loopTaskHandle;
|
||||||
|
extern bool loopTaskWDTEnabled;
|
||||||
|
|
||||||
|
void enableLoopWDT(){
|
||||||
|
if(loopTaskHandle != NULL){
|
||||||
|
if(esp_task_wdt_add(loopTaskHandle) != ESP_OK){
|
||||||
|
log_e("Failed to add loop task to WDT");
|
||||||
|
} else {
|
||||||
|
loopTaskWDTEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void disableLoopWDT(){
|
||||||
|
if(loopTaskHandle != NULL && loopTaskWDTEnabled){
|
||||||
|
loopTaskWDTEnabled = false;
|
||||||
|
if(esp_task_wdt_delete(loopTaskHandle) != ESP_OK){
|
||||||
|
log_e("Failed to remove loop task from WDT");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void feedLoopWDT(){
|
||||||
|
esp_err_t err = esp_task_wdt_reset();
|
||||||
|
if(err != ESP_OK){
|
||||||
|
log_e("Failed to feed WDT! Error: %d", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void enableCore0WDT(){
|
||||||
|
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(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){
|
||||||
|
log_e("Failed to remove Core 0 IDLE task from WDT");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||||||
|
void enableCore1WDT(){
|
||||||
|
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(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){
|
||||||
|
log_e("Failed to remove Core 1 IDLE task from WDT");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BaseType_t xTaskCreateUniversal( TaskFunction_t pxTaskCode,
|
||||||
|
const char * const pcName,
|
||||||
|
const uint32_t usStackDepth,
|
||||||
|
void * const pvParameters,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
TaskHandle_t * const pxCreatedTask,
|
||||||
|
const BaseType_t xCoreID ){
|
||||||
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||||||
|
if(xCoreID >= 0 && xCoreID < 2) {
|
||||||
|
return xTaskCreatePinnedToCore(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, xCoreID);
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
return xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask);
|
||||||
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long ARDUINO_ISR_ATTR micros()
|
unsigned long ARDUINO_ISR_ATTR micros()
|
||||||
{
|
{
|
||||||
return (unsigned long) (esp_timer_get_time());
|
return (unsigned long) (esp_timer_get_time());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long ARDUINO_ISR_ATTR millis()
|
||||||
|
{
|
||||||
|
return (unsigned long) (esp_timer_get_time() / 1000ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void delay(uint32_t ms)
|
||||||
|
{
|
||||||
|
vTaskDelay(ms / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
|
||||||
void ARDUINO_ISR_ATTR delayMicroseconds(uint32_t us)
|
void ARDUINO_ISR_ATTR delayMicroseconds(uint32_t us)
|
||||||
{
|
{
|
||||||
uint32_t m = micros();
|
uint64_t m = (uint64_t)esp_timer_get_time();
|
||||||
if(us){
|
if(us){
|
||||||
uint32_t e = (m + us);
|
uint64_t e = (m + us);
|
||||||
if(m > e){ //overflow
|
if(m > e){ //overflow
|
||||||
while(micros() > e){
|
while((uint64_t)esp_timer_get_time() > e){
|
||||||
NOP();
|
NOP();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(micros() < e){
|
while((uint64_t)esp_timer_get_time() < e){
|
||||||
NOP();
|
NOP();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initVariant() __attribute__((weak));
|
||||||
|
void initVariant() {}
|
||||||
|
|
||||||
|
void init() __attribute__((weak));
|
||||||
|
void init() {}
|
||||||
|
|
||||||
|
bool verifyOta() __attribute__((weak));
|
||||||
|
bool verifyOta() { return true; }
|
||||||
|
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
//overwritten in esp32-hal-bt.c
|
||||||
|
bool btInUse() __attribute__((weak));
|
||||||
|
bool btInUse(){ return false; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void initArduino()
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_APP_ROLLBACK_ENABLE
|
||||||
|
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||||
|
esp_ota_img_states_t ota_state;
|
||||||
|
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
|
||||||
|
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
|
||||||
|
if (verifyOta()) {
|
||||||
|
esp_ota_mark_app_valid_cancel_rollback();
|
||||||
|
} else {
|
||||||
|
log_e("OTA verification failed! Start rollback to the previous version ...");
|
||||||
|
esp_ota_mark_app_invalid_rollback_and_reboot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//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;
|
||||||
|
#ifdef F_CPU
|
||||||
|
setCpuFrequencyMhz(F_CPU/1000000);
|
||||||
|
#endif
|
||||||
|
#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
|
||||||
|
psramInit();
|
||||||
|
#endif
|
||||||
|
esp_log_level_set("*", CONFIG_LOG_DEFAULT_LEVEL);
|
||||||
|
esp_err_t err = nvs_flash_init();
|
||||||
|
if(err == ESP_ERR_NVS_NO_FREE_PAGES){
|
||||||
|
const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL);
|
||||||
|
if (partition != NULL) {
|
||||||
|
err = esp_partition_erase_range(partition, 0, partition->size);
|
||||||
|
if(!err){
|
||||||
|
err = nvs_flash_init();
|
||||||
|
} else {
|
||||||
|
log_e("Failed to format the broken NVS partition!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(err) {
|
||||||
|
log_e("Failed to initialize NVS! Error: %u", err);
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
if(!btInUse()){
|
||||||
|
esp_bt_controller_mem_release(ESP_BT_MODE_BTDM);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
init();
|
||||||
|
initVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
//used by hal log
|
||||||
|
const char * ARDUINO_ISR_ATTR pathToFileName(const char * path)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
size_t pos = 0;
|
||||||
|
char * p = (char *)path;
|
||||||
|
while(*p){
|
||||||
|
i++;
|
||||||
|
if(*p == '/' || *p == '\\'){
|
||||||
|
pos = i;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return path+pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void yield(void);
|
|
||||||
|
|
||||||
unsigned long micros();
|
|
||||||
void delayMicroseconds(uint32_t us);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -14,9 +14,6 @@
|
|||||||
|
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
|
#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
|
||||||
#include "soc/efuse_reg.h"
|
#include "soc/efuse_reg.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
|
@ -17,35 +17,38 @@
|
|||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
#include "esp32-hal-log.h"
|
|
||||||
#include "esp8266-compat.h"
|
#include "esp8266-compat.h"
|
||||||
#include "soc/gpio_reg.h"
|
#include "soc/gpio_reg.h"
|
||||||
#include "soc/rmt_struct.h"
|
#include "soc/rmt_struct.h"
|
||||||
#include <esp_private/periph_ctrl.h>
|
#include "driver/periph_ctrl.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
#include "hal/rmt_ll.h"
|
|
||||||
#include "driver/rmt.h"
|
|
||||||
#include "esp32-hal-rmt.h"
|
|
||||||
#include "esp32-hal-gpio.h"
|
|
||||||
#include "esp32-hal-matrix.h"
|
|
||||||
|
|
||||||
// RMTMEM address is declared in <target>.peripherals.ld
|
|
||||||
extern rmt_mem_t RMTMEM;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal macros
|
* Internal macros
|
||||||
*/
|
*/
|
||||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
#define MAX_CHANNELS 8
|
#define MAX_CHANNELS 8
|
||||||
|
#define MAX_DATA_PER_CHANNEL 64
|
||||||
|
#define MAX_DATA_PER_ITTERATION 62
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
#define MAX_CHANNELS 4
|
#define MAX_CHANNELS 4
|
||||||
|
#define MAX_DATA_PER_CHANNEL 64
|
||||||
|
#define MAX_DATA_PER_ITTERATION 62
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#define MAX_CHANNELS 4
|
||||||
|
#define MAX_DATA_PER_CHANNEL 48
|
||||||
|
#define MAX_DATA_PER_ITTERATION 46
|
||||||
#else
|
#else
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
#endif
|
#endif
|
||||||
#define MAX_DATA_PER_CHANNEL 64
|
|
||||||
#define MAX_DATA_PER_ITTERATION 62
|
|
||||||
#define _ABS(a) (a>0?a:-a)
|
#define _ABS(a) (a>0?a:-a)
|
||||||
#define _LIMIT(a,b) (a>b?b:a)
|
#define _LIMIT(a,b) (a>b?b:a)
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#define _INT_TX_END(channel) (1<<(channel))
|
||||||
|
#define _INT_RX_END(channel) (4<<(channel))
|
||||||
|
#define _INT_ERROR(channel) (16<<(channel))
|
||||||
|
#define _INT_THR_EVNT(channel) (256<<(channel))
|
||||||
|
#else
|
||||||
#define __INT_TX_END (1)
|
#define __INT_TX_END (1)
|
||||||
#define __INT_RX_END (2)
|
#define __INT_RX_END (2)
|
||||||
#define __INT_ERROR (4)
|
#define __INT_ERROR (4)
|
||||||
@ -55,6 +58,7 @@ extern rmt_mem_t RMTMEM;
|
|||||||
#define _INT_RX_END(channel) (__INT_RX_END<<(channel*3))
|
#define _INT_RX_END(channel) (__INT_RX_END<<(channel*3))
|
||||||
#define _INT_ERROR(channel) (__INT_ERROR<<(channel*3))
|
#define _INT_ERROR(channel) (__INT_ERROR<<(channel*3))
|
||||||
#define _INT_THR_EVNT(channel) ((__INT_THR_EVNT)<<(channel))
|
#define _INT_THR_EVNT(channel) ((__INT_THR_EVNT)<<(channel))
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_DISABLE_HAL_LOCKS
|
#if CONFIG_DISABLE_HAL_LOCKS
|
||||||
# define RMT_MUTEX_LOCK(channel)
|
# define RMT_MUTEX_LOCK(channel)
|
||||||
@ -64,7 +68,7 @@ extern rmt_mem_t RMTMEM;
|
|||||||
# define RMT_MUTEX_UNLOCK(channel) xSemaphoreGive(g_rmt_objlocks[channel])
|
# define RMT_MUTEX_UNLOCK(channel) xSemaphoreGive(g_rmt_objlocks[channel])
|
||||||
#endif /* CONFIG_DISABLE_HAL_LOCKS */
|
#endif /* CONFIG_DISABLE_HAL_LOCKS */
|
||||||
|
|
||||||
#define _RMT_INTERNAL_DEBUG
|
//#define _RMT_INTERNAL_DEBUG
|
||||||
#ifdef _RMT_INTERNAL_DEBUG
|
#ifdef _RMT_INTERNAL_DEBUG
|
||||||
# define DEBUG_INTERRUPT_START(pin) digitalWrite(pin, 1);
|
# define DEBUG_INTERRUPT_START(pin) digitalWrite(pin, 1);
|
||||||
# define DEBUG_INTERRUPT_END(pin) digitalWrite(pin, 0);
|
# define DEBUG_INTERRUPT_END(pin) digitalWrite(pin, 0);
|
||||||
@ -111,7 +115,7 @@ struct rmt_obj_s
|
|||||||
/**
|
/**
|
||||||
* Internal variables for channel descriptors
|
* Internal variables for channel descriptors
|
||||||
*/
|
*/
|
||||||
static SemaphoreHandle_t g_rmt_objlocks[MAX_CHANNELS] = {
|
static xSemaphoreHandle g_rmt_objlocks[MAX_CHANNELS] = {
|
||||||
NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL,
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
NULL, NULL, NULL, NULL
|
NULL, NULL, NULL, NULL
|
||||||
@ -138,7 +142,7 @@ static intr_handle_t intr_handle;
|
|||||||
|
|
||||||
static bool periph_enabled = false;
|
static bool periph_enabled = false;
|
||||||
|
|
||||||
static SemaphoreHandle_t g_rmt_block_lock = NULL;
|
static xSemaphoreHandle g_rmt_block_lock = NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal method (private) declarations
|
* Internal method (private) declarations
|
||||||
@ -171,12 +175,17 @@ bool rmtSetCarrier(rmt_obj_t* rmt, bool carrier_en, bool carrier_level, uint32_t
|
|||||||
size_t channel = rmt->channel;
|
size_t channel = rmt->channel;
|
||||||
|
|
||||||
RMT_MUTEX_LOCK(channel);
|
RMT_MUTEX_LOCK(channel);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.tx_carrier[channel].low = low;
|
||||||
|
RMT.tx_carrier[channel].high = high;
|
||||||
|
RMT.rx_conf[channel].conf0.carrier_en = carrier_en;
|
||||||
|
RMT.rx_conf[channel].conf0.carrier_out_lv = carrier_level;
|
||||||
|
#else
|
||||||
RMT.carrier_duty_ch[channel].low = low;
|
RMT.carrier_duty_ch[channel].low = low;
|
||||||
RMT.carrier_duty_ch[channel].high = high;
|
RMT.carrier_duty_ch[channel].high = high;
|
||||||
RMT.conf_ch[channel].conf0.carrier_en = carrier_en;
|
RMT.conf_ch[channel].conf0.carrier_en = carrier_en;
|
||||||
RMT.conf_ch[channel].conf0.carrier_out_lv = carrier_level;
|
RMT.conf_ch[channel].conf0.carrier_out_lv = carrier_level;
|
||||||
|
#endif
|
||||||
RMT_MUTEX_UNLOCK(channel);
|
RMT_MUTEX_UNLOCK(channel);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -192,8 +201,13 @@ bool rmtSetFilter(rmt_obj_t* rmt, bool filter_en, uint32_t filter_level)
|
|||||||
|
|
||||||
RMT_MUTEX_LOCK(channel);
|
RMT_MUTEX_LOCK(channel);
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.rx_conf[channel].conf1.rx_filter_thres = filter_level;
|
||||||
|
RMT.rx_conf[channel].conf1.rx_filter_en = filter_en;
|
||||||
|
#else
|
||||||
RMT.conf_ch[channel].conf1.rx_filter_thres = filter_level;
|
RMT.conf_ch[channel].conf1.rx_filter_thres = filter_level;
|
||||||
RMT.conf_ch[channel].conf1.rx_filter_en = filter_en;
|
RMT.conf_ch[channel].conf1.rx_filter_en = filter_en;
|
||||||
|
#endif
|
||||||
|
|
||||||
RMT_MUTEX_UNLOCK(channel);
|
RMT_MUTEX_UNLOCK(channel);
|
||||||
|
|
||||||
@ -209,7 +223,11 @@ bool rmtSetRxThreshold(rmt_obj_t* rmt, uint32_t value)
|
|||||||
size_t channel = rmt->channel;
|
size_t channel = rmt->channel;
|
||||||
|
|
||||||
RMT_MUTEX_LOCK(channel);
|
RMT_MUTEX_LOCK(channel);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.rx_conf[channel].conf0.idle_thres = value;
|
||||||
|
#else
|
||||||
RMT.conf_ch[channel].conf0.idle_thres = value;
|
RMT.conf_ch[channel].conf0.idle_thres = value;
|
||||||
|
#endif
|
||||||
RMT_MUTEX_UNLOCK(channel);
|
RMT_MUTEX_UNLOCK(channel);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -274,7 +292,7 @@ bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
|
|||||||
int channel = rmt->channel;
|
int channel = rmt->channel;
|
||||||
int allocated_size = MAX_DATA_PER_CHANNEL * rmt->buffers;
|
int allocated_size = MAX_DATA_PER_CHANNEL * rmt->buffers;
|
||||||
|
|
||||||
if (size > allocated_size) {
|
if (size > (allocated_size - 1)) {
|
||||||
|
|
||||||
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
|
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
|
||||||
RMT_MUTEX_LOCK(channel);
|
RMT_MUTEX_LOCK(channel);
|
||||||
@ -288,6 +306,18 @@ bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
|
|||||||
rmt->intr_mode = E_TX_INTR | E_TXTHR_INTR;
|
rmt->intr_mode = E_TX_INTR | E_TXTHR_INTR;
|
||||||
rmt->tx_state = E_SET_CONTI | E_FIRST_HALF;
|
rmt->tx_state = E_SET_CONTI | E_FIRST_HALF;
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
//uint32_t val = RMT.tx_conf[channel].val;
|
||||||
|
// init the tx limit for interruption
|
||||||
|
RMT.tx_lim[channel].limit = half_tx_nr+2;
|
||||||
|
//RMT.tx_conf[channel].val = val;
|
||||||
|
//RMT.tx_conf[channel].conf_update = 1;
|
||||||
|
// reset memory pointer
|
||||||
|
RMT.tx_conf[channel].mem_rst = 1;
|
||||||
|
//RMT.tx_conf[channel].mem_rst = 0;
|
||||||
|
RMT.tx_conf[channel].mem_rd_rst = 1;
|
||||||
|
//RMT.tx_conf[channel].mem_rd_rst = 0;
|
||||||
|
#else
|
||||||
// init the tx limit for interruption
|
// init the tx limit for interruption
|
||||||
RMT.tx_lim_ch[channel].limit = half_tx_nr+2;
|
RMT.tx_lim_ch[channel].limit = half_tx_nr+2;
|
||||||
// reset memory pointer
|
// reset memory pointer
|
||||||
@ -297,9 +327,9 @@ bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
|
|||||||
RMT.conf_ch[channel].conf1.mem_rd_rst = 0;
|
RMT.conf_ch[channel].conf1.mem_rd_rst = 0;
|
||||||
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
|
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
|
||||||
RMT.conf_ch[channel].conf1.mem_wr_rst = 0;
|
RMT.conf_ch[channel].conf1.mem_wr_rst = 0;
|
||||||
|
#endif
|
||||||
// set the tx end mark
|
// set the tx end mark
|
||||||
RMTMEM.chan[channel].data32[MAX_DATA_PER_ITTERATION].val = 0;
|
//RMTMEM.chan[channel].data32[MAX_DATA_PER_ITTERATION].val = 0;
|
||||||
|
|
||||||
// clear and enable both Tx completed and half tx event
|
// clear and enable both Tx completed and half tx event
|
||||||
RMT.int_clr.val = _INT_TX_END(channel);
|
RMT.int_clr.val = _INT_TX_END(channel);
|
||||||
@ -313,6 +343,7 @@ bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
|
|||||||
RMT_MUTEX_UNLOCK(channel);
|
RMT_MUTEX_UNLOCK(channel);
|
||||||
|
|
||||||
// start the transation
|
// start the transation
|
||||||
|
//return _rmtSendOnce(rmt, data, MAX_DATA_PER_ITTERATION, true);
|
||||||
return _rmtSendOnce(rmt, data, MAX_DATA_PER_ITTERATION, false);
|
return _rmtSendOnce(rmt, data, MAX_DATA_PER_ITTERATION, false);
|
||||||
} else {
|
} else {
|
||||||
// use one-go mode if data fits one buffer
|
// use one-go mode if data fits one buffer
|
||||||
@ -351,10 +382,15 @@ bool rmtBeginReceive(rmt_obj_t* rmt)
|
|||||||
RMT.int_clr.val = _INT_ERROR(channel);
|
RMT.int_clr.val = _INT_ERROR(channel);
|
||||||
RMT.int_ena.val |= _INT_ERROR(channel);
|
RMT.int_ena.val |= _INT_ERROR(channel);
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.rx_conf[channel].conf1.mem_owner = 1;
|
||||||
|
RMT.rx_conf[channel].conf1.mem_wr_rst = 1;
|
||||||
|
RMT.rx_conf[channel].conf1.rx_en = 1;
|
||||||
|
#else
|
||||||
RMT.conf_ch[channel].conf1.mem_owner = 1;
|
RMT.conf_ch[channel].conf1.mem_owner = 1;
|
||||||
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
|
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
|
||||||
RMT.conf_ch[channel].conf1.rx_en = 1;
|
RMT.conf_ch[channel].conf1.rx_en = 1;
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,17 +429,26 @@ bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb, void * arg)
|
|||||||
rmt->data_alloc = true;
|
rmt->data_alloc = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.rx_conf[channel].conf1.mem_owner = 1;
|
||||||
|
#else
|
||||||
RMT.conf_ch[channel].conf1.mem_owner = 1;
|
RMT.conf_ch[channel].conf1.mem_owner = 1;
|
||||||
|
#endif
|
||||||
RMT.int_clr.val = _INT_RX_END(channel);
|
RMT.int_clr.val = _INT_RX_END(channel);
|
||||||
RMT.int_clr.val = _INT_ERROR(channel);
|
RMT.int_clr.val = _INT_ERROR(channel);
|
||||||
|
|
||||||
RMT.int_ena.val |= _INT_RX_END(channel);
|
RMT.int_ena.val |= _INT_RX_END(channel);
|
||||||
RMT.int_ena.val |= _INT_ERROR(channel);
|
RMT.int_ena.val |= _INT_ERROR(channel);
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.rx_conf[channel].conf1.mem_wr_rst = 1;
|
||||||
|
|
||||||
|
RMT.rx_conf[channel].conf1.rx_en = 1;
|
||||||
|
#else
|
||||||
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
|
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
|
||||||
|
|
||||||
RMT.conf_ch[channel].conf1.rx_en = 1;
|
RMT.conf_ch[channel].conf1.rx_en = 1;
|
||||||
|
#endif
|
||||||
RMT_MUTEX_UNLOCK(channel);
|
RMT_MUTEX_UNLOCK(channel);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -416,7 +461,11 @@ bool rmtEnd(rmt_obj_t* rmt) {
|
|||||||
int channel = rmt->channel;
|
int channel = rmt->channel;
|
||||||
|
|
||||||
RMT_MUTEX_LOCK(channel);
|
RMT_MUTEX_LOCK(channel);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.rx_conf[channel].conf1.rx_en = 1;
|
||||||
|
#else
|
||||||
RMT.conf_ch[channel].conf1.rx_en = 1;
|
RMT.conf_ch[channel].conf1.rx_en = 1;
|
||||||
|
#endif
|
||||||
RMT_MUTEX_UNLOCK(channel);
|
RMT_MUTEX_UNLOCK(channel);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -446,7 +495,11 @@ bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag
|
|||||||
RMT_MUTEX_LOCK(channel);
|
RMT_MUTEX_LOCK(channel);
|
||||||
rmt->intr_mode = E_RX_INTR;
|
rmt->intr_mode = E_RX_INTR;
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.rx_conf[channel].conf1.mem_owner = 1;
|
||||||
|
#else
|
||||||
RMT.conf_ch[channel].conf1.mem_owner = 1;
|
RMT.conf_ch[channel].conf1.mem_owner = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
RMT.int_clr.val = _INT_RX_END(channel);
|
RMT.int_clr.val = _INT_RX_END(channel);
|
||||||
RMT.int_clr.val = _INT_ERROR(channel);
|
RMT.int_clr.val = _INT_ERROR(channel);
|
||||||
@ -454,9 +507,15 @@ bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag
|
|||||||
RMT.int_ena.val |= _INT_RX_END(channel);
|
RMT.int_ena.val |= _INT_RX_END(channel);
|
||||||
RMT.int_ena.val |= _INT_ERROR(channel);
|
RMT.int_ena.val |= _INT_ERROR(channel);
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.rx_conf[channel].conf1.mem_wr_rst = 1;
|
||||||
|
|
||||||
|
RMT.rx_conf[channel].conf1.rx_en = 1;
|
||||||
|
#else
|
||||||
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
|
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
|
||||||
|
|
||||||
RMT.conf_ch[channel].conf1.rx_en = 1;
|
RMT.conf_ch[channel].conf1.rx_en = 1;
|
||||||
|
#endif
|
||||||
RMT_MUTEX_UNLOCK(channel);
|
RMT_MUTEX_UNLOCK(channel);
|
||||||
|
|
||||||
// wait for data if requested so
|
// wait for data if requested so
|
||||||
@ -483,14 +542,20 @@ float rmtSetTick(rmt_obj_t* rmt, float tick)
|
|||||||
* rmt tick for 1 MHz -> 1us (1x) div_cnt = 0x01
|
* rmt tick for 1 MHz -> 1us (1x) div_cnt = 0x01
|
||||||
256us (256x) div_cnt = 0x00
|
256us (256x) div_cnt = 0x00
|
||||||
*/
|
*/
|
||||||
int apb_div = _LIMIT(tick/12.5, 256);
|
|
||||||
int ref_div = _LIMIT(tick/1000, 256);
|
|
||||||
|
|
||||||
float apb_tick = 12.5 * apb_div;
|
|
||||||
float ref_tick = 1000.0 * ref_div;
|
|
||||||
|
|
||||||
size_t channel = rmt->channel;
|
size_t channel = rmt->channel;
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
int apb_div = _LIMIT(tick/25.0, 256);
|
||||||
|
float apb_tick = 25.0 * apb_div;
|
||||||
|
RMT.tx_conf[channel].div_cnt = apb_div & 0xFF;
|
||||||
|
RMT.tx_conf[channel].conf_update = 1;
|
||||||
|
return apb_tick;
|
||||||
|
#else
|
||||||
|
int apb_div = _LIMIT(tick/12.5, 256);
|
||||||
|
int ref_div = _LIMIT(tick/1000, 256);
|
||||||
|
float apb_tick = 12.5 * apb_div;
|
||||||
|
float ref_tick = 1000.0 * ref_div;
|
||||||
if (_ABS(apb_tick - tick) < _ABS(ref_tick - tick)) {
|
if (_ABS(apb_tick - tick) < _ABS(ref_tick - tick)) {
|
||||||
RMT.conf_ch[channel].conf0.div_cnt = apb_div & 0xFF;
|
RMT.conf_ch[channel].conf0.div_cnt = apb_div & 0xFF;
|
||||||
RMT.conf_ch[channel].conf1.ref_always_on = 1;
|
RMT.conf_ch[channel].conf1.ref_always_on = 1;
|
||||||
@ -500,6 +565,7 @@ float rmtSetTick(rmt_obj_t* rmt, float tick)
|
|||||||
RMT.conf_ch[channel].conf1.ref_always_on = 0;
|
RMT.conf_ch[channel].conf1.ref_always_on = 0;
|
||||||
return ref_tick;
|
return ref_tick;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
|
rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
|
||||||
@ -562,6 +628,47 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
|
|||||||
// - no carrier, filter
|
// - no carrier, filter
|
||||||
// - timebase tick of 1us
|
// - timebase tick of 1us
|
||||||
// - idle threshold set to 0x8000 (max pulse width + 1)
|
// - idle threshold set to 0x8000 (max pulse width + 1)
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
|
||||||
|
RMT.sys_conf.fifo_mask = 1;
|
||||||
|
|
||||||
|
if (tx_not_rx) {
|
||||||
|
RMT.tx_lim[channel].limit = MAX_DATA_PER_ITTERATION/2 + 2;
|
||||||
|
RMT.tx_conf[channel].val = 0;
|
||||||
|
// RMT.tx_conf[channel].carrier_en = 0;
|
||||||
|
// RMT.tx_conf[channel].carrier_out_lv = 0;
|
||||||
|
// RMT.tx_conf[channel].tx_conti_mode = 0;
|
||||||
|
// RMT.tx_conf[channel].idle_out_lv = 0; // signal level for idle
|
||||||
|
// RMT.tx_conf[channel].tx_start = 0;
|
||||||
|
// RMT.tx_conf[channel].tx_stop = 0;
|
||||||
|
// RMT.tx_conf[channel].carrier_eff_en = 0;
|
||||||
|
// RMT.tx_conf[channel].afifo_rst = 0;
|
||||||
|
// RMT.tx_conf[channel].conf_update = 0;
|
||||||
|
// RMT.tx_conf[channel].mem_tx_wrap_en = 0;
|
||||||
|
// RMT.tx_conf[channel].mem_rst = 1;
|
||||||
|
|
||||||
|
RMT.tx_conf[channel].idle_out_en = 1; // enable idle
|
||||||
|
RMT.tx_conf[channel].div_cnt = 1;
|
||||||
|
RMT.tx_conf[channel].mem_size = buffers;
|
||||||
|
RMT.tx_conf[channel].mem_rd_rst = 1;
|
||||||
|
RMT.tx_conf[channel].conf_update = 1;
|
||||||
|
} else {
|
||||||
|
RMT.rx_conf[channel].conf0.div_cnt = 1;
|
||||||
|
RMT.rx_conf[channel].conf0.mem_size = buffers;
|
||||||
|
RMT.rx_conf[channel].conf0.carrier_en = 0;
|
||||||
|
RMT.rx_conf[channel].conf0.carrier_out_lv = 0;
|
||||||
|
RMT.rx_conf[channel].conf0.idle_thres = 0x80;
|
||||||
|
RMT.rx_conf[channel].conf1.rx_filter_en = 0;
|
||||||
|
RMT.rx_conf[channel].conf1.rx_filter_thres = 0;
|
||||||
|
RMT.rx_conf[channel].conf1.mem_rst = 0;
|
||||||
|
RMT.rx_conf[channel].conf1.mem_rx_wrap_en = 0;
|
||||||
|
RMT.rx_conf[channel].conf1.afifo_rst = 0;
|
||||||
|
RMT.rx_conf[channel].conf1.conf_update = 0;
|
||||||
|
RMT.rx_conf[channel].conf1.rx_en = 1;
|
||||||
|
RMT.rx_conf[channel].conf1.mem_owner = 1;
|
||||||
|
RMT.rx_conf[channel].conf1.mem_wr_rst = 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
RMT.conf_ch[channel].conf0.div_cnt = 1;
|
RMT.conf_ch[channel].conf0.div_cnt = 1;
|
||||||
RMT.conf_ch[channel].conf0.mem_size = buffers;
|
RMT.conf_ch[channel].conf0.mem_size = buffers;
|
||||||
RMT.conf_ch[channel].conf0.carrier_en = 0;
|
RMT.conf_ch[channel].conf0.carrier_en = 0;
|
||||||
@ -594,7 +701,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
|
|||||||
RMT.conf_ch[channel].conf1.mem_owner = 1;
|
RMT.conf_ch[channel].conf1.mem_owner = 1;
|
||||||
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
|
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// install interrupt if at least one channel is active
|
// install interrupt if at least one channel is active
|
||||||
if (!intr_handle) {
|
if (!intr_handle) {
|
||||||
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, _rmt_isr, NULL, &intr_handle);
|
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, _rmt_isr, NULL, &intr_handle);
|
||||||
@ -613,7 +720,11 @@ bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size, bool continuous
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int channel = rmt->channel;
|
int channel = rmt->channel;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.sys_conf.fifo_mask = 1;
|
||||||
|
#else
|
||||||
RMT.apb_conf.fifo_mask = 1;
|
RMT.apb_conf.fifo_mask = 1;
|
||||||
|
#endif
|
||||||
if (data && size>0) {
|
if (data && size>0) {
|
||||||
size_t i;
|
size_t i;
|
||||||
volatile uint32_t* rmt_mem_ptr = &(RMTMEM.chan[channel].data32[0].val);
|
volatile uint32_t* rmt_mem_ptr = &(RMTMEM.chan[channel].data32[0].val);
|
||||||
@ -625,9 +736,15 @@ bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size, bool continuous
|
|||||||
}
|
}
|
||||||
|
|
||||||
RMT_MUTEX_LOCK(channel);
|
RMT_MUTEX_LOCK(channel);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.tx_conf[channel].tx_conti_mode = continuous;
|
||||||
|
RMT.tx_conf[channel].mem_rd_rst = 1;
|
||||||
|
RMT.tx_conf[channel].tx_start = 1;
|
||||||
|
#else
|
||||||
RMT.conf_ch[channel].conf1.tx_conti_mode = continuous;
|
RMT.conf_ch[channel].conf1.tx_conti_mode = continuous;
|
||||||
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
|
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
|
||||||
RMT.conf_ch[channel].conf1.tx_start = 1;
|
RMT.conf_ch[channel].conf1.tx_start = 1;
|
||||||
|
#endif
|
||||||
RMT_MUTEX_UNLOCK(channel);
|
RMT_MUTEX_UNLOCK(channel);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -652,6 +769,7 @@ static void _initPin(int pin, int channel, bool tx_not_rx)
|
|||||||
{
|
{
|
||||||
if (!periph_enabled) {
|
if (!periph_enabled) {
|
||||||
periph_enabled = true;
|
periph_enabled = true;
|
||||||
|
periph_module_reset( PERIPH_RMT_MODULE );
|
||||||
periph_module_enable( PERIPH_RMT_MODULE );
|
periph_module_enable( PERIPH_RMT_MODULE );
|
||||||
}
|
}
|
||||||
if (tx_not_rx) {
|
if (tx_not_rx) {
|
||||||
@ -667,6 +785,7 @@ static void _initPin(int pin, int channel, bool tx_not_rx)
|
|||||||
|
|
||||||
static void ARDUINO_ISR_ATTR _rmt_isr(void* arg)
|
static void ARDUINO_ISR_ATTR _rmt_isr(void* arg)
|
||||||
{
|
{
|
||||||
|
//DEBUG_INTERRUPT_START(4);
|
||||||
int intr_val = RMT.int_st.val;
|
int intr_val = RMT.int_st.val;
|
||||||
size_t ch;
|
size_t ch;
|
||||||
for (ch = 0; ch < MAX_CHANNELS; ch++) {
|
for (ch = 0; ch < MAX_CHANNELS; ch++) {
|
||||||
@ -701,9 +820,15 @@ static void ARDUINO_ISR_ATTR _rmt_isr(void* arg)
|
|||||||
(g_rmt_objects[ch].cb)(data_received, _rmt_get_mem_len(ch), g_rmt_objects[ch].arg);
|
(g_rmt_objects[ch].cb)(data_received, _rmt_get_mem_len(ch), g_rmt_objects[ch].arg);
|
||||||
|
|
||||||
// restart the reception
|
// restart the reception
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.rx_conf[ch].conf1.mem_owner = 1;
|
||||||
|
RMT.rx_conf[ch].conf1.mem_wr_rst = 1;
|
||||||
|
RMT.rx_conf[ch].conf1.rx_en = 1;
|
||||||
|
#else
|
||||||
RMT.conf_ch[ch].conf1.mem_owner = 1;
|
RMT.conf_ch[ch].conf1.mem_owner = 1;
|
||||||
RMT.conf_ch[ch].conf1.mem_wr_rst = 1;
|
RMT.conf_ch[ch].conf1.mem_wr_rst = 1;
|
||||||
RMT.conf_ch[ch].conf1.rx_en = 1;
|
RMT.conf_ch[ch].conf1.rx_en = 1;
|
||||||
|
#endif
|
||||||
RMT.int_ena.val |= _INT_RX_END(ch);
|
RMT.int_ena.val |= _INT_RX_END(ch);
|
||||||
} else {
|
} else {
|
||||||
// if not callback provide, expect only one Rx
|
// if not callback provide, expect only one Rx
|
||||||
@ -729,10 +854,17 @@ static void ARDUINO_ISR_ATTR _rmt_isr(void* arg)
|
|||||||
xEventGroupSetBits(g_rmt_objects[ch].events, RMT_FLAG_ERROR);
|
xEventGroupSetBits(g_rmt_objects[ch].events, RMT_FLAG_ERROR);
|
||||||
}
|
}
|
||||||
// reset memory
|
// reset memory
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.tx_conf[ch].mem_rd_rst = 1;
|
||||||
|
RMT.tx_conf[ch].mem_rd_rst = 0;
|
||||||
|
RMT.rx_conf[ch].conf1.mem_wr_rst = 1;
|
||||||
|
RMT.rx_conf[ch].conf1.mem_wr_rst = 0;
|
||||||
|
#else
|
||||||
RMT.conf_ch[ch].conf1.mem_rd_rst = 1;
|
RMT.conf_ch[ch].conf1.mem_rd_rst = 1;
|
||||||
RMT.conf_ch[ch].conf1.mem_rd_rst = 0;
|
RMT.conf_ch[ch].conf1.mem_rd_rst = 0;
|
||||||
RMT.conf_ch[ch].conf1.mem_wr_rst = 1;
|
RMT.conf_ch[ch].conf1.mem_wr_rst = 1;
|
||||||
RMT.conf_ch[ch].conf1.mem_wr_rst = 0;
|
RMT.conf_ch[ch].conf1.mem_wr_rst = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intr_val & _INT_TX_END(ch)) {
|
if (intr_val & _INT_TX_END(ch)) {
|
||||||
@ -744,15 +876,24 @@ static void ARDUINO_ISR_ATTR _rmt_isr(void* arg)
|
|||||||
if (intr_val & _INT_THR_EVNT(ch)) {
|
if (intr_val & _INT_THR_EVNT(ch)) {
|
||||||
// clear the flag
|
// clear the flag
|
||||||
RMT.int_clr.val = _INT_THR_EVNT(ch);
|
RMT.int_clr.val = _INT_THR_EVNT(ch);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
//RMT.int_clr.val = _INT_TX_END(ch);
|
||||||
|
//RMT.int_ena.val |= _INT_TX_END(ch);
|
||||||
|
#endif
|
||||||
|
|
||||||
// initial setup of continuous mode
|
// initial setup of continuous mode
|
||||||
if (g_rmt_objects[ch].tx_state & E_SET_CONTI) {
|
if (g_rmt_objects[ch].tx_state & E_SET_CONTI) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.tx_conf[ch].tx_conti_mode = 1;
|
||||||
|
#else
|
||||||
RMT.conf_ch[ch].conf1.tx_conti_mode = 1;
|
RMT.conf_ch[ch].conf1.tx_conti_mode = 1;
|
||||||
|
#endif
|
||||||
g_rmt_objects[ch].intr_mode &= ~E_SET_CONTI;
|
g_rmt_objects[ch].intr_mode &= ~E_SET_CONTI;
|
||||||
}
|
}
|
||||||
_rmt_tx_mem_first(ch);
|
_rmt_tx_mem_first(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//DEBUG_INTERRUPT_END(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch)
|
static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch)
|
||||||
@ -762,14 +903,23 @@ static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch)
|
|||||||
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
|
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.tx_lim[ch].limit = half_tx_nr+2;
|
||||||
|
#else
|
||||||
RMT.tx_lim_ch[ch].limit = half_tx_nr+2;
|
RMT.tx_lim_ch[ch].limit = half_tx_nr+2;
|
||||||
|
#endif
|
||||||
RMT.int_clr.val = _INT_THR_EVNT(ch);
|
RMT.int_clr.val = _INT_THR_EVNT(ch);
|
||||||
RMT.int_ena.val |= _INT_THR_EVNT(ch);
|
RMT.int_ena.val |= _INT_THR_EVNT(ch);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
//RMT.int_clr.val = _INT_TX_END(ch);
|
||||||
|
//RMT.int_ena.val &= ~_INT_TX_END(ch);
|
||||||
|
#endif
|
||||||
|
|
||||||
g_rmt_objects[ch].tx_state |= E_FIRST_HALF;
|
g_rmt_objects[ch].tx_state |= E_FIRST_HALF;
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
int remaining_size = g_rmt_objects[ch].data_size;
|
int remaining_size = g_rmt_objects[ch].data_size;
|
||||||
|
//ets_printf("RMT Tx[%d] %d\n", ch, remaining_size);
|
||||||
// will the remaining data occupy the entire halfbuffer
|
// will the remaining data occupy the entire halfbuffer
|
||||||
if (remaining_size > half_tx_nr) {
|
if (remaining_size > half_tx_nr) {
|
||||||
for (i = 0; i < half_tx_nr; i++) {
|
for (i = 0; i < half_tx_nr; i++) {
|
||||||
@ -788,17 +938,30 @@ static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch)
|
|||||||
g_rmt_objects[ch].data_ptr = NULL;
|
g_rmt_objects[ch].data_ptr = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0;
|
||||||
|
RMT.tx_conf[ch].tx_start = 1;
|
||||||
|
#endif
|
||||||
} else if ((!(g_rmt_objects[ch].tx_state & E_LAST_DATA)) &&
|
} else if ((!(g_rmt_objects[ch].tx_state & E_LAST_DATA)) &&
|
||||||
(!(g_rmt_objects[ch].tx_state & E_END_TRANS))) {
|
(!(g_rmt_objects[ch].tx_state & E_END_TRANS))) {
|
||||||
|
//ets_printf("RMT Tx finishing %d!\n", ch);
|
||||||
for (i = 0; i < half_tx_nr; i++) {
|
for (i = 0; i < half_tx_nr; i++) {
|
||||||
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0x000F000F;
|
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0x000F000F;
|
||||||
}
|
}
|
||||||
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0;
|
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0;
|
||||||
g_rmt_objects[ch].tx_state |= E_LAST_DATA;
|
g_rmt_objects[ch].tx_state |= E_LAST_DATA;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.tx_conf[ch].tx_conti_mode = 0;
|
||||||
|
#else
|
||||||
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
|
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
log_d("RMT Tx finished %d!\n", ch);
|
//ets_printf("RMT Tx finished %d!\n", ch);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.tx_conf[ch].tx_conti_mode = 0;
|
||||||
|
#else
|
||||||
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
|
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
|
||||||
|
#endif
|
||||||
RMT.int_ena.val &= ~_INT_TX_END(ch);
|
RMT.int_ena.val &= ~_INT_TX_END(ch);
|
||||||
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
|
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
|
||||||
g_rmt_objects[ch].intr_mode = E_NO_INTR;
|
g_rmt_objects[ch].intr_mode = E_NO_INTR;
|
||||||
@ -814,10 +977,15 @@ static void ARDUINO_ISR_ATTR _rmt_tx_mem_first(uint8_t ch)
|
|||||||
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
|
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
|
||||||
int i;
|
int i;
|
||||||
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
|
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.tx_lim[ch].limit = 0;
|
||||||
|
#else
|
||||||
RMT.tx_lim_ch[ch].limit = 0;
|
RMT.tx_lim_ch[ch].limit = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
int remaining_size = g_rmt_objects[ch].data_size;
|
int remaining_size = g_rmt_objects[ch].data_size;
|
||||||
|
//ets_printf("RMT TxF[%d] %d\n", ch, remaining_size);
|
||||||
|
|
||||||
// will the remaining data occupy the entire halfbuffer
|
// will the remaining data occupy the entire halfbuffer
|
||||||
if (remaining_size > half_tx_nr) {
|
if (remaining_size > half_tx_nr) {
|
||||||
@ -828,7 +996,11 @@ static void ARDUINO_ISR_ATTR _rmt_tx_mem_first(uint8_t ch)
|
|||||||
g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF;
|
g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF;
|
||||||
// turn off the treshold interrupt
|
// turn off the treshold interrupt
|
||||||
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
|
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.tx_lim[ch].limit = 0;
|
||||||
|
#else
|
||||||
RMT.tx_lim_ch[ch].limit = 0;
|
RMT.tx_lim_ch[ch].limit = 0;
|
||||||
|
#endif
|
||||||
g_rmt_objects[ch].data_size -= half_tx_nr;
|
g_rmt_objects[ch].data_size -= half_tx_nr;
|
||||||
g_rmt_objects[ch].data_ptr += half_tx_nr;
|
g_rmt_objects[ch].data_ptr += half_tx_nr;
|
||||||
} else {
|
} else {
|
||||||
@ -845,32 +1017,43 @@ static void ARDUINO_ISR_ATTR _rmt_tx_mem_first(uint8_t ch)
|
|||||||
g_rmt_objects[ch].data_ptr = NULL;
|
g_rmt_objects[ch].data_ptr = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
//ets_printf("RMT TxF finished %d!\n", ch);
|
||||||
for (i = 0; i < half_tx_nr; i++) {
|
for (i = 0; i < half_tx_nr; i++) {
|
||||||
RMTMEM.chan[ch].data32[i].val = 0x000F000F;
|
RMTMEM.chan[ch].data32[i].val = 0x000F000F;
|
||||||
}
|
}
|
||||||
RMTMEM.chan[ch].data32[i].val = 0;
|
RMTMEM.chan[ch].data32[i].val = 0;
|
||||||
|
|
||||||
g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF;
|
g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.tx_lim[ch].limit = 0;
|
||||||
|
#else
|
||||||
RMT.tx_lim_ch[ch].limit = 0;
|
RMT.tx_lim_ch[ch].limit = 0;
|
||||||
|
#endif
|
||||||
g_rmt_objects[ch].tx_state |= E_LAST_DATA;
|
g_rmt_objects[ch].tx_state |= E_LAST_DATA;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
RMT.tx_conf[ch].tx_conti_mode = 0;
|
||||||
|
#else
|
||||||
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
|
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
DEBUG_INTERRUPT_END(2);
|
DEBUG_INTERRUPT_END(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ARDUINO_ISR_ATTR _rmt_get_mem_len(uint8_t channel)
|
static int ARDUINO_ISR_ATTR _rmt_get_mem_len(uint8_t channel)
|
||||||
{
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
int block_num = RMT.rx_conf[channel].conf0.mem_size;
|
||||||
|
int item_block_len = block_num * 48;
|
||||||
|
#else
|
||||||
int block_num = RMT.conf_ch[channel].conf0.mem_size;
|
int block_num = RMT.conf_ch[channel].conf0.mem_size;
|
||||||
int item_block_len = block_num * 64;
|
int item_block_len = block_num * 64;
|
||||||
volatile uint32_t* data = &RMTMEM.chan[channel].data32->val;
|
#endif
|
||||||
|
volatile rmt_item32_t* data = RMTMEM.chan[channel].data32;
|
||||||
int idx;
|
int idx;
|
||||||
for(idx = 0; idx < item_block_len; idx++) {
|
for(idx = 0; idx < item_block_len; idx++) {
|
||||||
rmt_item32_t helper;
|
if(data[idx].duration0 == 0) {
|
||||||
helper.val = data[idx];
|
|
||||||
|
|
||||||
if(helper.duration0 == 0) {
|
|
||||||
return idx;
|
return idx;
|
||||||
} else if(helper.duration1 == 0) {
|
} else if(data[idx].duration1 == 0) {
|
||||||
return idx + 1;
|
return idx + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,6 @@
|
|||||||
#include "esp32-hal-matrix.h"
|
#include "esp32-hal-matrix.h"
|
||||||
#include "soc/gpio_sd_reg.h"
|
#include "soc/gpio_sd_reg.h"
|
||||||
#include "soc/gpio_sd_struct.h"
|
#include "soc/gpio_sd_struct.h"
|
||||||
#include "freertos/semphr.h"
|
|
||||||
#include "esp32-hal-cpu.h"
|
|
||||||
#include "esp32-hal-gpio.h"
|
|
||||||
|
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
@ -29,6 +26,8 @@
|
|||||||
#include "esp32/rom/ets_sys.h"
|
#include "esp32/rom/ets_sys.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
#include "esp32s2/rom/ets_sys.h"
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/rom/ets_sys.h"
|
||||||
#else
|
#else
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
#endif
|
#endif
|
||||||
@ -43,7 +42,7 @@
|
|||||||
#else
|
#else
|
||||||
#define SD_MUTEX_LOCK() do {} while (xSemaphoreTake(_sd_sys_lock, portMAX_DELAY) != pdPASS)
|
#define SD_MUTEX_LOCK() do {} while (xSemaphoreTake(_sd_sys_lock, portMAX_DELAY) != pdPASS)
|
||||||
#define SD_MUTEX_UNLOCK() xSemaphoreGive(_sd_sys_lock)
|
#define SD_MUTEX_UNLOCK() xSemaphoreGive(_sd_sys_lock)
|
||||||
SemaphoreHandle_t _sd_sys_lock;
|
xSemaphoreHandle _sd_sys_lock;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
|
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
|
||||||
|
@ -12,8 +12,6 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "esp32-hal-spi.h"
|
#include "esp32-hal-spi.h"
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
@ -24,19 +22,25 @@
|
|||||||
#include "soc/spi_struct.h"
|
#include "soc/spi_struct.h"
|
||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
#include "soc/gpio_sig_map.h"
|
#include "soc/gpio_sig_map.h"
|
||||||
#include "soc/dport_reg.h"
|
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
|
#include "driver/periph_ctrl.h"
|
||||||
|
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "soc/dport_reg.h"
|
||||||
#include "esp32/rom/ets_sys.h"
|
#include "esp32/rom/ets_sys.h"
|
||||||
#include "esp32/rom/gpio.h"
|
#include "esp32/rom/gpio.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "soc/dport_reg.h"
|
||||||
#include "esp32s2/rom/ets_sys.h"
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
#include "esp32s2/rom/gpio.h"
|
#include "esp32s2/rom/gpio.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/rom/ets_sys.h"
|
||||||
|
#include "esp32c3/rom/gpio.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
#else
|
#else
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
#endif
|
#endif
|
||||||
@ -45,14 +49,11 @@
|
|||||||
#include "rom/gpio.h"
|
#include "rom/gpio.h"
|
||||||
#include "esp_intr.h"
|
#include "esp_intr.h"
|
||||||
#endif
|
#endif
|
||||||
#include "esp32-hal-gpio.h"
|
|
||||||
#include "esp32-hal-matrix.h"
|
|
||||||
#include "esp32-hal-cpu.h"
|
|
||||||
|
|
||||||
struct spi_struct_t {
|
struct spi_struct_t {
|
||||||
spi_dev_t * dev;
|
spi_dev_t * dev;
|
||||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||||
SemaphoreHandle_t lock;
|
xSemaphoreHandle lock;
|
||||||
#endif
|
#endif
|
||||||
uint8_t num;
|
uint8_t num;
|
||||||
};
|
};
|
||||||
@ -67,11 +68,24 @@ struct spi_struct_t {
|
|||||||
|
|
||||||
#define SPI_SPI_SS_IDX(n) ((n==0)?SPICS0_OUT_IDX:((n==1)?SPICS1_OUT_IDX:0))
|
#define SPI_SPI_SS_IDX(n) ((n==0)?SPICS0_OUT_IDX:((n==1)?SPICS1_OUT_IDX:0))
|
||||||
#define SPI_HSPI_SS_IDX(n) ((n==0)?SPI3_CS0_OUT_IDX:((n==1)?SPI3_CS1_OUT_IDX:((n==2)?SPI3_CS2_OUT_IDX:SPI3_CS0_OUT_IDX)))
|
#define SPI_HSPI_SS_IDX(n) ((n==0)?SPI3_CS0_OUT_IDX:((n==1)?SPI3_CS1_OUT_IDX:((n==2)?SPI3_CS2_OUT_IDX:SPI3_CS0_OUT_IDX)))
|
||||||
#define SPI_FSPI_SS_IDX(n) ((n==0)?FSPICS0_OUT_IDX:((n==1)?FSPICS1_OUT_IDX:((n==2)?FSPICS2_OUT_IDX:VSPICS0_OUT_IDX)))
|
#define SPI_FSPI_SS_IDX(n) ((n==0)?FSPICS0_OUT_IDX:((n==1)?FSPICS1_OUT_IDX:((n==2)?FSPICS2_OUT_IDX:FSPICS0_OUT_IDX)))
|
||||||
#define SPI_SS_IDX(p, n) ((p==0)?SPI_SPI_SS_IDX(n):((p==1)?SPI_SPI_SS_IDX(n):((p==2)?SPI_HSPI_SS_IDX(n):0)))
|
#define SPI_SS_IDX(p, n) ((p==0)?SPI_SPI_SS_IDX(n):((p==1)?SPI_SPI_SS_IDX(n):((p==2)?SPI_HSPI_SS_IDX(n):0)))
|
||||||
|
|
||||||
#define SPI_INTR_SOURCE(u) ((u==0)?ETS_SPI1_INTR_SOURCE:((u==1)?ETS_SPI2_INTR_SOURCE:((u==2)?ETS_SPI3_INTR_SOURCE:0)))
|
#define SPI_INTR_SOURCE(u) ((u==0)?ETS_SPI1_INTR_SOURCE:((u==1)?ETS_SPI2_INTR_SOURCE:((u==2)?ETS_SPI3_INTR_SOURCE:0)))
|
||||||
|
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
// ESP32S2
|
||||||
|
#define SPI_COUNT (1)
|
||||||
|
|
||||||
|
#define SPI_CLK_IDX(p) FSPICLK_OUT_IDX
|
||||||
|
#define SPI_MISO_IDX(p) FSPIQ_OUT_IDX
|
||||||
|
#define SPI_MOSI_IDX(p) FSPID_IN_IDX
|
||||||
|
|
||||||
|
#define SPI_SPI_SS_IDX(n) ((n==0)?FSPICS0_OUT_IDX:((n==1)?FSPICS1_OUT_IDX:((n==2)?FSPICS2_OUT_IDX:FSPICS0_OUT_IDX)))
|
||||||
|
#define SPI_SS_IDX(p, n) SPI_SPI_SS_IDX(n)
|
||||||
|
|
||||||
|
#define SPI_INTR_SOURCE(u) ETS_SPI2_INTR_SOURCE
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// ESP32
|
// ESP32
|
||||||
#define SPI_COUNT (4)
|
#define SPI_COUNT (4)
|
||||||
@ -114,6 +128,8 @@ static spi_t _spi_bus_array[] = {
|
|||||||
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 0},
|
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 0},
|
||||||
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 1},
|
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 1},
|
||||||
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 2}
|
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 2}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
{(volatile spi_dev_t *)(&GPSPI2), NULL, FSPI}
|
||||||
#else
|
#else
|
||||||
{(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0},
|
{(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0},
|
||||||
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1},
|
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1},
|
||||||
@ -136,7 +152,7 @@ void spiAttachSCK(spi_t * spi, int8_t sck)
|
|||||||
log_e("HSPI Does not have default pins on ESP32S2!");
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#elif CONFIG_IDF_TARGET_ESP32
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
sck = 14;
|
sck = 14;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -144,6 +160,9 @@ void spiAttachSCK(spi_t * spi, int8_t sck)
|
|||||||
} else {
|
} else {
|
||||||
sck = 6;
|
sck = 6;
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
log_e("SPI Does not have default pins on ESP32C3!");
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
pinMode(sck, OUTPUT);
|
pinMode(sck, OUTPUT);
|
||||||
@ -163,7 +182,7 @@ void spiAttachMISO(spi_t * spi, int8_t miso)
|
|||||||
log_e("HSPI Does not have default pins on ESP32S2!");
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#elif CONFIG_IDF_TARGET_ESP32
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
miso = 12;
|
miso = 12;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -171,6 +190,9 @@ void spiAttachMISO(spi_t * spi, int8_t miso)
|
|||||||
} else {
|
} else {
|
||||||
miso = 7;
|
miso = 7;
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
log_e("SPI Does not have default pins on ESP32C3!");
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
@ -192,7 +214,7 @@ void spiAttachMOSI(spi_t * spi, int8_t mosi)
|
|||||||
log_e("HSPI Does not have default pins on ESP32S2!");
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#elif CONFIG_IDF_TARGET_ESP32
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
mosi = 13;
|
mosi = 13;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -200,6 +222,9 @@ void spiAttachMOSI(spi_t * spi, int8_t mosi)
|
|||||||
} else {
|
} else {
|
||||||
mosi = 8;
|
mosi = 8;
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
log_e("SPI Does not have default pins on ESP32C3!");
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
pinMode(mosi, OUTPUT);
|
pinMode(mosi, OUTPUT);
|
||||||
@ -219,7 +244,7 @@ void spiDetachSCK(spi_t * spi, int8_t sck)
|
|||||||
log_e("HSPI Does not have default pins on ESP32S2!");
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#elif CONFIG_IDF_TARGET_ESP32
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
sck = 14;
|
sck = 14;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -227,6 +252,9 @@ void spiDetachSCK(spi_t * spi, int8_t sck)
|
|||||||
} else {
|
} else {
|
||||||
sck = 6;
|
sck = 6;
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
log_e("SPI Does not have default pins on ESP32C3!");
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
pinMatrixOutDetach(sck, false, false);
|
pinMatrixOutDetach(sck, false, false);
|
||||||
@ -246,7 +274,7 @@ void spiDetachMISO(spi_t * spi, int8_t miso)
|
|||||||
log_e("HSPI Does not have default pins on ESP32S2!");
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#elif CONFIG_IDF_TARGET_ESP32
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
miso = 12;
|
miso = 12;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -254,6 +282,9 @@ void spiDetachMISO(spi_t * spi, int8_t miso)
|
|||||||
} else {
|
} else {
|
||||||
miso = 7;
|
miso = 7;
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
log_e("SPI Does not have default pins on ESP32C3!");
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
pinMatrixInDetach(SPI_MISO_IDX(spi->num), false, false);
|
pinMatrixInDetach(SPI_MISO_IDX(spi->num), false, false);
|
||||||
@ -273,7 +304,7 @@ void spiDetachMOSI(spi_t * spi, int8_t mosi)
|
|||||||
log_e("HSPI Does not have default pins on ESP32S2!");
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#elif CONFIG_IDF_TARGET_ESP32
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
mosi = 13;
|
mosi = 13;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -281,6 +312,9 @@ void spiDetachMOSI(spi_t * spi, int8_t mosi)
|
|||||||
} else {
|
} else {
|
||||||
mosi = 8;
|
mosi = 8;
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
log_e("SPI Does not have default pins on ESP32C3!");
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
pinMatrixOutDetach(mosi, false, false);
|
pinMatrixOutDetach(mosi, false, false);
|
||||||
@ -304,7 +338,7 @@ void spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss)
|
|||||||
log_e("HSPI Does not have default pins on ESP32S2!");
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#elif CONFIG_IDF_TARGET_ESP32
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
ss = 15;
|
ss = 15;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -312,6 +346,9 @@ void spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss)
|
|||||||
} else {
|
} else {
|
||||||
ss = 11;
|
ss = 11;
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
log_e("SPI Does not have default pins on ESP32C3!");
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
pinMode(ss, OUTPUT);
|
pinMode(ss, OUTPUT);
|
||||||
@ -332,7 +369,7 @@ void spiDetachSS(spi_t * spi, int8_t ss)
|
|||||||
log_e("HSPI Does not have default pins on ESP32S2!");
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#elif CONFIG_IDF_TARGET_ESP32
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
ss = 15;
|
ss = 15;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -340,6 +377,9 @@ void spiDetachSS(spi_t * spi, int8_t ss)
|
|||||||
} else {
|
} else {
|
||||||
ss = 11;
|
ss = 11;
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
log_e("SPI Does not have default pins on ESP32C3!");
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
pinMatrixOutDetach(ss, false, false);
|
pinMatrixOutDetach(ss, false, false);
|
||||||
@ -352,7 +392,7 @@ void spiEnableSSPins(spi_t * spi, uint8_t cs_mask)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.val &= ~(cs_mask & SPI_CS_MASK_ALL);
|
spi->dev->misc.val &= ~(cs_mask & SPI_CS_MASK_ALL);
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.val &= ~(cs_mask & SPI_CS_MASK_ALL);
|
spi->dev->pin.val &= ~(cs_mask & SPI_CS_MASK_ALL);
|
||||||
@ -366,7 +406,7 @@ void spiDisableSSPins(spi_t * spi, uint8_t cs_mask)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.val |= (cs_mask & SPI_CS_MASK_ALL);
|
spi->dev->misc.val |= (cs_mask & SPI_CS_MASK_ALL);
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.val |= (cs_mask & SPI_CS_MASK_ALL);
|
spi->dev->pin.val |= (cs_mask & SPI_CS_MASK_ALL);
|
||||||
@ -402,7 +442,7 @@ void spiSSSet(spi_t * spi)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.cs_keep_active = 1;
|
spi->dev->misc.cs_keep_active = 1;
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.cs_keep_active = 1;
|
spi->dev->pin.cs_keep_active = 1;
|
||||||
@ -416,7 +456,7 @@ void spiSSClear(spi_t * spi)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.cs_keep_active = 0;
|
spi->dev->misc.cs_keep_active = 0;
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.cs_keep_active = 0;
|
spi->dev->pin.cs_keep_active = 0;
|
||||||
@ -447,7 +487,7 @@ uint8_t spiGetDataMode(spi_t * spi)
|
|||||||
if(!spi) {
|
if(!spi) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
bool idleEdge = spi->dev->misc.ck_idle_edge;
|
bool idleEdge = spi->dev->misc.ck_idle_edge;
|
||||||
#else
|
#else
|
||||||
bool idleEdge = spi->dev->pin.ck_idle_edge;
|
bool idleEdge = spi->dev->pin.ck_idle_edge;
|
||||||
@ -473,7 +513,7 @@ void spiSetDataMode(spi_t * spi, uint8_t dataMode)
|
|||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
switch (dataMode) {
|
switch (dataMode) {
|
||||||
case SPI_MODE1:
|
case SPI_MODE1:
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.ck_idle_edge = 0;
|
spi->dev->misc.ck_idle_edge = 0;
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.ck_idle_edge = 0;
|
spi->dev->pin.ck_idle_edge = 0;
|
||||||
@ -481,7 +521,7 @@ void spiSetDataMode(spi_t * spi, uint8_t dataMode)
|
|||||||
spi->dev->user.ck_out_edge = 1;
|
spi->dev->user.ck_out_edge = 1;
|
||||||
break;
|
break;
|
||||||
case SPI_MODE2:
|
case SPI_MODE2:
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.ck_idle_edge = 1;
|
spi->dev->misc.ck_idle_edge = 1;
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.ck_idle_edge = 1;
|
spi->dev->pin.ck_idle_edge = 1;
|
||||||
@ -489,7 +529,7 @@ void spiSetDataMode(spi_t * spi, uint8_t dataMode)
|
|||||||
spi->dev->user.ck_out_edge = 1;
|
spi->dev->user.ck_out_edge = 1;
|
||||||
break;
|
break;
|
||||||
case SPI_MODE3:
|
case SPI_MODE3:
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.ck_idle_edge = 1;
|
spi->dev->misc.ck_idle_edge = 1;
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.ck_idle_edge = 1;
|
spi->dev->pin.ck_idle_edge = 1;
|
||||||
@ -498,7 +538,7 @@ void spiSetDataMode(spi_t * spi, uint8_t dataMode)
|
|||||||
break;
|
break;
|
||||||
case SPI_MODE0:
|
case SPI_MODE0:
|
||||||
default:
|
default:
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.ck_idle_edge = 0;
|
spi->dev->misc.ck_idle_edge = 0;
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.ck_idle_edge = 0;
|
spi->dev->pin.ck_idle_edge = 0;
|
||||||
@ -547,9 +587,11 @@ static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb
|
|||||||
|
|
||||||
static void spiInitBus(spi_t * spi)
|
static void spiInitBus(spi_t * spi)
|
||||||
{
|
{
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->slave.trans_done = 0;
|
spi->dev->slave.trans_done = 0;
|
||||||
spi->dev->slave.slave_mode = 0;
|
#endif
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
spi->dev->slave.val = 0;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.val = 0;
|
spi->dev->misc.val = 0;
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.val = 0;
|
spi->dev->pin.val = 0;
|
||||||
@ -557,8 +599,15 @@ static void spiInitBus(spi_t * spi)
|
|||||||
spi->dev->user.val = 0;
|
spi->dev->user.val = 0;
|
||||||
spi->dev->user1.val = 0;
|
spi->dev->user1.val = 0;
|
||||||
spi->dev->ctrl.val = 0;
|
spi->dev->ctrl.val = 0;
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->ctrl1.val = 0;
|
spi->dev->ctrl1.val = 0;
|
||||||
spi->dev->ctrl2.val = 0;
|
spi->dev->ctrl2.val = 0;
|
||||||
|
#else
|
||||||
|
spi->dev->clk_gate.val = 0;
|
||||||
|
spi->dev->dma_conf.val = 0;
|
||||||
|
spi->dev->dma_conf.rx_afifo_rst = 1;
|
||||||
|
spi->dev->dma_conf.buf_afifo_rst = 1;
|
||||||
|
#endif
|
||||||
spi->dev->clock.val = 0;
|
spi->dev->clock.val = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,7 +652,7 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
|
|||||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
|
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);
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
|
||||||
}
|
}
|
||||||
#else
|
#elif CONFIG_IDF_TARGET_ESP32
|
||||||
if(spi_num == HSPI) {
|
if(spi_num == HSPI) {
|
||||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
|
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
|
||||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
|
||||||
@ -614,14 +663,24 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
|
|||||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
|
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);
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
periph_module_reset( PERIPH_SPI2_MODULE );
|
||||||
|
periph_module_enable( PERIPH_SPI2_MODULE );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
spiInitBus(spi);
|
spiInitBus(spi);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->clk_gate.clk_en = 1;
|
||||||
|
spi->dev->clk_gate.mst_clk_sel = 1;
|
||||||
|
spi->dev->clk_gate.mst_clk_active = 1;
|
||||||
|
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;
|
||||||
|
#endif
|
||||||
spi->dev->user.usr_mosi = 1;
|
spi->dev->user.usr_mosi = 1;
|
||||||
spi->dev->user.usr_miso = 1;
|
spi->dev->user.usr_miso = 1;
|
||||||
spi->dev->user.doutdin = 1;
|
spi->dev->user.doutdin = 1;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<16; i++) {
|
for(i=0; i<16; i++) {
|
||||||
spi->dev->data_buf[i] = 0x00000000;
|
spi->dev->data_buf[i] = 0x00000000;
|
||||||
@ -633,6 +692,7 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
|
|||||||
spiSetClockDiv(spi, clockDiv);
|
spiSetClockDiv(spi, clockDiv);
|
||||||
|
|
||||||
addApbChangeCallback(spi, _on_apb_change);
|
addApbChangeCallback(spi, _on_apb_change);
|
||||||
|
|
||||||
return spi;
|
return spi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,6 +707,11 @@ void spiWaitReady(spi_t * spi)
|
|||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
#define usr_mosi_dbitlen usr_mosi_bit_len
|
#define usr_mosi_dbitlen usr_mosi_bit_len
|
||||||
#define usr_miso_dbitlen usr_miso_bit_len
|
#define usr_miso_dbitlen usr_miso_bit_len
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#define usr_mosi_dbitlen ms_data_bitlen
|
||||||
|
#define usr_miso_dbitlen ms_data_bitlen
|
||||||
|
#define mosi_dlen ms_dlen
|
||||||
|
#define miso_dlen ms_dlen
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void spiWrite(spi_t * spi, const uint32_t *data, uint8_t len)
|
void spiWrite(spi_t * spi, const uint32_t *data, uint8_t len)
|
||||||
@ -660,10 +725,16 @@ void spiWrite(spi_t * spi, const uint32_t *data, uint8_t len)
|
|||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = (len * 32) - 1;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = (len * 32) - 1;
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
#endif
|
||||||
for(i=0; i<len; i++) {
|
for(i=0; i<len; i++) {
|
||||||
spi->dev->data_buf[i] = data[i];
|
spi->dev->data_buf[i] = data[i];
|
||||||
}
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
@ -684,6 +755,10 @@ void spiTransfer(spi_t * spi, uint32_t *data, uint8_t len)
|
|||||||
for(i=0; i<len; i++) {
|
for(i=0; i<len; i++) {
|
||||||
spi->dev->data_buf[i] = data[i];
|
spi->dev->data_buf[i] = data[i];
|
||||||
}
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
for(i=0; i<len; i++) {
|
for(i=0; i<len; i++) {
|
||||||
@ -699,8 +774,14 @@ void spiWriteByte(spi_t * spi, uint8_t data)
|
|||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
#endif
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
@ -715,6 +796,10 @@ uint8_t spiTransferByte(spi_t * spi, uint8_t data)
|
|||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 7;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 7;
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
data = spi->dev->data_buf[0] & 0xFF;
|
data = spi->dev->data_buf[0] & 0xFF;
|
||||||
@ -742,8 +827,14 @@ void spiWriteWord(spi_t * spi, uint16_t data)
|
|||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
#endif
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
@ -761,6 +852,10 @@ uint16_t spiTransferWord(spi_t * spi, uint16_t data)
|
|||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 15;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 15;
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
data = spi->dev->data_buf[0];
|
data = spi->dev->data_buf[0];
|
||||||
@ -781,8 +876,14 @@ void spiWriteLong(spi_t * spi, uint32_t data)
|
|||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
#endif
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
@ -800,6 +901,10 @@ uint32_t spiTransferLong(spi_t * spi, uint32_t data)
|
|||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 31;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 31;
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
data = spi->dev->data_buf[0];
|
data = spi->dev->data_buf[0];
|
||||||
@ -839,6 +944,10 @@ static void __spiTransferBytes(spi_t * spi, const uint8_t * data, uint8_t * out,
|
|||||||
spi->dev->data_buf[i] = wordsBuf[i]; //copy buffer to spi fifo
|
spi->dev->data_buf[i] = wordsBuf[i]; //copy buffer to spi fifo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
|
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
@ -903,7 +1012,7 @@ void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bi
|
|||||||
spi->dev->clock.val = clockDiv;
|
spi->dev->clock.val = clockDiv;
|
||||||
switch (dataMode) {
|
switch (dataMode) {
|
||||||
case SPI_MODE1:
|
case SPI_MODE1:
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.ck_idle_edge = 0;
|
spi->dev->misc.ck_idle_edge = 0;
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.ck_idle_edge = 0;
|
spi->dev->pin.ck_idle_edge = 0;
|
||||||
@ -911,7 +1020,7 @@ void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bi
|
|||||||
spi->dev->user.ck_out_edge = 1;
|
spi->dev->user.ck_out_edge = 1;
|
||||||
break;
|
break;
|
||||||
case SPI_MODE2:
|
case SPI_MODE2:
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.ck_idle_edge = 1;
|
spi->dev->misc.ck_idle_edge = 1;
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.ck_idle_edge = 1;
|
spi->dev->pin.ck_idle_edge = 1;
|
||||||
@ -919,7 +1028,7 @@ void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bi
|
|||||||
spi->dev->user.ck_out_edge = 1;
|
spi->dev->user.ck_out_edge = 1;
|
||||||
break;
|
break;
|
||||||
case SPI_MODE3:
|
case SPI_MODE3:
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.ck_idle_edge = 1;
|
spi->dev->misc.ck_idle_edge = 1;
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.ck_idle_edge = 1;
|
spi->dev->pin.ck_idle_edge = 1;
|
||||||
@ -928,7 +1037,7 @@ void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bi
|
|||||||
break;
|
break;
|
||||||
case SPI_MODE0:
|
case SPI_MODE0:
|
||||||
default:
|
default:
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->misc.ck_idle_edge = 0;
|
spi->dev->misc.ck_idle_edge = 0;
|
||||||
#else
|
#else
|
||||||
spi->dev->pin.ck_idle_edge = 0;
|
spi->dev->pin.ck_idle_edge = 0;
|
||||||
@ -967,8 +1076,14 @@ void ARDUINO_ISR_ATTR spiWriteByteNL(spi_t * spi, uint8_t data)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
#endif
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
}
|
}
|
||||||
@ -981,6 +1096,10 @@ uint8_t spiTransferByteNL(spi_t * spi, uint8_t data)
|
|||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 7;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 7;
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
data = spi->dev->data_buf[0] & 0xFF;
|
data = spi->dev->data_buf[0] & 0xFF;
|
||||||
@ -996,8 +1115,14 @@ void ARDUINO_ISR_ATTR spiWriteShortNL(spi_t * spi, uint16_t data)
|
|||||||
MSB_16_SET(data, data);
|
MSB_16_SET(data, data);
|
||||||
}
|
}
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
#endif
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
}
|
}
|
||||||
@ -1013,6 +1138,10 @@ uint16_t spiTransferShortNL(spi_t * spi, uint16_t data)
|
|||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 15;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 15;
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
data = spi->dev->data_buf[0] & 0xFFFF;
|
data = spi->dev->data_buf[0] & 0xFFFF;
|
||||||
@ -1031,8 +1160,14 @@ void ARDUINO_ISR_ATTR spiWriteLongNL(spi_t * spi, uint32_t data)
|
|||||||
MSB_32_SET(data, data);
|
MSB_32_SET(data, data);
|
||||||
}
|
}
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
#endif
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
}
|
}
|
||||||
@ -1048,6 +1183,10 @@ uint32_t spiTransferLongNL(spi_t * spi, uint32_t data)
|
|||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 31;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 31;
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
data = spi->dev->data_buf[0];
|
data = spi->dev->data_buf[0];
|
||||||
@ -1058,6 +1197,9 @@ uint32_t spiTransferLongNL(spi_t * spi, uint32_t data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void spiWriteNL(spi_t * spi, const void * data_in, uint32_t len){
|
void spiWriteNL(spi_t * spi, const void * data_in, uint32_t len){
|
||||||
|
if(!spi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
size_t longs = len >> 2;
|
size_t longs = len >> 2;
|
||||||
if(len & 3){
|
if(len & 3){
|
||||||
longs++;
|
longs++;
|
||||||
@ -1070,10 +1212,16 @@ void spiWriteNL(spi_t * spi, const void * data_in, uint32_t len){
|
|||||||
c_longs = (longs > 16)?16:longs;
|
c_longs = (longs > 16)?16:longs;
|
||||||
|
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = (c_len*8)-1;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = (c_len*8)-1;
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
#endif
|
||||||
for (int i=0; i<c_longs; i++) {
|
for (int i=0; i<c_longs; i++) {
|
||||||
spi->dev->data_buf[i] = data[i];
|
spi->dev->data_buf[i] = data[i];
|
||||||
}
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
|
|
||||||
@ -1110,13 +1258,29 @@ void spiTransferBytesNL(spi_t * spi, const void * data_in, uint8_t * data_out, u
|
|||||||
spi->dev->data_buf[i] = 0xFFFFFFFF;
|
spi->dev->data_buf[i] = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
if(result){
|
if(result){
|
||||||
|
if(c_len & 3){
|
||||||
|
for (int i=0; i<(c_longs-1); i++) {
|
||||||
|
result[i] = spi->dev->data_buf[i];
|
||||||
|
}
|
||||||
|
uint32_t last_data = spi->dev->data_buf[c_longs-1];
|
||||||
|
uint8_t * last_out8 = (uint8_t *)&result[c_longs-1];
|
||||||
|
uint8_t * last_data8 = (uint8_t *)&last_data;
|
||||||
|
for (int i=0; i<(c_len & 3); i++) {
|
||||||
|
last_out8[i] = last_data8[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for (int i=0; i<c_longs; i++) {
|
for (int i=0; i<c_longs; i++) {
|
||||||
result[i] = spi->dev->data_buf[i];
|
result[i] = spi->dev->data_buf[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(data){
|
if(data){
|
||||||
data += c_longs;
|
data += c_longs;
|
||||||
}
|
}
|
||||||
@ -1153,6 +1317,10 @@ 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->mosi_dlen.usr_mosi_dbitlen = (bits - 1);
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = (bits - 1);
|
spi->dev->miso_dlen.usr_miso_dbitlen = (bits - 1);
|
||||||
spi->dev->data_buf[0] = data;
|
spi->dev->data_buf[0] = data;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
data = spi->dev->data_buf[0];
|
data = spi->dev->data_buf[0];
|
||||||
@ -1185,7 +1353,9 @@ void ARDUINO_ISR_ATTR spiWritePixelsNL(spi_t * spi, const void * data_in, uint32
|
|||||||
l_bytes = (c_len & 3);
|
l_bytes = (c_len & 3);
|
||||||
|
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = (c_len*8)-1;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = (c_len*8)-1;
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
#endif
|
||||||
for (int i=0; i<c_longs; i++) {
|
for (int i=0; i<c_longs; i++) {
|
||||||
if(msb){
|
if(msb){
|
||||||
if(l_bytes && i == (c_longs - 1)){
|
if(l_bytes && i == (c_longs - 1)){
|
||||||
@ -1201,6 +1371,10 @@ void ARDUINO_ISR_ATTR spiWritePixelsNL(spi_t * spi, const void * data_in, uint32
|
|||||||
spi->dev->data_buf[i] = data[i];
|
spi->dev->data_buf[i] = data[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
spi->dev->cmd.update = 1;
|
||||||
|
while (spi->dev->cmd.update);
|
||||||
|
#endif
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
|
|
||||||
@ -1223,7 +1397,12 @@ typedef union {
|
|||||||
uint32_t clkcnt_l: 6; /*it must be equal to spi_clkcnt_N.*/
|
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_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)*/
|
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_ESP32C3
|
||||||
|
uint32_t clkdiv_pre: 4; /*it is pre-divider of spi_clk.*/
|
||||||
|
uint32_t reserved: 9; /*reserved*/
|
||||||
|
#else
|
||||||
uint32_t clkdiv_pre: 13; /*it is pre-divider of spi_clk.*/
|
uint32_t clkdiv_pre: 13; /*it is pre-divider of spi_clk.*/
|
||||||
|
#endif
|
||||||
uint32_t clk_equ_sysclk: 1; /*1: spi_clk is eqaul to system 0: spi_clk is divided from system clock.*/
|
uint32_t clk_equ_sysclk: 1; /*1: spi_clk is eqaul to system 0: spi_clk is divided from system clock.*/
|
||||||
};
|
};
|
||||||
} spiClk_t;
|
} spiClk_t;
|
||||||
@ -1265,8 +1444,13 @@ uint32_t spiFrequencyToClockDiv(uint32_t freq)
|
|||||||
|
|
||||||
while(calPreVari++ <= 1) {
|
while(calPreVari++ <= 1) {
|
||||||
calPre = (((apb_freq / (reg.clkcnt_n + 1)) / freq) - 1) + calPreVari;
|
calPre = (((apb_freq / (reg.clkcnt_n + 1)) / freq) - 1) + calPreVari;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
if(calPre > 0xF) {
|
||||||
|
reg.clkdiv_pre = 0xF;
|
||||||
|
#else
|
||||||
if(calPre > 0x1FFF) {
|
if(calPre > 0x1FFF) {
|
||||||
reg.clkdiv_pre = 0x1FFF;
|
reg.clkdiv_pre = 0x1FFF;
|
||||||
|
#endif
|
||||||
} else if(calPre <= 0) {
|
} else if(calPre <= 0) {
|
||||||
reg.clkdiv_pre = 0;
|
reg.clkdiv_pre = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -25,11 +25,16 @@ extern "C" {
|
|||||||
|
|
||||||
#define SPI_HAS_TRANSACTION
|
#define SPI_HAS_TRANSACTION
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#define FSPI 0
|
||||||
|
#define HSPI 1
|
||||||
|
#else
|
||||||
#define FSPI 1 //SPI bus attached to the flash (can use the same data lines but different SS)
|
#define FSPI 1 //SPI bus attached to the flash (can use the same data lines but different SS)
|
||||||
#define HSPI 2 //SPI bus normally mapped to pins 12 - 15, but can be matrixed to any pins
|
#define HSPI 2 //SPI bus normally mapped to pins 12 - 15, but can be matrixed to any pins
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
#define VSPI 3 //SPI bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins
|
#define VSPI 3 //SPI bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// This defines are not representing the real Divider of the ESP32
|
// This defines are not representing the real Divider of the ESP32
|
||||||
// the Defines match to an AVR Arduino on 16MHz for better compatibility
|
// the Defines match to an AVR Arduino on 16MHz for better compatibility
|
||||||
|
97
cores/esp32/esp32-hal-time.c
Normal file
97
cores/esp32/esp32-hal-time.c
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// Copyright 2015-2016 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.h"
|
||||||
|
#include "lwip/apps/sntp.h"
|
||||||
|
//#include "tcpip_adapter.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
|
||||||
|
static void setTimeZone(long offset, int daylight)
|
||||||
|
{
|
||||||
|
char cst[17] = {0};
|
||||||
|
char cdt[17] = "DST";
|
||||||
|
char tz[33] = {0};
|
||||||
|
|
||||||
|
if(offset % 3600){
|
||||||
|
sprintf(cst, "UTC%ld:%02u:%02u", offset / 3600, abs((offset % 3600) / 60), abs(offset % 60));
|
||||||
|
} else {
|
||||||
|
sprintf(cst, "UTC%ld", offset / 3600);
|
||||||
|
}
|
||||||
|
if(daylight != 3600){
|
||||||
|
long tz_dst = offset - daylight;
|
||||||
|
if(tz_dst % 3600){
|
||||||
|
sprintf(cdt, "DST%ld:%02u:%02u", tz_dst / 3600, abs((tz_dst % 3600) / 60), abs(tz_dst % 60));
|
||||||
|
} else {
|
||||||
|
sprintf(cdt, "DST%ld", tz_dst / 3600);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sprintf(tz, "%s%s", cst, cdt);
|
||||||
|
setenv("TZ", tz, 1);
|
||||||
|
tzset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* configTime
|
||||||
|
* Source: https://github.com/esp8266/Arduino/blob/master/cores/esp8266/time.c
|
||||||
|
* */
|
||||||
|
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();
|
||||||
|
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();
|
||||||
|
setTimeZone(-gmtOffset_sec, daylightOffset_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* configTzTime
|
||||||
|
* sntp setup using TZ environment variable
|
||||||
|
* */
|
||||||
|
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();
|
||||||
|
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();
|
||||||
|
setenv("TZ", tz, 1);
|
||||||
|
tzset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getLocalTime(struct tm * info, uint32_t ms)
|
||||||
|
{
|
||||||
|
uint32_t start = millis();
|
||||||
|
time_t now;
|
||||||
|
while((millis()-start) <= ms) {
|
||||||
|
time(&now);
|
||||||
|
localtime_r(&now, info);
|
||||||
|
if(info->tm_year > (2016 - 1900)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
365
cores/esp32/esp32-hal-timer.c
Normal file
365
cores/esp32/esp32-hal-timer.c
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
// Copyright 2015-2016 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-timer.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "freertos/xtensa_api.h"
|
||||||
|
#include "soc/dport_reg.h"
|
||||||
|
#endif
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "soc/timer_group_struct.h"
|
||||||
|
#include "esp_attr.h"
|
||||||
|
#include "driver/periph_ctrl.h"
|
||||||
|
|
||||||
|
#include "esp_system.h"
|
||||||
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "esp32/rom/ets_sys.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
#include "soc/periph_defs.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/rom/ets_sys.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
#include "soc/periph_defs.h"
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
|
#include "rom/ets_sys.h"
|
||||||
|
#include "esp_intr.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HWTIMER_LOCK() portENTER_CRITICAL(timer->lock)
|
||||||
|
#define HWTIMER_UNLOCK() portEXIT_CRITICAL(timer->lock)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint32_t reserved0: 10;
|
||||||
|
uint32_t alarm_en: 1; /*When set alarm is enabled*/
|
||||||
|
uint32_t level_int_en: 1; /*When set level type interrupt will be generated during alarm*/
|
||||||
|
uint32_t edge_int_en: 1; /*When set edge type interrupt will be generated during alarm*/
|
||||||
|
uint32_t divider: 16; /*Timer clock (T0/1_clk) pre-scale value.*/
|
||||||
|
uint32_t autoreload: 1; /*When set timer 0/1 auto-reload at alarming is enabled*/
|
||||||
|
uint32_t increase: 1; /*When set timer 0/1 time-base counter increment. When cleared timer 0 time-base counter decrement.*/
|
||||||
|
uint32_t enable: 1; /*When set timer 0/1 time-base counter is enabled*/
|
||||||
|
};
|
||||||
|
uint32_t val;
|
||||||
|
} config;
|
||||||
|
uint32_t cnt_low; /*Register to store timer 0/1 time-base counter current value lower 32 bits.*/
|
||||||
|
uint32_t cnt_high; /*Register to store timer 0 time-base counter current value higher 32 bits.*/
|
||||||
|
uint32_t update; /*Write any value will trigger a timer 0 time-base counter value update (timer 0 current value will be stored in registers above)*/
|
||||||
|
uint32_t alarm_low; /*Timer 0 time-base counter value lower 32 bits that will trigger the alarm*/
|
||||||
|
uint32_t alarm_high; /*Timer 0 time-base counter value higher 32 bits that will trigger the alarm*/
|
||||||
|
uint32_t load_low; /*Lower 32 bits of the value that will load into timer 0 time-base counter*/
|
||||||
|
uint32_t load_high; /*higher 32 bits of the value that will load into timer 0 time-base counter*/
|
||||||
|
uint32_t reload; /*Write any value will trigger timer 0 time-base counter reload*/
|
||||||
|
} hw_timer_reg_t;
|
||||||
|
|
||||||
|
typedef struct hw_timer_s {
|
||||||
|
hw_timer_reg_t * dev;
|
||||||
|
uint8_t num;
|
||||||
|
uint8_t group;
|
||||||
|
uint8_t timer;
|
||||||
|
portMUX_TYPE lock;
|
||||||
|
} hw_timer_t;
|
||||||
|
|
||||||
|
static hw_timer_t hw_timer[4] = {
|
||||||
|
{(hw_timer_reg_t *)(DR_REG_TIMERGROUP0_BASE),0,0,0,portMUX_INITIALIZER_UNLOCKED},
|
||||||
|
{(hw_timer_reg_t *)(DR_REG_TIMERGROUP0_BASE + 0x0024),1,0,1,portMUX_INITIALIZER_UNLOCKED},
|
||||||
|
{(hw_timer_reg_t *)(DR_REG_TIMERGROUP0_BASE + 0x1000),2,1,0,portMUX_INITIALIZER_UNLOCKED},
|
||||||
|
{(hw_timer_reg_t *)(DR_REG_TIMERGROUP0_BASE + 0x1024),3,1,1,portMUX_INITIALIZER_UNLOCKED}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*voidFuncPtr)(void);
|
||||||
|
static voidFuncPtr __timerInterruptHandlers[4] = {0,0,0,0};
|
||||||
|
|
||||||
|
void ARDUINO_ISR_ATTR __timerISR(void * arg){
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
uint32_t s0 = TIMERG0.int_st_timers.val;
|
||||||
|
uint32_t s1 = TIMERG1.int_st_timers.val;
|
||||||
|
TIMERG0.int_clr_timers.val = s0;
|
||||||
|
TIMERG1.int_clr_timers.val = s1;
|
||||||
|
#else
|
||||||
|
uint32_t s0 = TIMERG0.int_st.val;
|
||||||
|
uint32_t s1 = TIMERG1.int_st.val;
|
||||||
|
TIMERG0.int_clr.val = s0;
|
||||||
|
TIMERG1.int_clr.val = s1;
|
||||||
|
#endif
|
||||||
|
uint8_t status = (s1 & 3) << 2 | (s0 & 3);
|
||||||
|
uint8_t i = 4;
|
||||||
|
//restart the timers that should autoreload
|
||||||
|
while(i--){
|
||||||
|
hw_timer_reg_t * dev = hw_timer[i].dev;
|
||||||
|
if((status & (1 << i)) && dev->config.autoreload){
|
||||||
|
dev->config.alarm_en = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = 4;
|
||||||
|
//call callbacks
|
||||||
|
while(i--){
|
||||||
|
if(__timerInterruptHandlers[i] && (status & (1 << i))){
|
||||||
|
__timerInterruptHandlers[i]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t timerRead(hw_timer_t *timer){
|
||||||
|
timer->dev->update = 1;
|
||||||
|
uint64_t h = timer->dev->cnt_high;
|
||||||
|
uint64_t l = timer->dev->cnt_low;
|
||||||
|
return (h << 32) | l;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t timerAlarmRead(hw_timer_t *timer){
|
||||||
|
uint64_t h = timer->dev->alarm_high;
|
||||||
|
uint64_t l = timer->dev->alarm_low;
|
||||||
|
return (h << 32) | l;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerWrite(hw_timer_t *timer, uint64_t val){
|
||||||
|
timer->dev->load_high = (uint32_t) (val >> 32);
|
||||||
|
timer->dev->load_low = (uint32_t) (val);
|
||||||
|
timer->dev->reload = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload){
|
||||||
|
timer->dev->alarm_high = (uint32_t) (alarm_value >> 32);
|
||||||
|
timer->dev->alarm_low = (uint32_t) alarm_value;
|
||||||
|
timer->dev->config.autoreload = autoreload;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerSetConfig(hw_timer_t *timer, uint32_t config){
|
||||||
|
timer->dev->config.val = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t timerGetConfig(hw_timer_t *timer){
|
||||||
|
return timer->dev->config.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerSetCountUp(hw_timer_t *timer, bool countUp){
|
||||||
|
timer->dev->config.increase = countUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool timerGetCountUp(hw_timer_t *timer){
|
||||||
|
return timer->dev->config.increase;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerSetAutoReload(hw_timer_t *timer, bool autoreload){
|
||||||
|
timer->dev->config.autoreload = autoreload;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool timerGetAutoReload(hw_timer_t *timer){
|
||||||
|
return timer->dev->config.autoreload;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerSetDivider(hw_timer_t *timer, uint16_t divider){//2 to 65536
|
||||||
|
if(!divider){
|
||||||
|
divider = 0xFFFF;
|
||||||
|
} else if(divider == 1){
|
||||||
|
divider = 2;
|
||||||
|
}
|
||||||
|
int timer_en = timer->dev->config.enable;
|
||||||
|
timer->dev->config.enable = 0;
|
||||||
|
timer->dev->config.divider = divider;
|
||||||
|
timer->dev->config.enable = timer_en;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t timerGetDivider(hw_timer_t *timer){
|
||||||
|
return timer->dev->config.divider;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerStart(hw_timer_t *timer){
|
||||||
|
timer->dev->config.enable = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerStop(hw_timer_t *timer){
|
||||||
|
timer->dev->config.enable = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerRestart(hw_timer_t *timer){
|
||||||
|
timer->dev->config.enable = 0;
|
||||||
|
timer->dev->reload = 1;
|
||||||
|
timer->dev->config.enable = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool timerStarted(hw_timer_t *timer){
|
||||||
|
return timer->dev->config.enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerAlarmEnable(hw_timer_t *timer){
|
||||||
|
timer->dev->config.alarm_en = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerAlarmDisable(hw_timer_t *timer){
|
||||||
|
timer->dev->config.alarm_en = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool timerAlarmEnabled(hw_timer_t *timer){
|
||||||
|
return timer->dev->config.alarm_en;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
|
||||||
|
hw_timer_t * timer = (hw_timer_t *)arg;
|
||||||
|
if(ev_type == APB_BEFORE_CHANGE){
|
||||||
|
timer->dev->config.enable = 0;
|
||||||
|
} else {
|
||||||
|
old_apb /= 1000000;
|
||||||
|
new_apb /= 1000000;
|
||||||
|
timer->dev->config.divider = (new_apb * timer->dev->config.divider) / old_apb;
|
||||||
|
timer->dev->config.enable = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){
|
||||||
|
if(num > 3){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
hw_timer_t * timer = &hw_timer[num];
|
||||||
|
if(timer->group) {
|
||||||
|
periph_module_enable(PERIPH_TIMG1_MODULE);
|
||||||
|
} else {
|
||||||
|
periph_module_enable(PERIPH_TIMG0_MODULE);
|
||||||
|
}
|
||||||
|
timer->dev->config.enable = 0;
|
||||||
|
if(timer->group) {
|
||||||
|
TIMERG1.int_ena.val &= ~BIT(timer->timer);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
TIMERG1.int_clr_timers.val |= BIT(timer->timer);
|
||||||
|
#else
|
||||||
|
TIMERG1.int_clr.val = BIT(timer->timer);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
TIMERG0.int_ena.val &= ~BIT(timer->timer);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
TIMERG0.int_clr_timers.val |= BIT(timer->timer);
|
||||||
|
#else
|
||||||
|
TIMERG0.int_clr.val = BIT(timer->timer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK
|
||||||
|
timer->dev->config.use_xtal = 0;
|
||||||
|
#endif
|
||||||
|
timerSetDivider(timer, divider);
|
||||||
|
timerSetCountUp(timer, countUp);
|
||||||
|
timerSetAutoReload(timer, false);
|
||||||
|
timerAttachInterrupt(timer, NULL, false);
|
||||||
|
timerWrite(timer, 0);
|
||||||
|
timer->dev->config.enable = 1;
|
||||||
|
addApbChangeCallback(timer, _on_apb_change);
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerEnd(hw_timer_t *timer){
|
||||||
|
timer->dev->config.enable = 0;
|
||||||
|
timerAttachInterrupt(timer, NULL, false);
|
||||||
|
removeApbChangeCallback(timer, _on_apb_change);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
|
||||||
|
static bool initialized = false;
|
||||||
|
static intr_handle_t intr_handle = NULL;
|
||||||
|
if(intr_handle){
|
||||||
|
esp_intr_disable(intr_handle);
|
||||||
|
}
|
||||||
|
if(fn == NULL){
|
||||||
|
timer->dev->config.level_int_en = 0;
|
||||||
|
timer->dev->config.edge_int_en = 0;
|
||||||
|
timer->dev->config.alarm_en = 0;
|
||||||
|
if(timer->num & 2){
|
||||||
|
TIMERG1.int_ena.val &= ~BIT(timer->timer);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
TIMERG1.int_clr_timers.val |= BIT(timer->timer);
|
||||||
|
#else
|
||||||
|
TIMERG1.int_clr.val = BIT(timer->timer);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
TIMERG0.int_ena.val &= ~BIT(timer->timer);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
TIMERG0.int_clr_timers.val |= BIT(timer->timer);
|
||||||
|
#else
|
||||||
|
TIMERG0.int_clr.val = BIT(timer->timer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
__timerInterruptHandlers[timer->num] = NULL;
|
||||||
|
} else {
|
||||||
|
__timerInterruptHandlers[timer->num] = fn;
|
||||||
|
timer->dev->config.level_int_en = edge?0:1;//When set, an alarm will generate a level type interrupt.
|
||||||
|
timer->dev->config.edge_int_en = edge?1:0;//When set, an alarm will generate an edge type interrupt.
|
||||||
|
int intr_source = 0;
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
if(!edge){
|
||||||
|
#endif
|
||||||
|
if(timer->group){
|
||||||
|
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer->timer;
|
||||||
|
} else {
|
||||||
|
intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer->timer;
|
||||||
|
}
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
} else {
|
||||||
|
if(timer->group){
|
||||||
|
intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer->timer;
|
||||||
|
} else {
|
||||||
|
intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer->timer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if(!initialized){
|
||||||
|
initialized = true;
|
||||||
|
esp_intr_alloc(intr_source, (int)(ARDUINO_ISR_FLAG|ESP_INTR_FLAG_LOWMED), __timerISR, NULL, &intr_handle);
|
||||||
|
} else {
|
||||||
|
intr_matrix_set(esp_intr_get_cpu(intr_handle), intr_source, esp_intr_get_intno(intr_handle));
|
||||||
|
}
|
||||||
|
if(timer->group){
|
||||||
|
TIMERG1.int_ena.val |= BIT(timer->timer);
|
||||||
|
} else {
|
||||||
|
TIMERG0.int_ena.val |= BIT(timer->timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(intr_handle){
|
||||||
|
esp_intr_enable(intr_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerDetachInterrupt(hw_timer_t *timer){
|
||||||
|
timerAttachInterrupt(timer, NULL, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t timerReadMicros(hw_timer_t *timer){
|
||||||
|
uint64_t timer_val = timerRead(timer);
|
||||||
|
uint16_t div = timerGetDivider(timer);
|
||||||
|
return timer_val * div / (getApbFrequency() / 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
double timerReadSeconds(hw_timer_t *timer){
|
||||||
|
uint64_t timer_val = timerRead(timer);
|
||||||
|
uint16_t div = timerGetDivider(timer);
|
||||||
|
return (double)timer_val * div / getApbFrequency();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t timerAlarmReadMicros(hw_timer_t *timer){
|
||||||
|
uint64_t timer_val = timerAlarmRead(timer);
|
||||||
|
uint16_t div = timerGetDivider(timer);
|
||||||
|
return timer_val * div / (getApbFrequency() / 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
double timerAlarmReadSeconds(hw_timer_t *timer){
|
||||||
|
uint64_t timer_val = timerAlarmRead(timer);
|
||||||
|
uint16_t div = timerGetDivider(timer);
|
||||||
|
return (double)timer_val * div / getApbFrequency();
|
||||||
|
}
|
72
cores/esp32/esp32-hal-timer.h
Normal file
72
cores/esp32/esp32-hal-timer.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
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_TIMER_H_
|
||||||
|
#define MAIN_ESP32_HAL_TIMER_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
|
||||||
|
struct hw_timer_s;
|
||||||
|
typedef struct hw_timer_s hw_timer_t;
|
||||||
|
|
||||||
|
hw_timer_t * timerBegin(uint8_t timer, uint16_t divider, bool countUp);
|
||||||
|
void timerEnd(hw_timer_t *timer);
|
||||||
|
|
||||||
|
void timerSetConfig(hw_timer_t *timer, uint32_t config);
|
||||||
|
uint32_t timerGetConfig(hw_timer_t *timer);
|
||||||
|
|
||||||
|
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge);
|
||||||
|
void timerDetachInterrupt(hw_timer_t *timer);
|
||||||
|
|
||||||
|
void timerStart(hw_timer_t *timer);
|
||||||
|
void timerStop(hw_timer_t *timer);
|
||||||
|
void timerRestart(hw_timer_t *timer);
|
||||||
|
void timerWrite(hw_timer_t *timer, uint64_t val);
|
||||||
|
void timerSetDivider(hw_timer_t *timer, uint16_t divider);
|
||||||
|
void timerSetCountUp(hw_timer_t *timer, bool countUp);
|
||||||
|
void timerSetAutoReload(hw_timer_t *timer, bool autoreload);
|
||||||
|
|
||||||
|
bool timerStarted(hw_timer_t *timer);
|
||||||
|
uint64_t timerRead(hw_timer_t *timer);
|
||||||
|
uint64_t timerReadMicros(hw_timer_t *timer);
|
||||||
|
double timerReadSeconds(hw_timer_t *timer);
|
||||||
|
uint16_t timerGetDivider(hw_timer_t *timer);
|
||||||
|
bool timerGetCountUp(hw_timer_t *timer);
|
||||||
|
bool timerGetAutoReload(hw_timer_t *timer);
|
||||||
|
|
||||||
|
void timerAlarmEnable(hw_timer_t *timer);
|
||||||
|
void timerAlarmDisable(hw_timer_t *timer);
|
||||||
|
void timerAlarmWrite(hw_timer_t *timer, uint64_t interruptAt, bool autoreload);
|
||||||
|
|
||||||
|
bool timerAlarmEnabled(hw_timer_t *timer);
|
||||||
|
uint64_t timerAlarmRead(hw_timer_t *timer);
|
||||||
|
uint64_t timerAlarmReadMicros(hw_timer_t *timer);
|
||||||
|
double timerAlarmReadSeconds(hw_timer_t *timer);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* MAIN_ESP32_HAL_TIMER_H_ */
|
@ -1,7 +1,8 @@
|
|||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if CONFIG_USB_ENABLED
|
#if CONFIG_TINYUSB_ENABLED
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
@ -12,10 +13,14 @@
|
|||||||
#include "soc/usb_reg.h"
|
#include "soc/usb_reg.h"
|
||||||
#include "soc/usb_wrap_reg.h"
|
#include "soc/usb_wrap_reg.h"
|
||||||
#include "soc/usb_wrap_struct.h"
|
#include "soc/usb_wrap_struct.h"
|
||||||
|
#include "soc/usb_periph.h"
|
||||||
#include "soc/periph_defs.h"
|
#include "soc/periph_defs.h"
|
||||||
#include "soc/timer_group_struct.h"
|
#include "soc/timer_group_struct.h"
|
||||||
#include "soc/system_reg.h"
|
#include "soc/system_reg.h"
|
||||||
|
|
||||||
|
#include "hal/usb_hal.h"
|
||||||
|
#include "hal/gpio_ll.h"
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
|
||||||
@ -24,8 +29,8 @@
|
|||||||
|
|
||||||
#include "esp_efuse.h"
|
#include "esp_efuse.h"
|
||||||
#include "esp_efuse_table.h"
|
#include "esp_efuse_table.h"
|
||||||
|
#include "esp_rom_gpio.h"
|
||||||
|
|
||||||
#include "tinyusb.h"
|
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
|
|
||||||
#include "esp32-hal-tinyusb.h"
|
#include "esp32-hal-tinyusb.h"
|
||||||
@ -33,6 +38,66 @@
|
|||||||
#include "esp32s2/rom/usb/usb_dc.h"
|
#include "esp32s2/rom/usb/usb_dc.h"
|
||||||
#include "esp32s2/rom/usb/chip_usb_dw_wrapper.h"
|
#include "esp32s2/rom/usb/chip_usb_dw_wrapper.h"
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
TINYUSB_USBDEV_0,
|
||||||
|
} tinyusb_usbdev_t;
|
||||||
|
|
||||||
|
typedef char *tusb_desc_strarray_device_t[USB_STRING_DESCRIPTOR_ARRAY_SIZE];
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool external_phy;
|
||||||
|
} tinyusb_config_t;
|
||||||
|
|
||||||
|
static void configure_pins(usb_hal_context_t *usb)
|
||||||
|
{
|
||||||
|
for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) {
|
||||||
|
if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) {
|
||||||
|
esp_rom_gpio_pad_select_gpio(iopin->pin);
|
||||||
|
if (iopin->is_output) {
|
||||||
|
esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false);
|
||||||
|
} else {
|
||||||
|
esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false);
|
||||||
|
if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) {
|
||||||
|
gpio_ll_input_enable(&GPIO, iopin->pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
esp_rom_gpio_pad_unhold(iopin->pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!usb->use_external_phy) {
|
||||||
|
gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
|
||||||
|
gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t tinyusb_driver_install(const tinyusb_config_t *config)
|
||||||
|
{
|
||||||
|
log_i("Driver installation...");
|
||||||
|
|
||||||
|
// Hal init
|
||||||
|
usb_hal_context_t hal = {
|
||||||
|
.use_external_phy = config->external_phy
|
||||||
|
};
|
||||||
|
usb_hal_init(&hal);
|
||||||
|
configure_pins(&hal);
|
||||||
|
|
||||||
|
if (!tusb_init()) {
|
||||||
|
log_e("Can't initialize the TinyUSB stack.");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
log_i("Driver installed");
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef char tusb_str_t[127];
|
typedef char tusb_str_t[127];
|
||||||
|
|
||||||
static bool WEBUSB_ENABLED = false;
|
static bool WEBUSB_ENABLED = false;
|
||||||
@ -294,9 +359,9 @@ bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const
|
|||||||
* Required Callbacks
|
* Required Callbacks
|
||||||
* */
|
* */
|
||||||
#if CFG_TUD_HID
|
#if CFG_TUD_HID
|
||||||
__attribute__ ((weak)) const uint8_t * tud_hid_descriptor_report_cb(void){return NULL;}
|
__attribute__ ((weak)) const uint8_t * tud_hid_descriptor_report_cb(uint8_t itf){return NULL;}
|
||||||
__attribute__ ((weak)) uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen){return 0;}
|
__attribute__ ((weak)) uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen){return 0;}
|
||||||
__attribute__ ((weak)) void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, const uint8_t * buffer, uint16_t bufsize){}
|
__attribute__ ((weak)) void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, const uint8_t * buffer, uint16_t bufsize){}
|
||||||
#endif
|
#endif
|
||||||
#if CFG_TUD_MSC
|
#if CFG_TUD_MSC
|
||||||
__attribute__ ((weak)) bool tud_msc_test_unit_ready_cb(uint8_t lun){return false;}
|
__attribute__ ((weak)) bool tud_msc_test_unit_ready_cb(uint8_t lun){return false;}
|
||||||
@ -385,8 +450,8 @@ static bool tinyusb_load_enabled_interfaces(){
|
|||||||
};
|
};
|
||||||
memcpy(tinyusb_config_descriptor, descriptor, TUD_CONFIG_DESC_LEN);
|
memcpy(tinyusb_config_descriptor, descriptor, TUD_CONFIG_DESC_LEN);
|
||||||
if ((tinyusb_loaded_interfaces_mask == (BIT(USB_INTERFACE_CDC) | BIT(USB_INTERFACE_DFU))) || (tinyusb_loaded_interfaces_mask == BIT(USB_INTERFACE_CDC))) {
|
if ((tinyusb_loaded_interfaces_mask == (BIT(USB_INTERFACE_CDC) | BIT(USB_INTERFACE_DFU))) || (tinyusb_loaded_interfaces_mask == BIT(USB_INTERFACE_CDC))) {
|
||||||
usb_persist_enabled = true;
|
//usb_persist_enabled = true;
|
||||||
log_d("USB Persist enabled");
|
//log_d("USB Persist enabled");
|
||||||
}
|
}
|
||||||
log_d("Load Done: if_num: %u, descr_len: %u, if_mask: 0x%x", tinyusb_loaded_interfaces_num, tinyusb_config_descriptor_len, tinyusb_loaded_interfaces_mask);
|
log_d("Load Done: if_num: %u, descr_len: %u, if_mask: 0x%x", tinyusb_loaded_interfaces_num, tinyusb_config_descriptor_len, tinyusb_loaded_interfaces_mask);
|
||||||
return true;
|
return true;
|
||||||
@ -465,6 +530,9 @@ static void IRAM_ATTR usb_persist_shutdown_handler(void)
|
|||||||
//USB CDC Download
|
//USB CDC Download
|
||||||
if (usb_persist_enabled) {
|
if (usb_persist_enabled) {
|
||||||
chip_usb_set_persist_flags(USBDC_PERSIST_ENA);
|
chip_usb_set_persist_flags(USBDC_PERSIST_ENA);
|
||||||
|
} else {
|
||||||
|
periph_module_reset(PERIPH_USB_MODULE);
|
||||||
|
periph_module_enable(PERIPH_USB_MODULE);
|
||||||
}
|
}
|
||||||
REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
|
REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
|
||||||
} else if (usb_persist_mode == RESTART_BOOTLOADER_DFU) {
|
} else if (usb_persist_mode == RESTART_BOOTLOADER_DFU) {
|
||||||
@ -518,11 +586,12 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
|
|||||||
|
|
||||||
bool usb_did_persist = (USB_WRAP.date.val == USBDC_PERSIST_ENA);
|
bool usb_did_persist = (USB_WRAP.date.val == USBDC_PERSIST_ENA);
|
||||||
|
|
||||||
if(usb_did_persist && usb_persist_enabled){
|
//if(usb_did_persist && usb_persist_enabled){
|
||||||
// Enable USB/IO_MUX peripheral reset, if coming from persistent reboot
|
// Enable USB/IO_MUX peripheral reset, if coming from persistent reboot
|
||||||
REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_IO_MUX_RESET_DISABLE);
|
REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_IO_MUX_RESET_DISABLE);
|
||||||
REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_USB_RESET_DISABLE);
|
REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_USB_RESET_DISABLE);
|
||||||
} else {
|
//} else
|
||||||
|
if(!usb_did_persist || !usb_persist_enabled){
|
||||||
// Reset USB module
|
// Reset USB module
|
||||||
periph_module_reset(PERIPH_USB_MODULE);
|
periph_module_reset(PERIPH_USB_MODULE);
|
||||||
periph_module_enable(PERIPH_USB_MODULE);
|
periph_module_enable(PERIPH_USB_MODULE);
|
||||||
@ -694,4 +763,4 @@ void usb_dw_reg_dump(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
#endif /* CONFIG_USB_ENABLED */
|
#endif /* CONFIG_TINYUSB_ENABLED */
|
||||||
|
@ -16,13 +16,18 @@
|
|||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
#if CONFIG_USB_ENABLED
|
#if CONFIG_TINYUSB_ENABLED
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "tinyusb.h"
|
#include "tusb.h"
|
||||||
|
#include "tusb_option.h"
|
||||||
|
#include "tusb_config.h"
|
||||||
|
|
||||||
|
#define USB_ESPRESSIF_VID 0x303A
|
||||||
|
#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 10
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t vid;
|
uint16_t vid;
|
||||||
@ -46,10 +51,10 @@ typedef struct {
|
|||||||
#define TINYUSB_CONFIG_DEFAULT() { \
|
#define TINYUSB_CONFIG_DEFAULT() { \
|
||||||
.vid = USB_ESPRESSIF_VID, \
|
.vid = USB_ESPRESSIF_VID, \
|
||||||
.pid = 0x0002, \
|
.pid = 0x0002, \
|
||||||
.product_name = CONFIG_USB_DESC_PRODUCT_STRING, \
|
.product_name = CONFIG_TINYUSB_DESC_PRODUCT_STRING, \
|
||||||
.manufacturer_name = CONFIG_USB_DESC_MANUFACTURER_STRING, \
|
.manufacturer_name = CONFIG_TINYUSB_DESC_MANUFACTURER_STRING, \
|
||||||
.serial_number = CONFIG_USB_DESC_SERIAL_STRING, \
|
.serial_number = CONFIG_TINYUSB_DESC_SERIAL_STRING, \
|
||||||
.fw_version = CONFIG_USB_DESC_BCDDEVICE, \
|
.fw_version = CONFIG_TINYUSB_DESC_BCDDEVICE, \
|
||||||
.usb_version = 0x0200, \
|
.usb_version = 0x0200, \
|
||||||
.usb_class = TUSB_CLASS_MISC, \
|
.usb_class = TUSB_CLASS_MISC, \
|
||||||
.usb_subclass = MISC_SUBCLASS_COMMON, \
|
.usb_subclass = MISC_SUBCLASS_COMMON, \
|
||||||
@ -99,5 +104,5 @@ uint8_t tinyusb_get_free_out_endpoint(void);
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* CONFIG_USB_ENABLED */
|
#endif /* CONFIG_TINYUSB_ENABLED */
|
||||||
#endif /* CONFIG_IDF_TARGET_ESP32S2 */
|
#endif /* CONFIG_IDF_TARGET_ESP32S2 */
|
||||||
|
@ -12,15 +12,15 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "esp32-hal.h"
|
|
||||||
#include "esp32-hal-touch.h"
|
#include "esp32-hal-touch.h"
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "soc/rtc_io_reg.h"
|
#include "soc/rtc_io_reg.h"
|
||||||
#include "soc/rtc_cntl_reg.h"
|
|
||||||
#include "soc/sens_reg.h"
|
#include "soc/sens_reg.h"
|
||||||
#include "soc/sens_struct.h"
|
#include "soc/sens_struct.h"
|
||||||
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#include "driver/touch_sensor.h"
|
#include "driver/touch_sensor.h"
|
||||||
|
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
@ -39,7 +39,6 @@
|
|||||||
#include "rom/ets_sys.h"
|
#include "rom/ets_sys.h"
|
||||||
#include "esp_intr.h"
|
#include "esp_intr.h"
|
||||||
#endif
|
#endif
|
||||||
#include "esp32-hal-gpio.h"
|
|
||||||
|
|
||||||
static uint16_t __touchSleepCycles = 0x1000;
|
static uint16_t __touchSleepCycles = 0x1000;
|
||||||
static uint16_t __touchMeasureCycles = 0x1000;
|
static uint16_t __touchMeasureCycles = 0x1000;
|
||||||
@ -227,3 +226,4 @@ void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t thresh
|
|||||||
extern uint16_t touchRead(uint8_t pin) __attribute__ ((weak, alias("__touchRead")));
|
extern uint16_t touchRead(uint8_t pin) __attribute__ ((weak, alias("__touchRead")));
|
||||||
extern void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold) __attribute__ ((weak, alias("__touchAttachInterrupt")));
|
extern void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold) __attribute__ ((weak, alias("__touchAttachInterrupt")));
|
||||||
extern void touchSetCycles(uint16_t measure, uint16_t sleep) __attribute__ ((weak, alias("__touchSetCycles")));
|
extern void touchSetCycles(uint16_t measure, uint16_t sleep) __attribute__ ((weak, alias("__touchSetCycles")));
|
||||||
|
#endif
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "esp32-hal.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set cycles that measurement operation takes
|
* Set cycles that measurement operation takes
|
||||||
|
752
cores/esp32/esp32-hal-uart.c
Normal file
752
cores/esp32/esp32-hal-uart.c
Normal file
@ -0,0 +1,752 @@
|
|||||||
|
// Copyright 2015-2016 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-uart.h"
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "esp_attr.h"
|
||||||
|
#include "soc/uart_reg.h"
|
||||||
|
#include "soc/uart_struct.h"
|
||||||
|
#include "soc/io_mux_reg.h"
|
||||||
|
#include "soc/gpio_sig_map.h"
|
||||||
|
#include "soc/rtc.h"
|
||||||
|
#include "hal/uart_ll.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
|
||||||
|
#include "esp_system.h"
|
||||||
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "soc/dport_reg.h"
|
||||||
|
#include "esp32/rom/ets_sys.h"
|
||||||
|
#include "esp32/rom/uart.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "soc/dport_reg.h"
|
||||||
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
|
#include "esp32s2/rom/uart.h"
|
||||||
|
#include "soc/periph_defs.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/rom/ets_sys.h"
|
||||||
|
#include "esp32c3/rom/uart.h"
|
||||||
|
#include "soc/periph_defs.h"
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
|
#include "rom/ets_sys.h"
|
||||||
|
#include "rom/uart.h"
|
||||||
|
#include "esp_intr.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
#define UART_PORTS_NUM 3
|
||||||
|
#define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:( (u==2)?DR_REG_UART2_BASE:0)))
|
||||||
|
#define UART_RXD_IDX(u) ((u==0)?U0RXD_IN_IDX:( (u==1)?U1RXD_IN_IDX:( (u==2)?U2RXD_IN_IDX:0)))
|
||||||
|
#define UART_TXD_IDX(u) ((u==0)?U0TXD_OUT_IDX:( (u==1)?U1TXD_OUT_IDX:( (u==2)?U2TXD_OUT_IDX:0)))
|
||||||
|
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:((u==2)?ETS_UART2_INTR_SOURCE:0)))
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#define UART_PORTS_NUM 2
|
||||||
|
#define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:0))
|
||||||
|
#define UART_RXD_IDX(u) ((u==0)?U0RXD_IN_IDX:( (u==1)?U1RXD_IN_IDX:0))
|
||||||
|
#define UART_TXD_IDX(u) ((u==0)?U0TXD_OUT_IDX:( (u==1)?U1TXD_OUT_IDX:0))
|
||||||
|
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:0))
|
||||||
|
#else
|
||||||
|
#define UART_PORTS_NUM 2
|
||||||
|
#define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:0))
|
||||||
|
#define UART_RXD_IDX(u) ((u==0)?U0RXD_IN_IDX:( (u==1)?U1RXD_IN_IDX:0))
|
||||||
|
#define UART_TXD_IDX(u) ((u==0)?U0TXD_OUT_IDX:( (u==1)?U1TXD_OUT_IDX:0))
|
||||||
|
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:0))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int s_uart_debug_nr = 0;
|
||||||
|
|
||||||
|
struct uart_struct_t {
|
||||||
|
uart_dev_t * dev;
|
||||||
|
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||||
|
xSemaphoreHandle lock;
|
||||||
|
#endif
|
||||||
|
uint8_t num;
|
||||||
|
xQueueHandle queue;
|
||||||
|
intr_handle_t intr_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if CONFIG_DISABLE_HAL_LOCKS
|
||||||
|
#define UART_MUTEX_LOCK()
|
||||||
|
#define UART_MUTEX_UNLOCK()
|
||||||
|
|
||||||
|
static uart_t _uart_bus_array[] = {
|
||||||
|
{&UART0, 0, NULL, NULL},
|
||||||
|
{&UART1, 1, NULL, NULL},
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
{&UART2, 2, NULL, NULL}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
#define UART_MUTEX_LOCK() do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS)
|
||||||
|
#define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock)
|
||||||
|
|
||||||
|
static uart_t _uart_bus_array[] = {
|
||||||
|
{&UART0, NULL, 0, NULL, NULL},
|
||||||
|
{&UART1, NULL, 1, NULL, NULL},
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
{&UART2, NULL, 2, NULL, NULL}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void uart_on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb);
|
||||||
|
|
||||||
|
static void ARDUINO_ISR_ATTR _uart_isr(void *arg)
|
||||||
|
{
|
||||||
|
uint8_t i, c;
|
||||||
|
BaseType_t xHigherPriorityTaskWoken;
|
||||||
|
uart_t* uart;
|
||||||
|
|
||||||
|
for(i=0;i<UART_PORTS_NUM;i++){
|
||||||
|
uart = &_uart_bus_array[i];
|
||||||
|
if(uart->intr_handle == NULL){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uart->dev->int_clr.rxfifo_full = 1;
|
||||||
|
uart->dev->int_clr.frm_err = 1;
|
||||||
|
uart->dev->int_clr.rxfifo_tout = 1;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
while(uart->dev->status.rxfifo_cnt || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
|
||||||
|
c = uart->dev->fifo.rw_byte;
|
||||||
|
#else
|
||||||
|
uint32_t fifo_reg = UART_FIFO_AHB_REG(i);
|
||||||
|
while(uart->dev->status.rxfifo_cnt) {
|
||||||
|
c = ESP_REG(fifo_reg);
|
||||||
|
#endif
|
||||||
|
if(uart->queue != NULL) {
|
||||||
|
xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xHigherPriorityTaskWoken) {
|
||||||
|
portYIELD_FROM_ISR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uartEnableInterrupt(uart_t* uart, uint8_t rxfifo_full_thrhd)
|
||||||
|
{
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
uart->dev->conf1.rxfifo_full_thrhd = rxfifo_full_thrhd;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
uart->dev->conf1.rx_tout_thrhd = 2;
|
||||||
|
#else
|
||||||
|
uart->dev->mem_conf.rx_tout_thrhd = 2;
|
||||||
|
#endif
|
||||||
|
uart->dev->conf1.rx_tout_en = 1;
|
||||||
|
uart->dev->int_ena.rxfifo_full = 1;
|
||||||
|
uart->dev->int_ena.frm_err = 1;
|
||||||
|
uart->dev->int_ena.rxfifo_tout = 1;
|
||||||
|
uart->dev->int_clr.val = 0xffffffff;
|
||||||
|
|
||||||
|
esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ARDUINO_ISR_FLAG, _uart_isr, NULL, &uart->intr_handle);
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uartDisableInterrupt(uart_t* uart)
|
||||||
|
{
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
uart->dev->conf1.val = 0;
|
||||||
|
uart->dev->int_ena.val = 0;
|
||||||
|
uart->dev->int_clr.val = 0xffffffff;
|
||||||
|
|
||||||
|
esp_intr_free(uart->intr_handle);
|
||||||
|
uart->intr_handle = NULL;
|
||||||
|
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uartDetachRx(uart_t* uart, uint8_t rxPin)
|
||||||
|
{
|
||||||
|
if(uart == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pinMatrixInDetach(rxPin, false, false);
|
||||||
|
uartDisableInterrupt(uart);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uartDetachTx(uart_t* uart, uint8_t txPin)
|
||||||
|
{
|
||||||
|
if(uart == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pinMatrixOutDetach(txPin, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted, uint8_t rxfifo_full_thrhd)
|
||||||
|
{
|
||||||
|
if(uart == NULL || rxPin >= GPIO_PIN_COUNT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pinMode(rxPin, INPUT);
|
||||||
|
uartEnableInterrupt(uart, rxfifo_full_thrhd);
|
||||||
|
pinMatrixInAttach(rxPin, UART_RXD_IDX(uart->num), inverted);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted)
|
||||||
|
{
|
||||||
|
if(uart == NULL || txPin >= GPIO_PIN_COUNT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pinMode(txPin, OUTPUT);
|
||||||
|
pinMatrixOutAttach(txPin, UART_TXD_IDX(uart->num), inverted, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted, uint8_t rxfifo_full_thrhd)
|
||||||
|
{
|
||||||
|
if(uart_nr >= UART_PORTS_NUM) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rxPin == -1 && txPin == -1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uart_t* uart = &_uart_bus_array[uart_nr];
|
||||||
|
|
||||||
|
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||||
|
if(uart->lock == NULL) {
|
||||||
|
uart->lock = xSemaphoreCreateMutex();
|
||||||
|
if(uart->lock == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(queueLen && uart->queue == NULL) {
|
||||||
|
uart->queue = xQueueCreate(queueLen, sizeof(uint8_t)); //initialize the queue
|
||||||
|
if(uart->queue == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
|
||||||
|
#else
|
||||||
|
if(uart_nr == 1){
|
||||||
|
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN);
|
||||||
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
} else if(uart_nr == 2){
|
||||||
|
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART2_CLK_EN);
|
||||||
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART_CLK_EN);
|
||||||
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
uartFlush(uart);
|
||||||
|
uartSetBaudRate(uart, baudrate);
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
uart->dev->conf0.val = config;
|
||||||
|
#define TWO_STOP_BITS_CONF 0x3
|
||||||
|
#define ONE_STOP_BITS_CONF 0x1
|
||||||
|
|
||||||
|
if ( uart->dev->conf0.stop_bit_num == TWO_STOP_BITS_CONF) {
|
||||||
|
uart->dev->conf0.stop_bit_num = ONE_STOP_BITS_CONF;
|
||||||
|
uart->dev->rs485_conf.dl1_en = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tx_idle_num : idle interval after tx FIFO is empty(unit: the time it takes to send one bit under current baudrate)
|
||||||
|
// Setting it to 0 prevents line idle time/delays when sending messages with small intervals
|
||||||
|
uart->dev->idle_conf.tx_idle_num = 0; //
|
||||||
|
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
|
||||||
|
if(rxPin != -1) {
|
||||||
|
uartAttachRx(uart, rxPin, inverted, rxfifo_full_thrhd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(txPin != -1) {
|
||||||
|
uartAttachTx(uart, txPin, inverted);
|
||||||
|
}
|
||||||
|
addApbChangeCallback(uart, uart_on_apb_change);
|
||||||
|
return uart;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartEnd(uart_t* uart, uint8_t txPin, uint8_t rxPin)
|
||||||
|
{
|
||||||
|
if(uart == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
removeApbChangeCallback(uart, uart_on_apb_change);
|
||||||
|
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
if(uart->queue != NULL) {
|
||||||
|
vQueueDelete(uart->queue);
|
||||||
|
uart->queue = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uart->dev->conf0.val = 0;
|
||||||
|
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
|
||||||
|
uartDetachRx(uart, rxPin);
|
||||||
|
uartDetachTx(uart, txPin);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t uartResizeRxBuffer(uart_t * uart, size_t new_size) {
|
||||||
|
if(uart == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
if(uart->queue != NULL) {
|
||||||
|
vQueueDelete(uart->queue);
|
||||||
|
uart->queue = xQueueCreate(new_size, sizeof(uint8_t));
|
||||||
|
if(uart->queue == NULL) {
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
|
||||||
|
return new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartSetRxInvert(uart_t* uart, bool invert)
|
||||||
|
{
|
||||||
|
if (uart == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (invert)
|
||||||
|
uart->dev->conf0.rxd_inv = 1;
|
||||||
|
else
|
||||||
|
uart->dev->conf0.rxd_inv = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t uartAvailable(uart_t* uart)
|
||||||
|
{
|
||||||
|
if(uart == NULL || uart->queue == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#ifdef UART_READ_RX_FIFO
|
||||||
|
return (uxQueueMessagesWaiting(uart->queue) + uart->dev->status.rxfifo_cnt) ;
|
||||||
|
#else
|
||||||
|
return uxQueueMessagesWaiting(uart->queue);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t uartAvailableForWrite(uart_t* uart)
|
||||||
|
{
|
||||||
|
if(uart == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0x7f - uart->dev->status.txfifo_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UART_READ_RX_FIFO
|
||||||
|
void uartRxFifoToQueue(uart_t* uart)
|
||||||
|
{
|
||||||
|
uint8_t c;
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
//disable interrupts
|
||||||
|
uart->dev->int_ena.val = 0;
|
||||||
|
uart->dev->int_clr.val = 0xffffffff;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
while (uart->dev->status.rxfifo_cnt || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
|
||||||
|
c = uart->dev->fifo.rw_byte;
|
||||||
|
#else
|
||||||
|
uint32_t fifo_reg = UART_FIFO_AHB_REG(uart->num);
|
||||||
|
while (uart->dev->status.rxfifo_cnt) {
|
||||||
|
c = ESP_REG(fifo_reg);
|
||||||
|
#endif
|
||||||
|
xQueueSend(uart->queue, &c, 0);
|
||||||
|
}
|
||||||
|
//enable interrupts
|
||||||
|
uart->dev->int_ena.rxfifo_full = 1;
|
||||||
|
uart->dev->int_ena.frm_err = 1;
|
||||||
|
uart->dev->int_ena.rxfifo_tout = 1;
|
||||||
|
uart->dev->int_clr.val = 0xffffffff;
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t uartRead(uart_t* uart)
|
||||||
|
{
|
||||||
|
if(uart == NULL || uart->queue == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint8_t c;
|
||||||
|
#ifdef UART_READ_RX_FIFO
|
||||||
|
if ((uxQueueMessagesWaiting(uart->queue) == 0) && (uart->dev->status.rxfifo_cnt > 0))
|
||||||
|
{
|
||||||
|
uartRxFifoToQueue(uart);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if(xQueueReceive(uart->queue, &c, 0)) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t uartPeek(uart_t* uart)
|
||||||
|
{
|
||||||
|
if(uart == NULL || uart->queue == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint8_t c;
|
||||||
|
#ifdef UART_READ_RX_FIFO
|
||||||
|
if ((uxQueueMessagesWaiting(uart->queue) == 0) && (uart->dev->status.rxfifo_cnt > 0))
|
||||||
|
{
|
||||||
|
uartRxFifoToQueue(uart);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if(xQueuePeek(uart->queue, &c, 0)) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartWrite(uart_t* uart, uint8_t c)
|
||||||
|
{
|
||||||
|
if(uart == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
while(uart->dev->status.txfifo_cnt == 0x7F);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
uart->dev->fifo.rw_byte = c;
|
||||||
|
#else
|
||||||
|
ESP_REG(UART_FIFO_AHB_REG(uart->num)) = c;
|
||||||
|
#endif
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len)
|
||||||
|
{
|
||||||
|
if(uart == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32
|
||||||
|
uint32_t fifo_reg = UART_FIFO_AHB_REG(uart->num);
|
||||||
|
#endif
|
||||||
|
while(len) {
|
||||||
|
while(uart->dev->status.txfifo_cnt == 0x7F);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
uart->dev->fifo.rw_byte = *data++;
|
||||||
|
#else
|
||||||
|
ESP_REG(fifo_reg) = *data++;
|
||||||
|
#endif
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartFlush(uart_t* uart)
|
||||||
|
{
|
||||||
|
uartFlushTxOnly(uart,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartFlushTxOnly(uart_t* uart, bool txOnly)
|
||||||
|
{
|
||||||
|
if(uart == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out);
|
||||||
|
|
||||||
|
if( !txOnly ){
|
||||||
|
//Due to hardware issue, we can not use fifo_rst to reset uart fifo.
|
||||||
|
//See description about UART_TXFIFO_RST and UART_RXFIFO_RST in <<esp32_technical_reference_manual>> v2.6 or later.
|
||||||
|
|
||||||
|
// we read the data out and make `fifo_len == 0 && rd_addr == wr_addr`.
|
||||||
|
while(uart->dev->status.rxfifo_cnt != 0 || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
|
||||||
|
READ_PERI_REG(UART_FIFO_REG(uart->num));
|
||||||
|
}
|
||||||
|
|
||||||
|
xQueueReset(uart->queue);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
while(uart->dev->status.txfifo_cnt);
|
||||||
|
uart->dev->conf0.txfifo_rst = 1;
|
||||||
|
uart->dev->conf0.txfifo_rst = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartSetBaudRate(uart_t* uart, uint32_t baud_rate)
|
||||||
|
{
|
||||||
|
if(uart == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
uart_ll_set_baudrate(uart->dev, baud_rate);
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uart_on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb)
|
||||||
|
{
|
||||||
|
uart_t* uart = (uart_t*)arg;
|
||||||
|
if(ev_type == APB_BEFORE_CHANGE){
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
//disabple interrupt
|
||||||
|
uart->dev->int_ena.val = 0;
|
||||||
|
uart->dev->int_clr.val = 0xffffffff;
|
||||||
|
// read RX fifo
|
||||||
|
uint8_t c;
|
||||||
|
// BaseType_t xHigherPriorityTaskWoken;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
while(uart->dev->status.rxfifo_cnt != 0 || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
|
||||||
|
c = uart->dev->fifo.rw_byte;
|
||||||
|
#else
|
||||||
|
uint32_t fifo_reg = UART_FIFO_AHB_REG(uart->num);
|
||||||
|
while(uart->dev->status.rxfifo_cnt != 0) {
|
||||||
|
c = ESP_REG(fifo_reg);
|
||||||
|
#endif
|
||||||
|
if(uart->queue != NULL ) {
|
||||||
|
xQueueSend(uart->queue, &c, 1); //&xHigherPriorityTaskWoken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
|
||||||
|
// wait TX empty
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out);
|
||||||
|
#else
|
||||||
|
while(uart->dev->status.txfifo_cnt);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
//todo:
|
||||||
|
// set baudrate
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F);
|
||||||
|
uint32_t baud_rate = ((old_apb<<4)/clk_div);
|
||||||
|
clk_div = ((new_apb<<4)/baud_rate);
|
||||||
|
uart->dev->clk_div.div_int = clk_div>>4 ;
|
||||||
|
uart->dev->clk_div.div_frag = clk_div & 0xf;
|
||||||
|
//enable interrupts
|
||||||
|
uart->dev->int_ena.rxfifo_full = 1;
|
||||||
|
uart->dev->int_ena.frm_err = 1;
|
||||||
|
uart->dev->int_ena.rxfifo_tout = 1;
|
||||||
|
uart->dev->int_clr.val = 0xffffffff;
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t uartGetBaudRate(uart_t* uart)
|
||||||
|
{
|
||||||
|
if(uart == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F);
|
||||||
|
if(!clk_div) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((getApbFrequency()<<4)/clk_div);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ARDUINO_ISR_ATTR uart0_write_char(char c)
|
||||||
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
while(((ESP_REG(0x01C+DR_REG_UART_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
|
||||||
|
ESP_REG(DR_REG_UART_BASE) = c;
|
||||||
|
#else
|
||||||
|
while(UART0.status.txfifo_cnt == 0x7F);
|
||||||
|
WRITE_PERI_REG(UART_FIFO_AHB_REG(0), c);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ARDUINO_ISR_ATTR uart1_write_char(char c)
|
||||||
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
while(((ESP_REG(0x01C+DR_REG_UART1_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
|
||||||
|
ESP_REG(DR_REG_UART1_BASE) = c;
|
||||||
|
#else
|
||||||
|
while(UART1.status.txfifo_cnt == 0x7F);
|
||||||
|
WRITE_PERI_REG(UART_FIFO_AHB_REG(1), c);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
static void ARDUINO_ISR_ATTR uart2_write_char(char c)
|
||||||
|
{
|
||||||
|
while(((ESP_REG(0x01C+DR_REG_UART2_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
|
||||||
|
ESP_REG(DR_REG_UART2_BASE) = c;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void uart_install_putc()
|
||||||
|
{
|
||||||
|
switch(s_uart_debug_nr) {
|
||||||
|
case 0:
|
||||||
|
ets_install_putc1((void (*)(char)) &uart0_write_char);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ets_install_putc1((void (*)(char)) &uart1_write_char);
|
||||||
|
break;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
case 2:
|
||||||
|
ets_install_putc1((void (*)(char)) &uart2_write_char);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ets_install_putc1(NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartSetDebug(uart_t* uart)
|
||||||
|
{
|
||||||
|
if(uart == NULL || uart->num >= UART_PORTS_NUM) {
|
||||||
|
s_uart_debug_nr = -1;
|
||||||
|
//ets_install_putc1(NULL);
|
||||||
|
//return;
|
||||||
|
} else
|
||||||
|
if(s_uart_debug_nr == uart->num) {
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
s_uart_debug_nr = uart->num;
|
||||||
|
uart_install_putc();
|
||||||
|
}
|
||||||
|
|
||||||
|
int uartGetDebug()
|
||||||
|
{
|
||||||
|
return s_uart_debug_nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int log_printf(const char *format, ...)
|
||||||
|
{
|
||||||
|
static 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(NULL, 0, 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);
|
||||||
|
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||||
|
if(s_uart_debug_nr != -1 && _uart_bus_array[s_uart_debug_nr].lock){
|
||||||
|
xSemaphoreTake(_uart_bus_array[s_uart_debug_nr].lock, portMAX_DELAY);
|
||||||
|
ets_printf("%s", temp);
|
||||||
|
xSemaphoreGive(_uart_bus_array[s_uart_debug_nr].lock);
|
||||||
|
} else {
|
||||||
|
ets_printf("%s", temp);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ets_printf("%s", temp);
|
||||||
|
#endif
|
||||||
|
va_end(arg);
|
||||||
|
if(len >= sizeof(loc_buf)){
|
||||||
|
free(temp);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if enough pulses are detected return the minimum high pulse duration + minimum low pulse duration divided by two.
|
||||||
|
* This equals one bit period. If flag is true the function return inmediately, otherwise it waits for enough pulses.
|
||||||
|
*/
|
||||||
|
unsigned long uartBaudrateDetect(uart_t *uart, bool flg)
|
||||||
|
{
|
||||||
|
while(uart->dev->rxd_cnt.edge_cnt < 30) { // UART_PULSE_NUM(uart_num)
|
||||||
|
if(flg) return 0;
|
||||||
|
ets_delay_us(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
UART_MUTEX_LOCK();
|
||||||
|
unsigned long ret = ((uart->dev->lowpulse.min_cnt + uart->dev->highpulse.min_cnt) >> 1) + 12;
|
||||||
|
UART_MUTEX_UNLOCK();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To start detection of baud rate with the uart the auto_baud.en bit needs to be cleared and set. The bit period is
|
||||||
|
* detected calling uartBadrateDetect(). The raw baudrate is computed using the UART_CLK_FREQ. The raw baudrate is
|
||||||
|
* rounded to the closed real baudrate.
|
||||||
|
*/
|
||||||
|
void uartStartDetectBaudrate(uart_t *uart) {
|
||||||
|
if(!uart) return;
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
uart->dev->auto_baud.glitch_filt = 0x08;
|
||||||
|
uart->dev->auto_baud.en = 0;
|
||||||
|
uart->dev->auto_baud.en = 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long
|
||||||
|
uartDetectBaudrate(uart_t *uart)
|
||||||
|
{
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
static bool uartStateDetectingBaudrate = false;
|
||||||
|
|
||||||
|
if(!uartStateDetectingBaudrate) {
|
||||||
|
uart->dev->auto_baud.glitch_filt = 0x08;
|
||||||
|
uart->dev->auto_baud.en = 0;
|
||||||
|
uart->dev->auto_baud.en = 1;
|
||||||
|
uartStateDetectingBaudrate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long divisor = uartBaudrateDetect(uart, true);
|
||||||
|
if (!divisor) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uart->dev->auto_baud.en = 0;
|
||||||
|
uartStateDetectingBaudrate = false; // Initialize for the next round
|
||||||
|
|
||||||
|
unsigned long baudrate = getApbFrequency() / divisor;
|
||||||
|
|
||||||
|
static const unsigned long default_rates[] = {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 256000, 460800, 921600, 1843200, 3686400};
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
for (i = 1; i < sizeof(default_rates) / sizeof(default_rates[0]) - 1; i++) // find the nearest real baudrate
|
||||||
|
{
|
||||||
|
if (baudrate <= default_rates[i])
|
||||||
|
{
|
||||||
|
if (baudrate - default_rates[i - 1] < default_rates[i] - baudrate) {
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_rates[i];
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the status of the RX state machine, if the value is non-zero the state machine is active.
|
||||||
|
*/
|
||||||
|
bool uartRxActive(uart_t* uart) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
return uart->dev->status.st_urx_out != 0;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
87
cores/esp32/esp32-hal-uart.h
Normal file
87
cores/esp32/esp32-hal-uart.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Copyright 2015-2016 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 MAIN_ESP32_HAL_UART_H_
|
||||||
|
#define MAIN_ESP32_HAL_UART_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define SERIAL_5N1 0x8000010
|
||||||
|
#define SERIAL_6N1 0x8000014
|
||||||
|
#define SERIAL_7N1 0x8000018
|
||||||
|
#define SERIAL_8N1 0x800001c
|
||||||
|
#define SERIAL_5N2 0x8000030
|
||||||
|
#define SERIAL_6N2 0x8000034
|
||||||
|
#define SERIAL_7N2 0x8000038
|
||||||
|
#define SERIAL_8N2 0x800003c
|
||||||
|
#define SERIAL_5E1 0x8000012
|
||||||
|
#define SERIAL_6E1 0x8000016
|
||||||
|
#define SERIAL_7E1 0x800001a
|
||||||
|
#define SERIAL_8E1 0x800001e
|
||||||
|
#define SERIAL_5E2 0x8000032
|
||||||
|
#define SERIAL_6E2 0x8000036
|
||||||
|
#define SERIAL_7E2 0x800003a
|
||||||
|
#define SERIAL_8E2 0x800003e
|
||||||
|
#define SERIAL_5O1 0x8000013
|
||||||
|
#define SERIAL_6O1 0x8000017
|
||||||
|
#define SERIAL_7O1 0x800001b
|
||||||
|
#define SERIAL_8O1 0x800001f
|
||||||
|
#define SERIAL_5O2 0x8000033
|
||||||
|
#define SERIAL_6O2 0x8000037
|
||||||
|
#define SERIAL_7O2 0x800003b
|
||||||
|
#define SERIAL_8O2 0x800003f
|
||||||
|
|
||||||
|
struct uart_struct_t;
|
||||||
|
typedef struct uart_struct_t uart_t;
|
||||||
|
|
||||||
|
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted, uint8_t rxfifo_full_thrhd);
|
||||||
|
void uartEnd(uart_t* uart, uint8_t rxPin, uint8_t txPin);
|
||||||
|
|
||||||
|
uint32_t uartAvailable(uart_t* uart);
|
||||||
|
uint32_t uartAvailableForWrite(uart_t* uart);
|
||||||
|
uint8_t uartRead(uart_t* uart);
|
||||||
|
uint8_t uartPeek(uart_t* uart);
|
||||||
|
|
||||||
|
void uartWrite(uart_t* uart, uint8_t c);
|
||||||
|
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);
|
||||||
|
uint32_t uartGetBaudRate(uart_t* uart);
|
||||||
|
|
||||||
|
size_t uartResizeRxBuffer(uart_t* uart, size_t new_size);
|
||||||
|
|
||||||
|
void uartSetRxInvert(uart_t* uart, bool invert);
|
||||||
|
|
||||||
|
void uartSetDebug(uart_t* uart);
|
||||||
|
int uartGetDebug();
|
||||||
|
|
||||||
|
void uartStartDetectBaudrate(uart_t *uart);
|
||||||
|
unsigned long uartDetectBaudrate(uart_t *uart);
|
||||||
|
|
||||||
|
bool uartRxActive(uart_t* uart);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* MAIN_ESP32_HAL_UART_H_ */
|
@ -20,21 +20,29 @@
|
|||||||
#ifndef HAL_ESP32_HAL_H_
|
#ifndef HAL_ESP32_HAL_H_
|
||||||
#define HAL_ESP32_HAL_H_
|
#define HAL_ESP32_HAL_H_
|
||||||
|
|
||||||
//#include <stdint.h>
|
#include <stdint.h>
|
||||||
//#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
//#include <stdio.h>
|
#include <stdio.h>
|
||||||
//#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
//#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
//#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
//#include <string.h>
|
#include <string.h>
|
||||||
//#include <math.h>
|
#include <math.h>
|
||||||
//#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
//#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
//#include "esp_sleep.h"
|
#include "esp_sleep.h"
|
||||||
|
|
||||||
//#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
//extern "C" {
|
extern "C" {
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef F_CPU
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#define F_CPU (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000U)
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#define F_CPU (CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ * 1000000U)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_ARDUINO_ISR_IRAM
|
#if CONFIG_ARDUINO_ISR_IRAM
|
||||||
#define ARDUINO_ISR_ATTR IRAM_ATTR
|
#define ARDUINO_ISR_ATTR IRAM_ATTR
|
||||||
@ -44,32 +52,84 @@
|
|||||||
#define ARDUINO_ISR_FLAG (0)
|
#define ARDUINO_ISR_FLAG (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////forward declaration from freertos/portmacro.h
|
#ifndef ARDUINO_RUNNING_CORE
|
||||||
//void vPortYield(void);
|
#define ARDUINO_RUNNING_CORE CONFIG_ARDUINO_RUNNING_CORE
|
||||||
//#define optimistic_yield(u)
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARDUINO_EVENT_RUNNING_CORE
|
||||||
|
#define ARDUINO_EVENT_RUNNING_CORE CONFIG_ARDUINO_EVENT_RUNNING_CORE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//forward declaration from freertos/portmacro.h
|
||||||
|
void vPortYield(void);
|
||||||
|
void yield(void);
|
||||||
|
#define optimistic_yield(u)
|
||||||
|
|
||||||
#define ESP_REG(addr) *((volatile uint32_t *)(addr))
|
#define ESP_REG(addr) *((volatile uint32_t *)(addr))
|
||||||
#define NOP() asm volatile ("nop")
|
#define NOP() asm volatile ("nop")
|
||||||
|
|
||||||
////#include "esp32-hal-log.h"
|
#include "esp32-hal-log.h"
|
||||||
////#include "esp32-hal-matrix.h"
|
#include "esp32-hal-matrix.h"
|
||||||
////#include "esp32-hal-gpio.h"
|
#include "esp32-hal-uart.h"
|
||||||
////#include "esp32-hal-touch.h"
|
#include "esp32-hal-gpio.h"
|
||||||
////#include "esp32-hal-dac.h"
|
#include "esp32-hal-touch.h"
|
||||||
////#include "esp32-hal-adc.h"
|
#include "esp32-hal-dac.h"
|
||||||
////#include "esp32-hal-spi.h"
|
#include "esp32-hal-adc.h"
|
||||||
////#include "esp32-hal-i2c.h"
|
#include "esp32-hal-spi.h"
|
||||||
////#include "esp32-hal-ledc.h"
|
#include "esp32-hal-i2c.h"
|
||||||
////#include "esp32-hal-rmt.h"
|
#include "esp32-hal-ledc.h"
|
||||||
////#include "esp32-hal-sigmadelta.h"
|
#include "esp32-hal-rmt.h"
|
||||||
////#include "esp32-hal-psram.h"
|
#include "esp32-hal-sigmadelta.h"
|
||||||
////#include "esp32-hal-cpu.h"
|
#include "esp32-hal-timer.h"
|
||||||
|
#include "esp32-hal-bt.h"
|
||||||
|
#include "esp32-hal-psram.h"
|
||||||
|
#include "esp32-hal-cpu.h"
|
||||||
|
|
||||||
////returns chip temperature in Celsius
|
//returns chip temperature in Celsius
|
||||||
//float temperatureRead();
|
float temperatureRead();
|
||||||
|
|
||||||
//#ifdef __cplusplus
|
#if CONFIG_AUTOSTART_ARDUINO
|
||||||
//}
|
//enable/disable WDT for Arduino's setup and loop functions
|
||||||
//#endif
|
void enableLoopWDT();
|
||||||
|
void disableLoopWDT();
|
||||||
|
//feed WDT for the loop task
|
||||||
|
void feedLoopWDT();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//enable/disable WDT for the IDLE task on Core 0 (SYSTEM)
|
||||||
|
void enableCore0WDT();
|
||||||
|
void disableCore0WDT();
|
||||||
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||||||
|
//enable/disable WDT for the IDLE task on Core 1 (Arduino)
|
||||||
|
void enableCore1WDT();
|
||||||
|
void disableCore1WDT();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//if xCoreID < 0 or CPU is unicore, it will use xTaskCreate, else xTaskCreatePinnedToCore
|
||||||
|
//allows to easily handle all possible situations without repetitive code
|
||||||
|
BaseType_t xTaskCreateUniversal( TaskFunction_t pxTaskCode,
|
||||||
|
const char * const pcName,
|
||||||
|
const uint32_t usStackDepth,
|
||||||
|
void * const pvParameters,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
TaskHandle_t * const pxCreatedTask,
|
||||||
|
const BaseType_t xCoreID );
|
||||||
|
|
||||||
|
unsigned long micros();
|
||||||
|
unsigned long millis();
|
||||||
|
void delay(uint32_t);
|
||||||
|
void delayMicroseconds(uint32_t us);
|
||||||
|
|
||||||
|
#if !CONFIG_ESP32_PHY_AUTO_INIT
|
||||||
|
void arduino_phy_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !CONFIG_AUTOSTART_ARDUINO
|
||||||
|
void initArduino();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* HAL_ESP32_HAL_H_ */
|
#endif /* HAL_ESP32_HAL_H_ */
|
||||||
|
7
cores/esp32/libb64/AUTHORS
Executable file
7
cores/esp32/libb64/AUTHORS
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
libb64: Base64 Encoding/Decoding Routines
|
||||||
|
======================================
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
-------
|
||||||
|
|
||||||
|
Chris Venter chris.venter@gmail.com http://rocketpod.blogspot.com
|
29
cores/esp32/libb64/LICENSE
Executable file
29
cores/esp32/libb64/LICENSE
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
Copyright-Only Dedication (based on United States law)
|
||||||
|
or Public Domain Certification
|
||||||
|
|
||||||
|
The person or persons who have associated work with this document (the
|
||||||
|
"Dedicator" or "Certifier") hereby either (a) certifies that, to the best of
|
||||||
|
his knowledge, the work of authorship identified is in the public domain of the
|
||||||
|
country from which the work is published, or (b) hereby dedicates whatever
|
||||||
|
copyright the dedicators holds in the work of authorship identified below (the
|
||||||
|
"Work") to the public domain. A certifier, moreover, dedicates any copyright
|
||||||
|
interest he may have in the associated work, and for these purposes, is
|
||||||
|
described as a "dedicator" below.
|
||||||
|
|
||||||
|
A certifier has taken reasonable steps to verify the copyright status of this
|
||||||
|
work. Certifier recognizes that his good faith efforts may not shield him from
|
||||||
|
liability if in fact the work certified is not in the public domain.
|
||||||
|
|
||||||
|
Dedicator makes this dedication for the benefit of the public at large and to
|
||||||
|
the detriment of the Dedicator's heirs and successors. Dedicator intends this
|
||||||
|
dedication to be an overt act of relinquishment in perpetuity of all present
|
||||||
|
and future rights under copyright law, whether vested or contingent, in the
|
||||||
|
Work. Dedicator understands that such relinquishment of all rights includes
|
||||||
|
the relinquishment of all rights to enforce (by lawsuit or otherwise) those
|
||||||
|
copyrights in the Work.
|
||||||
|
|
||||||
|
Dedicator recognizes that, once placed in the public domain, the Work may be
|
||||||
|
freely reproduced, distributed, transmitted, used, modified, built upon, or
|
||||||
|
otherwise exploited by anyone for any purpose, commercial or non-commercial,
|
||||||
|
and in any way, including by methods that have not yet been invented or
|
||||||
|
conceived.
|
99
cores/esp32/libb64/cdecode.c
Executable file
99
cores/esp32/libb64/cdecode.c
Executable file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
cdecoder.c - c source to a base64 decoding algorithm implementation
|
||||||
|
|
||||||
|
This is part of the libb64 project, and has been placed in the public domain.
|
||||||
|
For details, see http://sourceforge.net/projects/libb64
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cdecode.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static int base64_decode_value_signed(int8_t value_in){
|
||||||
|
static const int8_t decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
|
||||||
|
static const int8_t decoding_size = sizeof(decoding);
|
||||||
|
value_in -= 43;
|
||||||
|
if (value_in < 0 || value_in > decoding_size) return -1;
|
||||||
|
return decoding[(int)value_in];
|
||||||
|
}
|
||||||
|
|
||||||
|
void base64_init_decodestate(base64_decodestate* state_in){
|
||||||
|
state_in->step = step_a;
|
||||||
|
state_in->plainchar = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int base64_decode_block_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out, base64_decodestate* state_in){
|
||||||
|
const int8_t* codechar = code_in;
|
||||||
|
int8_t* plainchar = plaintext_out;
|
||||||
|
int8_t fragment;
|
||||||
|
|
||||||
|
*plainchar = state_in->plainchar;
|
||||||
|
|
||||||
|
switch (state_in->step){
|
||||||
|
while (1){
|
||||||
|
case step_a:
|
||||||
|
do {
|
||||||
|
if (codechar == code_in+length_in){
|
||||||
|
state_in->step = step_a;
|
||||||
|
state_in->plainchar = *plainchar;
|
||||||
|
return plainchar - plaintext_out;
|
||||||
|
}
|
||||||
|
fragment = (int8_t)base64_decode_value_signed(*codechar++);
|
||||||
|
} while (fragment < 0);
|
||||||
|
*plainchar = (fragment & 0x03f) << 2;
|
||||||
|
case step_b:
|
||||||
|
do {
|
||||||
|
if (codechar == code_in+length_in){
|
||||||
|
state_in->step = step_b;
|
||||||
|
state_in->plainchar = *plainchar;
|
||||||
|
return plainchar - plaintext_out;
|
||||||
|
}
|
||||||
|
fragment = (int8_t)base64_decode_value_signed(*codechar++);
|
||||||
|
} while (fragment < 0);
|
||||||
|
*plainchar++ |= (fragment & 0x030) >> 4;
|
||||||
|
*plainchar = (fragment & 0x00f) << 4;
|
||||||
|
case step_c:
|
||||||
|
do {
|
||||||
|
if (codechar == code_in+length_in){
|
||||||
|
state_in->step = step_c;
|
||||||
|
state_in->plainchar = *plainchar;
|
||||||
|
return plainchar - plaintext_out;
|
||||||
|
}
|
||||||
|
fragment = (int8_t)base64_decode_value_signed(*codechar++);
|
||||||
|
} while (fragment < 0);
|
||||||
|
*plainchar++ |= (fragment & 0x03c) >> 2;
|
||||||
|
*plainchar = (fragment & 0x003) << 6;
|
||||||
|
case step_d:
|
||||||
|
do {
|
||||||
|
if (codechar == code_in+length_in){
|
||||||
|
state_in->step = step_d;
|
||||||
|
state_in->plainchar = *plainchar;
|
||||||
|
return plainchar - plaintext_out;
|
||||||
|
}
|
||||||
|
fragment = (int8_t)base64_decode_value_signed(*codechar++);
|
||||||
|
} while (fragment < 0);
|
||||||
|
*plainchar++ |= (fragment & 0x03f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* control should not reach here */
|
||||||
|
return plainchar - plaintext_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int base64_decode_chars_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out){
|
||||||
|
base64_decodestate _state;
|
||||||
|
base64_init_decodestate(&_state);
|
||||||
|
int len = base64_decode_block_signed(code_in, length_in, plaintext_out, &_state);
|
||||||
|
if(len > 0) plaintext_out[len] = 0;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int base64_decode_value(char value_in){
|
||||||
|
return base64_decode_value_signed(*((int8_t *) &value_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in){
|
||||||
|
return base64_decode_block_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out, state_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out){
|
||||||
|
return base64_decode_chars_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out);
|
||||||
|
}
|
38
cores/esp32/libb64/cdecode.h
Executable file
38
cores/esp32/libb64/cdecode.h
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
cdecode.h - c header for a base64 decoding algorithm
|
||||||
|
|
||||||
|
This is part of the libb64 project, and has been placed in the public domain.
|
||||||
|
For details, see http://sourceforge.net/projects/libb64
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BASE64_CDECODE_H
|
||||||
|
#define BASE64_CDECODE_H
|
||||||
|
|
||||||
|
#define base64_decode_expected_len(n) ((n * 3) / 4)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
step_a, step_b, step_c, step_d
|
||||||
|
} base64_decodestep;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
base64_decodestep step;
|
||||||
|
char plainchar;
|
||||||
|
} base64_decodestate;
|
||||||
|
|
||||||
|
void base64_init_decodestate(base64_decodestate* state_in);
|
||||||
|
|
||||||
|
int base64_decode_value(char value_in);
|
||||||
|
|
||||||
|
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
|
||||||
|
|
||||||
|
int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* BASE64_CDECODE_H */
|
102
cores/esp32/libb64/cencode.c
Executable file
102
cores/esp32/libb64/cencode.c
Executable file
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
cencoder.c - c source to a base64 encoding algorithm implementation
|
||||||
|
|
||||||
|
This is part of the libb64 project, and has been placed in the public domain.
|
||||||
|
For details, see http://sourceforge.net/projects/libb64
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cencode.h"
|
||||||
|
|
||||||
|
void base64_init_encodestate(base64_encodestate* state_in)
|
||||||
|
{
|
||||||
|
state_in->step = step_A;
|
||||||
|
state_in->result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char base64_encode_value(char value_in)
|
||||||
|
{
|
||||||
|
static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
if (value_in > 63) {
|
||||||
|
return '=';
|
||||||
|
}
|
||||||
|
return encoding[(int)value_in];
|
||||||
|
}
|
||||||
|
|
||||||
|
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
|
||||||
|
{
|
||||||
|
const char* plainchar = plaintext_in;
|
||||||
|
const char* const plaintextend = plaintext_in + length_in;
|
||||||
|
char* codechar = code_out;
|
||||||
|
char result;
|
||||||
|
char fragment;
|
||||||
|
|
||||||
|
result = state_in->result;
|
||||||
|
|
||||||
|
switch (state_in->step) {
|
||||||
|
while (1) {
|
||||||
|
case step_A:
|
||||||
|
if (plainchar == plaintextend) {
|
||||||
|
state_in->result = result;
|
||||||
|
state_in->step = step_A;
|
||||||
|
return codechar - code_out;
|
||||||
|
}
|
||||||
|
fragment = *plainchar++;
|
||||||
|
result = (fragment & 0x0fc) >> 2;
|
||||||
|
*codechar++ = base64_encode_value(result);
|
||||||
|
result = (fragment & 0x003) << 4;
|
||||||
|
case step_B:
|
||||||
|
if (plainchar == plaintextend) {
|
||||||
|
state_in->result = result;
|
||||||
|
state_in->step = step_B;
|
||||||
|
return codechar - code_out;
|
||||||
|
}
|
||||||
|
fragment = *plainchar++;
|
||||||
|
result |= (fragment & 0x0f0) >> 4;
|
||||||
|
*codechar++ = base64_encode_value(result);
|
||||||
|
result = (fragment & 0x00f) << 2;
|
||||||
|
case step_C:
|
||||||
|
if (plainchar == plaintextend) {
|
||||||
|
state_in->result = result;
|
||||||
|
state_in->step = step_C;
|
||||||
|
return codechar - code_out;
|
||||||
|
}
|
||||||
|
fragment = *plainchar++;
|
||||||
|
result |= (fragment & 0x0c0) >> 6;
|
||||||
|
*codechar++ = base64_encode_value(result);
|
||||||
|
result = (fragment & 0x03f) >> 0;
|
||||||
|
*codechar++ = base64_encode_value(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* control should not reach here */
|
||||||
|
return codechar - code_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
|
||||||
|
{
|
||||||
|
char* codechar = code_out;
|
||||||
|
|
||||||
|
switch (state_in->step) {
|
||||||
|
case step_B:
|
||||||
|
*codechar++ = base64_encode_value(state_in->result);
|
||||||
|
*codechar++ = '=';
|
||||||
|
*codechar++ = '=';
|
||||||
|
break;
|
||||||
|
case step_C:
|
||||||
|
*codechar++ = base64_encode_value(state_in->result);
|
||||||
|
*codechar++ = '=';
|
||||||
|
break;
|
||||||
|
case step_A:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*codechar = 0x00;
|
||||||
|
|
||||||
|
return codechar - code_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out)
|
||||||
|
{
|
||||||
|
base64_encodestate _state;
|
||||||
|
base64_init_encodestate(&_state);
|
||||||
|
int len = base64_encode_block(plaintext_in, length_in, code_out, &_state);
|
||||||
|
return len + base64_encode_blockend((code_out + len), &_state);
|
||||||
|
}
|
41
cores/esp32/libb64/cencode.h
Executable file
41
cores/esp32/libb64/cencode.h
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
cencode.h - c header for a base64 encoding algorithm
|
||||||
|
|
||||||
|
This is part of the libb64 project, and has been placed in the public domain.
|
||||||
|
For details, see http://sourceforge.net/projects/libb64
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BASE64_CENCODE_H
|
||||||
|
#define BASE64_CENCODE_H
|
||||||
|
|
||||||
|
#define base64_encode_expected_len(n) ((((4 * n) / 3) + 3) & ~3)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
step_A, step_B, step_C
|
||||||
|
} base64_encodestep;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
base64_encodestep step;
|
||||||
|
char result;
|
||||||
|
int stepcount;
|
||||||
|
} base64_encodestate;
|
||||||
|
|
||||||
|
void base64_init_encodestate(base64_encodestate* state_in);
|
||||||
|
|
||||||
|
char base64_encode_value(char value_in);
|
||||||
|
|
||||||
|
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
|
||||||
|
|
||||||
|
int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
|
||||||
|
|
||||||
|
int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* BASE64_CENCODE_H */
|
54
cores/esp32/main.cpp
Normal file
54
cores/esp32/main.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp_task_wdt.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
||||||
|
#include "USB.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_ARDUINO_LOOP_STACK_SIZE
|
||||||
|
#define CONFIG_ARDUINO_LOOP_STACK_SIZE 8192
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TaskHandle_t loopTaskHandle = NULL;
|
||||||
|
|
||||||
|
#if CONFIG_AUTOSTART_ARDUINO
|
||||||
|
#if CONFIG_FREERTOS_UNICORE
|
||||||
|
void yieldIfNecessary(void){
|
||||||
|
static uint64_t lastYield = 0;
|
||||||
|
uint64_t now = millis();
|
||||||
|
if((now - lastYield) > 2000) {
|
||||||
|
lastYield = now;
|
||||||
|
vTaskDelay(5); //delay 1 RTOS tick
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool loopTaskWDTEnabled;
|
||||||
|
|
||||||
|
void loopTask(void *pvParameters)
|
||||||
|
{
|
||||||
|
setup();
|
||||||
|
for(;;) {
|
||||||
|
#if CONFIG_FREERTOS_UNICORE
|
||||||
|
yieldIfNecessary();
|
||||||
|
#endif
|
||||||
|
if(loopTaskWDTEnabled){
|
||||||
|
esp_task_wdt_reset();
|
||||||
|
}
|
||||||
|
loop();
|
||||||
|
if (serialEventRun) serialEventRun();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void app_main()
|
||||||
|
{
|
||||||
|
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
||||||
|
USB.begin();
|
||||||
|
#endif
|
||||||
|
loopTaskWDTEnabled = false;
|
||||||
|
initArduino();
|
||||||
|
xTaskCreateUniversal(loopTask, "loopTask", CONFIG_ARDUINO_LOOP_STACK_SIZE, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -28,6 +28,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,22 +29,22 @@ extern uint32_t xthal_get_ccount();
|
|||||||
}
|
}
|
||||||
|
|
||||||
// max timeout is 27 seconds at 160MHz clock and 54 seconds at 80MHz clock
|
// max timeout is 27 seconds at 160MHz clock and 54 seconds at 80MHz clock
|
||||||
//unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
|
||||||
//{
|
{
|
||||||
// const uint32_t max_timeout_us = clockCyclesToMicroseconds(UINT_MAX);
|
const uint32_t max_timeout_us = clockCyclesToMicroseconds(UINT_MAX);
|
||||||
// if (timeout > max_timeout_us) {
|
if (timeout > max_timeout_us) {
|
||||||
// timeout = max_timeout_us;
|
timeout = max_timeout_us;
|
||||||
// }
|
}
|
||||||
// const uint32_t timeout_cycles = microsecondsToClockCycles(timeout);
|
const uint32_t timeout_cycles = microsecondsToClockCycles(timeout);
|
||||||
// const uint32_t start_cycle_count = xthal_get_ccount();
|
const uint32_t start_cycle_count = xthal_get_ccount();
|
||||||
// WAIT_FOR_PIN_STATE(!state);
|
WAIT_FOR_PIN_STATE(!state);
|
||||||
// WAIT_FOR_PIN_STATE(state);
|
WAIT_FOR_PIN_STATE(state);
|
||||||
// const uint32_t pulse_start_cycle_count = xthal_get_ccount();
|
const uint32_t pulse_start_cycle_count = xthal_get_ccount();
|
||||||
// WAIT_FOR_PIN_STATE(!state);
|
WAIT_FOR_PIN_STATE(!state);
|
||||||
// return clockCyclesToMicroseconds(xthal_get_ccount() - pulse_start_cycle_count);
|
return clockCyclesToMicroseconds(xthal_get_ccount() - pulse_start_cycle_count);
|
||||||
//}
|
}
|
||||||
|
|
||||||
//unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout)
|
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout)
|
||||||
//{
|
{
|
||||||
// return pulseIn(pin, state, timeout);
|
return pulseIn(pin, state, timeout);
|
||||||
//}
|
}
|
||||||
|
@ -17,10 +17,8 @@
|
|||||||
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "wiring_shift.h"
|
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
#include "wiring_private.h"
|
#include "wiring_private.h"
|
||||||
#include "esp32-hal-gpio.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) {
|
||||||
uint8_t value = 0;
|
uint8_t value = 0;
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define LSBFIRST 0
|
|
||||||
#define MSBFIRST 1
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
|
|
||||||
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
|
|
@ -8,8 +8,8 @@ Installation instructions for Debian / Ubuntu OS
|
|||||||
sudo usermod -a -G dialout $USER && \
|
sudo usermod -a -G dialout $USER && \
|
||||||
sudo apt-get install git && \
|
sudo apt-get install git && \
|
||||||
wget https://bootstrap.pypa.io/get-pip.py && \
|
wget https://bootstrap.pypa.io/get-pip.py && \
|
||||||
sudo python get-pip.py && \
|
sudo python3 get-pip.py && \
|
||||||
sudo pip install pyserial && \
|
sudo pip3 install pyserial && \
|
||||||
mkdir -p ~/Arduino/hardware/espressif && \
|
mkdir -p ~/Arduino/hardware/espressif && \
|
||||||
cd ~/Arduino/hardware/espressif && \
|
cd ~/Arduino/hardware/espressif && \
|
||||||
git clone https://github.com/espressif/arduino-esp32.git esp32 && \
|
git clone https://github.com/espressif/arduino-esp32.git esp32 && \
|
||||||
|
BIN
docs/esp32s2_pinmap.png
Normal file
BIN
docs/esp32s2_pinmap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 340 KiB |
68
libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino
Normal file
68
libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include <WiFi.h>
|
||||||
|
#include <ESPmDNS.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
#include <ArduinoOTA.h>
|
||||||
|
|
||||||
|
const char* ssid = "..........";
|
||||||
|
const char* password = "..........";
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println("Booting");
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
|
||||||
|
Serial.println("Connection Failed! Rebooting...");
|
||||||
|
delay(5000);
|
||||||
|
ESP.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port defaults to 3232
|
||||||
|
// ArduinoOTA.setPort(3232);
|
||||||
|
|
||||||
|
// Hostname defaults to esp3232-[MAC]
|
||||||
|
// ArduinoOTA.setHostname("myesp32");
|
||||||
|
|
||||||
|
// No authentication by default
|
||||||
|
// ArduinoOTA.setPassword("admin");
|
||||||
|
|
||||||
|
// Password can be set with it's md5 value as well
|
||||||
|
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
|
||||||
|
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
|
||||||
|
|
||||||
|
ArduinoOTA
|
||||||
|
.onStart([]() {
|
||||||
|
String type;
|
||||||
|
if (ArduinoOTA.getCommand() == U_FLASH)
|
||||||
|
type = "sketch";
|
||||||
|
else // U_SPIFFS
|
||||||
|
type = "filesystem";
|
||||||
|
|
||||||
|
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
|
||||||
|
Serial.println("Start updating " + type);
|
||||||
|
})
|
||||||
|
.onEnd([]() {
|
||||||
|
Serial.println("\nEnd");
|
||||||
|
})
|
||||||
|
.onProgress([](unsigned int progress, unsigned int total) {
|
||||||
|
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
||||||
|
})
|
||||||
|
.onError([](ota_error_t error) {
|
||||||
|
Serial.printf("Error[%u]: ", error);
|
||||||
|
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
|
||||||
|
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
|
||||||
|
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
|
||||||
|
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
|
||||||
|
else if (error == OTA_END_ERROR) Serial.println("End Failed");
|
||||||
|
});
|
||||||
|
|
||||||
|
ArduinoOTA.begin();
|
||||||
|
|
||||||
|
Serial.println("Ready");
|
||||||
|
Serial.print("IP address: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
ArduinoOTA.handle();
|
||||||
|
}
|
169
libraries/ArduinoOTA/examples/OTAWebUpdater/OTAWebUpdater.ino
Normal file
169
libraries/ArduinoOTA/examples/OTAWebUpdater/OTAWebUpdater.ino
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
#include <WiFi.h>
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
#include <WebServer.h>
|
||||||
|
#include <ESPmDNS.h>
|
||||||
|
#include <Update.h>
|
||||||
|
|
||||||
|
const char* host = "esp32";
|
||||||
|
const char* ssid = "xxx";
|
||||||
|
const char* password = "xxxx";
|
||||||
|
|
||||||
|
WebServer server(80);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Login page
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char* loginIndex =
|
||||||
|
"<form name='loginForm'>"
|
||||||
|
"<table width='20%' bgcolor='A09F9F' align='center'>"
|
||||||
|
"<tr>"
|
||||||
|
"<td colspan=2>"
|
||||||
|
"<center><font size=4><b>ESP32 Login Page</b></font></center>"
|
||||||
|
"<br>"
|
||||||
|
"</td>"
|
||||||
|
"<br>"
|
||||||
|
"<br>"
|
||||||
|
"</tr>"
|
||||||
|
"<tr>"
|
||||||
|
"<td>Username:</td>"
|
||||||
|
"<td><input type='text' size=25 name='userid'><br></td>"
|
||||||
|
"</tr>"
|
||||||
|
"<br>"
|
||||||
|
"<br>"
|
||||||
|
"<tr>"
|
||||||
|
"<td>Password:</td>"
|
||||||
|
"<td><input type='Password' size=25 name='pwd'><br></td>"
|
||||||
|
"<br>"
|
||||||
|
"<br>"
|
||||||
|
"</tr>"
|
||||||
|
"<tr>"
|
||||||
|
"<td><input type='submit' onclick='check(this.form)' value='Login'></td>"
|
||||||
|
"</tr>"
|
||||||
|
"</table>"
|
||||||
|
"</form>"
|
||||||
|
"<script>"
|
||||||
|
"function check(form)"
|
||||||
|
"{"
|
||||||
|
"if(form.userid.value=='admin' && form.pwd.value=='admin')"
|
||||||
|
"{"
|
||||||
|
"window.open('/serverIndex')"
|
||||||
|
"}"
|
||||||
|
"else"
|
||||||
|
"{"
|
||||||
|
" alert('Error Password or Username')/*displays error message*/"
|
||||||
|
"}"
|
||||||
|
"}"
|
||||||
|
"</script>";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Server Index Page
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char* serverIndex =
|
||||||
|
"<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
|
||||||
|
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
|
||||||
|
"<input type='file' name='update'>"
|
||||||
|
"<input type='submit' value='Update'>"
|
||||||
|
"</form>"
|
||||||
|
"<div id='prg'>progress: 0%</div>"
|
||||||
|
"<script>"
|
||||||
|
"$('form').submit(function(e){"
|
||||||
|
"e.preventDefault();"
|
||||||
|
"var form = $('#upload_form')[0];"
|
||||||
|
"var data = new FormData(form);"
|
||||||
|
" $.ajax({"
|
||||||
|
"url: '/update',"
|
||||||
|
"type: 'POST',"
|
||||||
|
"data: data,"
|
||||||
|
"contentType: false,"
|
||||||
|
"processData:false,"
|
||||||
|
"xhr: function() {"
|
||||||
|
"var xhr = new window.XMLHttpRequest();"
|
||||||
|
"xhr.upload.addEventListener('progress', function(evt) {"
|
||||||
|
"if (evt.lengthComputable) {"
|
||||||
|
"var per = evt.loaded / evt.total;"
|
||||||
|
"$('#prg').html('progress: ' + Math.round(per*100) + '%');"
|
||||||
|
"}"
|
||||||
|
"}, false);"
|
||||||
|
"return xhr;"
|
||||||
|
"},"
|
||||||
|
"success:function(d, s) {"
|
||||||
|
"console.log('success!')"
|
||||||
|
"},"
|
||||||
|
"error: function (a, b, c) {"
|
||||||
|
"}"
|
||||||
|
"});"
|
||||||
|
"});"
|
||||||
|
"</script>";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setup function
|
||||||
|
*/
|
||||||
|
void setup(void) {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// Connect to WiFi network
|
||||||
|
WiFi.begin(ssid, 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());
|
||||||
|
|
||||||
|
/*use mdns for host name resolution*/
|
||||||
|
if (!MDNS.begin(host)) { //http://esp32.local
|
||||||
|
Serial.println("Error setting up MDNS responder!");
|
||||||
|
while (1) {
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.println("mDNS responder started");
|
||||||
|
/*return index page which is stored in serverIndex */
|
||||||
|
server.on("/", HTTP_GET, []() {
|
||||||
|
server.sendHeader("Connection", "close");
|
||||||
|
server.send(200, "text/html", loginIndex);
|
||||||
|
});
|
||||||
|
server.on("/serverIndex", HTTP_GET, []() {
|
||||||
|
server.sendHeader("Connection", "close");
|
||||||
|
server.send(200, "text/html", serverIndex);
|
||||||
|
});
|
||||||
|
/*handling uploading firmware file */
|
||||||
|
server.on("/update", HTTP_POST, []() {
|
||||||
|
server.sendHeader("Connection", "close");
|
||||||
|
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
|
||||||
|
ESP.restart();
|
||||||
|
}, []() {
|
||||||
|
HTTPUpload& upload = server.upload();
|
||||||
|
if (upload.status == UPLOAD_FILE_START) {
|
||||||
|
Serial.printf("Update: %s\n", upload.filename.c_str());
|
||||||
|
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
|
||||||
|
Update.printError(Serial);
|
||||||
|
}
|
||||||
|
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||||
|
/* flashing firmware to ESP*/
|
||||||
|
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
|
||||||
|
Update.printError(Serial);
|
||||||
|
}
|
||||||
|
} else if (upload.status == UPLOAD_FILE_END) {
|
||||||
|
if (Update.end(true)) { //true to set the size to the current progress
|
||||||
|
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
|
||||||
|
} else {
|
||||||
|
Update.printError(Serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
server.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(void) {
|
||||||
|
server.handleClient();
|
||||||
|
delay(1);
|
||||||
|
}
|
26
libraries/ArduinoOTA/keywords.txt
Normal file
26
libraries/ArduinoOTA/keywords.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#######################################
|
||||||
|
# Syntax Coloring Map For Ultrasound
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Datatypes (KEYWORD1)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
ArduinoOTA KEYWORD1
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Methods and Functions (KEYWORD2)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
begin KEYWORD2
|
||||||
|
setup KEYWORD2
|
||||||
|
handle KEYWORD2
|
||||||
|
onStart KEYWORD2
|
||||||
|
onEnd KEYWORD2
|
||||||
|
onError KEYWORD2
|
||||||
|
onProgress KEYWORD2
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Constants (LITERAL1)
|
||||||
|
#######################################
|
||||||
|
|
9
libraries/ArduinoOTA/library.properties
Normal file
9
libraries/ArduinoOTA/library.properties
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name=ArduinoOTA
|
||||||
|
version=1.0
|
||||||
|
author=Ivan Grokhotkov and Hristo Gochkov
|
||||||
|
maintainer=Hristo Gochkov <hristo@espressif.com>
|
||||||
|
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.
|
||||||
|
category=Communication
|
||||||
|
url=
|
||||||
|
architectures=esp32
|
395
libraries/ArduinoOTA/src/ArduinoOTA.cpp
Normal file
395
libraries/ArduinoOTA/src/ArduinoOTA.cpp
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
#ifndef LWIP_OPEN_SRC
|
||||||
|
#define LWIP_OPEN_SRC
|
||||||
|
#endif
|
||||||
|
#include <functional>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
#include "ArduinoOTA.h"
|
||||||
|
#include "ESPmDNS.h"
|
||||||
|
#include "MD5Builder.h"
|
||||||
|
#include "Update.h"
|
||||||
|
|
||||||
|
|
||||||
|
// #define OTA_DEBUG Serial
|
||||||
|
|
||||||
|
ArduinoOTAClass::ArduinoOTAClass()
|
||||||
|
: _port(0)
|
||||||
|
, _initialized(false)
|
||||||
|
, _rebootOnSuccess(true)
|
||||||
|
, _mdnsEnabled(true)
|
||||||
|
, _state(OTA_IDLE)
|
||||||
|
, _size(0)
|
||||||
|
, _cmd(0)
|
||||||
|
, _ota_port(0)
|
||||||
|
, _ota_timeout(1000)
|
||||||
|
, _start_callback(NULL)
|
||||||
|
, _end_callback(NULL)
|
||||||
|
, _error_callback(NULL)
|
||||||
|
, _progress_callback(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoOTAClass::~ArduinoOTAClass(){
|
||||||
|
_udp_ota.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoOTAClass& ArduinoOTAClass::onStart(THandlerFunction fn) {
|
||||||
|
_start_callback = fn;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoOTAClass& ArduinoOTAClass::onEnd(THandlerFunction fn) {
|
||||||
|
_end_callback = fn;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoOTAClass& ArduinoOTAClass::onProgress(THandlerFunction_Progress fn) {
|
||||||
|
_progress_callback = fn;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoOTAClass& ArduinoOTAClass::onError(THandlerFunction_Error fn) {
|
||||||
|
_error_callback = fn;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoOTAClass& ArduinoOTAClass::setPort(uint16_t port) {
|
||||||
|
if (!_initialized && !_port && port) {
|
||||||
|
_port = port;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoOTAClass& ArduinoOTAClass::setHostname(const char * hostname) {
|
||||||
|
if (!_initialized && !_hostname.length() && hostname) {
|
||||||
|
_hostname = hostname;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String ArduinoOTAClass::getHostname() {
|
||||||
|
return _hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoOTAClass& ArduinoOTAClass::setPassword(const char * password) {
|
||||||
|
if (!_initialized && !_password.length() && password) {
|
||||||
|
MD5Builder passmd5;
|
||||||
|
passmd5.begin();
|
||||||
|
passmd5.add(password);
|
||||||
|
passmd5.calculate();
|
||||||
|
_password = passmd5.toString();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoOTAClass& ArduinoOTAClass::setPasswordHash(const char * password) {
|
||||||
|
if (!_initialized && !_password.length() && password) {
|
||||||
|
_password = password;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoOTAClass& ArduinoOTAClass::setPartitionLabel(const char * partition_label) {
|
||||||
|
if (!_initialized && !_partition_label.length() && partition_label) {
|
||||||
|
_partition_label = partition_label;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String ArduinoOTAClass::getPartitionLabel() {
|
||||||
|
return _partition_label;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoOTAClass& ArduinoOTAClass::setRebootOnSuccess(bool reboot){
|
||||||
|
_rebootOnSuccess = reboot;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoOTAClass& ArduinoOTAClass::setMdnsEnabled(bool enabled){
|
||||||
|
_mdnsEnabled = enabled;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoOTAClass::begin() {
|
||||||
|
if (_initialized){
|
||||||
|
log_w("already initialized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_port) {
|
||||||
|
_port = 3232;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!_udp_ota.begin(_port)){
|
||||||
|
log_e("udp bind failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!_hostname.length()) {
|
||||||
|
char tmp[20];
|
||||||
|
uint8_t mac[6];
|
||||||
|
WiFi.macAddress(mac);
|
||||||
|
sprintf(tmp, "esp32-%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
|
_hostname = tmp;
|
||||||
|
}
|
||||||
|
if(_mdnsEnabled){
|
||||||
|
MDNS.begin(_hostname.c_str());
|
||||||
|
MDNS.enableArduino(_port, (_password.length() > 0));
|
||||||
|
}
|
||||||
|
_initialized = true;
|
||||||
|
_state = OTA_IDLE;
|
||||||
|
log_i("OTA server at: %s.local:%u", _hostname.c_str(), _port);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ArduinoOTAClass::parseInt(){
|
||||||
|
char data[INT_BUFFER_SIZE];
|
||||||
|
uint8_t index = 0;
|
||||||
|
char value;
|
||||||
|
while(_udp_ota.peek() == ' ') _udp_ota.read();
|
||||||
|
while(index < INT_BUFFER_SIZE - 1){
|
||||||
|
value = _udp_ota.peek();
|
||||||
|
if(value < '0' || value > '9'){
|
||||||
|
data[index++] = '\0';
|
||||||
|
return atoi(data);
|
||||||
|
}
|
||||||
|
data[index++] = _udp_ota.read();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
String ArduinoOTAClass::readStringUntil(char end){
|
||||||
|
String res = "";
|
||||||
|
int value;
|
||||||
|
while(true){
|
||||||
|
value = _udp_ota.read();
|
||||||
|
if(value <= 0 || value == end){
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
res += (char)value;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoOTAClass::_onRx(){
|
||||||
|
if (_state == OTA_IDLE) {
|
||||||
|
int cmd = parseInt();
|
||||||
|
if (cmd != U_FLASH && cmd != U_SPIFFS)
|
||||||
|
return;
|
||||||
|
_cmd = cmd;
|
||||||
|
_ota_port = parseInt();
|
||||||
|
_size = parseInt();
|
||||||
|
_udp_ota.read();
|
||||||
|
_md5 = readStringUntil('\n');
|
||||||
|
_md5.trim();
|
||||||
|
if(_md5.length() != 32){
|
||||||
|
log_e("bad md5 length");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_password.length()){
|
||||||
|
MD5Builder nonce_md5;
|
||||||
|
nonce_md5.begin();
|
||||||
|
nonce_md5.add(String(micros()));
|
||||||
|
nonce_md5.calculate();
|
||||||
|
_nonce = nonce_md5.toString();
|
||||||
|
|
||||||
|
_udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort());
|
||||||
|
_udp_ota.printf("AUTH %s", _nonce.c_str());
|
||||||
|
_udp_ota.endPacket();
|
||||||
|
_state = OTA_WAITAUTH;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
_udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort());
|
||||||
|
_udp_ota.print("OK");
|
||||||
|
_udp_ota.endPacket();
|
||||||
|
_ota_ip = _udp_ota.remoteIP();
|
||||||
|
_state = OTA_RUNUPDATE;
|
||||||
|
}
|
||||||
|
} else if (_state == OTA_WAITAUTH) {
|
||||||
|
int cmd = parseInt();
|
||||||
|
if (cmd != U_AUTH) {
|
||||||
|
log_e("%d was expected. got %d instead", U_AUTH, cmd);
|
||||||
|
_state = OTA_IDLE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_udp_ota.read();
|
||||||
|
String cnonce = readStringUntil(' ');
|
||||||
|
String response = readStringUntil('\n');
|
||||||
|
if (cnonce.length() != 32 || response.length() != 32) {
|
||||||
|
log_e("auth param fail");
|
||||||
|
_state = OTA_IDLE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String challenge = _password + ":" + String(_nonce) + ":" + cnonce;
|
||||||
|
MD5Builder _challengemd5;
|
||||||
|
_challengemd5.begin();
|
||||||
|
_challengemd5.add(challenge);
|
||||||
|
_challengemd5.calculate();
|
||||||
|
String result = _challengemd5.toString();
|
||||||
|
|
||||||
|
if(result.equals(response)){
|
||||||
|
_udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort());
|
||||||
|
_udp_ota.print("OK");
|
||||||
|
_udp_ota.endPacket();
|
||||||
|
_ota_ip = _udp_ota.remoteIP();
|
||||||
|
_state = OTA_RUNUPDATE;
|
||||||
|
} else {
|
||||||
|
_udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort());
|
||||||
|
_udp_ota.print("Authentication Failed");
|
||||||
|
log_w("Authentication Failed");
|
||||||
|
_udp_ota.endPacket();
|
||||||
|
if (_error_callback) _error_callback(OTA_AUTH_ERROR);
|
||||||
|
_state = OTA_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoOTAClass::_runUpdate() {
|
||||||
|
const char *partition_label = _partition_label.length() ? _partition_label.c_str() : NULL;
|
||||||
|
if (!Update.begin(_size, _cmd, -1, LOW, partition_label)) {
|
||||||
|
|
||||||
|
log_e("Begin ERROR: %s", Update.errorString());
|
||||||
|
|
||||||
|
if (_error_callback) {
|
||||||
|
_error_callback(OTA_BEGIN_ERROR);
|
||||||
|
}
|
||||||
|
_state = OTA_IDLE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Update.setMD5(_md5.c_str());
|
||||||
|
|
||||||
|
if (_start_callback) {
|
||||||
|
_start_callback();
|
||||||
|
}
|
||||||
|
if (_progress_callback) {
|
||||||
|
_progress_callback(0, _size);
|
||||||
|
}
|
||||||
|
|
||||||
|
WiFiClient client;
|
||||||
|
if (!client.connect(_ota_ip, _ota_port)) {
|
||||||
|
if (_error_callback) {
|
||||||
|
_error_callback(OTA_CONNECT_ERROR);
|
||||||
|
}
|
||||||
|
_state = OTA_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t written = 0, total = 0, tried = 0;
|
||||||
|
|
||||||
|
while (!Update.isFinished() && client.connected()) {
|
||||||
|
size_t waited = _ota_timeout;
|
||||||
|
size_t available = client.available();
|
||||||
|
while (!available && waited){
|
||||||
|
delay(1);
|
||||||
|
waited -=1 ;
|
||||||
|
available = client.available();
|
||||||
|
}
|
||||||
|
if (!waited){
|
||||||
|
if(written && tried++ < 3){
|
||||||
|
log_i("Try[%u]: %u", tried, written);
|
||||||
|
if(!client.printf("%u", written)){
|
||||||
|
log_e("failed to respond");
|
||||||
|
_state = OTA_IDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
log_e("Receive Failed");
|
||||||
|
if (_error_callback) {
|
||||||
|
_error_callback(OTA_RECEIVE_ERROR);
|
||||||
|
}
|
||||||
|
_state = OTA_IDLE;
|
||||||
|
Update.abort();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!available){
|
||||||
|
log_e("No Data: %u", waited);
|
||||||
|
_state = OTA_IDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tried = 0;
|
||||||
|
static uint8_t buf[1460];
|
||||||
|
if(available > 1460){
|
||||||
|
available = 1460;
|
||||||
|
}
|
||||||
|
size_t r = client.read(buf, available);
|
||||||
|
if(r != available){
|
||||||
|
log_w("didn't read enough! %u != %u", r, available);
|
||||||
|
}
|
||||||
|
|
||||||
|
written = Update.write(buf, r);
|
||||||
|
if (written > 0) {
|
||||||
|
if(written != r){
|
||||||
|
log_w("didn't write enough! %u != %u", written, r);
|
||||||
|
}
|
||||||
|
if(!client.printf("%u", written)){
|
||||||
|
log_w("failed to respond");
|
||||||
|
}
|
||||||
|
total += written;
|
||||||
|
if(_progress_callback) {
|
||||||
|
_progress_callback(total, _size);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log_e("Write ERROR: %s", Update.errorString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Update.end()) {
|
||||||
|
client.print("OK");
|
||||||
|
client.stop();
|
||||||
|
delay(10);
|
||||||
|
if (_end_callback) {
|
||||||
|
_end_callback();
|
||||||
|
}
|
||||||
|
if(_rebootOnSuccess){
|
||||||
|
//let serial/network finish tasks that might be given in _end_callback
|
||||||
|
delay(100);
|
||||||
|
ESP.restart();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_error_callback) {
|
||||||
|
_error_callback(OTA_END_ERROR);
|
||||||
|
}
|
||||||
|
Update.printError(client);
|
||||||
|
client.stop();
|
||||||
|
delay(10);
|
||||||
|
log_e("Update ERROR: %s", Update.errorString());
|
||||||
|
_state = OTA_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoOTAClass::end() {
|
||||||
|
_initialized = false;
|
||||||
|
_udp_ota.stop();
|
||||||
|
if(_mdnsEnabled){
|
||||||
|
MDNS.end();
|
||||||
|
}
|
||||||
|
_state = OTA_IDLE;
|
||||||
|
log_i("OTA server stopped.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoOTAClass::handle() {
|
||||||
|
if (!_initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_state == OTA_RUNUPDATE) {
|
||||||
|
_runUpdate();
|
||||||
|
_state = OTA_IDLE;
|
||||||
|
}
|
||||||
|
if(_udp_ota.parsePacket()){
|
||||||
|
_onRx();
|
||||||
|
}
|
||||||
|
_udp_ota.flush(); // always flush, even zero length packets must be flushed.
|
||||||
|
}
|
||||||
|
|
||||||
|
int ArduinoOTAClass::getCommand() {
|
||||||
|
return _cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoOTAClass::setTimeout(int timeoutInMillis) {
|
||||||
|
_ota_timeout = timeoutInMillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_ARDUINOOTA)
|
||||||
|
ArduinoOTAClass ArduinoOTA;
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user