mirror of
https://github.com/0xFEEDC0DE64/arduino-esp32.git
synced 2025-06-25 18:01:33 +02:00
Compare commits
362 Commits
Author | SHA1 | Date | |
---|---|---|---|
cf60cf4c3b | |||
b5b45cd518 | |||
9a9fb2c3aa | |||
41e392f661 | |||
6be6abf35b | |||
baaff8480e | |||
54140dc5ca | |||
9f8b433196 | |||
b7c3607b5b | |||
2b0dbdc12a | |||
b06735a33a | |||
537b1a6d3a | |||
440437c905 | |||
9bb8224159 | |||
0db0af5932 | |||
8d9d7bbca9 | |||
291c519642 | |||
bbcc624c97 | |||
2656452d04 | |||
273a8d79b4 | |||
42b4a9927d | |||
383b999ddd | |||
52c284af75 | |||
5f057c7cac | |||
880fc0bdfb | |||
9eaa5873bf | |||
7678be447d | |||
c6f6522032 | |||
d2519843ad | |||
2cebf72876 | |||
4fa3cbab64 | |||
280bf4d014 | |||
dc0208ed1e | |||
f58cba0b4f | |||
38057d66ad | |||
4d98cea085 | |||
33f4745635 | |||
9f1ccb9c85 | |||
ea04207c8f | |||
e06f9b7fa6 | |||
2e19d27e3e | |||
b8fcea9a8d | |||
46bde99c06 | |||
7f61d2044a | |||
f13f84ddeb | |||
096af056d1 | |||
acadabb146 | |||
7d50114881 | |||
be074eec80 | |||
bd96f7f159 | |||
ca7ed86bbd | |||
a1bd429747 | |||
11cad8747e | |||
2d7ec30a1b | |||
ef961442d7 | |||
d5bd8e325c | |||
0a4b6599d2 | |||
8cb2a4ba3e | |||
d12af93ee2 | |||
7e9d75a974 | |||
61c98b8370 | |||
b92c58d74b | |||
35d9759fa6 | |||
04267e12da | |||
86494d5cb9 | |||
12a8779fd6 | |||
6ecd249a4a | |||
b15f5bac79 | |||
3d7f9d9282 | |||
dc3394d6ac | |||
351a651295 | |||
d009787a6f | |||
57b7e4c678 | |||
345055050b | |||
09bff5027d | |||
79f77afc98 | |||
594ee6d249 | |||
934841e236 | |||
cda6facdc7 | |||
eccbfdb48a | |||
27e61dcaf5 | |||
7553683bd2 | |||
40c325bd0a | |||
4f7e8065c0 | |||
05db08e20a | |||
ad067eab2d | |||
31d5120e04 | |||
d1110013af | |||
caca107719 | |||
279f7e33be | |||
f3835ea89f | |||
0d61996917 | |||
88f1b235e6 | |||
400aca52ce | |||
3fb164224d | |||
cebaf93dd8 | |||
176e5b0e79 | |||
9a16cd4600 | |||
b769dd0de3 | |||
7f1b7ade7b | |||
806e388d23 | |||
07f1bceef4 | |||
aa61b75aa4 | |||
48dfc89ccb | |||
c6bae38ce9 | |||
87d5f9d121 | |||
ed2115e361 | |||
644f7a8a2f | |||
81cdcc9e27 | |||
04988bdb21 | |||
2103a789b6 | |||
669cbec58e | |||
4f4bf07726 | |||
1840ba5c53 | |||
20028a2027 | |||
2977df4648 | |||
5320123e04 | |||
0a0ee87ba5 | |||
1bb1160dea | |||
a744383cbd | |||
7ea54ab6aa | |||
fd70e0d071 | |||
0e3994c966 | |||
5d7032d4f2 | |||
46abedcc1a | |||
a6a68a9546 | |||
062d4b123f | |||
ad68da6e41 | |||
f69b40dfff | |||
3a554c55f4 | |||
03d3d6112b | |||
05df11e0d9 | |||
c2be29eb97 | |||
49c47884a7 | |||
0ea23fe38a | |||
7f560284ff | |||
8569b2c893 | |||
49b76649f1 | |||
5d9bb5cf50 | |||
c8215315ae | |||
4d118b36a2 | |||
2c9b648502 | |||
5508689ea3 | |||
93d77859d9 | |||
0f772270fb | |||
13e02063d6 | |||
9b75c65fc7 | |||
109ba7a3b4 | |||
b2c678877c | |||
856e596c79 | |||
354e485c4b | |||
1c4966566c | |||
4bb60f68da | |||
ed220bd042 | |||
80f9f9aeec | |||
251d5ef92b | |||
8c723be135 | |||
b50a1755c8 | |||
bb0a194bb7 | |||
ed59ae6482 | |||
b4a9684a74 | |||
1977370e6f | |||
307b1368dd | |||
32d5654aa6 | |||
7637a739cc | |||
cd85239252 | |||
ac9d04a400 | |||
2195109ecc | |||
8d938c849d | |||
cb005fc8b5 | |||
89351e3ade | |||
86de90fe24 | |||
5960cd3e2a | |||
82e208c8c9 | |||
e7c9813625 | |||
dd78794311 | |||
0607d36734 | |||
6e77f7f3e5 | |||
915d45de7d | |||
c2b37d95e0 | |||
2f13a960ac | |||
579e04be25 | |||
5443d7ca93 | |||
7b3c1dfd50 | |||
85ef51ffbc | |||
36075257c2 | |||
7de1717640 | |||
8869d39d79 | |||
cfe8526ec8 | |||
c09ec5bd3d | |||
d8b2098461 | |||
3fc974f3aa | |||
9ad860758c | |||
cec3fca4ad | |||
dac493fb92 | |||
bc3d11364f | |||
f41beb92bf | |||
8c4ca5a235 | |||
b3085d4a8b | |||
547c2d3346 | |||
7d2632c024 | |||
e59355df71 | |||
ec63d09e54 | |||
188560e7f3 | |||
91e095f5a7 | |||
c8d8dc2265 | |||
b847f41e24 | |||
611ba8ea8a | |||
0cab2483e6 | |||
79e4339582 | |||
a35035f827 | |||
9ef3e2d2a6 | |||
0cdfb0b193 | |||
e50613622e | |||
24b277ad92 | |||
c2b3f2d6af | |||
8fb8e7d060 | |||
048b26547a | |||
b10ed77aaf | |||
4638628873 | |||
6f70e27011 | |||
d0b064a1ee | |||
85c77a9c3f | |||
c8e3f0c732 | |||
5ad468f9dc | |||
38c4c06108 | |||
b334b2c2f9 | |||
8a46697168 | |||
270a2759d9 | |||
01d9345d28 | |||
71e3d515f3 | |||
64cfb33deb | |||
5f1dff7dad | |||
40ebee1cb1 | |||
ed96d2a1b7 | |||
caa391ab34 | |||
3b71e136e1 | |||
1c77790a5b | |||
5bff89f0be | |||
9bbd720d4c | |||
589bb7032d | |||
f8c06894c5 | |||
a5c873b786 | |||
895a150840 | |||
ca88fdc273 | |||
f32083a6d0 | |||
b30e55efff | |||
0ac2de7aab | |||
0eec630314 | |||
731fd19bdf | |||
298c6104a2 | |||
8ea12f89f3 | |||
b3ba80d570 | |||
a5935ce1cc | |||
96d6975bd5 | |||
9eaeeb660c | |||
e22d8b6787 | |||
56fe2dbaff | |||
06a399b84a | |||
4ce2cc3c1d | |||
07390157df | |||
bab3a70f54 | |||
cd4f9038ee | |||
7fe2812f7f | |||
9710fedaf0 | |||
f5cacfee1a | |||
f71a4bd406 | |||
5f77b0108b | |||
717ca79ecb | |||
07613b3158 | |||
80ea521940 | |||
5c04de6f39 | |||
0d163a1ce2 | |||
2a7e509978 | |||
1b8c7e34f9 | |||
7a574399b1 | |||
fd089d8fd3 | |||
f356ccd54a | |||
6daf773464 | |||
70a896481d | |||
390da0d090 | |||
d5e2bb12ca | |||
f4acac4c2b | |||
5137fc5c80 | |||
03066e42ef | |||
cd5257ad78 | |||
ee6336a312 | |||
61f71930e9 | |||
ec40c4c96f | |||
2bda4a9617 | |||
91b9fae111 | |||
2a1fde7736 | |||
a12d609b22 | |||
73576674b8 | |||
007a93ec7e | |||
a5f3fc6fad | |||
65e256c40a | |||
fa55a2c91d | |||
a070884441 | |||
a9c8b46b1a | |||
6954150176 | |||
548f712df2 | |||
56ce580b0e | |||
509d31ba51 | |||
9e32cec9a2 | |||
3376ea1bd5 | |||
1c7e329140 | |||
c17b212cd0 | |||
7dbda4988b | |||
d1134fd45e | |||
d5fdd715ef | |||
ca7106e97e | |||
87e5787cf7 | |||
c13d11e7d1 | |||
b0d8d4dd44 | |||
05de017bd5 | |||
e1548e9b7e | |||
c29ec9da3d | |||
b3783fba95 | |||
a22ec4a978 | |||
20498cf8b1 | |||
02e51728c4 | |||
d2816b2f32 | |||
2e32022611 | |||
74ffdac74a | |||
4ee17ec3ee | |||
476660f763 | |||
f558e69181 | |||
5bf3aab527 | |||
1aced120ba | |||
7d7824701f | |||
89feacb813 | |||
aae6f24a37 | |||
43b781a158 | |||
e055b28d1a | |||
714ba948e6 | |||
e57de64a3c | |||
fd5a2f08f9 | |||
e9389e3122 | |||
0acf19af8f | |||
aff2e42ac6 | |||
2743e7b739 | |||
c453a0037b | |||
2f249edb8e | |||
bd57ff4ab4 | |||
43bf393dbf | |||
bea7bd1852 | |||
7dd537f8d3 | |||
50d142950d | |||
d13de284b8 | |||
697d4ff7c4 | |||
ab309e40d5 | |||
932666a03f | |||
a0ad987029 | |||
271e5cd206 | |||
619568db5b | |||
0202ba7c21 | |||
119ece2b0f | |||
606446a830 | |||
a28cf00295 | |||
672e4faa92 | |||
f8eebb5c39 |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -24,7 +24,7 @@ https://github.com/me-no-dev/EspExceptionDecoder
|
|||||||
|
|
||||||
### Hardware:
|
### Hardware:
|
||||||
Board: ?ESP32 Dev Module? ?node32? ?ttgo_lora?
|
Board: ?ESP32 Dev Module? ?node32? ?ttgo_lora?
|
||||||
Core Installation version: ?1.0.0? ?1.0.1-rc4? ?1.0.1? ?1.0.1-git?
|
Core Installation version: ?1.0.0? ?1.0.1-rc4? ?1.0.1? ?1.0.1-git? ?1.0.2? ?1.0.3?
|
||||||
IDE name: ?Arduino IDE? ?Platform.io? ?IDF component?
|
IDE name: ?Arduino IDE? ?Platform.io? ?IDF component?
|
||||||
Flash Frequency: ?40Mhz?
|
Flash Frequency: ?40Mhz?
|
||||||
PSRAM enabled: ?no? ?yes?
|
PSRAM enabled: ?no? ?yes?
|
||||||
|
27
.github/scripts/check-cmakelists.sh
vendored
Executable file
27
.github/scripts/check-cmakelists.sh
vendored
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# This script is for Travis. It checks all non-examples source files in libraries/ and cores/ are listed in
|
||||||
|
# CMakeLists.txt for the cmake-based IDF component
|
||||||
|
#
|
||||||
|
# If you see an error running this script, edit CMakeLists.txt and add any new source files into your PR
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# pull all submodules
|
||||||
|
git submodule update --init --recursive
|
||||||
|
|
||||||
|
# find all source files in repo
|
||||||
|
REPO_SRCS=`find cores/esp32/ libraries/ -name 'examples' -prune -o -name '*.c' -print -o -name '*.cpp' -print | sort`
|
||||||
|
|
||||||
|
# find all source files named in CMakeLists.txt COMPONENT_SRCS
|
||||||
|
CMAKE_SRCS=`cmake --trace-expand -C CMakeLists.txt 2>&1 | grep set\(srcs | cut -d'(' -f3 | sed 's/ )//' | sed 's/srcs //' | tr ' ;' '\n' | sort`
|
||||||
|
|
||||||
|
if ! diff -u0 --label "Repo Files" --label "srcs" <(echo "$REPO_SRCS") <(echo "$CMAKE_SRCS"); then
|
||||||
|
echo "Source files in repo (-) and source files in CMakeLists.txt (+) don't match"
|
||||||
|
echo "Edit CMakeLists.txt as appropriate to add/remove source files from COMPONENT_SRCS"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "CMakeLists.txt and repo source files match"
|
||||||
|
exit 0
|
36
.github/scripts/install-arduino-core-esp32.sh
vendored
Executable file
36
.github/scripts/install-arduino-core-esp32.sh
vendored
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export ARDUINO_ESP32_PATH="$ARDUINO_USR_PATH/hardware/espressif/esp32"
|
||||||
|
if [ ! -d "$ARDUINO_ESP32_PATH" ]; then
|
||||||
|
echo "Installing ESP32 Arduino Core ..."
|
||||||
|
script_init_path="$PWD"
|
||||||
|
mkdir -p "$ARDUINO_USR_PATH/hardware/espressif"
|
||||||
|
cd "$ARDUINO_USR_PATH/hardware/espressif"
|
||||||
|
|
||||||
|
echo "Installing Python Serial ..."
|
||||||
|
pip install pyserial > /dev/null
|
||||||
|
|
||||||
|
if [ "$OS_IS_WINDOWS" == "1" ]; then
|
||||||
|
echo "Installing Python Requests ..."
|
||||||
|
pip install requests > /dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then
|
||||||
|
echo "Linking Core..."
|
||||||
|
ln -s $GITHUB_WORKSPACE esp32
|
||||||
|
else
|
||||||
|
echo "Cloning Core Repository..."
|
||||||
|
git clone https://github.com/espressif/arduino-esp32.git esp32 > /dev/null 2>&1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#echo "Updating Submodules ..."
|
||||||
|
cd esp32
|
||||||
|
#git submodule update --init --recursive > /dev/null 2>&1
|
||||||
|
|
||||||
|
echo "Installing Platform Tools ..."
|
||||||
|
cd tools && python get.py
|
||||||
|
cd $script_init_path
|
||||||
|
|
||||||
|
echo "ESP32 Arduino has been installed in '$ARDUINO_ESP32_PATH'"
|
||||||
|
echo ""
|
||||||
|
fi
|
228
.github/scripts/install-arduino-ide.sh
vendored
Executable file
228
.github/scripts/install-arduino-ide.sh
vendored
Executable file
@ -0,0 +1,228 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#OSTYPE: 'linux-gnu', ARCH: 'x86_64' => linux64
|
||||||
|
#OSTYPE: 'msys', ARCH: 'x86_64' => win32
|
||||||
|
#OSTYPE: 'darwin18', ARCH: 'i386' => macos
|
||||||
|
|
||||||
|
OSBITS=`arch`
|
||||||
|
if [[ "$OSTYPE" == "linux"* ]]; then
|
||||||
|
export OS_IS_LINUX="1"
|
||||||
|
ARCHIVE_FORMAT="tar.xz"
|
||||||
|
if [[ "$OSBITS" == "i686" ]]; then
|
||||||
|
OS_NAME="linux32"
|
||||||
|
elif [[ "$OSBITS" == "x86_64" ]]; then
|
||||||
|
OS_NAME="linux64"
|
||||||
|
elif [[ "$OSBITS" == "armv7l" || "$OSBITS" == "aarch64" ]]; then
|
||||||
|
OS_NAME="linuxarm"
|
||||||
|
else
|
||||||
|
OS_NAME="$OSTYPE-$OSBITS"
|
||||||
|
echo "Unknown OS '$OS_NAME'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
export OS_IS_MACOS="1"
|
||||||
|
ARCHIVE_FORMAT="zip"
|
||||||
|
OS_NAME="macosx"
|
||||||
|
elif [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
|
||||||
|
export OS_IS_WINDOWS="1"
|
||||||
|
ARCHIVE_FORMAT="zip"
|
||||||
|
OS_NAME="windows"
|
||||||
|
else
|
||||||
|
OS_NAME="$OSTYPE-$OSBITS"
|
||||||
|
echo "Unknown OS '$OS_NAME'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
export OS_NAME
|
||||||
|
|
||||||
|
ARDUINO_BUILD_DIR="$HOME/.arduino/build.tmp"
|
||||||
|
ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp"
|
||||||
|
|
||||||
|
if [ "$OS_IS_MACOS" == "1" ]; then
|
||||||
|
export ARDUINO_IDE_PATH="/Applications/Arduino.app/Contents/Java"
|
||||||
|
export ARDUINO_USR_PATH="$HOME/Documents/Arduino"
|
||||||
|
elif [ "$OS_IS_WINDOWS" == "1" ]; then
|
||||||
|
export ARDUINO_IDE_PATH="$HOME/arduino_ide"
|
||||||
|
export ARDUINO_USR_PATH="$HOME/Documents/Arduino"
|
||||||
|
else
|
||||||
|
export ARDUINO_IDE_PATH="$HOME/arduino_ide"
|
||||||
|
export ARDUINO_USR_PATH="$HOME/Arduino"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Updated as of Nov 3rd 2020
|
||||||
|
ARDUINO_IDE_URL="https://github.com/espressif/arduino-esp32/releases/download/1.0.4/arduino-nightly-"
|
||||||
|
|
||||||
|
# Currently not working
|
||||||
|
#ARDUINO_IDE_URL="https://www.arduino.cc/download.php?f=/arduino-nightly-"
|
||||||
|
|
||||||
|
if [ ! -d "$ARDUINO_IDE_PATH" ]; then
|
||||||
|
echo "Installing Arduino IDE on $OS_NAME ..."
|
||||||
|
echo "Downloading '$ARDUINO_IDE_URL$OS_NAME.$ARCHIVE_FORMAT' to 'arduino.$ARCHIVE_FORMAT' ..."
|
||||||
|
if [ "$OS_IS_LINUX" == "1" ]; then
|
||||||
|
wget -O "arduino.$ARCHIVE_FORMAT" "$ARDUINO_IDE_URL$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1
|
||||||
|
echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..."
|
||||||
|
tar xf "arduino.$ARCHIVE_FORMAT" > /dev/null
|
||||||
|
mv arduino-nightly "$ARDUINO_IDE_PATH"
|
||||||
|
else
|
||||||
|
curl -o "arduino.$ARCHIVE_FORMAT" -L "$ARDUINO_IDE_URL$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1
|
||||||
|
echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..."
|
||||||
|
unzip "arduino.$ARCHIVE_FORMAT" > /dev/null
|
||||||
|
if [ "$OS_IS_MACOS" == "1" ]; then
|
||||||
|
mv "Arduino.app" "/Applications/Arduino.app"
|
||||||
|
else
|
||||||
|
mv arduino-nightly "$ARDUINO_IDE_PATH"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
rm -rf "arduino.$ARCHIVE_FORMAT"
|
||||||
|
|
||||||
|
mkdir -p "$ARDUINO_USR_PATH/libraries"
|
||||||
|
mkdir -p "$ARDUINO_USR_PATH/hardware"
|
||||||
|
|
||||||
|
echo "Arduino IDE Installed in '$ARDUINO_IDE_PATH'"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
function build_sketch(){ # build_sketch <fqbn> <path-to-ino> [extra-options]
|
||||||
|
if [ "$#" -lt 2 ]; then
|
||||||
|
echo "ERROR: Illegal number of parameters"
|
||||||
|
echo "USAGE: build_sketch <fqbn> <path-to-ino> [extra-options]"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local fqbn="$1"
|
||||||
|
local sketch="$2"
|
||||||
|
local xtra_opts="$3"
|
||||||
|
local win_opts=""
|
||||||
|
if [ "$OS_IS_WINDOWS" == "1" ]; then
|
||||||
|
local ctags_version=`ls "$ARDUINO_IDE_PATH/tools-builder/ctags/"`
|
||||||
|
local preprocessor_version=`ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/"`
|
||||||
|
win_opts="-prefs=runtime.tools.ctags.path=$ARDUINO_IDE_PATH/tools-builder/ctags/$ctags_version -prefs=runtime.tools.arduino-preprocessor.path=$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/$preprocessor_version"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Compiling '"$(basename "$sketch")"' ..."
|
||||||
|
mkdir -p "$ARDUINO_BUILD_DIR"
|
||||||
|
mkdir -p "$ARDUINO_CACHE_DIR"
|
||||||
|
$ARDUINO_IDE_PATH/arduino-builder -compile -logger=human -core-api-version=10810 \
|
||||||
|
-fqbn=$fqbn \
|
||||||
|
-warnings="all" \
|
||||||
|
-tools "$ARDUINO_IDE_PATH/tools-builder" \
|
||||||
|
-tools "$ARDUINO_IDE_PATH/tools" \
|
||||||
|
-built-in-libraries "$ARDUINO_IDE_PATH/libraries" \
|
||||||
|
-hardware "$ARDUINO_IDE_PATH/hardware" \
|
||||||
|
-hardware "$ARDUINO_USR_PATH/hardware" \
|
||||||
|
-libraries "$ARDUINO_USR_PATH/libraries" \
|
||||||
|
-build-cache "$ARDUINO_CACHE_DIR" \
|
||||||
|
-build-path "$ARDUINO_BUILD_DIR" \
|
||||||
|
$win_opts $xtra_opts "$sketch"
|
||||||
|
}
|
||||||
|
|
||||||
|
function count_sketches() # count_sketches <examples-path> <target-mcu>
|
||||||
|
{
|
||||||
|
local examples="$1"
|
||||||
|
local target="$2"
|
||||||
|
rm -rf sketches.txt
|
||||||
|
if [ ! -d "$examples" ]; then
|
||||||
|
touch sketches.txt
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
local sketches=$(find $examples -name *.ino)
|
||||||
|
local sketchnum=0
|
||||||
|
for sketch in $sketches; do
|
||||||
|
local sketchdir=$(dirname $sketch)
|
||||||
|
local sketchdirname=$(basename $sketchdir)
|
||||||
|
local sketchname=$(basename $sketch)
|
||||||
|
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
|
||||||
|
continue
|
||||||
|
fi;
|
||||||
|
if [[ -f "$sketchdir/.skip.$target" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo $sketch >> sketches.txt
|
||||||
|
sketchnum=$(($sketchnum + 1))
|
||||||
|
done
|
||||||
|
return $sketchnum
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_sketches() # build_sketches <fqbn> <target-mcu> <examples-path> <chunk> <total-chunks> [extra-options]
|
||||||
|
{
|
||||||
|
local fqbn=$1
|
||||||
|
local target="$2"
|
||||||
|
local examples=$3
|
||||||
|
local chunk_idex=$4
|
||||||
|
local chunks_num=$5
|
||||||
|
local xtra_opts=$6
|
||||||
|
|
||||||
|
if [ "$#" -lt 3 ]; then
|
||||||
|
echo "ERROR: Illegal number of parameters"
|
||||||
|
echo "USAGE: build_sketches <fqbn> <target-mcu <examples-path> [<chunk> <total-chunks>] [extra-options]"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$#" -lt 5 ]; then
|
||||||
|
chunk_idex="0"
|
||||||
|
chunks_num="1"
|
||||||
|
xtra_opts=$4
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$chunks_num" -le 0 ]; then
|
||||||
|
echo "ERROR: Chunks count must be positive number"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [ "$chunk_idex" -ge "$chunks_num" ]; then
|
||||||
|
echo "ERROR: Chunk index must be less than chunks count"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
count_sketches "$examples"
|
||||||
|
local sketchcount=$?
|
||||||
|
set -e
|
||||||
|
local sketches=$(cat sketches.txt)
|
||||||
|
rm -rf sketches.txt
|
||||||
|
|
||||||
|
local chunk_size=$(( $sketchcount / $chunks_num ))
|
||||||
|
local all_chunks=$(( $chunks_num * $chunk_size ))
|
||||||
|
if [ "$all_chunks" -lt "$sketchcount" ]; then
|
||||||
|
chunk_size=$(( $chunk_size + 1 ))
|
||||||
|
fi
|
||||||
|
|
||||||
|
local start_index=$(( $chunk_idex * $chunk_size ))
|
||||||
|
if [ "$sketchcount" -le "$start_index" ]; then
|
||||||
|
echo "Skipping job"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
|
||||||
|
if [ "$end_index" -gt "$sketchcount" ]; then
|
||||||
|
end_index=$sketchcount
|
||||||
|
fi
|
||||||
|
|
||||||
|
local start_num=$(( $start_index + 1 ))
|
||||||
|
echo "Found $sketchcount Sketches";
|
||||||
|
echo "Chunk Count : $chunks_num"
|
||||||
|
echo "Chunk Size : $chunk_size"
|
||||||
|
echo "Start Sketch: $start_num"
|
||||||
|
echo "End Sketch : $end_index"
|
||||||
|
|
||||||
|
local sketchnum=0
|
||||||
|
for sketch in $sketches; do
|
||||||
|
local sketchdir=$(dirname $sketch)
|
||||||
|
local sketchdirname=$(basename $sketchdir)
|
||||||
|
local sketchname=$(basename $sketch)
|
||||||
|
if [ "${sketchdirname}.ino" != "$sketchname" ] \
|
||||||
|
|| [ -f "$sketchdir/.skip.$target" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
sketchnum=$(($sketchnum + 1))
|
||||||
|
if [ "$sketchnum" -le "$start_index" ] \
|
||||||
|
|| [ "$sketchnum" -gt "$end_index" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
build_sketch "$fqbn" "$sketch" "$xtra_opts"
|
||||||
|
local result=$?
|
||||||
|
if [ $result -ne 0 ]; then
|
||||||
|
return $result
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
}
|
151
.github/scripts/install-platformio-esp32.sh
vendored
Executable file
151
.github/scripts/install-platformio-esp32.sh
vendored
Executable file
@ -0,0 +1,151 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export PLATFORMIO_ESP32_PATH="$HOME/.platformio/packages/framework-arduinoespressif32"
|
||||||
|
PLATFORMIO_ESP32_URL="https://github.com/platformio/platform-espressif32.git#feature/idf-v4.0"
|
||||||
|
|
||||||
|
echo "Installing Python Wheel ..."
|
||||||
|
pip install wheel > /dev/null 2>&1
|
||||||
|
|
||||||
|
echo "Installing PlatformIO ..."
|
||||||
|
pip install -U https://github.com/platformio/platformio/archive/develop.zip > /dev/null 2>&1
|
||||||
|
|
||||||
|
echo "Installing Platform ESP32 ..."
|
||||||
|
python -m platformio platform install $PLATFORMIO_ESP32_URL > /dev/null 2>&1
|
||||||
|
|
||||||
|
echo "Replacing the framework version ..."
|
||||||
|
python -c "import json; import os; fp=open(os.path.expanduser('~/.platformio/platforms/espressif32/platform.json'), 'r+'); data=json.load(fp); data['packages']['framework-arduinoespressif32']['version'] = '*'; del data['packages']['framework-arduinoespressif32']['owner']; fp.seek(0); fp.truncate(); json.dump(data, fp); fp.close()"
|
||||||
|
|
||||||
|
if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then
|
||||||
|
echo "Linking Core..."
|
||||||
|
ln -s $GITHUB_WORKSPACE "$PLATFORMIO_ESP32_PATH"
|
||||||
|
else
|
||||||
|
echo "Cloning Core Repository ..."
|
||||||
|
git clone --recursive https://github.com/espressif/arduino-esp32.git "$PLATFORMIO_ESP32_PATH" > /dev/null 2>&1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "PlatformIO for ESP32 has been installed"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
function build_pio_sketch(){ # build_pio_sketch <board> <options> <path-to-ino>
|
||||||
|
if [ "$#" -lt 3 ]; then
|
||||||
|
echo "ERROR: Illegal number of parameters"
|
||||||
|
echo "USAGE: build_pio_sketch <board> <options> <path-to-ino>"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local board="$1"
|
||||||
|
local options="$2"
|
||||||
|
local sketch="$3"
|
||||||
|
local sketch_dir=$(dirname "$sketch")
|
||||||
|
echo ""
|
||||||
|
echo "Compiling '"$(basename "$sketch")"' ..."
|
||||||
|
python -m platformio ci --board "$board" "$sketch_dir" --project-option="$options"
|
||||||
|
}
|
||||||
|
|
||||||
|
function count_sketches() # count_sketches <examples-path>
|
||||||
|
{
|
||||||
|
local examples="$1"
|
||||||
|
rm -rf sketches.txt
|
||||||
|
if [ ! -d "$examples" ]; then
|
||||||
|
touch sketches.txt
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
local sketches=$(find $examples -name *.ino)
|
||||||
|
local sketchnum=0
|
||||||
|
for sketch in $sketches; do
|
||||||
|
local sketchdir=$(dirname $sketch)
|
||||||
|
local sketchdirname=$(basename $sketchdir)
|
||||||
|
local sketchname=$(basename $sketch)
|
||||||
|
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
|
||||||
|
continue
|
||||||
|
fi;
|
||||||
|
if [[ -f "$sketchdir/.test.skip" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo $sketch >> sketches.txt
|
||||||
|
sketchnum=$(($sketchnum + 1))
|
||||||
|
done
|
||||||
|
return $sketchnum
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_pio_sketches() # build_pio_sketches <board> <options> <examples-path> <chunk> <total-chunks>
|
||||||
|
{
|
||||||
|
if [ "$#" -lt 3 ]; then
|
||||||
|
echo "ERROR: Illegal number of parameters"
|
||||||
|
echo "USAGE: build_pio_sketches <board> <options> <examples-path> [<chunk> <total-chunks>]"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local board=$1
|
||||||
|
local options="$2"
|
||||||
|
local examples=$3
|
||||||
|
local chunk_idex=$4
|
||||||
|
local chunks_num=$5
|
||||||
|
|
||||||
|
if [ "$#" -lt 5 ]; then
|
||||||
|
chunk_idex="0"
|
||||||
|
chunks_num="1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$chunks_num" -le 0 ]; then
|
||||||
|
echo "ERROR: Chunks count must be positive number"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [ "$chunk_idex" -ge "$chunks_num" ]; then
|
||||||
|
echo "ERROR: Chunk index must be less than chunks count"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
count_sketches "$examples"
|
||||||
|
local sketchcount=$?
|
||||||
|
set -e
|
||||||
|
local sketches=$(cat sketches.txt)
|
||||||
|
rm -rf sketches.txt
|
||||||
|
|
||||||
|
local chunk_size=$(( $sketchcount / $chunks_num ))
|
||||||
|
local all_chunks=$(( $chunks_num * $chunk_size ))
|
||||||
|
if [ "$all_chunks" -lt "$sketchcount" ]; then
|
||||||
|
chunk_size=$(( $chunk_size + 1 ))
|
||||||
|
fi
|
||||||
|
|
||||||
|
local start_index=$(( $chunk_idex * $chunk_size ))
|
||||||
|
if [ "$sketchcount" -le "$start_index" ]; then
|
||||||
|
echo "Skipping job"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
|
||||||
|
if [ "$end_index" -gt "$sketchcount" ]; then
|
||||||
|
end_index=$sketchcount
|
||||||
|
fi
|
||||||
|
|
||||||
|
local start_num=$(( $start_index + 1 ))
|
||||||
|
echo "Found $sketchcount Sketches";
|
||||||
|
echo "Chunk Count : $chunks_num"
|
||||||
|
echo "Chunk Size : $chunk_size"
|
||||||
|
echo "Start Sketch: $start_num"
|
||||||
|
echo "End Sketch : $end_index"
|
||||||
|
|
||||||
|
local sketchnum=0
|
||||||
|
for sketch in $sketches; do
|
||||||
|
local sketchdir=$(dirname $sketch)
|
||||||
|
local sketchdirname=$(basename $sketchdir)
|
||||||
|
local sketchname=$(basename $sketch)
|
||||||
|
if [ "${sketchdirname}.ino" != "$sketchname" ] \
|
||||||
|
|| [ -f "$sketchdir/.test.skip" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
sketchnum=$(($sketchnum + 1))
|
||||||
|
if [ "$sketchnum" -le "$start_index" ] \
|
||||||
|
|| [ "$sketchnum" -gt "$end_index" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
build_pio_sketch "$board" "$options" "$sketch"
|
||||||
|
local result=$?
|
||||||
|
if [ $result -ne 0 ]; then
|
||||||
|
return $result
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
}
|
6
package/merge_packages.py → .github/scripts/merge_packages.py
vendored
Normal file → Executable file
6
package/merge_packages.py → .github/scripts/merge_packages.py
vendored
Normal file → Executable file
@ -36,7 +36,11 @@ def pkgVersionNormalized(versionString):
|
|||||||
verParts = re.split('\.|-rc', verStr, flags=re.IGNORECASE)
|
verParts = re.split('\.|-rc', verStr, flags=re.IGNORECASE)
|
||||||
|
|
||||||
if len(verParts) == 3:
|
if len(verParts) == 3:
|
||||||
verStr = str(versionString) + '-rc' + str(sys.maxint)
|
if (sys.version_info > (3, 0)): # Python 3
|
||||||
|
verStr = str(versionString) + '-rc' + str(sys.maxsize)
|
||||||
|
else: # Python 2
|
||||||
|
verStr = str(versionString) + '-rc' + str(sys.maxint)
|
||||||
|
|
||||||
elif len(verParts) != 4:
|
elif len(verParts) != 4:
|
||||||
print("pkgVersionNormalized WARNING: unexpected version format: {0})".format(verStr), file=sys.stderr)
|
print("pkgVersionNormalized WARNING: unexpected version format: {0})".format(verStr), file=sys.stderr)
|
||||||
|
|
131
.github/scripts/on-pages.sh
vendored
Normal file
131
.github/scripts/on-pages.sh
vendored
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
function get_file_size(){
|
||||||
|
local file="$1"
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
eval `stat -s "$file"`
|
||||||
|
local res="$?"
|
||||||
|
echo "$st_size"
|
||||||
|
return $res
|
||||||
|
else
|
||||||
|
stat --printf="%s" "$file"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#git_remove_from_pages <file>
|
||||||
|
function git_remove_from_pages(){
|
||||||
|
local path=$1
|
||||||
|
local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
|
||||||
|
local type=`echo "$info" | jq -r '.type'`
|
||||||
|
if [ ! $type == "file" ]; then
|
||||||
|
if [ ! $type == "null" ]; then
|
||||||
|
echo "Wrong type '$type'"
|
||||||
|
else
|
||||||
|
echo "File is not on Pages"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
local sha=`echo "$info" | jq -r '.sha'`
|
||||||
|
local message="Deleting "$(basename $path)
|
||||||
|
local json="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"sha\":\"$sha\"}"
|
||||||
|
echo "$json" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X DELETE --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
|
||||||
|
}
|
||||||
|
|
||||||
|
function git_upload_to_pages(){
|
||||||
|
local path=$1
|
||||||
|
local src=$2
|
||||||
|
|
||||||
|
if [ ! -f "$src" ]; then
|
||||||
|
>&2 echo "Input is not a file! Aborting..."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
|
||||||
|
local type=`echo "$info" | jq -r '.type'`
|
||||||
|
local message=$(basename $path)
|
||||||
|
local sha=""
|
||||||
|
local content=""
|
||||||
|
|
||||||
|
if [ $type == "file" ]; then
|
||||||
|
sha=`echo "$info" | jq -r '.sha'`
|
||||||
|
sha=",\"sha\":\"$sha\""
|
||||||
|
message="Updating $message"
|
||||||
|
elif [ ! $type == "null" ]; then
|
||||||
|
>&2 echo "Wrong type '$type'"
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
message="Creating $message"
|
||||||
|
fi
|
||||||
|
|
||||||
|
content=`base64 -i "$src"`
|
||||||
|
data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}"
|
||||||
|
|
||||||
|
echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
|
||||||
|
}
|
||||||
|
|
||||||
|
function git_safe_upload_to_pages(){
|
||||||
|
local path=$1
|
||||||
|
local file="$2"
|
||||||
|
local name=$(basename "$file")
|
||||||
|
local size=`get_file_size "$file"`
|
||||||
|
local upload_res=`git_upload_to_pages "$path" "$file"`
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
>&2 echo "ERROR: Failed to upload '$name' ($?)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
up_size=`echo "$upload_res" | jq -r '.content.size'`
|
||||||
|
if [ $up_size -ne $size ]; then
|
||||||
|
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
|
||||||
|
#git_delete_asset
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo "$upload_res" | jq -r '.content.download_url'
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
EVENT_JSON=`cat $GITHUB_EVENT_PATH`
|
||||||
|
|
||||||
|
pages_added=`echo "$EVENT_JSON" | jq -r '.commits[].added[]'`
|
||||||
|
pages_modified=`echo "$EVENT_JSON" | jq -r '.commits[].modified[]'`
|
||||||
|
pages_removed=`echo "$EVENT_JSON" | jq -r '.commits[].removed[]'`
|
||||||
|
|
||||||
|
for page in $pages_added; do
|
||||||
|
if [[ $page != "README.md" && $page != "docs/"* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo "Adding '$page' to pages ..."
|
||||||
|
if [[ $page == "README.md" ]]; then
|
||||||
|
git_safe_upload_to_pages "index.md" "README.md"
|
||||||
|
else
|
||||||
|
git_safe_upload_to_pages "$page" "$page"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for page in $pages_modified; do
|
||||||
|
if [[ $page != "README.md" && $page != "docs/"* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo "Modifying '$page' ..."
|
||||||
|
if [[ $page == "README.md" ]]; then
|
||||||
|
git_safe_upload_to_pages "index.md" "README.md"
|
||||||
|
else
|
||||||
|
git_safe_upload_to_pages "$page" "$page"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for page in $pages_removed; do
|
||||||
|
if [[ $page != "README.md" && $page != "docs/"* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo "Removing '$page' from pages ..."
|
||||||
|
if [[ $page == "README.md" ]]; then
|
||||||
|
git_remove_from_pages "README.md" > /dev/null
|
||||||
|
else
|
||||||
|
git_remove_from_pages "$page" > /dev/null
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "DONE!"
|
91
.github/scripts/on-push.sh
vendored
Executable file
91
.github/scripts/on-push.sh
vendored
Executable file
@ -0,0 +1,91 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ ! -z "$TRAVIS_TAG" ]; then
|
||||||
|
echo "Skipping Test: Tagged build"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "$GITHUB_WORKSPACE" ]; then
|
||||||
|
export TRAVIS_BUILD_DIR="$GITHUB_WORKSPACE"
|
||||||
|
export TRAVIS_REPO_SLUG="$GITHUB_REPOSITORY"
|
||||||
|
elif [ ! -z "$TRAVIS_BUILD_DIR" ]; then
|
||||||
|
export GITHUB_WORKSPACE="$TRAVIS_BUILD_DIR"
|
||||||
|
export GITHUB_REPOSITORY="$TRAVIS_REPO_SLUG"
|
||||||
|
else
|
||||||
|
export GITHUB_WORKSPACE="$PWD"
|
||||||
|
export GITHUB_REPOSITORY="espressif/arduino-esp32"
|
||||||
|
fi
|
||||||
|
|
||||||
|
CHUNK_INDEX=$1
|
||||||
|
CHUNKS_CNT=$2
|
||||||
|
BUILD_PIO=0
|
||||||
|
if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then
|
||||||
|
CHUNK_INDEX=0
|
||||||
|
CHUNKS_CNT=1
|
||||||
|
elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ]; then
|
||||||
|
CHUNK_INDEX=$CHUNKS_CNT
|
||||||
|
elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then
|
||||||
|
BUILD_PIO=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#echo "Updating submodules ..."
|
||||||
|
#git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1
|
||||||
|
|
||||||
|
if [ "$BUILD_PIO" -eq 0 ]; then
|
||||||
|
# ArduinoIDE ESP32 Test
|
||||||
|
TARGET="esp32"
|
||||||
|
FQBN="espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app"
|
||||||
|
source ./.github/scripts/install-arduino-ide.sh
|
||||||
|
source ./.github/scripts/install-arduino-core-esp32.sh
|
||||||
|
if [ "$OS_IS_WINDOWS" == "1" ]; then
|
||||||
|
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \
|
||||||
|
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/BLE/examples/BLE_server/BLE_server.ino" && \
|
||||||
|
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.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" && \
|
||||||
|
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \
|
||||||
|
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/BLE/examples/BLE_server/BLE_server.ino" && \
|
||||||
|
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"
|
||||||
|
else
|
||||||
|
# CMake Test
|
||||||
|
if [ "$CHUNK_INDEX" -eq 0 ]; then
|
||||||
|
bash "$ARDUINO_ESP32_PATH/.github/scripts/check-cmakelists.sh"
|
||||||
|
fi
|
||||||
|
build_sketches "$FQBN" "$TARGET" "$ARDUINO_ESP32_PATH/libraries" "$CHUNK_INDEX" "$CHUNKS_CNT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ArduinoIDE ESP32S2 Test
|
||||||
|
TARGET="esp32s2"
|
||||||
|
FQBN="espressif:esp32:esp32s2:PSRAM=enabled,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
|
||||||
|
source ./.github/scripts/install-platformio-esp32.sh
|
||||||
|
# PlatformIO ESP32 Test
|
||||||
|
BOARD="esp32dev"
|
||||||
|
OPTIONS="board_build.partitions = huge_app.csv"
|
||||||
|
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
|
||||||
|
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \
|
||||||
|
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \
|
||||||
|
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BLE/examples/BLE_server/BLE_server.ino" && \
|
||||||
|
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"
|
||||||
|
|
||||||
|
# PlatformIO ESP32 Test
|
||||||
|
# OPTIONS="board_build.mcu = esp32s2"
|
||||||
|
# build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
|
||||||
|
# build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino"
|
||||||
|
|
||||||
|
python -m platformio ci --board "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient" --project-option="board_build.mcu = esp32s2" --project-option="board_build.partitions = huge_app.csv"
|
||||||
|
|
||||||
|
#build_pio_sketches "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries"
|
||||||
|
fi
|
380
.github/scripts/on-release.sh
vendored
Executable file
380
.github/scripts/on-release.sh
vendored
Executable file
@ -0,0 +1,380 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ ! $GITHUB_EVENT_NAME == "release" ]; then
|
||||||
|
echo "Wrong event '$GITHUB_EVENT_NAME'!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
EVENT_JSON=`cat $GITHUB_EVENT_PATH`
|
||||||
|
|
||||||
|
action=`echo $EVENT_JSON | jq -r '.action'`
|
||||||
|
if [ ! $action == "published" ]; then
|
||||||
|
echo "Wrong action '$action'. Exiting now..."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
draft=`echo $EVENT_JSON | jq -r '.release.draft'`
|
||||||
|
if [ $draft == "true" ]; then
|
||||||
|
echo "It's a draft release. Exiting now..."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
RELEASE_PRE=`echo $EVENT_JSON | jq -r '.release.prerelease'`
|
||||||
|
RELEASE_TAG=`echo $EVENT_JSON | jq -r '.release.tag_name'`
|
||||||
|
RELEASE_BRANCH=`echo $EVENT_JSON | jq -r '.release.target_commitish'`
|
||||||
|
RELEASE_ID=`echo $EVENT_JSON | jq -r '.release.id'`
|
||||||
|
RELEASE_BODY=`echo $EVENT_JSON | jq -r '.release.body'`
|
||||||
|
|
||||||
|
OUTPUT_DIR="$GITHUB_WORKSPACE/build"
|
||||||
|
PACKAGE_NAME="esp32-$RELEASE_TAG"
|
||||||
|
PACKAGE_JSON_MERGE="$GITHUB_WORKSPACE/.github/scripts/merge_packages.py"
|
||||||
|
PACKAGE_JSON_TEMPLATE="$GITHUB_WORKSPACE/package/package_esp32_index.template.json"
|
||||||
|
PACKAGE_JSON_DEV="package_esp32_dev_index.json"
|
||||||
|
PACKAGE_JSON_REL="package_esp32_index.json"
|
||||||
|
|
||||||
|
echo "Event: $GITHUB_EVENT_NAME, Repo: $GITHUB_REPOSITORY, Path: $GITHUB_WORKSPACE, Ref: $GITHUB_REF"
|
||||||
|
echo "Action: $action, Branch: $RELEASE_BRANCH, ID: $RELEASE_ID"
|
||||||
|
echo "Tag: $RELEASE_TAG, Draft: $draft, Pre-Release: $RELEASE_PRE"
|
||||||
|
|
||||||
|
function get_file_size(){
|
||||||
|
local file="$1"
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
eval `stat -s "$file"`
|
||||||
|
local res="$?"
|
||||||
|
echo "$st_size"
|
||||||
|
return $res
|
||||||
|
else
|
||||||
|
stat --printf="%s" "$file"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function git_upload_asset(){
|
||||||
|
local name=$(basename "$1")
|
||||||
|
# local mime=$(file -b --mime-type "$1")
|
||||||
|
curl -k -X POST -sH "Authorization: token $GITHUB_TOKEN" -H "Content-Type: application/octet-stream" --data-binary @"$1" "https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID/assets?name=$name"
|
||||||
|
}
|
||||||
|
|
||||||
|
function git_safe_upload_asset(){
|
||||||
|
local file="$1"
|
||||||
|
local name=$(basename "$file")
|
||||||
|
local size=`get_file_size "$file"`
|
||||||
|
local upload_res=`git_upload_asset "$file"`
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
>&2 echo "ERROR: Failed to upload '$name' ($?)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
up_size=`echo "$upload_res" | jq -r '.size'`
|
||||||
|
if [ $up_size -ne $size ]; then
|
||||||
|
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
|
||||||
|
#git_delete_asset
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo "$upload_res" | jq -r '.browser_download_url'
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
function git_upload_to_pages(){
|
||||||
|
local path=$1
|
||||||
|
local src=$2
|
||||||
|
|
||||||
|
if [ ! -f "$src" ]; then
|
||||||
|
>&2 echo "Input is not a file! Aborting..."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
|
||||||
|
local type=`echo "$info" | jq -r '.type'`
|
||||||
|
local message=$(basename $path)
|
||||||
|
local sha=""
|
||||||
|
local content=""
|
||||||
|
|
||||||
|
if [ $type == "file" ]; then
|
||||||
|
sha=`echo "$info" | jq -r '.sha'`
|
||||||
|
sha=",\"sha\":\"$sha\""
|
||||||
|
message="Updating $message"
|
||||||
|
elif [ ! $type == "null" ]; then
|
||||||
|
>&2 echo "Wrong type '$type'"
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
message="Creating $message"
|
||||||
|
fi
|
||||||
|
|
||||||
|
content=`base64 -i "$src"`
|
||||||
|
data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}"
|
||||||
|
|
||||||
|
echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
|
||||||
|
}
|
||||||
|
|
||||||
|
function git_safe_upload_to_pages(){
|
||||||
|
local path=$1
|
||||||
|
local file="$2"
|
||||||
|
local name=$(basename "$file")
|
||||||
|
local size=`get_file_size "$file"`
|
||||||
|
local upload_res=`git_upload_to_pages "$path" "$file"`
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
>&2 echo "ERROR: Failed to upload '$name' ($?)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
up_size=`echo "$upload_res" | jq -r '.content.size'`
|
||||||
|
if [ $up_size -ne $size ]; then
|
||||||
|
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
|
||||||
|
#git_delete_asset
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo "$upload_res" | jq -r '.content.download_url'
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
function merge_package_json(){
|
||||||
|
local jsonLink=$1
|
||||||
|
local jsonOut=$2
|
||||||
|
local old_json=$OUTPUT_DIR/oldJson.json
|
||||||
|
local merged_json=$OUTPUT_DIR/mergedJson.json
|
||||||
|
|
||||||
|
echo "Downloading previous JSON $jsonLink ..."
|
||||||
|
curl -L -o "$old_json" "https://github.com/$GITHUB_REPOSITORY/releases/download/$jsonLink?access_token=$GITHUB_TOKEN" 2>/dev/null
|
||||||
|
if [ $? -ne 0 ]; then echo "ERROR: Download Failed! $?"; exit 1; fi
|
||||||
|
|
||||||
|
echo "Creating new JSON ..."
|
||||||
|
set +e
|
||||||
|
stdbuf -oL python "$PACKAGE_JSON_MERGE" "$jsonOut" "$old_json" > "$merged_json"
|
||||||
|
set -e
|
||||||
|
|
||||||
|
set -v
|
||||||
|
if [ ! -s $merged_json ]; then
|
||||||
|
rm -f "$merged_json"
|
||||||
|
echo "Nothing to merge"
|
||||||
|
else
|
||||||
|
rm -f "$jsonOut"
|
||||||
|
mv "$merged_json" "$jsonOut"
|
||||||
|
echo "JSON data successfully merged"
|
||||||
|
fi
|
||||||
|
rm -f "$old_json"
|
||||||
|
set +v
|
||||||
|
}
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
##
|
||||||
|
## PACKAGE ZIP
|
||||||
|
##
|
||||||
|
|
||||||
|
mkdir -p "$OUTPUT_DIR"
|
||||||
|
PKG_DIR="$OUTPUT_DIR/$PACKAGE_NAME"
|
||||||
|
PACKAGE_ZIP="$PACKAGE_NAME.zip"
|
||||||
|
|
||||||
|
echo "Updating submodules ..."
|
||||||
|
git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1
|
||||||
|
|
||||||
|
mkdir -p "$PKG_DIR/tools"
|
||||||
|
|
||||||
|
# Copy all core files to the package folder
|
||||||
|
echo "Copying files for packaging ..."
|
||||||
|
cp -f "$GITHUB_WORKSPACE/boards.txt" "$PKG_DIR/"
|
||||||
|
cp -f "$GITHUB_WORKSPACE/programmers.txt" "$PKG_DIR/"
|
||||||
|
cp -Rf "$GITHUB_WORKSPACE/cores" "$PKG_DIR/"
|
||||||
|
cp -Rf "$GITHUB_WORKSPACE/libraries" "$PKG_DIR/"
|
||||||
|
cp -Rf "$GITHUB_WORKSPACE/variants" "$PKG_DIR/"
|
||||||
|
cp -f "$GITHUB_WORKSPACE/tools/espota.exe" "$PKG_DIR/tools/"
|
||||||
|
cp -f "$GITHUB_WORKSPACE/tools/espota.py" "$PKG_DIR/tools/"
|
||||||
|
cp -f "$GITHUB_WORKSPACE/tools/esptool.py" "$PKG_DIR/tools/"
|
||||||
|
cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.py" "$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/sdk" "$PKG_DIR/tools/"
|
||||||
|
|
||||||
|
# Remove unnecessary files in the package folder
|
||||||
|
echo "Cleaning up folders ..."
|
||||||
|
find "$PKG_DIR" -name '*.DS_Store' -exec rm -f {} \;
|
||||||
|
find "$PKG_DIR" -name '*.git*' -type f -delete
|
||||||
|
|
||||||
|
# Replace tools locations in platform.txt
|
||||||
|
echo "Generating platform.txt..."
|
||||||
|
cat "$GITHUB_WORKSPACE/platform.txt" | \
|
||||||
|
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/tools.esptool_py.path={runtime.platform.path}\/tools\/esptool/tools.esptool_py.path=\{runtime.tools.esptool_py.path\}/g' \
|
||||||
|
> "$PKG_DIR/platform.txt"
|
||||||
|
|
||||||
|
# Add header with version information
|
||||||
|
echo "Generating core_version.h ..."
|
||||||
|
ver_define=`echo $RELEASE_TAG | tr "[:lower:].\055" "[:upper:]_"`
|
||||||
|
ver_hex=`git -C "$GITHUB_WORKSPACE" rev-parse --short=8 HEAD 2>/dev/null`
|
||||||
|
echo \#define ARDUINO_ESP32_GIT_VER 0x$ver_hex > "$PKG_DIR/cores/esp32/core_version.h"
|
||||||
|
echo \#define ARDUINO_ESP32_GIT_DESC `git -C "$GITHUB_WORKSPACE" describe --tags 2>/dev/null` >> "$PKG_DIR/cores/esp32/core_version.h"
|
||||||
|
echo \#define ARDUINO_ESP32_RELEASE_$ver_define >> "$PKG_DIR/cores/esp32/core_version.h"
|
||||||
|
echo \#define ARDUINO_ESP32_RELEASE \"$ver_define\" >> "$PKG_DIR/cores/esp32/core_version.h"
|
||||||
|
|
||||||
|
# Compress package folder
|
||||||
|
echo "Creating ZIP ..."
|
||||||
|
pushd "$OUTPUT_DIR" >/dev/null
|
||||||
|
zip -qr "$PACKAGE_ZIP" "$PACKAGE_NAME"
|
||||||
|
if [ $? -ne 0 ]; then echo "ERROR: Failed to create $PACKAGE_ZIP ($?)"; exit 1; fi
|
||||||
|
|
||||||
|
# Calculate SHA-256
|
||||||
|
echo "Calculating SHA sum ..."
|
||||||
|
PACKAGE_PATH="$OUTPUT_DIR/$PACKAGE_ZIP"
|
||||||
|
PACKAGE_SHA=`shasum -a 256 "$PACKAGE_ZIP" | cut -f 1 -d ' '`
|
||||||
|
PACKAGE_SIZE=`get_file_size "$PACKAGE_ZIP"`
|
||||||
|
popd >/dev/null
|
||||||
|
rm -rf "$PKG_DIR"
|
||||||
|
echo "'$PACKAGE_ZIP' Created! Size: $PACKAGE_SIZE, SHA-256: $PACKAGE_SHA"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Upload package to release page
|
||||||
|
echo "Uploading package to release page ..."
|
||||||
|
PACKAGE_URL=`git_safe_upload_asset "$PACKAGE_PATH"`
|
||||||
|
echo "Package Uploaded"
|
||||||
|
echo "Download URL: $PACKAGE_URL"
|
||||||
|
echo
|
||||||
|
|
||||||
|
##
|
||||||
|
## PACKAGE JSON
|
||||||
|
##
|
||||||
|
|
||||||
|
# Construct JQ argument with package data
|
||||||
|
jq_arg=".packages[0].platforms[0].version = \"$RELEASE_TAG\" | \
|
||||||
|
.packages[0].platforms[0].url = \"$PACKAGE_URL\" |\
|
||||||
|
.packages[0].platforms[0].archiveFileName = \"$PACKAGE_ZIP\" |\
|
||||||
|
.packages[0].platforms[0].size = \"$PACKAGE_SIZE\" |\
|
||||||
|
.packages[0].platforms[0].checksum = \"SHA-256:$PACKAGE_SHA\""
|
||||||
|
|
||||||
|
# Generate package JSONs
|
||||||
|
echo "Genarating $PACKAGE_JSON_DEV ..."
|
||||||
|
cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_DEV"
|
||||||
|
if [ "$RELEASE_PRE" == "false" ]; then
|
||||||
|
echo "Genarating $PACKAGE_JSON_REL ..."
|
||||||
|
cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_REL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Figure out the last release or pre-release
|
||||||
|
echo "Getting previous releases ..."
|
||||||
|
releasesJson=`curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases" 2>/dev/null`
|
||||||
|
if [ $? -ne 0 ]; then echo "ERROR: Get Releases Failed! ($?)"; exit 1; fi
|
||||||
|
|
||||||
|
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_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name')
|
||||||
|
shopt -s nocasematch
|
||||||
|
if [ "$prev_any_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_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name')
|
||||||
|
fi
|
||||||
|
COMMITS_SINCE_RELEASE="$prev_any_release"
|
||||||
|
shopt -u nocasematch
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Merge package JSONs with previous releases
|
||||||
|
if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
|
||||||
|
echo "Merging with JSON from $prev_any_release ..."
|
||||||
|
merge_package_json "$prev_any_release/$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$RELEASE_PRE" == "false" ]; then
|
||||||
|
COMMITS_SINCE_RELEASE="$prev_release"
|
||||||
|
if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then
|
||||||
|
echo "Merging with JSON from $prev_release ..."
|
||||||
|
merge_package_json "$prev_release/$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Previous Release: $prev_release"
|
||||||
|
echo "Previous (any)release: $prev_any_release"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Upload package JSONs
|
||||||
|
echo "Uploading $PACKAGE_JSON_DEV ..."
|
||||||
|
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
|
||||||
|
echo "Pages URL: "`git_safe_upload_to_pages "$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
|
||||||
|
echo
|
||||||
|
if [ "$RELEASE_PRE" == "false" ]; then
|
||||||
|
echo "Uploading $PACKAGE_JSON_REL ..."
|
||||||
|
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_REL"`
|
||||||
|
echo "Pages URL: "`git_safe_upload_to_pages "$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"`
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
##
|
||||||
|
## RELEASE NOTES
|
||||||
|
##
|
||||||
|
|
||||||
|
# Create release notes
|
||||||
|
echo "Preparing release notes ..."
|
||||||
|
releaseNotes=""
|
||||||
|
|
||||||
|
# Process annotated tags
|
||||||
|
relNotesRaw=`git -C "$GITHUB_WORKSPACE" show -s --format=%b $RELEASE_TAG`
|
||||||
|
readarray -t msgArray <<<"$relNotesRaw"
|
||||||
|
arrLen=${#msgArray[@]}
|
||||||
|
if [ $arrLen > 3 ] && [ "${msgArray[0]:0:3}" == "tag" ]; then
|
||||||
|
ind=3
|
||||||
|
while [ $ind -lt $arrLen ]; do
|
||||||
|
if [ $ind -eq 3 ]; then
|
||||||
|
releaseNotes="#### ${msgArray[ind]}"
|
||||||
|
releaseNotes+=$'\r\n'
|
||||||
|
else
|
||||||
|
oneLine="$(echo -e "${msgArray[ind]}" | sed -e 's/^[[:space:]]*//')"
|
||||||
|
if [ ${#oneLine} -gt 0 ]; then
|
||||||
|
if [ "${oneLine:0:2}" == "* " ]; then oneLine=$(echo ${oneLine/\*/-}); fi
|
||||||
|
if [ "${oneLine:0:2}" != "- " ]; then releaseNotes+="- "; fi
|
||||||
|
releaseNotes+="$oneLine"
|
||||||
|
releaseNotes+=$'\r\n'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
let ind=$ind+1
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Append Commit Messages
|
||||||
|
if [ ! -z "$COMMITS_SINCE_RELEASE" ] && [ "$COMMITS_SINCE_RELEASE" != "null" ]; then
|
||||||
|
echo "Getting commits since $COMMITS_SINCE_RELEASE ..."
|
||||||
|
commitFile=$OUTPUT_DIR/commits.txt
|
||||||
|
git -C "$GITHUB_WORKSPACE" log --oneline $COMMITS_SINCE_RELEASE.. > "$OUTPUT_DIR/commits.txt"
|
||||||
|
releaseNotes+=$'\r\n##### Commits\r\n'
|
||||||
|
IFS=$'\n'
|
||||||
|
for next in `cat $commitFile`
|
||||||
|
do
|
||||||
|
IFS=' ' read -r commitId commitMsg <<< "$next"
|
||||||
|
commitLine="- [$commitId](https://github.com/$GITHUB_REPOSITORY/commit/$commitId) $commitMsg"
|
||||||
|
releaseNotes+="$commitLine"
|
||||||
|
releaseNotes+=$'\r\n'
|
||||||
|
done
|
||||||
|
rm -f $commitFile
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prepend the original release body
|
||||||
|
if [ "${RELEASE_BODY: -1}" == $'\r' ]; then
|
||||||
|
RELEASE_BODY="${RELEASE_BODY:0:-1}"
|
||||||
|
else
|
||||||
|
RELEASE_BODY="$RELEASE_BODY"
|
||||||
|
fi
|
||||||
|
RELEASE_BODY+=$'\r\n'
|
||||||
|
releaseNotes="$RELEASE_BODY$releaseNotes"
|
||||||
|
|
||||||
|
# Update release page
|
||||||
|
echo "Updating release notes ..."
|
||||||
|
releaseNotes=$(printf '%s' "$releaseNotes" | python -c 'import json,sys; print(json.dumps(sys.stdin.read()))')
|
||||||
|
releaseNotes=${releaseNotes:1:-1}
|
||||||
|
curlData="{\"body\": \"$releaseNotes\"}"
|
||||||
|
releaseData=`curl --data "$curlData" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID?access_token=$GITHUB_TOKEN" 2>/dev/null`
|
||||||
|
if [ $? -ne 0 ]; then echo "ERROR: Updating Release Failed: $?"; exit 1; fi
|
||||||
|
echo "Release notes successfully updated"
|
||||||
|
echo
|
||||||
|
|
||||||
|
##
|
||||||
|
## SUBMODULE VERSIONS
|
||||||
|
##
|
||||||
|
|
||||||
|
# Upload submodules versions
|
||||||
|
echo "Generating submodules.txt ..."
|
||||||
|
git -C "$GITHUB_WORKSPACE" submodule status > "$OUTPUT_DIR/submodules.txt"
|
||||||
|
echo "Uploading submodules.txt ..."
|
||||||
|
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/submodules.txt"`
|
||||||
|
echo ""
|
||||||
|
set +e
|
||||||
|
|
||||||
|
##
|
||||||
|
## DONE
|
||||||
|
##
|
||||||
|
echo "DONE!"
|
64
.github/stale.yml
vendored
Normal file
64
.github/stale.yml
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
# Configuration for probot-stale - https://github.com/probot/stale
|
||||||
|
|
||||||
|
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||||
|
daysUntilStale: 60
|
||||||
|
|
||||||
|
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
|
||||||
|
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||||
|
daysUntilClose: 14
|
||||||
|
|
||||||
|
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
|
||||||
|
onlyLabels: []
|
||||||
|
|
||||||
|
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||||
|
exemptLabels:
|
||||||
|
- pinned
|
||||||
|
- security
|
||||||
|
- "to be implemented"
|
||||||
|
- "for reference"
|
||||||
|
- "move to PR"
|
||||||
|
- "enhancement"
|
||||||
|
|
||||||
|
# Set to true to ignore issues in a project (defaults to false)
|
||||||
|
exemptProjects: false
|
||||||
|
|
||||||
|
# Set to true to ignore issues in a milestone (defaults to false)
|
||||||
|
exemptMilestones: false
|
||||||
|
|
||||||
|
# Set to true to ignore issues with an assignee (defaults to false)
|
||||||
|
exemptAssignees: false
|
||||||
|
|
||||||
|
# Label to use when marking as stale
|
||||||
|
staleLabel: stale
|
||||||
|
|
||||||
|
# Comment to post when marking as stale. Set to `false` to disable
|
||||||
|
markComment: >
|
||||||
|
[STALE_SET] This issue has been automatically marked as stale because it has not had
|
||||||
|
recent activity. It will be closed in 14 days if no further activity occurs. Thank you
|
||||||
|
for your contributions.
|
||||||
|
|
||||||
|
# Comment to post when removing the stale label.
|
||||||
|
unmarkComment: >
|
||||||
|
[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.
|
||||||
|
|
||||||
|
# Comment to post when closing a stale Issue or Pull Request.
|
||||||
|
closeComment: >
|
||||||
|
[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.
|
||||||
|
|
||||||
|
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||||
|
limitPerRun: 30
|
||||||
|
|
||||||
|
# Limit to only `issues` or `pulls`
|
||||||
|
only: issues
|
||||||
|
|
||||||
|
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||||
|
# pulls:
|
||||||
|
# daysUntilStale: 30
|
||||||
|
# markComment: >
|
||||||
|
# This pull request has been automatically marked as stale because it has not had
|
||||||
|
# recent activity. It will be closed if no further activity occurs. Thank you
|
||||||
|
# for your contributions.
|
||||||
|
|
||||||
|
# issues:
|
||||||
|
# exemptLabels:
|
||||||
|
# - confirmed
|
21
.github/workflows/gh-pages.yml
vendored
Normal file
21
.github/workflows/gh-pages.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
name: GitHub Pages CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths:
|
||||||
|
- 'README.md'
|
||||||
|
- 'docs/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
build-pages:
|
||||||
|
name: Build GitHub Pages
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Copy Files
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: bash ./.github/scripts/on-pages.sh
|
58
.github/workflows/push.yml
vendored
Normal file
58
.github/workflows/push.yml
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
name: ESP32 Arduino CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- release/*
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
# Ubuntu
|
||||||
|
build-arduino-linux:
|
||||||
|
name: Arduino ${{ matrix.chunk }} on ubuntu-latest
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
chunk: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- uses: actions/setup-python@v1
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
- name: Build Sketches
|
||||||
|
run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} 15
|
||||||
|
|
||||||
|
# Windows and MacOS
|
||||||
|
build-arduino-win-mac:
|
||||||
|
name: Arduino on ${{ matrix.os }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [windows-latest, macOS-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- uses: actions/setup-python@v1
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
- name: Build Sketches
|
||||||
|
run: bash ./.github/scripts/on-push.sh
|
||||||
|
|
||||||
|
# PlatformIO on Windows, Ubuntu and Mac
|
||||||
|
build-platformio:
|
||||||
|
name: PlatformIO on ${{ matrix.os }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- uses: actions/setup-python@v1
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
- name: Build Sketches
|
||||||
|
run: bash ./.github/scripts/on-push.sh 1 1 #equal and non-zero to trigger PIO
|
20
.github/workflows/release.yml
vendored
Normal file
20
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
name: ESP32 Arduino Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: published
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Publish Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
- uses: actions/setup-python@v1
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
- name: Build Release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: bash ./.github/scripts/on-release.sh
|
11
.gitignore
vendored
11
.gitignore
vendored
@ -1,7 +1,18 @@
|
|||||||
tools/xtensa-esp32-elf
|
tools/xtensa-esp32-elf
|
||||||
|
tools/xtensa-esp32s2-elf
|
||||||
tools/dist
|
tools/dist
|
||||||
tools/esptool
|
tools/esptool
|
||||||
tools/esptool.exe
|
tools/esptool.exe
|
||||||
tools/mkspiffs/mkspiffs
|
tools/mkspiffs/mkspiffs
|
||||||
tools/mkspiffs/mkspiffs.exe
|
tools/mkspiffs/mkspiffs.exe
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
#Ignore files built by Visual Studio/Visual Micro
|
||||||
|
[Dd]ebug*/
|
||||||
|
[Rr]elease*/
|
||||||
|
.vs/
|
||||||
|
__vm/
|
||||||
|
*.vcxproj*
|
||||||
|
.vscode/
|
||||||
|
platform.sloeber.txt
|
||||||
|
boards.sloeber.txt
|
||||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "libraries/AzureIoT"]
|
|
||||||
path = libraries/AzureIoT
|
|
||||||
url = https://github.com/VSChina/ESP32_AzureIoT_Arduino
|
|
||||||
|
46
.travis.yml
46
.travis.yml
@ -1,8 +1,6 @@
|
|||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
language: python
|
language: python
|
||||||
python:
|
|
||||||
- "2.7"
|
|
||||||
|
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
@ -10,22 +8,40 @@ os:
|
|||||||
git:
|
git:
|
||||||
depth: false
|
depth: false
|
||||||
|
|
||||||
env:
|
before_install:
|
||||||
global:
|
- git submodule update --init --recursive
|
||||||
- secure: "l/4Dt+KQ/mACtGAHDUsPr66fUte840PZoQ4xpPikqWZI0uARu4l+Ym7+sHinnT6fBqrj8AJeBYGz4nFa8NK4LutZn9mSD40w+sxl0wSV4oHV8rzKe3Cd8+sMG3+o33yWoikMNjSvqa73Q0rm+SgrlInNdZbuAyixL+a2alaWSnGPm4F2xwUGj+S33TOy5P/Xp77CYtCV5S8vzyk/eEdNhoF0GYePJVdfuzCOUjXMyT5OWxORkzzQ7Hnn/Ka/RDfV8Si4HgujLQBrK5q6iPnNBFqBSqilYBepSMn4opnOBpIm0SCgePz7XQEFC83buA7GUcnCnfg38bf+dCwHaODf1d1PmqVRYt2QmfinexXtM4afAtL0iBUDtvrfnXHzwW9w82VeZhpbJSVh9DUQvB0IlsZeCz9J9PUBAi3N+SMX+9l+BomYwRUlPuKY+Ef2JKk9q6mxtUkky5R0daAlVxEhpVdQks1rT+T+NMoDMemxQ3SKEiqAHh6EgHecruszffmZ71uLX9MpERpew0qN+UFiafws+jkTjx+3yF9yut0Hf9sMbeAYzzkGzRqJTUEBJ6B29Cql8M0yRXCNN/8wuuTHhG8esstozga4ZQoIVrq7mEAgup376PTcNfr1+imbbWVQ7lJdYIuDe6OS5V3OX6np11vgK/DbhfyzvQv9Z1zAGnM="
|
|
||||||
- REMOTE_URL=https://github.com/$TRAVIS_REPO_SLUG/releases/download/$TRAVIS_TAG
|
|
||||||
|
|
||||||
script:
|
|
||||||
- bash $TRAVIS_BUILD_DIR/tools/build.sh
|
|
||||||
|
|
||||||
deploy:
|
stages:
|
||||||
provider: script
|
- build
|
||||||
skip_cleanup: true
|
- deploy
|
||||||
script: bash $TRAVIS_BUILD_DIR/tools/deploy.sh -t$TRAVIS_TAG -a$ESP32_GITHUB_TOKEN -s$TRAVIS_REPO_SLUG -drelease
|
|
||||||
|
|
||||||
on:
|
jobs:
|
||||||
tags: true
|
include:
|
||||||
|
|
||||||
|
- name: "Build Arduino 0"
|
||||||
|
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
|
||||||
|
stage: build
|
||||||
|
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 0 10
|
||||||
|
|
||||||
|
- name: "Build Arduino 1"
|
||||||
|
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
|
||||||
|
stage: build
|
||||||
|
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 10
|
||||||
|
|
||||||
|
- name: "Build Arduino 2"
|
||||||
|
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
|
||||||
|
stage: build
|
||||||
|
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 2 10
|
||||||
|
|
||||||
|
- name: "Build Arduino 3"
|
||||||
|
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
|
||||||
|
stage: build
|
||||||
|
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 3 10
|
||||||
|
|
||||||
|
- name: "Build PlatformIO"
|
||||||
|
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
|
||||||
|
stage: build
|
||||||
|
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 1
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email:
|
email:
|
||||||
|
@ -15,6 +15,7 @@ set(CORE_SRCS
|
|||||||
cores/esp32/esp32-hal-spi.c
|
cores/esp32/esp32-hal-spi.c
|
||||||
cores/esp32/esp32-hal-time.c
|
cores/esp32/esp32-hal-time.c
|
||||||
cores/esp32/esp32-hal-timer.c
|
cores/esp32/esp32-hal-timer.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-uart.c
|
||||||
cores/esp32/esp32-hal-rmt.c
|
cores/esp32/esp32-hal-rmt.c
|
||||||
@ -31,6 +32,8 @@ set(CORE_SRCS
|
|||||||
cores/esp32/stdlib_noniso.c
|
cores/esp32/stdlib_noniso.c
|
||||||
cores/esp32/Stream.cpp
|
cores/esp32/Stream.cpp
|
||||||
cores/esp32/StreamString.cpp
|
cores/esp32/StreamString.cpp
|
||||||
|
cores/esp32/USB.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
|
||||||
@ -49,6 +52,7 @@ set(LIBRARY_SRCS
|
|||||||
libraries/FS/src/vfs_api.cpp
|
libraries/FS/src/vfs_api.cpp
|
||||||
libraries/HTTPClient/src/HTTPClient.cpp
|
libraries/HTTPClient/src/HTTPClient.cpp
|
||||||
libraries/HTTPUpdate/src/HTTPUpdate.cpp
|
libraries/HTTPUpdate/src/HTTPUpdate.cpp
|
||||||
|
libraries/LITTLEFS/src/LITTLEFS.cpp
|
||||||
libraries/NetBIOS/src/NetBIOS.cpp
|
libraries/NetBIOS/src/NetBIOS.cpp
|
||||||
libraries/Preferences/src/Preferences.cpp
|
libraries/Preferences/src/Preferences.cpp
|
||||||
libraries/SD_MMC/src/SD_MMC.cpp
|
libraries/SD_MMC/src/SD_MMC.cpp
|
||||||
@ -71,6 +75,7 @@ set(LIBRARY_SRCS
|
|||||||
libraries/WiFi/src/WiFi.cpp
|
libraries/WiFi/src/WiFi.cpp
|
||||||
libraries/WiFi/src/WiFiGeneric.cpp
|
libraries/WiFi/src/WiFiGeneric.cpp
|
||||||
libraries/WiFi/src/WiFiMulti.cpp
|
libraries/WiFi/src/WiFiMulti.cpp
|
||||||
|
libraries/WiFi/src/WiFiProv.cpp
|
||||||
libraries/WiFi/src/WiFiScan.cpp
|
libraries/WiFi/src/WiFiScan.cpp
|
||||||
libraries/WiFi/src/WiFiServer.cpp
|
libraries/WiFi/src/WiFiServer.cpp
|
||||||
libraries/WiFi/src/WiFiSTA.cpp
|
libraries/WiFi/src/WiFiSTA.cpp
|
||||||
@ -78,66 +83,6 @@ set(LIBRARY_SRCS
|
|||||||
libraries/Wire/src/Wire.cpp
|
libraries/Wire/src/Wire.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(AZURE_SRCS
|
|
||||||
libraries/AzureIoT/src/az_iot/azureiotcerts.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/pal/agenttime.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/pal/dns_async.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/pal/freertos/lock.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/pal/freertos/threadapi.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/pal/freertos/tickcounter.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/pal/lwip/sntp_lwip.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/pal/socket_async.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/pal/src/platform_openssl_compact.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/pal/src/tlsio_openssl_compact.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/pal/tlsio_options.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/base64.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/buffer.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/connection_string_parser.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/consolelogger.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/constbuffer.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/constmap.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/crt_abstractions.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/doublylinkedlist.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/gballoc.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/gb_stdio.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/gb_time.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/hmac.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/hmacsha256.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/httpapiex.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/httpapiexsas.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/httpheaders.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/http_proxy_io.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/map.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/optionhandler.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/sastoken.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/sha1.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/sha224.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/sha384-512.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/singlylinkedlist.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/strings.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/string_tokenizer.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/urlencode.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/usha.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/vector.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/xio.c
|
|
||||||
libraries/AzureIoT/src/az_iot/c-utility/src/xlogging.c
|
|
||||||
libraries/AzureIoT/src/az_iot/iothub_client/src/blob.c
|
|
||||||
libraries/AzureIoT/src/az_iot/iothub_client/src/iothub_client_authorization.c
|
|
||||||
libraries/AzureIoT/src/az_iot/iothub_client/src/iothub_client.c
|
|
||||||
libraries/AzureIoT/src/az_iot/iothub_client/src/iothub_client_ll.c
|
|
||||||
libraries/AzureIoT/src/az_iot/iothub_client/src/iothub_client_retry_control.c
|
|
||||||
libraries/AzureIoT/src/az_iot/iothub_client/src/iothub_message.c
|
|
||||||
libraries/AzureIoT/src/az_iot/iothub_client/src/iothubtransport.c
|
|
||||||
libraries/AzureIoT/src/az_iot/iothub_client/src/iothubtransportmqtt.c
|
|
||||||
libraries/AzureIoT/src/az_iot/iothub_client/src/iothubtransport_mqtt_common.c
|
|
||||||
libraries/AzureIoT/src/az_iot/iothub_client/src/version.c
|
|
||||||
libraries/AzureIoT/src/az_iot/umqtt/src/mqtt_client.c
|
|
||||||
libraries/AzureIoT/src/az_iot/umqtt/src/mqtt_codec.c
|
|
||||||
libraries/AzureIoT/src/az_iot/umqtt/src/mqtt_message.c
|
|
||||||
libraries/AzureIoT/src/AzureIotHub.cpp
|
|
||||||
libraries/AzureIoT/src/Esp32MQTTClient.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
set(BLE_SRCS
|
set(BLE_SRCS
|
||||||
libraries/BLE/src/BLE2902.cpp
|
libraries/BLE/src/BLE2902.cpp
|
||||||
libraries/BLE/src/BLE2904.cpp
|
libraries/BLE/src/BLE2904.cpp
|
||||||
@ -170,14 +115,12 @@ set(BLE_SRCS
|
|||||||
libraries/BLE/src/GeneralUtils.cpp
|
libraries/BLE/src/GeneralUtils.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(COMPONENT_SRCS ${CORE_SRCS} ${LIBRARY_SRCS} ${AZURE_SRCS} ${BLE_SRCS})
|
|
||||||
|
|
||||||
set(COMPONENT_ADD_INCLUDEDIRS
|
set(includedirs
|
||||||
variants/esp32/
|
variants/esp32/
|
||||||
cores/esp32/
|
cores/esp32/
|
||||||
libraries/ArduinoOTA/src
|
libraries/ArduinoOTA/src
|
||||||
libraries/AsyncUDP/src
|
libraries/AsyncUDP/src
|
||||||
libraries/AzureIoT/src
|
|
||||||
libraries/BLE/src
|
libraries/BLE/src
|
||||||
libraries/BluetoothSerial/src
|
libraries/BluetoothSerial/src
|
||||||
libraries/DNSServer/src
|
libraries/DNSServer/src
|
||||||
@ -188,6 +131,7 @@ set(COMPONENT_ADD_INCLUDEDIRS
|
|||||||
libraries/FS/src
|
libraries/FS/src
|
||||||
libraries/HTTPClient/src
|
libraries/HTTPClient/src
|
||||||
libraries/HTTPUpdate/src
|
libraries/HTTPUpdate/src
|
||||||
|
libraries/LITTLEFS/src
|
||||||
libraries/NetBIOS/src
|
libraries/NetBIOS/src
|
||||||
libraries/Preferences/src
|
libraries/Preferences/src
|
||||||
libraries/SD_MMC/src
|
libraries/SD_MMC/src
|
||||||
@ -203,9 +147,16 @@ set(COMPONENT_ADD_INCLUDEDIRS
|
|||||||
libraries/Wire/src
|
libraries/Wire/src
|
||||||
)
|
)
|
||||||
|
|
||||||
set(COMPONENT_PRIV_INCLUDEDIRS cores/esp32/libb64)
|
set(srcs ${CORE_SRCS} ${LIBRARY_SRCS} ${BLE_SRCS})
|
||||||
|
set(priv_includes cores/esp32/libb64)
|
||||||
|
set(requires spi_flash mbedtls mdns esp_adc_cal)
|
||||||
|
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support openssl bt tinyusb main)
|
||||||
|
|
||||||
set(COMPONENT_REQUIRES spi_flash mbedtls mdns ethernet)
|
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})
|
||||||
set(COMPONENT_PRIV_REQUIRES fatfs nvs_flash app_update spiffs bootloader_support openssl bt)
|
|
||||||
|
|
||||||
register_component()
|
if(IDF_TARGET STREQUAL "esp32")
|
||||||
|
target_compile_options(${COMPONENT_TARGET} PUBLIC -DARDUINO=10812 -DARDUINO_ESP32_DEV -DARDUINO_ARCH_ESP32 -DARDUINO_BOARD="ESP32_DEV" -DARDUINO_VARIANT="esp32" -DESP32)
|
||||||
|
endif()
|
||||||
|
if(IDF_TARGET STREQUAL "esp32s2")
|
||||||
|
target_compile_options(${COMPONENT_TARGET} PUBLIC -DARDUINO=10812 -DARDUINO_ESP32S2_DEV -DARDUINO_ARCH_ESP32 -DARDUINO_BOARD="ESP32S2_DEV" -DARDUINO_VARIANT="esp32s2" -DESP32)
|
||||||
|
endif()
|
||||||
|
@ -5,7 +5,7 @@ config ENABLE_ARDUINO_DEPENDS
|
|||||||
select LWIP_SO_RCVBUF
|
select LWIP_SO_RCVBUF
|
||||||
select ETHERNET
|
select ETHERNET
|
||||||
select WIFI_ENABLED
|
select WIFI_ENABLED
|
||||||
select ESP32_PHY_CALIBRATION_AND_DATA_STORAGE
|
select ESP32_PHY_CALIBRATION_AND_DATA_STORAGE if IDF_TARGET_ESP32
|
||||||
select MEMMAP_SMP
|
select MEMMAP_SMP
|
||||||
default "y"
|
default "y"
|
||||||
|
|
||||||
@ -82,6 +82,15 @@ config ARDUINO_UDP_RUNNING_CORE
|
|||||||
default 1 if ARDUINO_UDP_RUN_CORE1
|
default 1 if ARDUINO_UDP_RUN_CORE1
|
||||||
default -1 if ARDUINO_UDP_RUN_NO_AFFINITY
|
default -1 if ARDUINO_UDP_RUN_NO_AFFINITY
|
||||||
|
|
||||||
|
config ARDUINO_ISR_IRAM
|
||||||
|
bool "Run interrupts in IRAM"
|
||||||
|
default "n"
|
||||||
|
help
|
||||||
|
Enabling this option will Attach all interrupts with the IRAm flag.
|
||||||
|
It will also make some HAL function, like, digitalRead/Write and more
|
||||||
|
be loaded into IRAM for access inside ISRs.
|
||||||
|
Beware that this is a very dangerous setting. Enable it only if you
|
||||||
|
are fully aware of the consequences.
|
||||||
|
|
||||||
config DISABLE_HAL_LOCKS
|
config DISABLE_HAL_LOCKS
|
||||||
bool "Disable mutex locks for HAL"
|
bool "Disable mutex locks for HAL"
|
||||||
@ -232,6 +241,12 @@ config ARDUINO_SELECTIVE_ESPmDNS
|
|||||||
select ARDUINO_SELECTIVE_WiFi
|
select ARDUINO_SELECTIVE_WiFi
|
||||||
default y
|
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
|
||||||
|
23
README.md
23
README.md
@ -1,4 +1,5 @@
|
|||||||
# Arduino core for ESP32 WiFi chip [](https://travis-ci.org/espressif/arduino-esp32)
|
# Arduino core for the ESP32
|
||||||
|
[](https://travis-ci.org/espressif/arduino-esp32) 
|
||||||
|
|
||||||
### Need help or have a question? Join the chat at [](https://gitter.im/espressif/arduino-esp32?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
### Need help or have a question? Join the chat at [](https://gitter.im/espressif/arduino-esp32?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
@ -9,17 +10,12 @@
|
|||||||
- [Issue/Bug report template](#issuebug-report-template)
|
- [Issue/Bug report template](#issuebug-report-template)
|
||||||
- [ESP32Dev Board PINMAP](#esp32dev-board-pinmap)
|
- [ESP32Dev Board PINMAP](#esp32dev-board-pinmap)
|
||||||
|
|
||||||
## Development Status
|
### Development Status
|
||||||
[Latest stable release  ](https://github.com/espressif/arduino-esp32/releases/latest/) 
|
[Latest stable release  ](https://github.com/espressif/arduino-esp32/releases/latest/) 
|
||||||
|
|
||||||
[Latest development release  ](https://github.com/espressif/arduino-esp32/releases/latest/) 
|
[Latest development release  ](https://github.com/espressif/arduino-esp32/releases/latest/) 
|
||||||
|
|
||||||
Most of the framework is implemented. Most noticable is the missing analogWrite. While analogWrite is on it's way, there are a few other options that you can use:
|
### Installation Instructions
|
||||||
- 16 channels [LEDC](cores/esp32/esp32-hal-ledc.h) which is PWM
|
|
||||||
- 8 channels [SigmaDelta](cores/esp32/esp32-hal-sigmadelta.h) which uses SigmaDelta modulation
|
|
||||||
- 2 channels [DAC](cores/esp32/esp32-hal-dac.h) which gives real analog output
|
|
||||||
|
|
||||||
## Installation Instructions
|
|
||||||
- Using Arduino IDE Boards Manager (preferred)
|
- Using Arduino IDE Boards Manager (preferred)
|
||||||
+ [Instructions for Boards Manager](docs/arduino-ide/boards_manager.md)
|
+ [Instructions for Boards Manager](docs/arduino-ide/boards_manager.md)
|
||||||
- Using Arduino IDE with the development repository
|
- Using Arduino IDE with the development repository
|
||||||
@ -33,20 +29,19 @@ Most of the framework is implemented. Most noticable is the missing analogWrite.
|
|||||||
- [Using as ESP-IDF component](docs/esp-idf_component.md)
|
- [Using as ESP-IDF component](docs/esp-idf_component.md)
|
||||||
- [Using OTAWebUpdater](docs/OTAWebUpdate/OTAWebUpdate.md)
|
- [Using OTAWebUpdater](docs/OTAWebUpdate/OTAWebUpdate.md)
|
||||||
|
|
||||||
#### Decoding exceptions
|
### Decoding exceptions
|
||||||
|
|
||||||
You can use [EspExceptionDecoder](https://github.com/me-no-dev/EspExceptionDecoder) to get meaningful call trace.
|
You can use [EspExceptionDecoder](https://github.com/me-no-dev/EspExceptionDecoder) to get meaningful call trace.
|
||||||
|
|
||||||
#### Issue/Bug report template
|
### Issue/Bug report template
|
||||||
Before reporting an issue, make sure you've searched for similar one that was already created. Also make sure to go through all the issues labelled as [for reference](https://github.com/espressif/arduino-esp32/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3A%22for%20reference%22%20).
|
Before reporting an issue, make sure you've searched for similar one that was already created. Also make sure to go through all the issues labelled as [for reference](https://github.com/espressif/arduino-esp32/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3A%22for%20reference%22%20).
|
||||||
|
|
||||||
Finally, if you're sure no one else had the issue, follow the [ISSUE_TEMPLATE](docs/ISSUE_TEMPLATE.md) while reporting any issue.
|
Finally, if you are sure no one else had the issue, follow the [ISSUE_TEMPLATE](docs/ISSUE_TEMPLATE.md) while reporting any issue.
|
||||||
|
|
||||||
|
### ESP32Dev Board PINMAP
|
||||||
## ESP32Dev Board PINMAP
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Hint
|
### 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
|
||||||
|
19
appveyor.yml
19
appveyor.yml
@ -1,19 +0,0 @@
|
|||||||
build: off
|
|
||||||
environment:
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiClient"
|
|
||||||
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiClientBasic"
|
|
||||||
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiClientEvents"
|
|
||||||
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiIPv6"
|
|
||||||
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiScan"
|
|
||||||
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiSmartConfig"
|
|
||||||
|
|
||||||
install:
|
|
||||||
- cmd: git submodule update --init --recursive
|
|
||||||
- cmd: SET PATH=%PATH%;C:\Python27\Scripts
|
|
||||||
- cmd: pip install -U https://github.com/platformio/platformio/archive/develop.zip
|
|
||||||
- cmd: platformio platform install https://github.com/platformio/platform-espressif32.git#feature/stage
|
|
||||||
|
|
||||||
test_script:
|
|
||||||
- cmd: platformio ci -b esp32dev -b nano32 -b node32s
|
|
2325
boards.txt
2325
boards.txt
File diff suppressed because it is too large
Load Diff
@ -68,12 +68,6 @@
|
|||||||
#define __STRINGIFY(a) #a
|
#define __STRINGIFY(a) #a
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// undefine stdlib's abs if encountered
|
|
||||||
#ifdef abs
|
|
||||||
#undef abs
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define abs(x) ((x)>0?(x):-(x))
|
|
||||||
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
||||||
#define radians(deg) ((deg)*DEG_TO_RAD)
|
#define radians(deg) ((deg)*DEG_TO_RAD)
|
||||||
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
||||||
@ -121,10 +115,12 @@ typedef bool boolean;
|
|||||||
typedef uint8_t byte;
|
typedef uint8_t byte;
|
||||||
typedef unsigned int word;
|
typedef unsigned int word;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
void setup(void);
|
void setup(void);
|
||||||
void loop(void);
|
void loop(void);
|
||||||
|
|
||||||
long random(long, long);
|
long random(long, long);
|
||||||
|
#endif
|
||||||
void randomSeed(unsigned long);
|
void randomSeed(unsigned long);
|
||||||
long map(long, long, long, long, long);
|
long map(long, long, long, long, long);
|
||||||
|
|
||||||
@ -160,6 +156,7 @@ void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
|
|||||||
#include "HardwareSerial.h"
|
#include "HardwareSerial.h"
|
||||||
#include "Esp.h"
|
#include "Esp.h"
|
||||||
|
|
||||||
|
using std::abs;
|
||||||
using std::isinf;
|
using std::isinf;
|
||||||
using std::isnan;
|
using std::isnan;
|
||||||
using std::max;
|
using std::max;
|
||||||
|
@ -28,8 +28,6 @@ class Client: public Stream
|
|||||||
public:
|
public:
|
||||||
virtual int connect(IPAddress ip, uint16_t port) =0;
|
virtual int connect(IPAddress ip, uint16_t port) =0;
|
||||||
virtual int connect(const char *host, uint16_t port) =0;
|
virtual int connect(const char *host, uint16_t port) =0;
|
||||||
virtual int connect(IPAddress ip, uint16_t port, int timeout) =0;
|
|
||||||
virtual int connect(const char *host, uint16_t port, int timeout) =0;
|
|
||||||
virtual size_t write(uint8_t) =0;
|
virtual size_t write(uint8_t) =0;
|
||||||
virtual size_t write(const uint8_t *buf, size_t size) =0;
|
virtual size_t write(const uint8_t *buf, size_t size) =0;
|
||||||
virtual int available() = 0;
|
virtual int available() = 0;
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "Esp.h"
|
#include "Esp.h"
|
||||||
#include "rom/spi_flash.h"
|
|
||||||
#include "esp_sleep.h"
|
#include "esp_sleep.h"
|
||||||
#include "esp_spi_flash.h"
|
#include "esp_spi_flash.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -32,6 +31,19 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
#include <MD5Builder.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"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/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
|
* User-defined Literals
|
||||||
* usage:
|
* usage:
|
||||||
@ -92,13 +104,6 @@ void EspClass::deepSleep(uint32_t time_us)
|
|||||||
esp_deep_sleep(time_us);
|
esp_deep_sleep(time_us);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getCycleCount()
|
|
||||||
{
|
|
||||||
uint32_t ccount;
|
|
||||||
__asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
|
|
||||||
return ccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EspClass::restart(void)
|
void EspClass::restart(void)
|
||||||
{
|
{
|
||||||
esp_restart();
|
esp_restart();
|
||||||
@ -128,24 +133,36 @@ uint32_t EspClass::getMaxAllocHeap(void)
|
|||||||
|
|
||||||
uint32_t EspClass::getPsramSize(void)
|
uint32_t EspClass::getPsramSize(void)
|
||||||
{
|
{
|
||||||
multi_heap_info_t info;
|
if(psramFound()){
|
||||||
heap_caps_get_info(&info, MALLOC_CAP_SPIRAM);
|
multi_heap_info_t info;
|
||||||
return info.total_free_bytes + info.total_allocated_bytes;
|
heap_caps_get_info(&info, MALLOC_CAP_SPIRAM);
|
||||||
|
return info.total_free_bytes + info.total_allocated_bytes;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getFreePsram(void)
|
uint32_t EspClass::getFreePsram(void)
|
||||||
{
|
{
|
||||||
return heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
if(psramFound()){
|
||||||
|
return heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getMinFreePsram(void)
|
uint32_t EspClass::getMinFreePsram(void)
|
||||||
{
|
{
|
||||||
return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM);
|
if(psramFound()){
|
||||||
|
return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getMaxAllocPsram(void)
|
uint32_t EspClass::getMaxAllocPsram(void)
|
||||||
{
|
{
|
||||||
return heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
|
if(psramFound()){
|
||||||
|
return heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t sketchSize(sketchSize_t response) {
|
static uint32_t sketchSize(sketchSize_t response) {
|
||||||
|
@ -75,8 +75,8 @@ public:
|
|||||||
uint32_t getMaxAllocPsram();
|
uint32_t getMaxAllocPsram();
|
||||||
|
|
||||||
uint8_t getChipRevision();
|
uint8_t getChipRevision();
|
||||||
uint8_t getCpuFreqMHz(){ return CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ; }
|
uint32_t getCpuFreqMHz(){ return getCpuFrequencyMhz(); }
|
||||||
uint32_t getCycleCount();
|
inline uint32_t getCycleCount() __attribute__((always_inline));
|
||||||
const char * getSdkVersion();
|
const char * getSdkVersion();
|
||||||
|
|
||||||
void deepSleep(uint32_t time_us);
|
void deepSleep(uint32_t time_us);
|
||||||
@ -101,6 +101,13 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint32_t ARDUINO_ISR_ATTR EspClass::getCycleCount()
|
||||||
|
{
|
||||||
|
uint32_t ccount;
|
||||||
|
__asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
|
||||||
|
return ccount;
|
||||||
|
}
|
||||||
|
|
||||||
extern EspClass ESP;
|
extern EspClass ESP;
|
||||||
|
|
||||||
#endif //ESP_H
|
#endif //ESP_H
|
||||||
|
@ -16,7 +16,7 @@ extern "C"
|
|||||||
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional);
|
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR interruptFunctional(void* arg)
|
void ARDUINO_ISR_ATTR interruptFunctional(void* arg)
|
||||||
{
|
{
|
||||||
InterruptArgStructure* localArg = (InterruptArgStructure*)arg;
|
InterruptArgStructure* localArg = (InterruptArgStructure*)arg;
|
||||||
if (localArg->interruptFunction)
|
if (localArg->interruptFunction)
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include "pins_arduino.h"
|
#include "pins_arduino.h"
|
||||||
#include "HardwareSerial.h"
|
#include "HardwareSerial.h"
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
|
||||||
#ifndef RX1
|
#ifndef RX1
|
||||||
#define RX1 9
|
#define RX1 9
|
||||||
#endif
|
#endif
|
||||||
@ -22,11 +24,29 @@
|
|||||||
#define TX2 17
|
#define TX2 17
|
||||||
#endif
|
#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 !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
||||||
|
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
||||||
|
HardwareSerial Serial0(0);
|
||||||
|
#else
|
||||||
HardwareSerial Serial(0);
|
HardwareSerial Serial(0);
|
||||||
|
#endif
|
||||||
HardwareSerial Serial1(1);
|
HardwareSerial Serial1(1);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
HardwareSerial Serial2(2);
|
HardwareSerial Serial2(2);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL) {}
|
HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL) {}
|
||||||
|
|
||||||
@ -40,21 +60,28 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
|
|||||||
end();
|
end();
|
||||||
}
|
}
|
||||||
if(_uart_nr == 0 && rxPin < 0 && txPin < 0) {
|
if(_uart_nr == 0 && rxPin < 0 && txPin < 0) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
rxPin = 3;
|
rxPin = 3;
|
||||||
txPin = 1;
|
txPin = 1;
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
rxPin = 44;
|
||||||
|
txPin = 43;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if(_uart_nr == 1 && rxPin < 0 && txPin < 0) {
|
if(_uart_nr == 1 && rxPin < 0 && txPin < 0) {
|
||||||
rxPin = RX1;
|
rxPin = RX1;
|
||||||
txPin = TX1;
|
txPin = TX1;
|
||||||
}
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
if(_uart_nr == 2 && rxPin < 0 && txPin < 0) {
|
if(_uart_nr == 2 && rxPin < 0 && txPin < 0) {
|
||||||
rxPin = RX2;
|
rxPin = RX2;
|
||||||
txPin = TX2;
|
txPin = TX2;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert);
|
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert);
|
||||||
|
|
||||||
if(!baud) {
|
if(!baud) {
|
||||||
|
uartStartDetectBaudrate(_uart);
|
||||||
time_t startMillis = millis();
|
time_t startMillis = millis();
|
||||||
unsigned long detectedBaudRate = 0;
|
unsigned long detectedBaudRate = 0;
|
||||||
while(millis() - startMillis < timeout_ms && !(detectedBaudRate = uartDetectBaudrate(_uart))) {
|
while(millis() - startMillis < timeout_ms && !(detectedBaudRate = uartDetectBaudrate(_uart))) {
|
||||||
@ -100,7 +127,7 @@ void HardwareSerial::setDebugOutput(bool en)
|
|||||||
uartSetDebug(_uart);
|
uartSetDebug(_uart);
|
||||||
} else {
|
} else {
|
||||||
if(uartGetDebug() == _uart_nr) {
|
if(uartGetDebug() == _uart_nr) {
|
||||||
uartSetDebug(0);
|
uartSetDebug(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,11 +157,34 @@ int HardwareSerial::read(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HardwareSerial::flush()
|
// 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);
|
uartFlush(_uart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::flush(bool txOnly)
|
||||||
|
{
|
||||||
|
uartFlushTxOnly(_uart, txOnly);
|
||||||
|
}
|
||||||
|
|
||||||
size_t HardwareSerial::write(uint8_t c)
|
size_t HardwareSerial::write(uint8_t c)
|
||||||
{
|
{
|
||||||
uartWrite(_uart, c);
|
uartWrite(_uart, c);
|
||||||
|
@ -62,10 +62,19 @@ public:
|
|||||||
int availableForWrite(void);
|
int availableForWrite(void);
|
||||||
int peek(void);
|
int peek(void);
|
||||||
int read(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(void);
|
||||||
|
void flush( bool txOnly);
|
||||||
size_t write(uint8_t);
|
size_t write(uint8_t);
|
||||||
size_t write(const uint8_t *buffer, size_t size);
|
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)
|
inline size_t write(const char * s)
|
||||||
{
|
{
|
||||||
return write((uint8_t*) s, strlen(s));
|
return write((uint8_t*) s, strlen(s));
|
||||||
@ -97,10 +106,23 @@ protected:
|
|||||||
uart_t* _uart;
|
uart_t* _uart;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern void serialEventRun(void) __attribute__((weak));
|
||||||
|
|
||||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
#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;
|
extern HardwareSerial Serial;
|
||||||
|
#endif
|
||||||
extern HardwareSerial Serial1;
|
extern HardwareSerial Serial1;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
extern HardwareSerial Serial2;
|
extern HardwareSerial Serial2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // HardwareSerial_h
|
||||||
|
@ -21,7 +21,19 @@
|
|||||||
|
|
||||||
#include <WString.h>
|
#include <WString.h>
|
||||||
#include <Stream.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"
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
#include "rom/md5_hash.h"
|
#include "rom/md5_hash.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class MD5Builder
|
class MD5Builder
|
||||||
{
|
{
|
||||||
|
@ -52,19 +52,24 @@ size_t Print::printf(const char *format, ...)
|
|||||||
va_list copy;
|
va_list copy;
|
||||||
va_start(arg, format);
|
va_start(arg, format);
|
||||||
va_copy(copy, arg);
|
va_copy(copy, arg);
|
||||||
size_t len = vsnprintf(NULL, 0, format, arg);
|
int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
|
||||||
va_end(copy);
|
va_end(copy);
|
||||||
|
if(len < 0) {
|
||||||
|
va_end(arg);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
if(len >= sizeof(loc_buf)){
|
if(len >= sizeof(loc_buf)){
|
||||||
temp = new char[len+1];
|
temp = (char*) malloc(len+1);
|
||||||
if(temp == NULL) {
|
if(temp == NULL) {
|
||||||
|
va_end(arg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
len = vsnprintf(temp, len+1, format, arg);
|
||||||
}
|
}
|
||||||
len = vsnprintf(temp, len+1, format, arg);
|
|
||||||
write((uint8_t*)temp, len);
|
|
||||||
va_end(arg);
|
va_end(arg);
|
||||||
if(len >= sizeof(loc_buf)){
|
len = write((uint8_t*)temp, len);
|
||||||
delete[] temp;
|
if(temp != loc_buf){
|
||||||
|
free(temp);
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -154,8 +159,10 @@ size_t Print::print(struct tm * timeinfo, const char * format)
|
|||||||
}
|
}
|
||||||
char buf[64];
|
char buf[64];
|
||||||
size_t written = strftime(buf, 64, f, timeinfo);
|
size_t written = strftime(buf, 64, f, timeinfo);
|
||||||
print(buf);
|
if(written == 0){
|
||||||
return written;
|
return written;
|
||||||
|
}
|
||||||
|
return print(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(void)
|
size_t Print::println(void)
|
||||||
|
@ -97,8 +97,8 @@ public:
|
|||||||
|
|
||||||
float parseFloat(); // float version of parseInt
|
float parseFloat(); // float version of parseInt
|
||||||
|
|
||||||
size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer
|
virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer
|
||||||
size_t readBytes(uint8_t *buffer, size_t length)
|
virtual size_t readBytes(uint8_t *buffer, size_t length)
|
||||||
{
|
{
|
||||||
return readBytes((char *) buffer, length);
|
return readBytes((char *) buffer, length);
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ public:
|
|||||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||||
|
|
||||||
// Arduino String functions to be added here
|
// Arduino String functions to be added here
|
||||||
String readString();
|
virtual String readString();
|
||||||
String readStringUntil(char terminator);
|
String readStringUntil(char terminator);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
StreamString.cpp
|
StreamString.cpp
|
||||||
|
|
||||||
Copyright (c) 2015 Markus Sattler. All rights reserved.
|
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
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
@ -22,31 +23,28 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "StreamString.h"
|
#include "StreamString.h"
|
||||||
|
|
||||||
size_t StreamString::write(const uint8_t *data, size_t size)
|
size_t StreamString::write(const uint8_t *data, size_t size) {
|
||||||
{
|
|
||||||
if(size && data) {
|
if(size && data) {
|
||||||
if(reserve(length() + size + 1)) {
|
const unsigned int newlen = length() + size;
|
||||||
memcpy((void *) (buffer + len), (const void *) data, size);
|
if(reserve(newlen + 1)) {
|
||||||
len += size;
|
memcpy((void *) (wbuffer() + len()), (const void *) data, size);
|
||||||
*(buffer + len) = 0x00; // add null for string end
|
setLen(newlen);
|
||||||
|
*(wbuffer() + newlen) = 0x00; // add null for string end
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t StreamString::write(uint8_t data)
|
size_t StreamString::write(uint8_t data) {
|
||||||
{
|
|
||||||
return concat((char) data);
|
return concat((char) data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int StreamString::available()
|
int StreamString::available() {
|
||||||
{
|
|
||||||
return length();
|
return length();
|
||||||
}
|
}
|
||||||
|
|
||||||
int StreamString::read()
|
int StreamString::read() {
|
||||||
{
|
|
||||||
if(length()) {
|
if(length()) {
|
||||||
char c = charAt(0);
|
char c = charAt(0);
|
||||||
remove(0, 1);
|
remove(0, 1);
|
||||||
@ -56,8 +54,7 @@ int StreamString::read()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int StreamString::peek()
|
int StreamString::peek() {
|
||||||
{
|
|
||||||
if(length()) {
|
if(length()) {
|
||||||
char c = charAt(0);
|
char c = charAt(0);
|
||||||
return c;
|
return c;
|
||||||
@ -65,7 +62,6 @@ int StreamString::peek()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamString::flush()
|
void StreamString::flush() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
338
cores/esp32/USB.cpp
Normal file
338
cores/esp32/USB.cpp
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
// Copyright 2015-2020 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 "esp32-hal-tinyusb.h"
|
||||||
|
#include "USB.h"
|
||||||
|
#if CONFIG_USB_ENABLED
|
||||||
|
|
||||||
|
#ifndef USB_VID
|
||||||
|
#define USB_VID USB_ESPRESSIF_VID
|
||||||
|
#endif
|
||||||
|
#ifndef USB_PID
|
||||||
|
#define USB_PID 0x0002
|
||||||
|
#endif
|
||||||
|
#ifndef USB_MANUFACTURER
|
||||||
|
#define USB_MANUFACTURER "Espressif Systems"
|
||||||
|
#endif
|
||||||
|
#ifndef USB_PRODUCT
|
||||||
|
#define USB_PRODUCT ARDUINO_BOARD
|
||||||
|
#endif
|
||||||
|
#ifndef USB_SERIAL
|
||||||
|
#define USB_SERIAL "0"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "tinyusb.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CFG_TUD_DFU_RT
|
||||||
|
static uint16_t load_dfu_descriptor(uint8_t * dst, uint8_t * itf)
|
||||||
|
{
|
||||||
|
#define DFU_ATTR_CAN_DOWNLOAD 1
|
||||||
|
#define DFU_ATTR_CAN_UPLOAD 2
|
||||||
|
#define DFU_ATTR_MANIFESTATION_TOLERANT 4
|
||||||
|
#define DFU_ATTR_WILL_DETACH 8
|
||||||
|
#define DFU_ATTRS (DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_CAN_UPLOAD | DFU_ATTR_MANIFESTATION_TOLERANT)
|
||||||
|
|
||||||
|
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB DFU_RT");
|
||||||
|
uint8_t descriptor[TUD_DFU_RT_DESC_LEN] = {
|
||||||
|
// Interface number, string index, attributes, detach timeout, transfer size */
|
||||||
|
TUD_DFU_RT_DESCRIPTOR(*itf, str_index, DFU_ATTRS, 700, 64)
|
||||||
|
};
|
||||||
|
*itf+=1;
|
||||||
|
memcpy(dst, descriptor, TUD_DFU_RT_DESC_LEN);
|
||||||
|
return TUD_DFU_RT_DESC_LEN;
|
||||||
|
}
|
||||||
|
// Invoked on DFU_DETACH request to reboot to the bootloader
|
||||||
|
void tud_dfu_rt_reboot_to_dfu(void)
|
||||||
|
{
|
||||||
|
usb_persist_restart(RESTART_BOOTLOADER_DFU);
|
||||||
|
}
|
||||||
|
#endif /* CFG_TUD_DFU_RT */
|
||||||
|
|
||||||
|
ESP_EVENT_DEFINE_BASE(ARDUINO_USB_EVENTS);
|
||||||
|
|
||||||
|
static esp_event_loop_handle_t arduino_usb_event_loop_handle = NULL;
|
||||||
|
|
||||||
|
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){
|
||||||
|
if(arduino_usb_event_loop_handle == NULL){
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
return esp_event_post_to(arduino_usb_event_loop_handle, event_base, event_id, event_data, event_data_size, 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){
|
||||||
|
if(arduino_usb_event_loop_handle == NULL){
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
return esp_event_handler_register_with(arduino_usb_event_loop_handle, event_base, event_id, event_handler, event_handler_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tinyusb_device_mounted = false;
|
||||||
|
static bool tinyusb_device_suspended = false;
|
||||||
|
|
||||||
|
// Invoked when device is mounted (configured)
|
||||||
|
void tud_mount_cb(void){
|
||||||
|
tinyusb_device_mounted = true;
|
||||||
|
arduino_usb_event_data_t p = {0};
|
||||||
|
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STARTED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoked when device is unmounted
|
||||||
|
void tud_umount_cb(void){
|
||||||
|
tinyusb_device_mounted = false;
|
||||||
|
arduino_usb_event_data_t p = {0};
|
||||||
|
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoked when usb bus is suspended
|
||||||
|
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
|
||||||
|
void tud_suspend_cb(bool remote_wakeup_en){
|
||||||
|
tinyusb_device_suspended = true;
|
||||||
|
arduino_usb_event_data_t p = {0};
|
||||||
|
p.suspend.remote_wakeup_en = remote_wakeup_en;
|
||||||
|
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_SUSPEND_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoked when usb bus is resumed
|
||||||
|
void tud_resume_cb(void){
|
||||||
|
tinyusb_device_suspended = false;
|
||||||
|
arduino_usb_event_data_t p = {0};
|
||||||
|
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_RESUME_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESPUSB::ESPUSB(size_t task_stack_size, uint8_t event_task_priority)
|
||||||
|
:vid(USB_VID)
|
||||||
|
,pid(USB_PID)
|
||||||
|
,product_name(USB_PRODUCT)
|
||||||
|
,manufacturer_name(USB_MANUFACTURER)
|
||||||
|
,serial_number(USB_SERIAL)
|
||||||
|
,fw_version(0x0100)
|
||||||
|
,usb_version(0x0200)// at least 2.1 or 3.x for BOS & webUSB
|
||||||
|
,usb_class(TUSB_CLASS_MISC)
|
||||||
|
,usb_subclass(MISC_SUBCLASS_COMMON)
|
||||||
|
,usb_protocol(MISC_PROTOCOL_IAD)
|
||||||
|
,usb_attributes(TUSB_DESC_CONFIG_ATT_SELF_POWERED)
|
||||||
|
,usb_power_ma(500)
|
||||||
|
,webusb_enabled(false)
|
||||||
|
,webusb_url("espressif.github.io/arduino-esp32/webusb.html")
|
||||||
|
,_started(false)
|
||||||
|
,_task_stack_size(task_stack_size)
|
||||||
|
,_event_task_priority(event_task_priority)
|
||||||
|
{
|
||||||
|
if (!arduino_usb_event_loop_handle) {
|
||||||
|
esp_event_loop_args_t event_task_args = {
|
||||||
|
.queue_size = 5,
|
||||||
|
.task_name = "arduino_usb_events",
|
||||||
|
.task_priority = _event_task_priority,
|
||||||
|
.task_stack_size = _task_stack_size,
|
||||||
|
.task_core_id = tskNO_AFFINITY
|
||||||
|
};
|
||||||
|
if (esp_event_loop_create(&event_task_args, &arduino_usb_event_loop_handle) != ESP_OK) {
|
||||||
|
log_e("esp_event_loop_create failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESPUSB::~ESPUSB(){
|
||||||
|
if (arduino_usb_event_loop_handle) {
|
||||||
|
esp_event_loop_delete(arduino_usb_event_loop_handle);
|
||||||
|
arduino_usb_event_loop_handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::begin(){
|
||||||
|
if(!_started){
|
||||||
|
tinyusb_device_config_t tinyusb_device_config = {
|
||||||
|
.vid = vid,
|
||||||
|
.pid = pid,
|
||||||
|
.product_name = product_name.c_str(),
|
||||||
|
.manufacturer_name = manufacturer_name.c_str(),
|
||||||
|
.serial_number = serial_number.c_str(),
|
||||||
|
.fw_version = fw_version,
|
||||||
|
.usb_version = usb_version,
|
||||||
|
.usb_class = usb_class,
|
||||||
|
.usb_subclass = usb_subclass,
|
||||||
|
.usb_protocol = usb_protocol,
|
||||||
|
.usb_attributes = usb_attributes,
|
||||||
|
.usb_power_ma = usb_power_ma,
|
||||||
|
.webusb_enabled = webusb_enabled,
|
||||||
|
.webusb_url = webusb_url.c_str()
|
||||||
|
};
|
||||||
|
_started = tinyusb_init(&tinyusb_device_config) == ESP_OK;
|
||||||
|
}
|
||||||
|
return _started;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESPUSB::onEvent(esp_event_handler_t callback){
|
||||||
|
onEvent(ARDUINO_USB_ANY_EVENT, callback);
|
||||||
|
}
|
||||||
|
void ESPUSB::onEvent(arduino_usb_event_t event, esp_event_handler_t callback){
|
||||||
|
arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, event, callback, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESPUSB::operator bool() const
|
||||||
|
{
|
||||||
|
return _started && tinyusb_device_mounted;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::enableDFU(){
|
||||||
|
#if CFG_TUD_DFU_RT
|
||||||
|
return tinyusb_enable_interface(USB_INTERFACE_DFU, TUD_DFU_RT_DESC_LEN, load_dfu_descriptor) == ESP_OK;
|
||||||
|
#endif /* CFG_TUD_DFU_RT */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::VID(uint16_t v){
|
||||||
|
if(!_started){
|
||||||
|
vid = v;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
uint16_t ESPUSB::VID(void){
|
||||||
|
return vid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::PID(uint16_t p){
|
||||||
|
if(!_started){
|
||||||
|
pid = p;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
uint16_t ESPUSB::PID(void){
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::firmwareVersion(uint16_t version){
|
||||||
|
if(!_started){
|
||||||
|
fw_version = version;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
uint16_t ESPUSB::firmwareVersion(void){
|
||||||
|
return fw_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::usbVersion(uint16_t version){
|
||||||
|
if(!_started){
|
||||||
|
usb_version = version;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
uint16_t ESPUSB::usbVersion(void){
|
||||||
|
return usb_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::usbPower(uint16_t mA){
|
||||||
|
if(!_started){
|
||||||
|
usb_power_ma = mA;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
uint16_t ESPUSB::usbPower(void){
|
||||||
|
return usb_power_ma;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::usbClass(uint8_t _class){
|
||||||
|
if(!_started){
|
||||||
|
usb_class = _class;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
uint8_t ESPUSB::usbClass(void){
|
||||||
|
return usb_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::usbSubClass(uint8_t subClass){
|
||||||
|
if(!_started){
|
||||||
|
usb_subclass = subClass;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
uint8_t ESPUSB::usbSubClass(void){
|
||||||
|
return usb_subclass;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::usbProtocol(uint8_t protocol){
|
||||||
|
if(!_started){
|
||||||
|
usb_protocol = protocol;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
uint8_t ESPUSB::usbProtocol(void){
|
||||||
|
return usb_protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::usbAttributes(uint8_t attr){
|
||||||
|
if(!_started){
|
||||||
|
usb_attributes = attr;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
uint8_t ESPUSB::usbAttributes(void){
|
||||||
|
return usb_attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::webUSB(bool enabled){
|
||||||
|
if(!_started){
|
||||||
|
webusb_enabled = enabled;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
bool ESPUSB::webUSB(void){
|
||||||
|
return webusb_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::productName(const char * name){
|
||||||
|
if(!_started){
|
||||||
|
product_name = name;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
const char * ESPUSB::productName(void){
|
||||||
|
return product_name.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::manufacturerName(const char * name){
|
||||||
|
if(!_started){
|
||||||
|
manufacturer_name = name;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
const char * ESPUSB::manufacturerName(void){
|
||||||
|
return manufacturer_name.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::serialNumber(const char * name){
|
||||||
|
if(!_started){
|
||||||
|
serial_number = name;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
const char * ESPUSB::serialNumber(void){
|
||||||
|
return serial_number.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPUSB::webUSBURL(const char * name){
|
||||||
|
if(!_started){
|
||||||
|
webusb_url = name;
|
||||||
|
}
|
||||||
|
return !_started;
|
||||||
|
}
|
||||||
|
const char * ESPUSB::webUSBURL(void){
|
||||||
|
return webusb_url.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
ESPUSB USB;
|
||||||
|
|
||||||
|
#endif /* CONFIG_USB_ENABLED */
|
118
cores/esp32/USB.h
Normal file
118
cores/esp32/USB.h
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#if CONFIG_USB_ENABLED
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "USBCDC.h"
|
||||||
|
|
||||||
|
#include "esp_event.h"
|
||||||
|
|
||||||
|
ESP_EVENT_DECLARE_BASE(ARDUINO_USB_EVENTS);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ARDUINO_USB_ANY_EVENT = ESP_EVENT_ANY_ID,
|
||||||
|
ARDUINO_USB_STARTED_EVENT = 0,
|
||||||
|
ARDUINO_USB_STOPPED_EVENT,
|
||||||
|
ARDUINO_USB_SUSPEND_EVENT,
|
||||||
|
ARDUINO_USB_RESUME_EVENT,
|
||||||
|
ARDUINO_USB_MAX_EVENT,
|
||||||
|
} arduino_usb_event_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
bool remote_wakeup_en;
|
||||||
|
} suspend;
|
||||||
|
} arduino_usb_event_data_t;
|
||||||
|
|
||||||
|
class ESPUSB {
|
||||||
|
public:
|
||||||
|
ESPUSB(size_t event_task_stack_size=2048, uint8_t event_task_priority=5);
|
||||||
|
~ESPUSB();
|
||||||
|
|
||||||
|
void onEvent(esp_event_handler_t callback);
|
||||||
|
void onEvent(arduino_usb_event_t event, esp_event_handler_t callback);
|
||||||
|
|
||||||
|
bool VID(uint16_t v);
|
||||||
|
uint16_t VID(void);
|
||||||
|
|
||||||
|
bool PID(uint16_t p);
|
||||||
|
uint16_t PID(void);
|
||||||
|
|
||||||
|
bool firmwareVersion(uint16_t version);
|
||||||
|
uint16_t firmwareVersion(void);
|
||||||
|
|
||||||
|
bool usbVersion(uint16_t version);
|
||||||
|
uint16_t usbVersion(void);
|
||||||
|
|
||||||
|
bool usbPower(uint16_t mA);
|
||||||
|
uint16_t usbPower(void);
|
||||||
|
|
||||||
|
bool usbClass(uint8_t _class);
|
||||||
|
uint8_t usbClass(void);
|
||||||
|
|
||||||
|
bool usbSubClass(uint8_t subClass);
|
||||||
|
uint8_t usbSubClass(void);
|
||||||
|
|
||||||
|
bool usbProtocol(uint8_t protocol);
|
||||||
|
uint8_t usbProtocol(void);
|
||||||
|
|
||||||
|
bool usbAttributes(uint8_t attr);
|
||||||
|
uint8_t usbAttributes(void);
|
||||||
|
|
||||||
|
bool webUSB(bool enabled);
|
||||||
|
bool webUSB(void);
|
||||||
|
|
||||||
|
bool productName(const char * name);
|
||||||
|
const char * productName(void);
|
||||||
|
|
||||||
|
bool manufacturerName(const char * name);
|
||||||
|
const char * manufacturerName(void);
|
||||||
|
|
||||||
|
bool serialNumber(const char * name);
|
||||||
|
const char * serialNumber(void);
|
||||||
|
|
||||||
|
bool webUSBURL(const char * name);
|
||||||
|
const char * webUSBURL(void);
|
||||||
|
|
||||||
|
bool enableDFU();
|
||||||
|
bool begin();
|
||||||
|
operator bool() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t vid;
|
||||||
|
uint16_t pid;
|
||||||
|
String product_name;
|
||||||
|
String manufacturer_name;
|
||||||
|
String serial_number;
|
||||||
|
uint16_t fw_version;
|
||||||
|
uint16_t usb_version;
|
||||||
|
uint8_t usb_class;
|
||||||
|
uint8_t usb_subclass;
|
||||||
|
uint8_t usb_protocol;
|
||||||
|
uint8_t usb_attributes;
|
||||||
|
uint16_t usb_power_ma;
|
||||||
|
bool webusb_enabled;
|
||||||
|
String webusb_url;
|
||||||
|
|
||||||
|
bool _started;
|
||||||
|
size_t _task_stack_size;
|
||||||
|
uint8_t _event_task_priority;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ESPUSB USB;
|
||||||
|
|
||||||
|
#endif /* CONFIG_USB_ENABLED */
|
338
cores/esp32/USBCDC.cpp
Normal file
338
cores/esp32/USBCDC.cpp
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
// Copyright 2015-2020 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 "esp32-hal-tinyusb.h"
|
||||||
|
#include "USB.h"
|
||||||
|
#include "USBCDC.h"
|
||||||
|
#if CONFIG_USB_ENABLED
|
||||||
|
|
||||||
|
ESP_EVENT_DEFINE_BASE(ARDUINO_USB_CDC_EVENTS);
|
||||||
|
esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait);
|
||||||
|
esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg);
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "tinyusb.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CFG_TUD_CDC
|
||||||
|
#define MAX_USB_CDC_DEVICES 2
|
||||||
|
USBCDC * devices[MAX_USB_CDC_DEVICES] = {NULL, NULL};
|
||||||
|
|
||||||
|
static uint16_t load_cdc_descriptor(uint8_t * dst, uint8_t * itf)
|
||||||
|
{
|
||||||
|
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC");
|
||||||
|
// Interface number, string index, attributes, detach timeout, transfer size */
|
||||||
|
uint8_t descriptor[TUD_CDC_DESC_LEN] = {
|
||||||
|
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||||
|
TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, 64, 0x03, 0x84, 64)
|
||||||
|
};
|
||||||
|
*itf+=2;
|
||||||
|
memcpy(dst, descriptor, TUD_CDC_DESC_LEN);
|
||||||
|
return TUD_CDC_DESC_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
|
||||||
|
{
|
||||||
|
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
|
||||||
|
devices[itf]->_onLineState(dtr, rts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding)
|
||||||
|
{
|
||||||
|
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
|
||||||
|
devices[itf]->_onLineCoding(p_line_coding->bit_rate, p_line_coding->stop_bits, p_line_coding->parity, p_line_coding->data_bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tud_cdc_rx_cb(uint8_t itf)
|
||||||
|
{
|
||||||
|
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
|
||||||
|
devices[itf]->_onRX();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t tinyusb_cdc_write(uint8_t itf, const uint8_t *buffer, size_t size){
|
||||||
|
if(itf >= MAX_USB_CDC_DEVICES){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!tud_cdc_n_connected(itf)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t tosend = size, sofar = 0;
|
||||||
|
while(tosend){
|
||||||
|
uint32_t space = tud_cdc_n_write_available(itf);
|
||||||
|
if(!space){
|
||||||
|
delay(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(tosend < space){
|
||||||
|
space = tosend;
|
||||||
|
}
|
||||||
|
uint32_t sent = tud_cdc_n_write(itf, buffer + sofar, space);
|
||||||
|
if(!sent){
|
||||||
|
return sofar;
|
||||||
|
}
|
||||||
|
sofar += sent;
|
||||||
|
tosend -= sent;
|
||||||
|
tud_cdc_n_write_flush(itf);
|
||||||
|
}
|
||||||
|
return sofar;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ARDUINO_ISR_ATTR cdc0_write_char(char c)
|
||||||
|
{
|
||||||
|
tinyusb_cdc_write(0, (const uint8_t *)&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char);
|
||||||
|
|
||||||
|
static void usb_unplugged_cb(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){
|
||||||
|
((USBCDC*)arg)->_onUnplugged();
|
||||||
|
}
|
||||||
|
|
||||||
|
USBCDC::USBCDC(uint8_t itfn) : itf(itfn), bit_rate(0), stop_bits(0), parity(0), data_bits(0), dtr(false), rts(false), connected(false), reboot_enable(true), rx_queue(NULL) {
|
||||||
|
tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor);
|
||||||
|
if(itf < MAX_USB_CDC_DEVICES){
|
||||||
|
devices[itf] = this;
|
||||||
|
arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBCDC::onEvent(esp_event_handler_t callback){
|
||||||
|
onEvent(ARDUINO_USB_CDC_ANY_EVENT, callback);
|
||||||
|
}
|
||||||
|
void USBCDC::onEvent(arduino_usb_cdc_event_t event, esp_event_handler_t callback){
|
||||||
|
arduino_usb_event_handler_register_with(ARDUINO_USB_CDC_EVENTS, event, callback, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t USBCDC::setRxBufferSize(size_t rx_queue_len){
|
||||||
|
if(rx_queue){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
rx_queue = xQueueCreate(rx_queue_len, sizeof(uint8_t));
|
||||||
|
if(!rx_queue){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return rx_queue_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBCDC::begin(unsigned long baud)
|
||||||
|
{
|
||||||
|
setRxBufferSize(256);//default if not preset
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBCDC::end()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBCDC::_onUnplugged(void){
|
||||||
|
if(connected){
|
||||||
|
connected = false;
|
||||||
|
dtr = false;
|
||||||
|
rts = false;
|
||||||
|
arduino_usb_cdc_event_data_t p = {0};
|
||||||
|
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum { CDC_LINE_IDLE, CDC_LINE_1, CDC_LINE_2, CDC_LINE_3 };
|
||||||
|
void USBCDC::_onLineState(bool _dtr, bool _rts){
|
||||||
|
static uint8_t lineState = CDC_LINE_IDLE;
|
||||||
|
dtr = _dtr;
|
||||||
|
rts = _rts;
|
||||||
|
|
||||||
|
if(reboot_enable){
|
||||||
|
if(!dtr && rts){
|
||||||
|
if(lineState == CDC_LINE_IDLE){
|
||||||
|
lineState++;
|
||||||
|
} else {
|
||||||
|
lineState = CDC_LINE_IDLE;
|
||||||
|
}
|
||||||
|
} else if(dtr && rts){
|
||||||
|
if(lineState == CDC_LINE_1){
|
||||||
|
lineState++;
|
||||||
|
} else {
|
||||||
|
lineState = CDC_LINE_IDLE;
|
||||||
|
}
|
||||||
|
} else if(dtr && !rts){
|
||||||
|
if(lineState == CDC_LINE_2){
|
||||||
|
lineState++;
|
||||||
|
} else {
|
||||||
|
lineState = CDC_LINE_IDLE;
|
||||||
|
}
|
||||||
|
} else if(!dtr && !rts){
|
||||||
|
if(lineState == CDC_LINE_3){
|
||||||
|
usb_persist_restart(RESTART_BOOTLOADER);
|
||||||
|
} else {
|
||||||
|
lineState = CDC_LINE_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lineState == CDC_LINE_IDLE){
|
||||||
|
if(dtr && rts && !connected){
|
||||||
|
connected = true;
|
||||||
|
arduino_usb_cdc_event_data_t p = {0};
|
||||||
|
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_CONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||||
|
} else if(!dtr && !rts && connected){
|
||||||
|
connected = false;
|
||||||
|
arduino_usb_cdc_event_data_t p = {0};
|
||||||
|
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||||
|
}
|
||||||
|
arduino_usb_cdc_event_data_t l = {0};
|
||||||
|
l.line_state.dtr = dtr;
|
||||||
|
l.line_state.rts = rts;
|
||||||
|
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_LINE_STATE_EVENT, &l, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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){
|
||||||
|
bit_rate = _bit_rate;
|
||||||
|
data_bits = _data_bits;
|
||||||
|
stop_bits = _stop_bits;
|
||||||
|
parity = _parity;
|
||||||
|
arduino_usb_cdc_event_data_t p = {0};
|
||||||
|
p.line_coding.bit_rate = bit_rate;
|
||||||
|
p.line_coding.data_bits = data_bits;
|
||||||
|
p.line_coding.stop_bits = stop_bits;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBCDC::_onRX(){
|
||||||
|
uint8_t buf[CONFIG_USB_CDC_RX_BUFSIZE+1];
|
||||||
|
uint32_t count = tud_cdc_n_read(itf, buf, CONFIG_USB_CDC_RX_BUFSIZE);
|
||||||
|
for(uint32_t i=0; i<count; i++){
|
||||||
|
if(rx_queue == NULL || !xQueueSend(rx_queue, buf+i, 0)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arduino_usb_cdc_event_data_t p = {0};
|
||||||
|
p.rx.len = count;
|
||||||
|
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_RX_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBCDC::enableReboot(bool enable){
|
||||||
|
reboot_enable = enable;
|
||||||
|
}
|
||||||
|
bool USBCDC::rebootEnabled(void){
|
||||||
|
return reboot_enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
int USBCDC::available(void)
|
||||||
|
{
|
||||||
|
if(itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return uxQueueMessagesWaiting(rx_queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int USBCDC::peek(void)
|
||||||
|
{
|
||||||
|
if(itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint8_t c;
|
||||||
|
if(xQueuePeek(rx_queue, &c, 0)) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int USBCDC::read(void)
|
||||||
|
{
|
||||||
|
if(itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint8_t c = 0;
|
||||||
|
if(xQueueReceive(rx_queue, &c, 0)) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t USBCDC::read(uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
if(itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint8_t c = 0;
|
||||||
|
size_t count = 0;
|
||||||
|
while(count < size && xQueueReceive(rx_queue, &c, 0)){
|
||||||
|
buffer[count++] = c;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBCDC::flush(void)
|
||||||
|
{
|
||||||
|
if(itf >= MAX_USB_CDC_DEVICES){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tud_cdc_n_write_flush(itf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int USBCDC::availableForWrite(void)
|
||||||
|
{
|
||||||
|
if(itf >= MAX_USB_CDC_DEVICES){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return tud_cdc_n_write_available(itf);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t USBCDC::write(const uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
return tinyusb_cdc_write(itf, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t USBCDC::write(uint8_t c)
|
||||||
|
{
|
||||||
|
return write(&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t USBCDC::baudRate()
|
||||||
|
{
|
||||||
|
return bit_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBCDC::setDebugOutput(bool en)
|
||||||
|
{
|
||||||
|
if(en) {
|
||||||
|
uartSetDebug(NULL);
|
||||||
|
ets_install_putc1((void (*)(char)) &cdc0_write_char);
|
||||||
|
} else {
|
||||||
|
ets_install_putc1(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
USBCDC::operator bool() const
|
||||||
|
{
|
||||||
|
if(itf >= MAX_USB_CDC_DEVICES){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
||||||
|
USBCDC Serial(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONFIG_USB_CDC_ENABLED */
|
||||||
|
|
||||||
|
#endif /* CONFIG_USB_ENABLED */
|
133
cores/esp32/USBCDC.h
Normal file
133
cores/esp32/USBCDC.h
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "Stream.h"
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
#if CONFIG_USB_CDC_ENABLED
|
||||||
|
|
||||||
|
#include "esp_event.h"
|
||||||
|
|
||||||
|
ESP_EVENT_DECLARE_BASE(ARDUINO_USB_CDC_EVENTS);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ARDUINO_USB_CDC_ANY_EVENT = ESP_EVENT_ANY_ID,
|
||||||
|
ARDUINO_USB_CDC_CONNECTED_EVENT = 0,
|
||||||
|
ARDUINO_USB_CDC_DISCONNECTED_EVENT,
|
||||||
|
ARDUINO_USB_CDC_LINE_STATE_EVENT,
|
||||||
|
ARDUINO_USB_CDC_LINE_CODING_EVENT,
|
||||||
|
ARDUINO_USB_CDC_RX_EVENT,
|
||||||
|
ARDUINO_USB_CDC_MAX_EVENT,
|
||||||
|
} arduino_usb_cdc_event_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
bool dtr;
|
||||||
|
bool rts;
|
||||||
|
} line_state;
|
||||||
|
struct {
|
||||||
|
uint32_t bit_rate;
|
||||||
|
uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits
|
||||||
|
uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space
|
||||||
|
uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16
|
||||||
|
} line_coding;
|
||||||
|
struct {
|
||||||
|
size_t len;
|
||||||
|
} rx;
|
||||||
|
} arduino_usb_cdc_event_data_t;
|
||||||
|
|
||||||
|
class USBCDC: public Stream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
USBCDC(uint8_t itf=0);
|
||||||
|
|
||||||
|
void onEvent(esp_event_handler_t callback);
|
||||||
|
void onEvent(arduino_usb_cdc_event_t event, esp_event_handler_t callback);
|
||||||
|
|
||||||
|
size_t setRxBufferSize(size_t);
|
||||||
|
void begin(unsigned long baud=0);
|
||||||
|
void end();
|
||||||
|
|
||||||
|
int available(void);
|
||||||
|
int availableForWrite(void);
|
||||||
|
int peek(void);
|
||||||
|
int read(void);
|
||||||
|
size_t read(uint8_t *buffer, size_t size);
|
||||||
|
size_t write(uint8_t);
|
||||||
|
size_t write(const uint8_t *buffer, size_t size);
|
||||||
|
void flush(void);
|
||||||
|
|
||||||
|
inline size_t read(char * buffer, size_t size)
|
||||||
|
{
|
||||||
|
return read((uint8_t*) buffer, 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();
|
||||||
|
void setDebugOutput(bool);
|
||||||
|
operator bool() const;
|
||||||
|
|
||||||
|
void enableReboot(bool enable);
|
||||||
|
bool rebootEnabled(void);
|
||||||
|
|
||||||
|
//internal methods
|
||||||
|
void _onDFU(void);
|
||||||
|
void _onLineState(bool _dtr, bool _rts);
|
||||||
|
void _onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _parity, uint8_t _data_bits);
|
||||||
|
void _onRX(void);
|
||||||
|
void _onUnplugged(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint8_t itf;
|
||||||
|
uint32_t bit_rate;
|
||||||
|
uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits
|
||||||
|
uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space
|
||||||
|
uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16
|
||||||
|
bool dtr;
|
||||||
|
bool rts;
|
||||||
|
bool connected;
|
||||||
|
bool reboot_enable;
|
||||||
|
xQueueHandle rx_queue;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
||||||
|
extern USBCDC Serial;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONFIG_USB_CDC_ENABLED */
|
@ -65,9 +65,12 @@ long random(long howsmall, long howbig)
|
|||||||
return random(diff) + howsmall;
|
return random(diff) + howsmall;
|
||||||
}
|
}
|
||||||
|
|
||||||
long map(long x, long in_min, long in_max, long out_min, long out_max)
|
long map(long x, long in_min, long in_max, long out_min, long out_max) {
|
||||||
{
|
long divisor = (in_max - in_min);
|
||||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
if(divisor == 0){
|
||||||
|
return -1; //AVR returns -1, SAM returns 0
|
||||||
|
}
|
||||||
|
return (x - in_min) * (out_max - out_min) / divisor + out_min;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int makeWord(unsigned int w)
|
unsigned int makeWord(unsigned int w)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <pgmspace.h>
|
#include <pgmspace.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
// An inherited class for holding the result of a concatenation. These
|
// An inherited class for holding the result of a concatenation. These
|
||||||
// result objects are assumed to be writable by subsequent concatenations.
|
// result objects are assumed to be writable by subsequent concatenations.
|
||||||
@ -35,295 +36,327 @@ class StringSumHelper;
|
|||||||
// an abstract class used as a means to proide a unique pointer type
|
// an abstract class used as a means to proide a unique pointer type
|
||||||
// but really has no body
|
// but really has no body
|
||||||
class __FlashStringHelper;
|
class __FlashStringHelper;
|
||||||
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
|
#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
|
||||||
|
#define F(string_literal) (FPSTR(PSTR(string_literal)))
|
||||||
|
|
||||||
// The string class
|
// The string class
|
||||||
class String
|
class String {
|
||||||
{
|
// use a function pointer to allow for "if (s)" without the
|
||||||
// use a function pointer to allow for "if (s)" without the
|
// complications of an operator bool(). for more information, see:
|
||||||
// complications of an operator bool(). for more information, see:
|
// http://www.artima.com/cppsource/safebool.html
|
||||||
// http://www.artima.com/cppsource/safebool.html
|
typedef void (String::*StringIfHelperType)() const;
|
||||||
typedef void (String::*StringIfHelperType)() const;
|
void StringIfHelper() 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) : String(reinterpret_cast<const char *>(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;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// creates a copy of the assigned value. if the value is null or
|
public:
|
||||||
// invalid, or if the memory allocation fails, the string will be
|
// constructors
|
||||||
// marked as invalid ("if (s)" will be false).
|
// creates a copy of the initial value.
|
||||||
String & operator =(const String &rhs);
|
// if the initial value is null or invalid, or if memory allocation
|
||||||
String & operator =(const char *cstr);
|
// fails, the string will be marked as invalid (i.e. "if (s)" will
|
||||||
String & operator = (const __FlashStringHelper *str);
|
// be false).
|
||||||
|
String(const char *cstr = "");
|
||||||
|
String(const String &str);
|
||||||
|
String(const __FlashStringHelper *str);
|
||||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
String & operator =(String &&rval);
|
String(String &&rval);
|
||||||
String & operator =(StringSumHelper &&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
|
#endif
|
||||||
|
|
||||||
// concatenate (works w/ built-in types)
|
// concatenate (works w/ built-in types)
|
||||||
|
|
||||||
// returns true on success, false on failure (in which case, the string
|
// returns true on success, false on failure (in which case, the string
|
||||||
// is left unchanged). if the argument is null or invalid, the
|
// is left unchanged). if the argument is null or invalid, the
|
||||||
// concatenation is considered unsucessful.
|
// concatenation is considered unsuccessful.
|
||||||
unsigned char concat(const String &str);
|
unsigned char concat(const String &str);
|
||||||
unsigned char concat(const char *cstr);
|
unsigned char concat(const char *cstr);
|
||||||
unsigned char concat(char c);
|
unsigned char concat(char c);
|
||||||
unsigned char concat(unsigned char c);
|
unsigned char concat(unsigned char c);
|
||||||
unsigned char concat(int num);
|
unsigned char concat(int num);
|
||||||
unsigned char concat(unsigned int num);
|
unsigned char concat(unsigned int num);
|
||||||
unsigned char concat(long num);
|
unsigned char concat(long num);
|
||||||
unsigned char concat(unsigned long num);
|
unsigned char concat(unsigned long num);
|
||||||
unsigned char concat(float num);
|
unsigned char concat(float num);
|
||||||
unsigned char concat(double num);
|
unsigned char concat(double num);
|
||||||
unsigned char concat(const __FlashStringHelper * str);
|
unsigned char concat(const __FlashStringHelper * str);
|
||||||
|
|
||||||
// if there's not enough memory for the concatenated value, the string
|
// if there's not enough memory for the concatenated value, the string
|
||||||
// will be left unchanged (but this isn't signalled in any way)
|
// will be left unchanged (but this isn't signalled in any way)
|
||||||
String & operator +=(const String &rhs)
|
String & operator +=(const String &rhs) {
|
||||||
{
|
concat(rhs);
|
||||||
concat(rhs);
|
return (*this);
|
||||||
return (*this);
|
}
|
||||||
}
|
String & operator +=(const char *cstr) {
|
||||||
String & operator +=(const char *cstr)
|
concat(cstr);
|
||||||
{
|
return (*this);
|
||||||
concat(cstr);
|
}
|
||||||
return (*this);
|
String & operator +=(char c) {
|
||||||
}
|
concat(c);
|
||||||
String & operator +=(char c)
|
return (*this);
|
||||||
{
|
}
|
||||||
concat(c);
|
String & operator +=(unsigned char num) {
|
||||||
return (*this);
|
concat(num);
|
||||||
}
|
return (*this);
|
||||||
String & operator +=(unsigned char num)
|
}
|
||||||
{
|
String & operator +=(int num) {
|
||||||
concat(num);
|
concat(num);
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
String & operator +=(int num)
|
String & operator +=(unsigned int num) {
|
||||||
{
|
concat(num);
|
||||||
concat(num);
|
return (*this);
|
||||||
return (*this);
|
}
|
||||||
}
|
String & operator +=(long num) {
|
||||||
String & operator +=(unsigned int num)
|
concat(num);
|
||||||
{
|
return (*this);
|
||||||
concat(num);
|
}
|
||||||
return (*this);
|
String & operator +=(unsigned long num) {
|
||||||
}
|
concat(num);
|
||||||
String & operator +=(long num)
|
return (*this);
|
||||||
{
|
}
|
||||||
concat(num);
|
String & operator +=(float num) {
|
||||||
return (*this);
|
concat(num);
|
||||||
}
|
return (*this);
|
||||||
String & operator +=(unsigned long num)
|
}
|
||||||
{
|
String & operator +=(double num) {
|
||||||
concat(num);
|
concat(num);
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
String & operator +=(float num)
|
String & operator += (const __FlashStringHelper *str){
|
||||||
{
|
concat(str);
|
||||||
concat(num);
|
return (*this);
|
||||||
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 String &rhs);
|
||||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr);
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr);
|
||||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, char c);
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, char c);
|
||||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num);
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num);
|
||||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, int num);
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, int num);
|
||||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned 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, long num);
|
||||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned 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, float num);
|
||||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, double num);
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, double num);
|
||||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, const __FlashStringHelper *rhs);
|
friend StringSumHelper & operator +(const StringSumHelper &lhs, const __FlashStringHelper *rhs);
|
||||||
|
|
||||||
// comparison (only works w/ Strings and "strings")
|
// comparison (only works w/ Strings and "strings")
|
||||||
operator StringIfHelperType() const
|
operator StringIfHelperType() const {
|
||||||
{
|
return buffer() ? &String::StringIfHelper : 0;
|
||||||
return buffer ? &String::StringIfHelper : 0;
|
}
|
||||||
}
|
int compareTo(const String &s) const;
|
||||||
int compareTo(const String &s) const;
|
unsigned char equals(const String &s) const;
|
||||||
unsigned char equals(const String &s) const;
|
unsigned char equals(const char *cstr) const;
|
||||||
unsigned char equals(const char *cstr) const;
|
unsigned char operator ==(const String &rhs) const {
|
||||||
unsigned char operator ==(const String &rhs) const
|
return equals(rhs);
|
||||||
{
|
}
|
||||||
return equals(rhs);
|
unsigned char operator ==(const char *cstr) const {
|
||||||
}
|
return equals(cstr);
|
||||||
unsigned char operator ==(const char *cstr) const
|
}
|
||||||
{
|
unsigned char operator !=(const String &rhs) const {
|
||||||
return equals(cstr);
|
return !equals(rhs);
|
||||||
}
|
}
|
||||||
unsigned char operator !=(const String &rhs) const
|
unsigned char operator !=(const char *cstr) const {
|
||||||
{
|
return !equals(cstr);
|
||||||
return !equals(rhs);
|
}
|
||||||
}
|
unsigned char operator <(const String &rhs) const;
|
||||||
unsigned char operator !=(const char *cstr) const
|
unsigned char operator >(const String &rhs) const;
|
||||||
{
|
unsigned char operator <=(const String &rhs) const;
|
||||||
return !equals(cstr);
|
unsigned char operator >=(const String &rhs) const;
|
||||||
}
|
unsigned char equalsIgnoreCase(const String &s) const;
|
||||||
unsigned char operator <(const String &rhs) const;
|
unsigned char equalsConstantTime(const String &s) const;
|
||||||
unsigned char operator >(const String &rhs) const;
|
unsigned char startsWith(const String &prefix) const;
|
||||||
unsigned char operator <=(const String &rhs) const;
|
unsigned char startsWith(const char *prefix) const {
|
||||||
unsigned char operator >=(const String &rhs) const;
|
return this->startsWith(String(prefix));
|
||||||
unsigned char equalsIgnoreCase(const String &s) const;
|
}
|
||||||
unsigned char equalsConstantTime(const String &s) const;
|
unsigned char startsWith(const __FlashStringHelper *prefix) const {
|
||||||
unsigned char startsWith(const String &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 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 acccess
|
// character access
|
||||||
char charAt(unsigned int index) const;
|
char charAt(unsigned int index) const;
|
||||||
void setCharAt(unsigned int index, char c);
|
void setCharAt(unsigned int index, char c);
|
||||||
char operator [](unsigned int index) const;
|
char operator [](unsigned int index) const;
|
||||||
char& operator [](unsigned int index);
|
char& operator [](unsigned int index);
|
||||||
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index = 0) const;
|
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
|
void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const {
|
||||||
{
|
getBytes((unsigned char *) buf, bufsize, index);
|
||||||
getBytes((unsigned char *) buf, bufsize, index);
|
}
|
||||||
}
|
const char* c_str() const { return buffer(); }
|
||||||
const char * c_str() const
|
char* begin() { return wbuffer(); }
|
||||||
{
|
char* end() { return wbuffer() + length(); }
|
||||||
return buffer;
|
const char* begin() const { return c_str(); }
|
||||||
}
|
const char* end() const { return c_str() + length(); }
|
||||||
|
|
||||||
// search
|
// search
|
||||||
int indexOf(char ch) const;
|
int indexOf(char ch) const;
|
||||||
int indexOf(char ch, unsigned int fromIndex) const;
|
int indexOf(char ch, unsigned int fromIndex) const;
|
||||||
int indexOf(const String &str) const;
|
int indexOf(const String &str) const;
|
||||||
int indexOf(const String &str, unsigned int fromIndex) const;
|
int indexOf(const String &str, unsigned int fromIndex) const;
|
||||||
int lastIndexOf(char ch) const;
|
int lastIndexOf(char ch) const;
|
||||||
int lastIndexOf(char ch, unsigned int fromIndex) const;
|
int lastIndexOf(char ch, unsigned int fromIndex) const;
|
||||||
int lastIndexOf(const String &str) const;
|
int lastIndexOf(const String &str) const;
|
||||||
int lastIndexOf(const String &str, unsigned int fromIndex) const;
|
int lastIndexOf(const String &str, unsigned int fromIndex) const;
|
||||||
String substring(unsigned int beginIndex) const
|
String substring(unsigned int beginIndex) const {
|
||||||
{
|
return substring(beginIndex, len());
|
||||||
return substring(beginIndex, len);
|
}
|
||||||
}
|
;
|
||||||
;
|
String substring(unsigned int beginIndex, unsigned int endIndex) const;
|
||||||
String substring(unsigned int beginIndex, unsigned int endIndex) const;
|
|
||||||
|
|
||||||
// modification
|
// modification
|
||||||
void replace(char find, char replace);
|
void replace(char find, char replace);
|
||||||
void replace(const String& find, const String& replace);
|
void replace(const String &find, const String &replace);
|
||||||
void remove(unsigned int index);
|
void replace(const char *find, const String &replace) {
|
||||||
void remove(unsigned int index, unsigned int count);
|
this->replace(String(find), replace);
|
||||||
void toLowerCase(void);
|
}
|
||||||
void toUpperCase(void);
|
void replace(const __FlashStringHelper *find, const String &replace) {
|
||||||
void trim(void);
|
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
|
// parsing/conversion
|
||||||
long toInt(void) const;
|
long toInt(void) const;
|
||||||
float toFloat(void) const;
|
float toFloat(void) const;
|
||||||
double toDouble(void) const;
|
double toDouble(void) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
char *buffer; // the actual char array
|
// Contains the string info when we're not in SSO mode
|
||||||
unsigned int capacity; // the array length minus one (for the '\0')
|
struct _ptr {
|
||||||
unsigned int len; // the String length (not counting the '\0')
|
char * buff;
|
||||||
protected:
|
uint16_t cap;
|
||||||
void init(void);
|
uint16_t len;
|
||||||
void invalidate(void);
|
};
|
||||||
unsigned char changeBuffer(unsigned int maxStrLen);
|
// This allows strings up up to 11 (10 + \0 termination) without any extra space.
|
||||||
unsigned char concat(const char *cstr, unsigned int length);
|
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
|
||||||
|
enum { CAPACITY_MAX = 65535 }; // If typeof(cap) changed from uint16_t, be sure to update this enum to the max value storable in the type
|
||||||
|
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; else ptr.len = len; }
|
||||||
|
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
|
||||||
|
|
||||||
// copy and move
|
protected:
|
||||||
String & copy(const char *cstr, unsigned int length);
|
void init(void);
|
||||||
String & copy(const __FlashStringHelper *pstr, unsigned int length);
|
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__
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
void move(String &rhs);
|
void move(String &rhs);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringSumHelper: public String
|
class StringSumHelper: public String {
|
||||||
{
|
public:
|
||||||
public:
|
StringSumHelper(const String &s) :
|
||||||
StringSumHelper(const String &s) :
|
String(s) {
|
||||||
String(s)
|
}
|
||||||
{
|
StringSumHelper(const char *p) :
|
||||||
}
|
String(p) {
|
||||||
StringSumHelper(const char *p) :
|
}
|
||||||
String(p)
|
StringSumHelper(char c) :
|
||||||
{
|
String(c) {
|
||||||
}
|
}
|
||||||
StringSumHelper(char c) :
|
StringSumHelper(unsigned char num) :
|
||||||
String(c)
|
String(num) {
|
||||||
{
|
}
|
||||||
}
|
StringSumHelper(int num) :
|
||||||
StringSumHelper(unsigned char num) :
|
String(num) {
|
||||||
String(num)
|
}
|
||||||
{
|
StringSumHelper(unsigned int num) :
|
||||||
}
|
String(num) {
|
||||||
StringSumHelper(int num) :
|
}
|
||||||
String(num)
|
StringSumHelper(long num) :
|
||||||
{
|
String(num) {
|
||||||
}
|
}
|
||||||
StringSumHelper(unsigned int num) :
|
StringSumHelper(unsigned long num) :
|
||||||
String(num)
|
String(num) {
|
||||||
{
|
}
|
||||||
}
|
StringSumHelper(float num) :
|
||||||
StringSumHelper(long num) :
|
String(num) {
|
||||||
String(num)
|
}
|
||||||
{
|
StringSumHelper(double 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 // __cplusplus
|
||||||
#endif // String_class_h
|
#endif // String_class_h
|
||||||
|
@ -31,11 +31,11 @@ extern "C" {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* convert input data to base64
|
* convert input data to base64
|
||||||
* @param data uint8_t *
|
* @param data const uint8_t *
|
||||||
* @param length size_t
|
* @param length size_t
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
String base64::encode(uint8_t * data, size_t length)
|
String base64::encode(const uint8_t * data, size_t length)
|
||||||
{
|
{
|
||||||
size_t size = base64_encode_expected_len(length) + 1;
|
size_t size = base64_encode_expected_len(length) + 1;
|
||||||
char * buffer = (char *) malloc(size);
|
char * buffer = (char *) malloc(size);
|
||||||
@ -54,10 +54,10 @@ String base64::encode(uint8_t * data, size_t length)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* convert input data to base64
|
* convert input data to base64
|
||||||
* @param text String
|
* @param text const String&
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
String base64::encode(String text)
|
String base64::encode(const String& text)
|
||||||
{
|
{
|
||||||
return base64::encode((uint8_t *) text.c_str(), text.length());
|
return base64::encode((uint8_t *) text.c_str(), text.length());
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
class base64
|
class base64
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static String encode(uint8_t * data, size_t length);
|
static String encode(const uint8_t * data, size_t length);
|
||||||
static String encode(String text);
|
static String encode(const String& text);
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,103 +15,72 @@
|
|||||||
#include "esp32-hal-adc.h"
|
#include "esp32-hal-adc.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "rom/ets_sys.h"
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_intr.h"
|
|
||||||
#include "soc/rtc_io_reg.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 "soc/sens_reg.h"
|
||||||
|
|
||||||
|
#include "driver/adc.h"
|
||||||
|
|
||||||
|
#include "esp_system.h"
|
||||||
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "esp_adc_cal.h"
|
||||||
|
#include "esp32/rom/ets_sys.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
#define DEFAULT_VREF 1100
|
||||||
|
static esp_adc_cal_characteristics_t *__analogCharacteristics[2] = {NULL, NULL};
|
||||||
|
static uint16_t __analogVRef = 0;
|
||||||
|
static uint8_t __analogVRefPin = 0;
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/ets_sys.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
|
||||||
|
|
||||||
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
|
||||||
static uint8_t __analogCycles = 8;
|
|
||||||
static uint8_t __analogSamples = 0;//1 sample
|
|
||||||
static uint8_t __analogClockDiv = 1;
|
static uint8_t __analogClockDiv = 1;
|
||||||
|
|
||||||
// Width of returned answer ()
|
void __analogSetClockDiv(uint8_t clockDiv){
|
||||||
static uint8_t __analogReturnedWidth = 12;
|
if(!clockDiv){
|
||||||
|
clockDiv = 1;
|
||||||
|
}
|
||||||
|
__analogClockDiv = clockDiv;
|
||||||
|
adc_set_clk_div(__analogClockDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __analogSetAttenuation(adc_attenuation_t attenuation)
|
||||||
|
{
|
||||||
|
__analogAttenuation = attenuation & 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
void __analogSetWidth(uint8_t bits){
|
void __analogSetWidth(uint8_t bits){
|
||||||
if(bits < 9){
|
if(bits < 9){
|
||||||
bits = 9;
|
bits = 9;
|
||||||
} else if(bits > 12){
|
} else if(bits > 12){
|
||||||
bits = 12;
|
bits = 12;
|
||||||
}
|
}
|
||||||
__analogReturnedWidth = bits;
|
|
||||||
__analogWidth = bits - 9;
|
__analogWidth = bits - 9;
|
||||||
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR1_BIT_WIDTH, __analogWidth, SENS_SAR1_BIT_WIDTH_S);
|
adc1_config_width(__analogWidth);
|
||||||
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_BIT, __analogWidth, SENS_SAR1_SAMPLE_BIT_S);
|
|
||||||
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR2_BIT_WIDTH, __analogWidth, SENS_SAR2_BIT_WIDTH_S);
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_BIT, __analogWidth, SENS_SAR2_SAMPLE_BIT_S);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void __analogSetCycles(uint8_t cycles){
|
void __analogInit(){
|
||||||
__analogCycles = cycles;
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_CYCLE, __analogCycles, SENS_SAR1_SAMPLE_CYCLE_S);
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_CYCLE, __analogCycles, SENS_SAR2_SAMPLE_CYCLE_S);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __analogSetSamples(uint8_t samples){
|
|
||||||
if(!samples){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
__analogSamples = samples - 1;
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_NUM, __analogSamples, SENS_SAR1_SAMPLE_NUM_S);
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_NUM, __analogSamples, SENS_SAR2_SAMPLE_NUM_S);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __analogSetClockDiv(uint8_t clockDiv){
|
|
||||||
if(!clockDiv){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
__analogClockDiv = clockDiv;
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_CLK_DIV, __analogClockDiv, SENS_SAR1_CLK_DIV_S);
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_CLK_DIV, __analogClockDiv, SENS_SAR2_CLK_DIV_S);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __analogSetAttenuation(adc_attenuation_t attenuation)
|
|
||||||
{
|
|
||||||
__analogAttenuation = attenuation & 3;
|
|
||||||
uint32_t att_data = 0;
|
|
||||||
int i = 10;
|
|
||||||
while(i--){
|
|
||||||
att_data |= __analogAttenuation << (i * 2);
|
|
||||||
}
|
|
||||||
WRITE_PERI_REG(SENS_SAR_ATTEN1_REG, att_data & 0xFFFF);//ADC1 has 8 channels
|
|
||||||
WRITE_PERI_REG(SENS_SAR_ATTEN2_REG, att_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRAM_ATTR __analogInit(){
|
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
if(initialized){
|
if(initialized){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
__analogSetAttenuation(__analogAttenuation);
|
|
||||||
__analogSetCycles(__analogCycles);
|
|
||||||
__analogSetSamples(__analogSamples + 1);//in samples
|
|
||||||
__analogSetClockDiv(__analogClockDiv);
|
|
||||||
__analogSetWidth(__analogWidth + 9);//in bits
|
|
||||||
|
|
||||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DATA_INV);
|
|
||||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV);
|
|
||||||
|
|
||||||
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_FORCE_M); //SAR ADC1 controller (in RTC) is started by SW
|
|
||||||
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD_FORCE_M); //SAR ADC1 pad enable bitmap is controlled by SW
|
|
||||||
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_FORCE_M); //SAR ADC2 controller (in RTC) is started by SW
|
|
||||||
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD_FORCE_M); //SAR ADC2 pad enable bitmap is controlled by SW
|
|
||||||
|
|
||||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR_M); //force XPD_SAR=0, use XPD_FSM
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_AMP, 0x2, SENS_FORCE_XPD_AMP_S); //force XPD_AMP=0
|
|
||||||
|
|
||||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_CTRL_REG, 0xfff << SENS_AMP_RST_FB_FSM_S); //clear FSM
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT1, 0x1, SENS_SAR_AMP_WAIT1_S);
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT2, 0x1, SENS_SAR_AMP_WAIT2_S);
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_SAR_AMP_WAIT3, 0x1, SENS_SAR_AMP_WAIT3_S);
|
|
||||||
while (GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR1_REG, 0x7, SENS_MEAS_STATUS_S) != 0); //wait det_fsm==
|
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
__analogSetClockDiv(__analogClockDiv);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
__analogSetWidth(__analogWidth + 9);//in bits
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation)
|
void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation)
|
||||||
@ -120,23 +89,23 @@ void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation)
|
|||||||
if(channel < 0 || attenuation > 3){
|
if(channel < 0 || attenuation > 3){
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
__analogInit();
|
if(channel > 9){
|
||||||
if(channel > 7){
|
adc2_config_channel_atten(channel - 10, attenuation);
|
||||||
SET_PERI_REG_BITS(SENS_SAR_ATTEN2_REG, 3, attenuation, ((channel - 10) * 2));
|
|
||||||
} else {
|
} else {
|
||||||
SET_PERI_REG_BITS(SENS_SAR_ATTEN1_REG, 3, attenuation, (channel * 2));
|
adc1_config_channel_atten(channel, attenuation);
|
||||||
}
|
}
|
||||||
|
__analogInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IRAM_ATTR __adcAttachPin(uint8_t pin){
|
bool __adcAttachPin(uint8_t pin){
|
||||||
|
|
||||||
int8_t channel = digitalPinToAnalogChannel(pin);
|
int8_t channel = digitalPinToAnalogChannel(pin);
|
||||||
if(channel < 0){
|
if(channel < 0){
|
||||||
return false;//not adc pin
|
log_e("Pin %u is not ADC pin!", pin);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t pad = digitalPinToTouchChannel(pin);
|
int8_t pad = digitalPinToTouchChannel(pin);
|
||||||
if(pad >= 0){
|
if(pad >= 0){
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
uint32_t touch = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
|
uint32_t touch = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
|
||||||
if(touch & (1 << pad)){
|
if(touch & (1 << pad)){
|
||||||
touch &= ~((1 << (pad + SENS_TOUCH_PAD_OUTEN2_S))
|
touch &= ~((1 << (pad + SENS_TOUCH_PAD_OUTEN2_S))
|
||||||
@ -144,6 +113,7 @@ bool IRAM_ATTR __adcAttachPin(uint8_t pin){
|
|||||||
| (1 << (pad + SENS_TOUCH_PAD_WORKEN_S)));
|
| (1 << (pad + SENS_TOUCH_PAD_WORKEN_S)));
|
||||||
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, touch);
|
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, touch);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} else if(pin == 25){
|
} 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){
|
||||||
@ -151,86 +121,120 @@ bool IRAM_ATTR __adcAttachPin(uint8_t pin){
|
|||||||
}
|
}
|
||||||
|
|
||||||
pinMode(pin, ANALOG);
|
pinMode(pin, ANALOG);
|
||||||
|
__analogSetPinAttenuation(pin, __analogAttenuation);
|
||||||
__analogInit();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IRAM_ATTR __adcStart(uint8_t pin){
|
|
||||||
|
|
||||||
int8_t channel = digitalPinToAnalogChannel(pin);
|
|
||||||
if(channel < 0){
|
|
||||||
return false;//not adc pin
|
|
||||||
}
|
|
||||||
|
|
||||||
if(channel > 9){
|
|
||||||
channel -= 10;
|
|
||||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_SAR_M);
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD, (1 << channel), SENS_SAR2_EN_PAD_S);
|
|
||||||
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_SAR_M);
|
|
||||||
} else {
|
|
||||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M);
|
|
||||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD, (1 << channel), SENS_SAR1_EN_PAD_S);
|
|
||||||
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IRAM_ATTR __adcBusy(uint8_t pin){
|
|
||||||
|
|
||||||
int8_t channel = digitalPinToAnalogChannel(pin);
|
|
||||||
if(channel < 0){
|
|
||||||
return false;//not adc pin
|
|
||||||
}
|
|
||||||
|
|
||||||
if(channel > 7){
|
|
||||||
return (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0);
|
|
||||||
}
|
|
||||||
return (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t IRAM_ATTR __adcEnd(uint8_t pin)
|
|
||||||
{
|
|
||||||
|
|
||||||
uint16_t value = 0;
|
|
||||||
int8_t channel = digitalPinToAnalogChannel(pin);
|
|
||||||
if(channel < 0){
|
|
||||||
return 0;//not adc pin
|
|
||||||
}
|
|
||||||
if(channel > 7){
|
|
||||||
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0); //wait for conversion
|
|
||||||
value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DATA_SAR, SENS_MEAS2_DATA_SAR_S);
|
|
||||||
} else {
|
|
||||||
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0); //wait for conversion
|
|
||||||
value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DATA_SAR, SENS_MEAS1_DATA_SAR_S);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shift result if necessary
|
|
||||||
uint8_t from = __analogWidth + 9;
|
|
||||||
if (from == __analogReturnedWidth) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
if (from > __analogReturnedWidth) {
|
|
||||||
return value >> (from - __analogReturnedWidth);
|
|
||||||
}
|
|
||||||
return value << (__analogReturnedWidth - from);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t IRAM_ATTR __analogRead(uint8_t pin)
|
|
||||||
{
|
|
||||||
if(!__adcAttachPin(pin) || !__adcStart(pin)){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return __adcEnd(pin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __analogReadResolution(uint8_t bits)
|
void __analogReadResolution(uint8_t bits)
|
||||||
{
|
{
|
||||||
if(!bits || bits > 16){
|
if(!bits || bits > 16){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
__analogSetWidth(bits); // hadware from 9 to 12
|
__analogSetWidth(bits); // hadware from 9 to 12
|
||||||
__analogReturnedWidth = bits; // software from 1 to 16
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t __analogRead(uint8_t pin)
|
||||||
|
{
|
||||||
|
int8_t channel = digitalPinToAnalogChannel(pin);
|
||||||
|
int value = 0;
|
||||||
|
esp_err_t r = ESP_OK;
|
||||||
|
if(channel < 0){
|
||||||
|
log_e("Pin %u is not ADC pin!", pin);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
__adcAttachPin(pin);
|
||||||
|
if(channel > 9){
|
||||||
|
channel -= 10;
|
||||||
|
r = adc2_get_raw( channel, __analogWidth, &value);
|
||||||
|
if ( r == ESP_OK ) {
|
||||||
|
return value;
|
||||||
|
} else if ( r == ESP_ERR_INVALID_STATE ) {
|
||||||
|
log_e("GPIO%u: %s: ADC2 not initialized yet.", pin, esp_err_to_name(r));
|
||||||
|
} else if ( r == ESP_ERR_TIMEOUT ) {
|
||||||
|
log_e("GPIO%u: %s: ADC2 is in use by Wi-Fi.", pin, esp_err_to_name(r));
|
||||||
|
} else {
|
||||||
|
log_e("GPIO%u: %s", pin, esp_err_to_name(r));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return adc1_get_raw(channel);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t __analogReadMilliVolts(uint8_t pin){
|
||||||
|
int8_t channel = digitalPinToAnalogChannel(pin);
|
||||||
|
if(channel < 0){
|
||||||
|
log_e("Pin %u is not ADC pin!", pin);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
if(!__analogVRef){
|
||||||
|
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
|
||||||
|
log_d("eFuse Two Point: Supported");
|
||||||
|
__analogVRef = DEFAULT_VREF;
|
||||||
|
}
|
||||||
|
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
|
||||||
|
log_d("eFuse Vref: Supported");
|
||||||
|
__analogVRef = DEFAULT_VREF;
|
||||||
|
}
|
||||||
|
if(!__analogVRef){
|
||||||
|
__analogVRef = DEFAULT_VREF;
|
||||||
|
if(__analogVRefPin){
|
||||||
|
esp_adc_cal_characteristics_t chars;
|
||||||
|
if(adc2_vref_to_gpio(__analogVRefPin) == ESP_OK){
|
||||||
|
__analogVRef = __analogRead(__analogVRefPin);
|
||||||
|
esp_adc_cal_characterize(1, __analogAttenuation, __analogWidth, DEFAULT_VREF, &chars);
|
||||||
|
__analogVRef = esp_adc_cal_raw_to_voltage(__analogVRef, &chars);
|
||||||
|
log_d("Vref to GPIO%u: %u", __analogVRefPin, __analogVRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t unit = 1;
|
||||||
|
if(channel > 9){
|
||||||
|
unit = 2;
|
||||||
|
}
|
||||||
|
uint16_t adc_reading = __analogRead(pin);
|
||||||
|
if(__analogCharacteristics[unit - 1] == NULL){
|
||||||
|
__analogCharacteristics[unit - 1] = calloc(1, sizeof(esp_adc_cal_characteristics_t));
|
||||||
|
if(__analogCharacteristics[unit - 1] == NULL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, __analogAttenuation, __analogWidth, __analogVRef, __analogCharacteristics[unit - 1]);
|
||||||
|
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
|
||||||
|
log_i("ADC%u: Characterized using Two Point Value: %u\n", unit, __analogCharacteristics[unit - 1]->vref);
|
||||||
|
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
|
||||||
|
log_i("ADC%u: Characterized using eFuse Vref: %u\n", unit, __analogCharacteristics[unit - 1]->vref);
|
||||||
|
} else if(__analogVRef != DEFAULT_VREF){
|
||||||
|
log_i("ADC%u: Characterized using Vref to GPIO%u: %u\n", unit, __analogVRefPin, __analogCharacteristics[unit - 1]->vref);
|
||||||
|
} else {
|
||||||
|
log_i("ADC%u: Characterized using Default Vref: %u\n", unit, __analogCharacteristics[unit - 1]->vref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return esp_adc_cal_raw_to_voltage(adc_reading, __analogCharacteristics[unit - 1]);
|
||||||
|
#else
|
||||||
|
uint16_t adc_reading = __analogRead(pin);
|
||||||
|
uint16_t max_reading = 8191;
|
||||||
|
uint16_t max_mv = 1100;
|
||||||
|
switch(__analogAttenuation){
|
||||||
|
case 3: max_mv = 3900; break;
|
||||||
|
case 2: max_mv = 2200; break;
|
||||||
|
case 1: max_mv = 1500; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return (adc_reading * max_mv) / max_reading;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
|
||||||
|
void __analogSetVRefPin(uint8_t pin){
|
||||||
|
if(pin <25 || pin > 27){
|
||||||
|
pin = 0;
|
||||||
|
}
|
||||||
|
__analogVRefPin = pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __hallRead() //hall sensor without LNA
|
int __hallRead() //hall sensor without LNA
|
||||||
@ -256,18 +260,20 @@ int __hallRead() //hall sensor without LNA
|
|||||||
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE);
|
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE);
|
||||||
return (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0);
|
return (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
extern uint16_t analogRead(uint8_t pin) __attribute__ ((weak, alias("__analogRead")));
|
extern uint16_t analogRead(uint8_t pin) __attribute__ ((weak, alias("__analogRead")));
|
||||||
|
extern uint32_t analogReadMilliVolts(uint8_t pin) __attribute__ ((weak, alias("__analogReadMilliVolts")));
|
||||||
extern void analogReadResolution(uint8_t bits) __attribute__ ((weak, alias("__analogReadResolution")));
|
extern void analogReadResolution(uint8_t bits) __attribute__ ((weak, alias("__analogReadResolution")));
|
||||||
extern void analogSetWidth(uint8_t bits) __attribute__ ((weak, alias("__analogSetWidth")));
|
|
||||||
extern void analogSetCycles(uint8_t cycles) __attribute__ ((weak, alias("__analogSetCycles")));
|
|
||||||
extern void analogSetSamples(uint8_t samples) __attribute__ ((weak, alias("__analogSetSamples")));
|
|
||||||
extern void analogSetClockDiv(uint8_t clockDiv) __attribute__ ((weak, alias("__analogSetClockDiv")));
|
extern void analogSetClockDiv(uint8_t clockDiv) __attribute__ ((weak, alias("__analogSetClockDiv")));
|
||||||
extern void analogSetAttenuation(adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetAttenuation")));
|
extern void analogSetAttenuation(adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetAttenuation")));
|
||||||
extern void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetPinAttenuation")));
|
extern void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetPinAttenuation")));
|
||||||
extern int hallRead() __attribute__ ((weak, alias("__hallRead")));
|
|
||||||
|
|
||||||
extern bool adcAttachPin(uint8_t pin) __attribute__ ((weak, alias("__adcAttachPin")));
|
extern bool adcAttachPin(uint8_t pin) __attribute__ ((weak, alias("__adcAttachPin")));
|
||||||
extern bool adcStart(uint8_t pin) __attribute__ ((weak, alias("__adcStart")));
|
|
||||||
extern bool adcBusy(uint8_t pin) __attribute__ ((weak, alias("__adcBusy")));
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
extern uint16_t adcEnd(uint8_t pin) __attribute__ ((weak, alias("__adcEnd")));
|
extern void analogSetVRefPin(uint8_t pin) __attribute__ ((weak, alias("__analogSetVRefPin")));
|
||||||
|
extern void analogSetWidth(uint8_t bits) __attribute__ ((weak, alias("__analogSetWidth")));
|
||||||
|
extern int hallRead() __attribute__ ((weak, alias("__hallRead")));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -38,6 +38,11 @@ typedef enum {
|
|||||||
* */
|
* */
|
||||||
uint16_t analogRead(uint8_t pin);
|
uint16_t analogRead(uint8_t pin);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get MilliVolts value for pin
|
||||||
|
* */
|
||||||
|
uint32_t analogReadMilliVolts(uint8_t pin);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the resolution of analogRead return values. Default is 12 bits (range from 0 to 4096).
|
* Set the resolution of analogRead return values. Default is 12 bits (range from 0 to 4096).
|
||||||
* If between 9 and 12, it will equal the set hardware resolution, else value will be shifted.
|
* If between 9 and 12, it will equal the set hardware resolution, else value will be shifted.
|
||||||
@ -47,31 +52,6 @@ uint16_t analogRead(uint8_t pin);
|
|||||||
*/
|
*/
|
||||||
void analogReadResolution(uint8_t bits);
|
void analogReadResolution(uint8_t bits);
|
||||||
|
|
||||||
/*
|
|
||||||
* Sets the sample bits and read resolution
|
|
||||||
* Default is 12bit (0 - 4095)
|
|
||||||
* Range is 9 - 12
|
|
||||||
* */
|
|
||||||
void analogSetWidth(uint8_t bits);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set number of cycles per sample
|
|
||||||
* Default is 8 and seems to do well
|
|
||||||
* Range is 1 - 255
|
|
||||||
* */
|
|
||||||
void analogSetCycles(uint8_t cycles);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set number of samples in the range.
|
|
||||||
* Default is 1
|
|
||||||
* Range is 1 - 255
|
|
||||||
* This setting splits the range into
|
|
||||||
* "samples" pieces, which could look
|
|
||||||
* like the sensitivity has been multiplied
|
|
||||||
* that many times
|
|
||||||
* */
|
|
||||||
void analogSetSamples(uint8_t samples);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the divider for the ADC clock.
|
* Set the divider for the ADC clock.
|
||||||
* Default is 1
|
* Default is 1
|
||||||
@ -91,40 +71,30 @@ void analogSetAttenuation(adc_attenuation_t attenuation);
|
|||||||
* */
|
* */
|
||||||
void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation);
|
void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation);
|
||||||
|
|
||||||
/*
|
|
||||||
* Get value for HALL sensor (without LNA)
|
|
||||||
* connected to pins 36(SVP) and 39(SVN)
|
|
||||||
* */
|
|
||||||
int hallRead();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Non-Blocking API (almost)
|
|
||||||
*
|
|
||||||
* Note: ADC conversion can run only for single pin at a time.
|
|
||||||
* That means that if you want to run ADC on two pins on the same bus,
|
|
||||||
* you need to run them one after another. Probably the best use would be
|
|
||||||
* to start conversion on both buses in parallel.
|
|
||||||
* */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attach pin to ADC (will also clear any other analog mode that could be on)
|
* Attach pin to ADC (will also clear any other analog mode that could be on)
|
||||||
* */
|
* */
|
||||||
bool adcAttachPin(uint8_t pin);
|
bool adcAttachPin(uint8_t pin);
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
/*
|
/*
|
||||||
* Start ADC conversion on attached pin's bus
|
* Sets the sample bits and read resolution
|
||||||
|
* Default is 12bit (0 - 4095)
|
||||||
|
* Range is 9 - 12
|
||||||
* */
|
* */
|
||||||
bool adcStart(uint8_t pin);
|
void analogSetWidth(uint8_t bits);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if conversion on the pin's ADC bus is currently running
|
* Set pin to use for ADC calibration if the esp is not already calibrated (25, 26 or 27)
|
||||||
* */
|
* */
|
||||||
bool adcBusy(uint8_t pin);
|
void analogSetVRefPin(uint8_t pin);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the result of the conversion (will wait if it have not finished)
|
* Get value for HALL sensor (without LNA)
|
||||||
|
* connected to pins 36(SVP) and 39(SVN)
|
||||||
* */
|
* */
|
||||||
uint16_t adcEnd(uint8_t pin);
|
int hallRead();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,14 @@ bool btStop(){
|
|||||||
while(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED);
|
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_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;
|
return true;
|
||||||
}
|
}
|
||||||
log_e("BT Stop failed");
|
log_e("BT Stop failed");
|
||||||
|
@ -21,18 +21,31 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#include "rom/rtc.h"
|
|
||||||
#include "soc/apb_ctrl_reg.h"
|
#include "soc/apb_ctrl_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 "esp_system.h"
|
||||||
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "esp32/rom/rtc.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/rtc.h"
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
|
#include "rom/rtc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct apb_change_cb_s {
|
typedef struct apb_change_cb_s {
|
||||||
|
struct apb_change_cb_s * prev;
|
||||||
struct apb_change_cb_s * next;
|
struct apb_change_cb_s * next;
|
||||||
void * arg;
|
void * arg;
|
||||||
apb_change_cb_t cb;
|
apb_change_cb_t cb;
|
||||||
} apb_change_t;
|
} apb_change_t;
|
||||||
|
|
||||||
const uint32_t MHZ = 1000000;
|
|
||||||
|
|
||||||
static apb_change_t * apb_change_callbacks = NULL;
|
static apb_change_t * apb_change_callbacks = NULL;
|
||||||
static xSemaphoreHandle apb_change_lock = NULL;
|
static xSemaphoreHandle apb_change_lock = NULL;
|
||||||
@ -52,9 +65,19 @@ static void triggerApbChangeCallback(apb_change_ev_t ev_type, uint32_t old_apb,
|
|||||||
initApbChangeCallback();
|
initApbChangeCallback();
|
||||||
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
||||||
apb_change_t * r = apb_change_callbacks;
|
apb_change_t * r = apb_change_callbacks;
|
||||||
while(r != NULL){
|
if( r != NULL ){
|
||||||
r->cb(r->arg, ev_type, old_apb, new_apb);
|
if(ev_type == APB_BEFORE_CHANGE )
|
||||||
r=r->next;
|
while(r != NULL){
|
||||||
|
r->cb(r->arg, ev_type, old_apb, new_apb);
|
||||||
|
r=r->next;
|
||||||
|
}
|
||||||
|
else { // run backwards through chain
|
||||||
|
while(r->next != NULL) r = r->next; // find first added
|
||||||
|
while( r != NULL){
|
||||||
|
r->cb(r->arg, ev_type, old_apb, new_apb);
|
||||||
|
r=r->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
xSemaphoreGive(apb_change_lock);
|
xSemaphoreGive(apb_change_lock);
|
||||||
}
|
}
|
||||||
@ -67,6 +90,7 @@ bool addApbChangeCallback(void * arg, apb_change_cb_t cb){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
c->next = NULL;
|
c->next = NULL;
|
||||||
|
c->prev = NULL;
|
||||||
c->arg = arg;
|
c->arg = arg;
|
||||||
c->cb = cb;
|
c->cb = cb;
|
||||||
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
||||||
@ -74,18 +98,20 @@ bool addApbChangeCallback(void * arg, apb_change_cb_t cb){
|
|||||||
apb_change_callbacks = c;
|
apb_change_callbacks = c;
|
||||||
} else {
|
} else {
|
||||||
apb_change_t * r = apb_change_callbacks;
|
apb_change_t * r = apb_change_callbacks;
|
||||||
if(r->cb != cb || r->arg != arg){
|
// look for duplicate callbacks
|
||||||
while(r->next){
|
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
|
||||||
r = r->next;
|
if (r) {
|
||||||
if(r->cb == cb && r->arg == arg){
|
log_e("duplicate func=%08X arg=%08X",c->cb,c->arg);
|
||||||
free(c);
|
free(c);
|
||||||
goto unlock_and_exit;
|
xSemaphoreGive(apb_change_lock);
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
r->next = c;
|
else {
|
||||||
|
c->next = apb_change_callbacks;
|
||||||
|
apb_change_callbacks-> prev = c;
|
||||||
|
apb_change_callbacks = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unlock_and_exit:
|
|
||||||
xSemaphoreGive(apb_change_lock);
|
xSemaphoreGive(apb_change_lock);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -94,24 +120,21 @@ bool removeApbChangeCallback(void * arg, apb_change_cb_t cb){
|
|||||||
initApbChangeCallback();
|
initApbChangeCallback();
|
||||||
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
||||||
apb_change_t * r = apb_change_callbacks;
|
apb_change_t * r = apb_change_callbacks;
|
||||||
if(r == NULL){
|
// look for matching callback
|
||||||
|
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
|
||||||
|
if ( r == NULL ) {
|
||||||
|
log_e("not found func=%08X arg=%08X",cb,arg);
|
||||||
xSemaphoreGive(apb_change_lock);
|
xSemaphoreGive(apb_change_lock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(r->cb == cb && r->arg == arg){
|
else {
|
||||||
apb_change_callbacks = r->next;
|
// patch links
|
||||||
|
if(r->prev) r->prev->next = r->next;
|
||||||
|
else { // this is first link
|
||||||
|
apb_change_callbacks = r->next;
|
||||||
|
}
|
||||||
|
if(r->next) r->next->prev = r->prev;
|
||||||
free(r);
|
free(r);
|
||||||
} else {
|
|
||||||
while(r->next && (r->next->cb != cb || r->next->arg != arg)){
|
|
||||||
r = r->next;
|
|
||||||
}
|
|
||||||
if(r->next == NULL || r->next->cb != cb || r->next->arg != arg){
|
|
||||||
xSemaphoreGive(apb_change_lock);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
apb_change_t * c = r->next;
|
|
||||||
r->next = c->next;
|
|
||||||
free(c);
|
|
||||||
}
|
}
|
||||||
xSemaphoreGive(apb_change_lock);
|
xSemaphoreGive(apb_change_lock);
|
||||||
return true;
|
return true;
|
||||||
@ -131,6 +154,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
|
|||||||
uint32_t capb, apb;
|
uint32_t capb, apb;
|
||||||
//Get XTAL Frequency and calculate min CPU MHz
|
//Get XTAL Frequency and calculate min CPU MHz
|
||||||
rtc_xtal_freq_t xtal = rtc_clk_xtal_freq_get();
|
rtc_xtal_freq_t xtal = rtc_clk_xtal_freq_get();
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
if(xtal > RTC_XTAL_FREQ_AUTO){
|
if(xtal > RTC_XTAL_FREQ_AUTO){
|
||||||
if(xtal < RTC_XTAL_FREQ_40M) {
|
if(xtal < RTC_XTAL_FREQ_40M) {
|
||||||
if(cpu_freq_mhz <= xtal && cpu_freq_mhz != xtal && cpu_freq_mhz != (xtal/2)){
|
if(cpu_freq_mhz <= xtal && cpu_freq_mhz != xtal && cpu_freq_mhz != (xtal/2)){
|
||||||
@ -142,6 +166,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if(cpu_freq_mhz > xtal && cpu_freq_mhz != 240 && cpu_freq_mhz != 160 && cpu_freq_mhz != 80){
|
if(cpu_freq_mhz > xtal && cpu_freq_mhz != 240 && cpu_freq_mhz != 160 && cpu_freq_mhz != 80){
|
||||||
if(xtal >= RTC_XTAL_FREQ_40M){
|
if(xtal >= RTC_XTAL_FREQ_40M){
|
||||||
log_e("Bad frequency: %u MHz! Options are: 240, 160, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal/2, xtal/4);
|
log_e("Bad frequency: %u MHz! Options are: 240, 160, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal/2, xtal/4);
|
||||||
@ -150,6 +175,17 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
//check if cpu supports the frequency
|
||||||
|
if(cpu_freq_mhz == 240){
|
||||||
|
//Check if ESP32 is rated for a CPU frequency of 160MHz only
|
||||||
|
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) &&
|
||||||
|
REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
|
||||||
|
log_e("Can not switch to 240 MHz! Chip CPU frequency rated for 160MHz.");
|
||||||
|
cpu_freq_mhz = 160;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
//Get current CPU clock configuration
|
//Get current CPU clock configuration
|
||||||
rtc_clk_cpu_freq_get_config(&cconf);
|
rtc_clk_cpu_freq_get_config(&cconf);
|
||||||
//return if frequency has not changed
|
//return if frequency has not changed
|
||||||
@ -176,7 +212,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
|
|||||||
//Update REF_TICK (uncomment if REF_TICK is different than 1MHz)
|
//Update REF_TICK (uncomment if REF_TICK is different than 1MHz)
|
||||||
//if(conf.freq_mhz < 80){
|
//if(conf.freq_mhz < 80){
|
||||||
// ESP_REG(APB_CTRL_XTAL_TICK_CONF_REG) = conf.freq_mhz / (REF_CLK_FREQ / MHZ) - 1;
|
// ESP_REG(APB_CTRL_XTAL_TICK_CONF_REG) = conf.freq_mhz / (REF_CLK_FREQ / MHZ) - 1;
|
||||||
//}
|
// }
|
||||||
//Update APB Freq REG
|
//Update APB Freq REG
|
||||||
rtc_clk_apb_freq_update(apb);
|
rtc_clk_apb_freq_update(apb);
|
||||||
//Update esp_timer divisor
|
//Update esp_timer divisor
|
||||||
|
@ -12,43 +12,45 @@
|
|||||||
// 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-dac.h"
|
#include "esp32-hal.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "rom/ets_sys.h"
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_intr.h"
|
|
||||||
#include "soc/rtc_io_reg.h"
|
#include "soc/rtc_io_reg.h"
|
||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
#include "soc/rtc_io_periph.h"
|
||||||
#include "soc/sens_reg.h"
|
#include "soc/sens_reg.h"
|
||||||
|
#include "soc/sens_struct.h"
|
||||||
|
#include "driver/dac.h"
|
||||||
|
|
||||||
void IRAM_ATTR __dacWrite(uint8_t pin, uint8_t value)
|
#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)
|
||||||
{
|
{
|
||||||
if(pin < 25 || pin > 26){
|
if(pin < DAC1 || pin > DAC2){
|
||||||
return;//not dac pin
|
return;//not dac pin
|
||||||
}
|
}
|
||||||
pinMode(pin, ANALOG);
|
pinMode(pin, ANALOG);
|
||||||
uint8_t channel = pin - 25;
|
uint8_t channel = pin - DAC1;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
|
||||||
//Disable Tone
|
|
||||||
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN);
|
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
if (channel) {
|
SENS.sar_dac_ctrl1.dac_clkgate_en = 1;
|
||||||
//Disable Channel Tone
|
#endif
|
||||||
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN2_M);
|
RTCIO.pad_dac[channel].dac_xpd_force = 1;
|
||||||
//Set the Dac value
|
RTCIO.pad_dac[channel].xpd_dac = 1;
|
||||||
SET_PERI_REG_BITS(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_DAC, value, RTC_IO_PDAC2_DAC_S); //dac_output
|
if (channel == 0) {
|
||||||
//Channel output enable
|
SENS.sar_dac_ctrl2.dac_cw_en1 = 0;
|
||||||
SET_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE);
|
} else if (channel == 1) {
|
||||||
} else {
|
SENS.sar_dac_ctrl2.dac_cw_en2 = 0;
|
||||||
//Disable Channel Tone
|
|
||||||
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN1_M);
|
|
||||||
//Set the Dac value
|
|
||||||
SET_PERI_REG_BITS(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_DAC, value, RTC_IO_PDAC1_DAC_S); //dac_output
|
|
||||||
//Channel output enable
|
|
||||||
SET_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);
|
|
||||||
}
|
}
|
||||||
|
RTCIO.pad_dac[channel].dac = 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")));
|
||||||
|
@ -13,20 +13,45 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "esp32-hal-gpio.h"
|
#include "esp32-hal-gpio.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "rom/ets_sys.h"
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_intr.h"
|
|
||||||
#include "rom/gpio.h"
|
|
||||||
#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 "soc/rtc_io_reg.h"
|
||||||
|
|
||||||
const int8_t esp32_adc2gpio[20] = {36, 37, 38, 39, 32, 33, 34, 35, -1, -1, 4, 0, 2, 15, 13, 12, 14, 27, 25, 26};
|
#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 "esp32/rom/gpio.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
#define GPIO_FUNC 2
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
|
#include "esp32s2/rom/gpio.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
#include "soc/periph_defs.h"
|
||||||
|
#define GPIO_FUNC 1
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
|
#include "rom/ets_sys.h"
|
||||||
|
#include "rom/gpio.h"
|
||||||
|
#include "esp_intr.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
const DRAM_ATTR esp32_gpioMux_t esp32_gpioMux[GPIO_PIN_COUNT]={
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
const int8_t esp32_adc2gpio[20] = {36, 37, 38, 39, 32, 33, 34, 35, -1, -1, 4, 0, 2, 15, 13, 12, 14, 27, 25, 26};
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
const int8_t esp32_adc2gpio[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const DRAM_ATTR esp32_gpioMux_t esp32_gpioMux[SOC_GPIO_PIN_COUNT]={
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
{0x44, 11, 11, 1},
|
{0x44, 11, 11, 1},
|
||||||
{0x88, -1, -1, -1},
|
{0x88, -1, -1, -1},
|
||||||
{0x40, 12, 12, 2},
|
{0x40, 12, 12, 2},
|
||||||
@ -59,14 +84,64 @@ const DRAM_ATTR esp32_gpioMux_t esp32_gpioMux[GPIO_PIN_COUNT]={
|
|||||||
{0, -1, -1, -1},
|
{0, -1, -1, -1},
|
||||||
{0, -1, -1, -1},
|
{0, -1, -1, -1},
|
||||||
{0, -1, -1, -1},
|
{0, -1, -1, -1},
|
||||||
{0x1c, 9, 4, 9},
|
{0x1c, 9, 4, 8},
|
||||||
{0x20, 8, 5, 8},
|
{0x20, 8, 5, 9},
|
||||||
{0x14, 4, 6, -1},
|
{0x14, 4, 6, -1},
|
||||||
{0x18, 5, 7, -1},
|
{0x18, 5, 7, -1},
|
||||||
{0x04, 0, 0, -1},
|
{0x04, 0, 0, -1},
|
||||||
{0x08, 1, 1, -1},
|
{0x08, 1, 1, -1},
|
||||||
{0x0c, 2, 2, -1},
|
{0x0c, 2, 2, -1},
|
||||||
{0x10, 3, 3, -1}
|
{0x10, 3, 3, -1}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
{0x04, 0, -1, -1},
|
||||||
|
{0x08, 1, 0, 1},
|
||||||
|
{0x0c, 2, 1, 2},
|
||||||
|
{0x10, 3, 2, 3},
|
||||||
|
{0x14, 4, 3, 4},
|
||||||
|
{0x18, 5, 4, 5},
|
||||||
|
{0x1c, 6, 5, 6},
|
||||||
|
{0x20, 7, 6, 7},
|
||||||
|
{0x24, 8, 7, 8},
|
||||||
|
{0x28, 9, 8, 9},//FSPI_HD
|
||||||
|
{0x2c, 10, 9, 10},//FSPI_CS0 / FSPI_D4
|
||||||
|
{0x30, 11, 10, 11},//FSPI_D / FSPI_D5
|
||||||
|
{0x34, 12, 11, 12},//FSPI_CLK / FSPI_D6
|
||||||
|
{0x38, 13, 12, 13},//FSPI_Q / FSPI_D7
|
||||||
|
{0x3c, 14, 13, 14},//FSPI_WP / FSPI_DQS
|
||||||
|
{0x40, 15, 14, -1},//32K+ / RTS0
|
||||||
|
{0x44, 16, 15, -1},//32K- / CTS0
|
||||||
|
{0x48, 17, 16, -1},//DAC1 / TXD1
|
||||||
|
{0x4c, 18, 17, -1},//DAC2 / RXD1
|
||||||
|
{0x50, 19, 18, -1},//USB D- / RTS1
|
||||||
|
{0x54, 20, 19, -1},//USB D+ / CTS1
|
||||||
|
{0x58, 21, -1, -1},//SDA?
|
||||||
|
{ 0, -1, -1, -1},//UNAVAILABLE
|
||||||
|
{ 0, -1, -1, -1},//UNAVAILABLE
|
||||||
|
{ 0, -1, -1, -1},//UNAVAILABLE
|
||||||
|
{ 0, -1, -1, -1},//UNAVAILABLE
|
||||||
|
{0x6c, -1, -1, -1},//RESERVED SPI_CS1
|
||||||
|
{0x70, -1, -1, -1},//RESERVED SPI_HD
|
||||||
|
{0x74, -1, -1, -1},//RESERVED SPI_WP
|
||||||
|
{0x78, -1, -1, -1},//RESERVED SPI_CS0
|
||||||
|
{0x7c, -1, -1, -1},//RESERVED SPI_CLK
|
||||||
|
{0x80, -1, -1, -1},//RESERVED SPI_Q
|
||||||
|
{0x84, -1, -1, -1},//RESERVED SPI_D
|
||||||
|
{0x88, -1, -1, -1},//FSPI_HD
|
||||||
|
{0x8c, -1, -1, -1},//FSPI_CS0
|
||||||
|
{0x90, -1, -1, -1},//FSPI_D
|
||||||
|
{0x94, -1, -1, -1},//FSPI_CLK
|
||||||
|
{0x98, -1, -1, -1},//FSPI_Q
|
||||||
|
{0x9c, -1, -1, -1},//FSPI_WP
|
||||||
|
{0xa0, -1, -1, -1},//MTCK
|
||||||
|
{0xa4, -1, -1, -1},//MTDO
|
||||||
|
{0xa8, -1, -1, -1},//MTDI
|
||||||
|
{0xac, -1, -1, -1},//MTMS
|
||||||
|
{0xb0, -1, -1, -1},//TXD0
|
||||||
|
{0xb4, -1, -1, -1},//RXD0
|
||||||
|
{0xb8, -1, -1, -1},//SCL?
|
||||||
|
{0xbc, -1, -1, -1},//INPUT ONLY
|
||||||
|
{0, -1, -1, -1}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*voidFuncPtr)(void);
|
typedef void (*voidFuncPtr)(void);
|
||||||
@ -76,56 +151,57 @@ typedef struct {
|
|||||||
void* arg;
|
void* arg;
|
||||||
bool functional;
|
bool functional;
|
||||||
} InterruptHandle_t;
|
} InterruptHandle_t;
|
||||||
static InterruptHandle_t __pinInterruptHandlers[GPIO_PIN_COUNT] = {0,};
|
static InterruptHandle_t __pinInterruptHandlers[SOC_GPIO_PIN_COUNT] = {0,};
|
||||||
|
|
||||||
#include "driver/rtc_io.h"
|
#include "driver/rtc_io.h"
|
||||||
|
|
||||||
extern void IRAM_ATTR __pinMode(uint8_t pin, uint8_t mode)
|
extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(!digitalPinIsValid(pin)) {
|
if(!digitalPinIsValid(pin)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rtc_reg = rtc_gpio_desc[pin].reg;
|
int8_t rtc_io = esp32_gpioMux[pin].rtc;
|
||||||
|
uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0;
|
||||||
if(mode == ANALOG) {
|
if(mode == ANALOG) {
|
||||||
if(!rtc_reg) {
|
if(!rtc_reg) {
|
||||||
return;//not rtc pin
|
return;//not rtc pin
|
||||||
}
|
}
|
||||||
//lock rtc
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
uint32_t reg_val = ESP_REG(rtc_reg);
|
SENS.sar_io_mux_conf.iomux_clk_gate_en = 1;
|
||||||
if(reg_val & rtc_gpio_desc[pin].mux){
|
#endif
|
||||||
return;//already in adc mode
|
SET_PERI_REG_MASK(rtc_io_desc[rtc_io].reg, (rtc_io_desc[rtc_io].mux));
|
||||||
|
SET_PERI_REG_BITS(rtc_io_desc[rtc_io].reg, RTC_IO_TOUCH_PAD1_FUN_SEL_V, 0, rtc_io_desc[rtc_io].func);
|
||||||
|
|
||||||
|
RTCIO.pin[rtc_io].pad_driver = 0;//OD = 1
|
||||||
|
RTCIO.enable_w1tc.w1tc = (1U << rtc_io);
|
||||||
|
CLEAR_PERI_REG_MASK(rtc_io_desc[rtc_io].reg, rtc_io_desc[rtc_io].ie);
|
||||||
|
|
||||||
|
if (rtc_io_desc[rtc_io].pullup) {
|
||||||
|
CLEAR_PERI_REG_MASK(rtc_io_desc[rtc_io].reg, rtc_io_desc[rtc_io].pullup);
|
||||||
}
|
}
|
||||||
reg_val &= ~(
|
if (rtc_io_desc[rtc_io].pulldown) {
|
||||||
(RTC_IO_TOUCH_PAD1_FUN_SEL_V << rtc_gpio_desc[pin].func)
|
CLEAR_PERI_REG_MASK(rtc_io_desc[rtc_io].reg, rtc_io_desc[rtc_io].pulldown);
|
||||||
|rtc_gpio_desc[pin].ie
|
}
|
||||||
|rtc_gpio_desc[pin].pullup
|
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = ((uint32_t)GPIO_FUNC << MCU_SEL_S) | ((uint32_t)2 << FUN_DRV_S) | FUN_IE;
|
||||||
|rtc_gpio_desc[pin].pulldown);
|
|
||||||
ESP_REG(RTC_GPIO_ENABLE_W1TC_REG) = (1 << (rtc_gpio_desc[pin].rtc_num + RTC_GPIO_ENABLE_W1TC_S));
|
|
||||||
ESP_REG(rtc_reg) = reg_val | rtc_gpio_desc[pin].mux;
|
|
||||||
//unlock rtc
|
|
||||||
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = ((uint32_t)2 << MCU_SEL_S) | ((uint32_t)2 << FUN_DRV_S) | FUN_IE;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//RTC pins PULL settings
|
//RTC pins PULL settings
|
||||||
if(rtc_reg) {
|
if(rtc_reg) {
|
||||||
//lock rtc
|
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].mux);
|
||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
|
|
||||||
if(mode & PULLUP) {
|
if(mode & PULLUP) {
|
||||||
ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_gpio_desc[pin].pullup) & ~(rtc_gpio_desc[pin].pulldown);
|
ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_io_desc[rtc_io].pullup) & ~(rtc_io_desc[rtc_io].pulldown);
|
||||||
} else if(mode & PULLDOWN) {
|
} else if(mode & PULLDOWN) {
|
||||||
ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_gpio_desc[pin].pulldown) & ~(rtc_gpio_desc[pin].pullup);
|
ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_io_desc[rtc_io].pulldown) & ~(rtc_io_desc[rtc_io].pullup);
|
||||||
} else {
|
} else {
|
||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
|
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].pullup | rtc_io_desc[rtc_io].pulldown);
|
||||||
}
|
}
|
||||||
//unlock rtc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pinFunction = 0, pinControl = 0;
|
uint32_t pinFunction = 0, pinControl = 0;
|
||||||
|
|
||||||
//lock gpio
|
|
||||||
if(mode & INPUT) {
|
if(mode & INPUT) {
|
||||||
if(pin < 32) {
|
if(pin < 32) {
|
||||||
GPIO.enable_w1tc = ((uint32_t)1 << pin);
|
GPIO.enable_w1tc = ((uint32_t)1 << pin);
|
||||||
@ -133,9 +209,8 @@ extern void IRAM_ATTR __pinMode(uint8_t pin, uint8_t mode)
|
|||||||
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
||||||
}
|
}
|
||||||
} else if(mode & OUTPUT) {
|
} else if(mode & OUTPUT) {
|
||||||
if(pin > 33){
|
if(pin >= NUM_OUPUT_PINS){
|
||||||
//unlock gpio
|
return;
|
||||||
return;//pins above 33 can be only inputs
|
|
||||||
} else if(pin < 32) {
|
} else if(pin < 32) {
|
||||||
GPIO.enable_w1ts = ((uint32_t)1 << pin);
|
GPIO.enable_w1ts = ((uint32_t)1 << pin);
|
||||||
} else {
|
} else {
|
||||||
@ -153,9 +228,17 @@ extern void IRAM_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)2 << 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) {
|
||||||
pinFunction |= ((uint32_t)(((pin)==1||(pin)==3)?0:1) << MCU_SEL_S);
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
pinFunction |= ((uint32_t)(((pin)==RX||(pin)==TX)?0:1) << MCU_SEL_S);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
pinFunction |= ((uint32_t)(((pin)==RX||(pin)==TX)?0:2) << MCU_SEL_S);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
pinFunction |= ((uint32_t)(mode >> 5) << MCU_SEL_S);
|
pinFunction |= ((uint32_t)(mode >> 5) << MCU_SEL_S);
|
||||||
}
|
}
|
||||||
@ -167,31 +250,30 @@ extern void IRAM_ATTR __pinMode(uint8_t pin, uint8_t mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GPIO.pin[pin].val = pinControl;
|
GPIO.pin[pin].val = pinControl;
|
||||||
//unlock gpio
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void IRAM_ATTR __digitalWrite(uint8_t pin, uint8_t val)
|
extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val)
|
||||||
{
|
{
|
||||||
if(val) {
|
if(val) {
|
||||||
if(pin < 32) {
|
if(pin < 32) {
|
||||||
GPIO.out_w1ts = ((uint32_t)1 << pin);
|
GPIO.out_w1ts = ((uint32_t)1 << pin);
|
||||||
} else if(pin < 34) {
|
} else if(pin < NUM_OUPUT_PINS) {
|
||||||
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
|
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(pin < 32) {
|
if(pin < 32) {
|
||||||
GPIO.out_w1tc = ((uint32_t)1 << pin);
|
GPIO.out_w1tc = ((uint32_t)1 << pin);
|
||||||
} else if(pin < 34) {
|
} else if(pin < NUM_OUPUT_PINS) {
|
||||||
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int IRAM_ATTR __digitalRead(uint8_t pin)
|
extern int ARDUINO_ISR_ATTR __digitalRead(uint8_t pin)
|
||||||
{
|
{
|
||||||
if(pin < 32) {
|
if(pin < 32) {
|
||||||
return (GPIO.in >> pin) & 0x1;
|
return (GPIO.in >> pin) & 0x1;
|
||||||
} else if(pin < 40) {
|
} else if(pin < GPIO_PIN_COUNT) {
|
||||||
return (GPIO.in1.val >> (pin - 32)) & 0x1;
|
return (GPIO.in1.val >> (pin - 32)) & 0x1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -199,7 +281,7 @@ extern int IRAM_ATTR __digitalRead(uint8_t pin)
|
|||||||
|
|
||||||
static intr_handle_t gpio_intr_handle = NULL;
|
static intr_handle_t gpio_intr_handle = NULL;
|
||||||
|
|
||||||
static void IRAM_ATTR __onPinInterrupt()
|
static void ARDUINO_ISR_ATTR __onPinInterrupt()
|
||||||
{
|
{
|
||||||
uint32_t gpio_intr_status_l=0;
|
uint32_t gpio_intr_status_l=0;
|
||||||
uint32_t gpio_intr_status_h=0;
|
uint32_t gpio_intr_status_h=0;
|
||||||
@ -247,7 +329,7 @@ extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc,
|
|||||||
|
|
||||||
if(!interrupt_initialized) {
|
if(!interrupt_initialized) {
|
||||||
interrupt_initialized = true;
|
interrupt_initialized = true;
|
||||||
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, __onPinInterrupt, NULL, &gpio_intr_handle);
|
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, __onPinInterrupt, NULL, &gpio_intr_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if new attach without detach remove old info
|
// if new attach without detach remove old info
|
||||||
@ -260,11 +342,15 @@ extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc,
|
|||||||
__pinInterruptHandlers[pin].functional = functional;
|
__pinInterruptHandlers[pin].functional = functional;
|
||||||
|
|
||||||
esp_intr_disable(gpio_intr_handle);
|
esp_intr_disable(gpio_intr_handle);
|
||||||
|
#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
|
||||||
|
#endif
|
||||||
GPIO.pin[pin].int_ena = 1;
|
GPIO.pin[pin].int_ena = 1;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
} else { //PRO_CPU
|
} else { //PRO_CPU
|
||||||
GPIO.pin[pin].int_ena = 4;
|
GPIO.pin[pin].int_ena = 4;
|
||||||
}
|
}
|
||||||
|
#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);
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,17 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
|
||||||
|
#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
#define NUM_OUPUT_PINS 45
|
||||||
|
#define PIN_DAC1 17
|
||||||
|
#define PIN_DAC2 18
|
||||||
|
#else
|
||||||
|
#define NUM_OUPUT_PINS 34
|
||||||
|
#define PIN_DAC1 25
|
||||||
|
#define PIN_DAC2 26
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LOW 0x0
|
#define LOW 0x0
|
||||||
#define HIGH 0x1
|
#define HIGH 0x1
|
||||||
@ -64,15 +75,15 @@ typedef struct {
|
|||||||
int8_t touch; /*!< Touch Channel number (-1 if not Touch pin) */
|
int8_t touch; /*!< Touch Channel number (-1 if not Touch pin) */
|
||||||
} esp32_gpioMux_t;
|
} esp32_gpioMux_t;
|
||||||
|
|
||||||
extern const esp32_gpioMux_t esp32_gpioMux[40];
|
extern const esp32_gpioMux_t esp32_gpioMux[SOC_GPIO_PIN_COUNT];
|
||||||
extern const int8_t esp32_adc2gpio[20];
|
extern const int8_t esp32_adc2gpio[20];
|
||||||
|
|
||||||
#define digitalPinIsValid(pin) ((pin) < 40 && esp32_gpioMux[(pin)].reg)
|
#define digitalPinIsValid(pin) ((pin) < SOC_GPIO_PIN_COUNT && esp32_gpioMux[(pin)].reg)
|
||||||
#define digitalPinCanOutput(pin) ((pin) < 34 && esp32_gpioMux[(pin)].reg)
|
#define digitalPinCanOutput(pin) ((pin) < NUM_OUPUT_PINS && esp32_gpioMux[(pin)].reg)
|
||||||
#define digitalPinToRtcPin(pin) (((pin) < 40)?esp32_gpioMux[(pin)].rtc:-1)
|
#define digitalPinToRtcPin(pin) (((pin) < SOC_GPIO_PIN_COUNT)?esp32_gpioMux[(pin)].rtc:-1)
|
||||||
#define digitalPinToAnalogChannel(pin) (((pin) < 40)?esp32_gpioMux[(pin)].adc:-1)
|
#define digitalPinToAnalogChannel(pin) (((pin) < SOC_GPIO_PIN_COUNT)?esp32_gpioMux[(pin)].adc:-1)
|
||||||
#define digitalPinToTouchChannel(pin) (((pin) < 40)?esp32_gpioMux[(pin)].touch:-1)
|
#define digitalPinToTouchChannel(pin) (((pin) < SOC_GPIO_PIN_COUNT)?esp32_gpioMux[(pin)].touch:-1)
|
||||||
#define digitalPinToDacChannel(pin) (((pin) == 25)?0:((pin) == 26)?1:-1)
|
#define digitalPinToDacChannel(pin) (((pin) == PIN_DAC1)?0:((pin) == PIN_DAC2)?1:-1)
|
||||||
|
|
||||||
void pinMode(uint8_t pin, uint8_t mode);
|
void pinMode(uint8_t pin, uint8_t mode);
|
||||||
void digitalWrite(uint8_t pin, uint8_t val);
|
void digitalWrite(uint8_t pin, uint8_t val);
|
||||||
|
@ -18,13 +18,28 @@
|
|||||||
#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 "rom/ets_sys.h"
|
|
||||||
#include "driver/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 "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 "esp_system.h"
|
||||||
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "esp32/rom/ets_sys.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
|
#include "rom/ets_sys.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
//#define I2C_DEV(i) (volatile i2c_dev_t *)((i)?DR_REG_I2C1_EXT_BASE:DR_REG_I2C_EXT_BASE)
|
//#define I2C_DEV(i) (volatile i2c_dev_t *)((i)?DR_REG_I2C1_EXT_BASE:DR_REG_I2C_EXT_BASE)
|
||||||
//#define I2C_DEV(i) ((i2c_dev_t *)(REG_I2C_BASE(i)))
|
//#define I2C_DEV(i) ((i2c_dev_t *)(REG_I2C_BASE(i)))
|
||||||
#define I2C_SCL_IDX(p) ((p==0)?I2CEXT0_SCL_OUT_IDX:((p==1)?I2CEXT1_SCL_OUT_IDX:0))
|
#define I2C_SCL_IDX(p) ((p==0)?I2CEXT0_SCL_OUT_IDX:((p==1)?I2CEXT1_SCL_OUT_IDX:0))
|
||||||
@ -227,7 +242,7 @@ static i2c_t _i2c_bus_array[2] = {
|
|||||||
|
|
||||||
/* Stickbreaker ISR mode debug support
|
/* Stickbreaker ISR mode debug support
|
||||||
*/
|
*/
|
||||||
static void IRAM_ATTR i2cDumpCmdQueue(i2c_t *i2c)
|
static void ARDUINO_ISR_ATTR i2cDumpCmdQueue(i2c_t *i2c)
|
||||||
{
|
{
|
||||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR)&&(defined ENABLE_I2C_DEBUG_BUFFER)
|
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR)&&(defined ENABLE_I2C_DEBUG_BUFFER)
|
||||||
static const char * const cmdName[] ={"RSTART","WRITE","READ","STOP","END"};
|
static const char * const cmdName[] ={"RSTART","WRITE","READ","STOP","END"};
|
||||||
@ -357,7 +372,7 @@ static void i2cDumpInts(uint8_t num)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
|
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
|
||||||
static void IRAM_ATTR i2cDumpStatus(i2c_t * i2c){
|
static void ARDUINO_ISR_ATTR i2cDumpStatus(i2c_t * i2c){
|
||||||
typedef union {
|
typedef union {
|
||||||
struct {
|
struct {
|
||||||
uint32_t ack_rec: 1; /*This register stores the value of ACK bit.*/
|
uint32_t ack_rec: 1; /*This register stores the value of ACK bit.*/
|
||||||
@ -431,7 +446,7 @@ if(i != fifoPos){// actual data
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void IRAM_ATTR i2cTriggerDumps(i2c_t * i2c, uint8_t trigger, const char locus[]){
|
static void ARDUINO_ISR_ATTR i2cTriggerDumps(i2c_t * i2c, uint8_t trigger, const char locus[]){
|
||||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
|
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
|
||||||
if( trigger ){
|
if( trigger ){
|
||||||
log_i("%s",locus);
|
log_i("%s",locus);
|
||||||
@ -478,7 +493,7 @@ static void i2cApbChangeCallback(void * arg, apb_change_ev_t ev_type, uint32_t o
|
|||||||
}
|
}
|
||||||
/* End of CPU Clock change Support
|
/* End of CPU Clock change Support
|
||||||
*/
|
*/
|
||||||
static void IRAM_ATTR i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uint8_t byte_num, bool ack_val, bool ack_exp, bool ack_check)
|
static void ARDUINO_ISR_ATTR i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uint8_t byte_num, bool ack_val, bool ack_exp, bool ack_check)
|
||||||
{
|
{
|
||||||
I2C_COMMAND_t cmd;
|
I2C_COMMAND_t cmd;
|
||||||
cmd.val=0;
|
cmd.val=0;
|
||||||
@ -491,7 +506,7 @@ static void IRAM_ATTR i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void IRAM_ATTR fillCmdQueue(i2c_t * i2c, bool INTS)
|
static void ARDUINO_ISR_ATTR fillCmdQueue(i2c_t * i2c, bool INTS)
|
||||||
{
|
{
|
||||||
/* this function is called on initial i2cProcQueue() or when a I2C_END_DETECT_INT occurs
|
/* this function is called on initial i2cProcQueue() or when a I2C_END_DETECT_INT occurs
|
||||||
*/
|
*/
|
||||||
@ -649,7 +664,7 @@ static void IRAM_ATTR fillCmdQueue(i2c_t * i2c, bool INTS)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IRAM_ATTR fillTxFifo(i2c_t * i2c)
|
static void ARDUINO_ISR_ATTR fillTxFifo(i2c_t * i2c)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
12/01/2017 The Fifo's are independent, 32 bytes of tx and 32 bytes of Rx.
|
12/01/2017 The Fifo's are independent, 32 bytes of tx and 32 bytes of Rx.
|
||||||
@ -741,7 +756,7 @@ static void IRAM_ATTR fillTxFifo(i2c_t * i2c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void IRAM_ATTR emptyRxFifo(i2c_t * i2c)
|
static void ARDUINO_ISR_ATTR emptyRxFifo(i2c_t * i2c)
|
||||||
{
|
{
|
||||||
uint32_t d, cnt=0, moveCnt;
|
uint32_t d, cnt=0, moveCnt;
|
||||||
|
|
||||||
@ -800,7 +815,7 @@ static void IRAM_ATTR emptyRxFifo(i2c_t * i2c)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IRAM_ATTR i2cIsrExit(i2c_t * i2c,const uint32_t eventCode,bool Fatal)
|
static void ARDUINO_ISR_ATTR i2cIsrExit(i2c_t * i2c,const uint32_t eventCode,bool Fatal)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch(eventCode) {
|
switch(eventCode) {
|
||||||
@ -845,7 +860,7 @@ static void IRAM_ATTR i2cIsrExit(i2c_t * i2c,const uint32_t eventCode,bool Fatal
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IRAM_ATTR i2c_update_error_byte_cnt(i2c_t * i2c)
|
static void ARDUINO_ISR_ATTR i2c_update_error_byte_cnt(i2c_t * i2c)
|
||||||
{
|
{
|
||||||
/* i2c_update_error_byte_cnt 07/18/2018
|
/* i2c_update_error_byte_cnt 07/18/2018
|
||||||
Only called after an error has occurred, so, most of the time this function is never used.
|
Only called after an error has occurred, so, most of the time this function is never used.
|
||||||
@ -892,7 +907,7 @@ static void IRAM_ATTR i2c_update_error_byte_cnt(i2c_t * i2c)
|
|||||||
i2c->errorByteCnt = bc;
|
i2c->errorByteCnt = bc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IRAM_ATTR i2c_isr_handler_default(void* arg)
|
static void ARDUINO_ISR_ATTR i2c_isr_handler_default(void* arg)
|
||||||
{
|
{
|
||||||
i2c_t* p_i2c = (i2c_t*) arg; // recover data
|
i2c_t* p_i2c = (i2c_t*) arg; // recover data
|
||||||
uint32_t activeInt = p_i2c->dev->int_status.val&0x7FF;
|
uint32_t activeInt = p_i2c->dev->int_status.val&0x7FF;
|
||||||
@ -1239,7 +1254,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
|
|||||||
if(!i2c->intr_handle) { // create ISR for either peripheral
|
if(!i2c->intr_handle) { // create ISR for either peripheral
|
||||||
// log_i("create ISR %d",i2c->num);
|
// log_i("create ISR %d",i2c->num);
|
||||||
uint32_t ret = 0;
|
uint32_t ret = 0;
|
||||||
uint32_t flags = ESP_INTR_FLAG_IRAM | //< ISR can be called if cache is disabled
|
uint32_t flags = ARDUINO_ISR_FLAG | //< ISR can be called if cache is disabled
|
||||||
ESP_INTR_FLAG_LOWMED | //< Low and medium prio interrupts. These can be handled in C.
|
ESP_INTR_FLAG_LOWMED | //< Low and medium prio interrupts. These can be handled in C.
|
||||||
ESP_INTR_FLAG_SHARED; //< Reduce resource requirements, Share interrupts
|
ESP_INTR_FLAG_SHARED; //< Reduce resource requirements, Share interrupts
|
||||||
|
|
||||||
@ -1270,7 +1285,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
|
|||||||
|
|
||||||
i2c->dev->ctr.trans_start=1; // go for it
|
i2c->dev->ctr.trans_start=1; // go for it
|
||||||
|
|
||||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
|
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
|
||||||
portTickType tBefore=xTaskGetTickCount();
|
portTickType tBefore=xTaskGetTickCount();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1278,7 +1293,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
|
|||||||
|
|
||||||
uint32_t eBits = xEventGroupWaitBits(i2c->i2c_event,EVENT_DONE,pdFALSE,pdTRUE,ticksTimeOut);
|
uint32_t eBits = xEventGroupWaitBits(i2c->i2c_event,EVENT_DONE,pdFALSE,pdTRUE,ticksTimeOut);
|
||||||
|
|
||||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
|
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
|
||||||
portTickType tAfter=xTaskGetTickCount();
|
portTickType tAfter=xTaskGetTickCount();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1757,7 +1772,133 @@ uint32_t i2cGetStatus(i2c_t * i2c){
|
|||||||
}
|
}
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#include "driver/i2c.h"
|
||||||
|
|
||||||
|
#define ACK_CHECK_EN 1 /*!< I2C master will check ack from slave*/
|
||||||
|
#define ACK_CHECK_DIS 0 /*!< I2C master will not check ack from slave */
|
||||||
|
#define ACK_VAL 0x0 /*!< I2C ack value */
|
||||||
|
#define NACK_VAL 0x1 /*!< I2C nack value */
|
||||||
|
|
||||||
|
struct i2c_struct_t {
|
||||||
|
i2c_port_t num;
|
||||||
|
};
|
||||||
|
|
||||||
|
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){
|
||||||
|
if(i2c_num >= 2){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
i2c_t * out = NULL;
|
||||||
|
if(i2c_ports[i2c_num] == NULL){
|
||||||
|
out = (i2c_t*)malloc(sizeof(i2c_t));
|
||||||
|
if(out == NULL){
|
||||||
|
log_e("malloc failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
out->num = (i2c_port_t)i2c_num;
|
||||||
|
i2c_ports[i2c_num] = out;
|
||||||
|
} else {
|
||||||
|
out = i2c_ports[i2c_num];
|
||||||
|
i2c_driver_delete((i2c_port_t)i2c_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_config_t conf;
|
||||||
|
conf.mode = I2C_MODE_MASTER;
|
||||||
|
conf.scl_io_num = (gpio_num_t)scl;
|
||||||
|
conf.sda_io_num = (gpio_num_t)sda;
|
||||||
|
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
||||||
|
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
||||||
|
conf.master.clk_speed = clk_speed;
|
||||||
|
esp_err_t ret = i2c_param_config(out->num, &conf);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
log_e("i2c_param_config failed");
|
||||||
|
free(out);
|
||||||
|
i2c_ports[i2c_num] = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ret = i2c_driver_install(out->num, conf.mode, 0, 0, 0);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
log_e("i2c_driver_install failed");
|
||||||
|
free(out);
|
||||||
|
i2c_ports[i2c_num] = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, uint8_t* buff, uint16_t size, bool sendStop, uint16_t timeOutMillis){
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||||
|
i2c_master_write(cmd, buff, size, ACK_CHECK_EN);
|
||||||
|
//if send stop?
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
ret = i2c_master_cmd_begin(i2c->num, cmd, timeOutMillis / portTICK_RATE_MS);
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, uint8_t* buff, uint16_t size, bool sendStop, uint16_t timeOutMillis, uint32_t *readCount){
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_READ, ACK_CHECK_EN);
|
||||||
|
if (size > 1) {
|
||||||
|
i2c_master_read(cmd, buff, size - 1, ACK_VAL);
|
||||||
|
}
|
||||||
|
i2c_master_read_byte(cmd, buff + size - 1, NACK_VAL);
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
ret = i2c_master_cmd_begin(i2c->num, cmd, timeOutMillis / portTICK_RATE_MS);
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
if(ret == ESP_OK){
|
||||||
|
*readCount = size;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2cRelease(i2c_t *i2c){
|
||||||
|
log_w("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i2c_err_t i2cFlush(i2c_t *i2c){
|
||||||
|
esp_err_t ret = i2c_reset_tx_fifo(i2c->num);
|
||||||
|
if(ret != ESP_OK){
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return i2c_reset_rx_fifo(i2c->num);
|
||||||
|
}
|
||||||
|
i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed){
|
||||||
|
log_w("");
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
uint32_t i2cGetFrequency(i2c_t * i2c){
|
||||||
|
log_w("");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t i2cGetStatus(i2c_t * i2c){
|
||||||
|
log_w("");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Functions below should be used only if well understood
|
||||||
|
//Might be deprecated and removed in future
|
||||||
|
i2c_err_t i2cAttachSCL(i2c_t * i2c, int8_t scl){
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
i2c_err_t i2cDetachSCL(i2c_t * i2c, int8_t scl){
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
i2c_err_t i2cAttachSDA(i2c_t * i2c, int8_t sda){
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda){
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_IDF_TARGET_ESP32 */
|
||||||
|
|
||||||
/* todo
|
/* todo
|
||||||
22JUL18
|
22JUL18
|
||||||
|
@ -16,19 +16,34 @@
|
|||||||
#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 "rom/ets_sys.h"
|
|
||||||
#include "esp32-hal-matrix.h"
|
#include "esp32-hal-matrix.h"
|
||||||
#include "soc/dport_reg.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 "esp_system.h"
|
||||||
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "esp32/rom/ets_sys.h"
|
||||||
|
#define LAST_CHAN (15)
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
|
#define LAST_CHAN (7)
|
||||||
|
#define LEDC_DIV_NUM_HSTIMER0_V LEDC_CLK_DIV_LSTIMER0_V
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
|
#include "rom/ets_sys.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_DISABLE_HAL_LOCKS
|
#if CONFIG_DISABLE_HAL_LOCKS
|
||||||
#define LEDC_MUTEX_LOCK()
|
#define LEDC_MUTEX_LOCK()
|
||||||
#define LEDC_MUTEX_UNLOCK()
|
#define LEDC_MUTEX_UNLOCK()
|
||||||
#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)
|
||||||
xSemaphoreHandle _ledc_sys_lock;
|
xSemaphoreHandle _ledc_sys_lock = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -55,27 +70,35 @@ xSemaphoreHandle _ledc_sys_lock;
|
|||||||
|
|
||||||
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){
|
||||||
if(ev_type == APB_AFTER_CHANGE && old_apb != new_apb){
|
if(ev_type == APB_AFTER_CHANGE && old_apb != new_apb){
|
||||||
uint32_t iarg = (uint32_t)arg;
|
uint16_t iarg = *(uint16_t*)arg;
|
||||||
uint8_t chan = iarg;
|
uint8_t chan = 0;
|
||||||
uint8_t group=(chan/8), timer=((chan/2)%4);
|
|
||||||
old_apb /= 1000000;
|
old_apb /= 1000000;
|
||||||
new_apb /= 1000000;
|
new_apb /= 1000000;
|
||||||
if(LEDC_TIMER(group, timer).conf.tick_sel){
|
while(iarg){ // run though all active channels, adjusting timing configurations
|
||||||
LEDC_MUTEX_LOCK();
|
if(iarg & 1) {// this channel is active
|
||||||
uint32_t old_div = LEDC_TIMER(group, timer).conf.clock_divider;
|
uint8_t group=(chan/8), timer=((chan/2)%4);
|
||||||
uint32_t div_num = (new_apb * old_div) / old_apb;
|
if(LEDC_TIMER(group, timer).conf.tick_sel){
|
||||||
if(div_num > LEDC_DIV_NUM_HSTIMER0_V){
|
LEDC_MUTEX_LOCK();
|
||||||
new_apb = REF_CLK_FREQ / 1000000;
|
uint32_t old_div = LEDC_TIMER(group, timer).conf.clock_divider;
|
||||||
div_num = (new_apb * old_div) / old_apb;
|
uint32_t div_num = (new_apb * old_div) / old_apb;
|
||||||
if(div_num > LEDC_DIV_NUM_HSTIMER0_V) {
|
if(div_num > LEDC_DIV_NUM_HSTIMER0_V){
|
||||||
div_num = LEDC_DIV_NUM_HSTIMER0_V;//lowest clock possible
|
div_num = ((REF_CLK_FREQ /1000000) * old_div) / old_apb;
|
||||||
|
if(div_num > LEDC_DIV_NUM_HSTIMER0_V) {
|
||||||
|
div_num = LEDC_DIV_NUM_HSTIMER0_V;//lowest clock possible
|
||||||
|
}
|
||||||
|
LEDC_TIMER(group, timer).conf.tick_sel = 0;
|
||||||
|
} else if(div_num < 256) {
|
||||||
|
div_num = 256;//highest clock possible
|
||||||
|
}
|
||||||
|
LEDC_TIMER(group, timer).conf.clock_divider = div_num;
|
||||||
|
LEDC_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log_d("using REF_CLK chan=%d",chan);
|
||||||
}
|
}
|
||||||
LEDC_TIMER(group, timer).conf.tick_sel = 0;
|
|
||||||
} else if(div_num < 256) {
|
|
||||||
div_num = 256;//highest clock possible
|
|
||||||
}
|
}
|
||||||
LEDC_TIMER(group, timer).conf.clock_divider = div_num;
|
iarg = iarg >> 1;
|
||||||
LEDC_MUTEX_UNLOCK();
|
chan++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,11 +108,14 @@ static void _ledcSetupTimer(uint8_t chan, uint32_t div_num, uint8_t bit_num, boo
|
|||||||
{
|
{
|
||||||
uint8_t group=(chan/8), timer=((chan/2)%4);
|
uint8_t group=(chan/8), timer=((chan/2)%4);
|
||||||
static bool tHasStarted = false;
|
static bool tHasStarted = false;
|
||||||
|
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);
|
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN);
|
||||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST);
|
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);
|
||||||
|
|
||||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||||
_ledc_sys_lock = xSemaphoreCreateMutex();
|
_ledc_sys_lock = xSemaphoreCreateMutex();
|
||||||
#endif
|
#endif
|
||||||
@ -98,15 +124,18 @@ static void _ledcSetupTimer(uint8_t chan, uint32_t div_num, uint8_t bit_num, boo
|
|||||||
LEDC_TIMER(group, timer).conf.clock_divider = div_num;//18 bit (10.8) This register is used to configure parameter for divider in timer the least significant eight bits represent the decimal part.
|
LEDC_TIMER(group, timer).conf.clock_divider = div_num;//18 bit (10.8) This register is used to configure parameter for divider in timer the least significant eight bits represent the decimal part.
|
||||||
LEDC_TIMER(group, timer).conf.duty_resolution = bit_num;//5 bit This register controls the range of the counter in timer. the counter range is [0 2**bit_num] the max bit width for counter is 20.
|
LEDC_TIMER(group, timer).conf.duty_resolution = bit_num;//5 bit This register controls the range of the counter in timer. the counter range is [0 2**bit_num] the max bit width for counter is 20.
|
||||||
LEDC_TIMER(group, timer).conf.tick_sel = apb_clk;//apb clock
|
LEDC_TIMER(group, timer).conf.tick_sel = apb_clk;//apb clock
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
if(group) {
|
if(group) {
|
||||||
|
#endif
|
||||||
LEDC_TIMER(group, timer).conf.low_speed_update = 1;//This bit is only useful for low speed timer channels, reserved for high speed timers
|
LEDC_TIMER(group, timer).conf.low_speed_update = 1;//This bit is only useful for low speed timer channels, reserved for high speed timers
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
LEDC_TIMER(group, timer).conf.pause = 0;
|
LEDC_TIMER(group, timer).conf.pause = 0;
|
||||||
LEDC_TIMER(group, timer).conf.rst = 1;//This bit is used to reset timer the counter will be 0 after reset.
|
LEDC_TIMER(group, timer).conf.rst = 1;//This bit is used to reset timer the counter will be 0 after reset.
|
||||||
LEDC_TIMER(group, timer).conf.rst = 0;
|
LEDC_TIMER(group, timer).conf.rst = 0;
|
||||||
LEDC_MUTEX_UNLOCK();
|
LEDC_MUTEX_UNLOCK();
|
||||||
uint32_t iarg = chan;
|
_activeChannels |= (1 << chan); // mark as active for APB callback
|
||||||
addApbChangeCallback((void*)iarg, _on_apb_change);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//max div_num 0x3FFFF (262143)
|
//max div_num 0x3FFFF (262143)
|
||||||
@ -166,17 +195,21 @@ static void _ledcSetupChannel(uint8_t chan, uint8_t idle_level)
|
|||||||
LEDC_CHAN(group, channel).duty.duty = 0;
|
LEDC_CHAN(group, channel).duty.duty = 0;
|
||||||
LEDC_CHAN(group, channel).conf0.sig_out_en = 0;//This is the output enable control bit for channel
|
LEDC_CHAN(group, channel).conf0.sig_out_en = 0;//This is the output enable control bit for channel
|
||||||
LEDC_CHAN(group, channel).conf1.duty_start = 0;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware.
|
LEDC_CHAN(group, channel).conf1.duty_start = 0;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware.
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
if(group) {
|
if(group) {
|
||||||
|
#endif
|
||||||
LEDC_CHAN(group, channel).conf0.low_speed_update = 1;
|
LEDC_CHAN(group, channel).conf0.low_speed_update = 1;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
} else {
|
} else {
|
||||||
LEDC_CHAN(group, channel).conf0.clk_en = 0;
|
LEDC_CHAN(group, channel).conf0.clk_en = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
LEDC_MUTEX_UNLOCK();
|
LEDC_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
double ledcSetup(uint8_t chan, double freq, uint8_t bit_num)
|
double ledcSetup(uint8_t chan, double freq, uint8_t bit_num)
|
||||||
{
|
{
|
||||||
if(chan > 15) {
|
if(chan > LAST_CHAN) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
double res_freq = _ledcSetupTimerFreq(chan, freq, bit_num);
|
double res_freq = _ledcSetupTimerFreq(chan, freq, bit_num);
|
||||||
@ -186,7 +219,7 @@ double ledcSetup(uint8_t chan, double freq, uint8_t bit_num)
|
|||||||
|
|
||||||
void ledcWrite(uint8_t chan, uint32_t duty)
|
void ledcWrite(uint8_t chan, uint32_t duty)
|
||||||
{
|
{
|
||||||
if(chan > 15) {
|
if(chan > LAST_CHAN) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint8_t group=(chan/8), channel=(chan%8);
|
uint8_t group=(chan/8), channel=(chan%8);
|
||||||
@ -195,26 +228,34 @@ void ledcWrite(uint8_t chan, uint32_t duty)
|
|||||||
if(duty) {
|
if(duty) {
|
||||||
LEDC_CHAN(group, channel).conf0.sig_out_en = 1;//This is the output enable control bit for channel
|
LEDC_CHAN(group, channel).conf0.sig_out_en = 1;//This is the output enable control bit for channel
|
||||||
LEDC_CHAN(group, channel).conf1.duty_start = 1;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware.
|
LEDC_CHAN(group, channel).conf1.duty_start = 1;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware.
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
if(group) {
|
if(group) {
|
||||||
|
#endif
|
||||||
LEDC_CHAN(group, channel).conf0.low_speed_update = 1;
|
LEDC_CHAN(group, channel).conf0.low_speed_update = 1;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
} else {
|
} else {
|
||||||
LEDC_CHAN(group, channel).conf0.clk_en = 1;
|
LEDC_CHAN(group, channel).conf0.clk_en = 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
LEDC_CHAN(group, channel).conf0.sig_out_en = 0;//This is the output enable control bit for channel
|
LEDC_CHAN(group, channel).conf0.sig_out_en = 0;//This is the output enable control bit for channel
|
||||||
LEDC_CHAN(group, channel).conf1.duty_start = 0;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware.
|
LEDC_CHAN(group, channel).conf1.duty_start = 0;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware.
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
if(group) {
|
if(group) {
|
||||||
|
#endif
|
||||||
LEDC_CHAN(group, channel).conf0.low_speed_update = 1;
|
LEDC_CHAN(group, channel).conf0.low_speed_update = 1;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
} else {
|
} else {
|
||||||
LEDC_CHAN(group, channel).conf0.clk_en = 0;
|
LEDC_CHAN(group, channel).conf0.clk_en = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
LEDC_MUTEX_UNLOCK();
|
LEDC_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ledcRead(uint8_t chan)
|
uint32_t ledcRead(uint8_t chan)
|
||||||
{
|
{
|
||||||
if(chan > 15) {
|
if(chan > LAST_CHAN) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return LEDC.channel_group[chan/8].channel[chan%8].duty.duty >> 4;
|
return LEDC.channel_group[chan/8].channel[chan%8].duty.duty >> 4;
|
||||||
@ -230,7 +271,7 @@ double ledcReadFreq(uint8_t chan)
|
|||||||
|
|
||||||
double ledcWriteTone(uint8_t chan, double freq)
|
double ledcWriteTone(uint8_t chan, double freq)
|
||||||
{
|
{
|
||||||
if(chan > 15) {
|
if(chan > LAST_CHAN) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(!freq) {
|
if(!freq) {
|
||||||
@ -257,11 +298,15 @@ double ledcWriteNote(uint8_t chan, note_t note, uint8_t octave){
|
|||||||
|
|
||||||
void ledcAttachPin(uint8_t pin, uint8_t chan)
|
void ledcAttachPin(uint8_t pin, uint8_t chan)
|
||||||
{
|
{
|
||||||
if(chan > 15) {
|
if(chan > LAST_CHAN) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pinMode(pin, OUTPUT);
|
pinMode(pin, OUTPUT);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
pinMatrixOutAttach(pin, LEDC_LS_SIG_OUT0_IDX + chan, false, false);
|
||||||
|
#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);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ledcDetachPin(uint8_t pin)
|
void ledcDetachPin(uint8_t pin)
|
||||||
|
@ -20,6 +20,7 @@ extern "C"
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_timer.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)
|
||||||
@ -75,7 +76,7 @@ const char * pathToFileName(const char * path);
|
|||||||
int log_printf(const char *fmt, ...);
|
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_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 "[" #letter "][%s:%u] %s(): " format ARDUHAL_LOG_RESET_COLOR "\r\n", pathToFileName(__FILE__), __LINE__, __FUNCTION__
|
#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, ...) log_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
|
#define log_v(format, ...) log_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
|
||||||
|
@ -14,33 +14,45 @@
|
|||||||
|
|
||||||
#include "esp32-hal-matrix.h"
|
#include "esp32-hal-matrix.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
|
|
||||||
|
#include "esp_system.h"
|
||||||
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "esp32/rom/gpio.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/gpio.h"
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
#include "rom/gpio.h"
|
#include "rom/gpio.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MATRIX_DETACH_OUT_SIG 0x100
|
#define MATRIX_DETACH_OUT_SIG 0x100
|
||||||
#define MATRIX_DETACH_IN_LOW_PIN 0x30
|
#define MATRIX_DETACH_IN_LOW_PIN 0x30
|
||||||
#define MATRIX_DETACH_IN_LOW_HIGH 0x38
|
#define MATRIX_DETACH_IN_LOW_HIGH 0x38
|
||||||
|
|
||||||
void IRAM_ATTR pinMatrixOutAttach(uint8_t pin, uint8_t function, bool invertOut, bool invertEnable)
|
void ARDUINO_ISR_ATTR pinMatrixOutAttach(uint8_t pin, uint8_t function, bool invertOut, bool invertEnable)
|
||||||
{
|
{
|
||||||
gpio_matrix_out(pin, function, invertOut, invertEnable);
|
gpio_matrix_out(pin, function, invertOut, invertEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR pinMatrixOutDetach(uint8_t pin, bool invertOut, bool invertEnable)
|
void ARDUINO_ISR_ATTR pinMatrixOutDetach(uint8_t pin, bool invertOut, bool invertEnable)
|
||||||
{
|
{
|
||||||
gpio_matrix_out(pin, MATRIX_DETACH_OUT_SIG, invertOut, invertEnable);
|
gpio_matrix_out(pin, MATRIX_DETACH_OUT_SIG, invertOut, invertEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR pinMatrixInAttach(uint8_t pin, uint8_t signal, bool inverted)
|
void ARDUINO_ISR_ATTR pinMatrixInAttach(uint8_t pin, uint8_t signal, bool inverted)
|
||||||
{
|
{
|
||||||
gpio_matrix_in(pin, signal, inverted);
|
gpio_matrix_in(pin, signal, inverted);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR pinMatrixInDetach(uint8_t signal, bool high, bool inverted)
|
void ARDUINO_ISR_ATTR pinMatrixInDetach(uint8_t signal, bool high, bool inverted)
|
||||||
{
|
{
|
||||||
gpio_matrix_in(high?MATRIX_DETACH_IN_LOW_HIGH:MATRIX_DETACH_IN_LOW_PIN, signal, inverted);
|
gpio_matrix_in(high?MATRIX_DETACH_IN_LOW_HIGH:MATRIX_DETACH_IN_LOW_PIN, signal, inverted);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
void IRAM_ATTR intrMatrixAttach(uint32_t source, uint32_t inum){
|
void ARDUINO_ISR_ATTR intrMatrixAttach(uint32_t source, uint32_t inum){
|
||||||
intr_matrix_set(PRO_CPU_NUM, source, inum);
|
intr_matrix_set(PRO_CPU_NUM, source, inum);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -31,10 +31,22 @@
|
|||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#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 "rom/rtc.h"
|
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
|
|
||||||
|
#include "esp_system.h"
|
||||||
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "esp32/rom/rtc.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/rtc.h"
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
|
#include "rom/rtc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
//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
|
||||||
uint8_t temprature_sens_read();
|
uint8_t temprature_sens_read();
|
||||||
@ -44,11 +56,13 @@ float temperatureRead()
|
|||||||
return (temprature_sens_read() - 32) / 1.8;
|
return (temprature_sens_read() - 32) / 1.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void yield()
|
void __yield()
|
||||||
{
|
{
|
||||||
vPortYield();
|
vPortYield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void yield() __attribute__ ((weak, alias("__yield")));
|
||||||
|
|
||||||
#if CONFIG_AUTOSTART_ARDUINO
|
#if CONFIG_AUTOSTART_ARDUINO
|
||||||
|
|
||||||
extern TaskHandle_t loopTaskHandle;
|
extern TaskHandle_t loopTaskHandle;
|
||||||
@ -129,12 +143,12 @@ BaseType_t xTaskCreateUniversal( TaskFunction_t pxTaskCode,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long IRAM_ATTR micros()
|
unsigned long ARDUINO_ISR_ATTR micros()
|
||||||
{
|
{
|
||||||
return (unsigned long) (esp_timer_get_time());
|
return (unsigned long) (esp_timer_get_time());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long IRAM_ATTR millis()
|
unsigned long ARDUINO_ISR_ATTR millis()
|
||||||
{
|
{
|
||||||
return (unsigned long) (esp_timer_get_time() / 1000ULL);
|
return (unsigned long) (esp_timer_get_time() / 1000ULL);
|
||||||
}
|
}
|
||||||
@ -144,7 +158,7 @@ void delay(uint32_t ms)
|
|||||||
vTaskDelay(ms / portTICK_PERIOD_MS);
|
vTaskDelay(ms / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR delayMicroseconds(uint32_t us)
|
void ARDUINO_ISR_ATTR delayMicroseconds(uint32_t us)
|
||||||
{
|
{
|
||||||
uint32_t m = micros();
|
uint32_t m = micros();
|
||||||
if(us){
|
if(us){
|
||||||
@ -196,7 +210,7 @@ void initArduino()
|
|||||||
#ifdef F_CPU
|
#ifdef F_CPU
|
||||||
setCpuFrequencyMhz(F_CPU/1000000);
|
setCpuFrequencyMhz(F_CPU/1000000);
|
||||||
#endif
|
#endif
|
||||||
#if CONFIG_SPIRAM_SUPPORT
|
#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
|
||||||
psramInit();
|
psramInit();
|
||||||
#endif
|
#endif
|
||||||
esp_log_level_set("*", CONFIG_LOG_DEFAULT_LEVEL);
|
esp_log_level_set("*", CONFIG_LOG_DEFAULT_LEVEL);
|
||||||
@ -225,7 +239,7 @@ void initArduino()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//used by hal log
|
//used by hal log
|
||||||
const char * IRAM_ATTR pathToFileName(const char * path)
|
const char * ARDUINO_ISR_ATTR pathToFileName(const char * path)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
|
@ -1,11 +1,37 @@
|
|||||||
|
// 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 "esp32-hal.h"
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_SUPPORT
|
#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
|
||||||
#include "esp_spiram.h"
|
|
||||||
#include "soc/efuse_reg.h"
|
#include "soc/efuse_reg.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
|
|
||||||
|
#include "esp_system.h"
|
||||||
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "esp32/spiram.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/spiram.h"
|
||||||
|
#include "esp32s2/rom/cache.h"
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
|
#include "esp_spiram.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static volatile bool spiramDetected = false;
|
static volatile bool spiramDetected = false;
|
||||||
static volatile bool spiramFailed = false;
|
static volatile bool spiramFailed = false;
|
||||||
|
|
||||||
@ -17,6 +43,7 @@ bool psramInit(){
|
|||||||
if (spiramFailed) {
|
if (spiramFailed) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
|
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
|
||||||
uint32_t pkg_ver = chip_ver & 0x7;
|
uint32_t pkg_ver = chip_ver & 0x7;
|
||||||
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
|
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
|
||||||
@ -25,13 +52,21 @@ bool psramInit(){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
esp_spiram_init_cache();
|
esp_spiram_init_cache();
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
extern void esp_config_data_cache_mode(void);
|
||||||
|
esp_config_data_cache_mode();
|
||||||
|
Cache_Enable_DCache(0);
|
||||||
|
#endif
|
||||||
if (esp_spiram_init() != ESP_OK) {
|
if (esp_spiram_init() != ESP_OK) {
|
||||||
spiramFailed = true;
|
spiramFailed = true;
|
||||||
log_w("PSRAM init failed!");
|
log_w("PSRAM init failed!");
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
pinMatrixOutDetach(16, false, false);
|
pinMatrixOutDetach(16, false, false);
|
||||||
pinMatrixOutDetach(17, false, false);
|
pinMatrixOutDetach(17, false, false);
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
esp_spiram_init_cache();
|
||||||
if (!esp_spiram_test()) {
|
if (!esp_spiram_test()) {
|
||||||
spiramFailed = true;
|
spiramFailed = true;
|
||||||
log_e("PSRAM test failed!");
|
log_e("PSRAM test failed!");
|
||||||
@ -42,31 +77,34 @@ bool psramInit(){
|
|||||||
log_e("PSRAM could not be added to the heap!");
|
log_e("PSRAM could not be added to the heap!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#if CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL && !CONFIG_ARDUINO_ISR_IRAM
|
||||||
|
heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
spiramDetected = true;
|
spiramDetected = true;
|
||||||
log_d("PSRAM enabled");
|
log_d("PSRAM enabled");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IRAM_ATTR psramFound(){
|
bool ARDUINO_ISR_ATTR psramFound(){
|
||||||
return spiramDetected;
|
return spiramDetected;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR *ps_malloc(size_t size){
|
void ARDUINO_ISR_ATTR *ps_malloc(size_t size){
|
||||||
if(!spiramDetected){
|
if(!spiramDetected){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR *ps_calloc(size_t n, size_t size){
|
void ARDUINO_ISR_ATTR *ps_calloc(size_t n, size_t size){
|
||||||
if(!spiramDetected){
|
if(!spiramDetected){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR *ps_realloc(void *ptr, size_t size){
|
void ARDUINO_ISR_ATTR *ps_realloc(void *ptr, size_t size){
|
||||||
if(!spiramDetected){
|
if(!spiramDetected){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -79,19 +117,19 @@ bool psramInit(){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IRAM_ATTR psramFound(){
|
bool ARDUINO_ISR_ATTR psramFound(){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR *ps_malloc(size_t size){
|
void ARDUINO_ISR_ATTR *ps_malloc(size_t size){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR *ps_calloc(size_t n, size_t size){
|
void ARDUINO_ISR_ATTR *ps_calloc(size_t n, size_t size){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR *ps_realloc(void *ptr, size_t size){
|
void ARDUINO_ISR_ATTR *ps_realloc(void *ptr, size_t size){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,17 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#ifndef BOARD_HAS_PSRAM
|
||||||
|
#ifdef CONFIG_SPIRAM_SUPPORT
|
||||||
|
#undef CONFIG_SPIRAM_SUPPORT
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_SPIRAM
|
||||||
|
#undef CONFIG_SPIRAM
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
bool psramInit();
|
bool psramInit();
|
||||||
bool psramFound();
|
bool psramFound();
|
||||||
|
|
||||||
|
@ -19,18 +19,20 @@
|
|||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
#include "esp8266-compat.h"
|
#include "esp8266-compat.h"
|
||||||
#include "soc/gpio_reg.h"
|
#include "soc/gpio_reg.h"
|
||||||
#include "soc/gpio_reg.h"
|
|
||||||
|
|
||||||
#include "esp32-hal-rmt.h"
|
|
||||||
#include "driver/periph_ctrl.h"
|
|
||||||
|
|
||||||
#include "soc/rmt_struct.h"
|
#include "soc/rmt_struct.h"
|
||||||
|
#include "driver/periph_ctrl.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal macros
|
* Internal macros
|
||||||
*/
|
*/
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
#define MAX_CHANNELS 8
|
#define MAX_CHANNELS 8
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#define MAX_CHANNELS 4
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
#define MAX_DATA_PER_CHANNEL 64
|
#define MAX_DATA_PER_CHANNEL 64
|
||||||
#define MAX_DATA_PER_ITTERATION 62
|
#define MAX_DATA_PER_ITTERATION 62
|
||||||
#define _ABS(a) (a>0?a:-a)
|
#define _ABS(a) (a>0?a:-a)
|
||||||
@ -100,7 +102,10 @@ struct rmt_obj_s
|
|||||||
* Internal variables for channel descriptors
|
* Internal variables for channel descriptors
|
||||||
*/
|
*/
|
||||||
static xSemaphoreHandle g_rmt_objlocks[MAX_CHANNELS] = {
|
static xSemaphoreHandle g_rmt_objlocks[MAX_CHANNELS] = {
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
NULL, NULL, NULL, NULL,
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
NULL, NULL, NULL, NULL
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
|
static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
|
||||||
@ -108,10 +113,12 @@ static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
|
|||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,19 +135,19 @@ static xSemaphoreHandle g_rmt_block_lock = NULL;
|
|||||||
*/
|
*/
|
||||||
static void _initPin(int pin, int channel, bool tx_not_rx);
|
static void _initPin(int pin, int channel, bool tx_not_rx);
|
||||||
|
|
||||||
static bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size);
|
static bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size, bool continuous);
|
||||||
|
|
||||||
static void IRAM_ATTR _rmt_isr(void* arg);
|
static void ARDUINO_ISR_ATTR _rmt_isr(void* arg);
|
||||||
|
|
||||||
static rmt_obj_t* _rmtAllocate(int pin, int from, int size);
|
static rmt_obj_t* _rmtAllocate(int pin, int from, int size);
|
||||||
|
|
||||||
static void _initPin(int pin, int channel, bool tx_not_rx);
|
static void _initPin(int pin, int channel, bool tx_not_rx);
|
||||||
|
|
||||||
static int IRAM_ATTR _rmt_get_mem_len(uint8_t channel);
|
static int ARDUINO_ISR_ATTR _rmt_get_mem_len(uint8_t channel);
|
||||||
|
|
||||||
static void IRAM_ATTR _rmt_tx_mem_first(uint8_t ch);
|
static void ARDUINO_ISR_ATTR _rmt_tx_mem_first(uint8_t ch);
|
||||||
|
|
||||||
static void IRAM_ATTR _rmt_tx_mem_second(uint8_t ch);
|
static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -234,6 +241,20 @@ bool rmtDeinit(rmt_obj_t *rmt)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rmtLoop(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
|
||||||
|
{
|
||||||
|
if (!rmt) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int allocated_size = MAX_DATA_PER_CHANNEL * rmt->buffers;
|
||||||
|
|
||||||
|
if (size > allocated_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return _rmtSendOnce(rmt, data, size, true);
|
||||||
|
}
|
||||||
|
|
||||||
bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
|
bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
|
||||||
{
|
{
|
||||||
if (!rmt) {
|
if (!rmt) {
|
||||||
@ -249,7 +270,7 @@ bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
|
|||||||
RMT_MUTEX_LOCK(channel);
|
RMT_MUTEX_LOCK(channel);
|
||||||
// setup interrupt handler if not yet installed for half and full tx
|
// setup interrupt handler if not yet installed for half and full tx
|
||||||
if (!intr_handle) {
|
if (!intr_handle) {
|
||||||
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, _rmt_isr, NULL, &intr_handle);
|
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, _rmt_isr, NULL, &intr_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
rmt->data_size = size - MAX_DATA_PER_ITTERATION;
|
rmt->data_size = size - MAX_DATA_PER_ITTERATION;
|
||||||
@ -282,10 +303,10 @@ 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);
|
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
|
||||||
return _rmtSendOnce(rmt, data, size);
|
return _rmtSendOnce(rmt, data, size, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,7 +504,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i == MAX_CHANNELS || i+j >= MAX_CHANNELS || j != buffers) {
|
if (i == MAX_CHANNELS || i+j > MAX_CHANNELS || j != buffers) {
|
||||||
xSemaphoreGive(g_rmt_block_lock);
|
xSemaphoreGive(g_rmt_block_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -518,12 +539,17 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
|
|||||||
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;
|
||||||
RMT.conf_ch[channel].conf0.carrier_out_lv = 0;
|
RMT.conf_ch[channel].conf0.carrier_out_lv = 0;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
RMT.conf_ch[channel].conf0.mem_pd = 0;
|
RMT.conf_ch[channel].conf0.mem_pd = 0;
|
||||||
|
#endif
|
||||||
RMT.conf_ch[channel].conf0.idle_thres = 0x80;
|
RMT.conf_ch[channel].conf0.idle_thres = 0x80;
|
||||||
RMT.conf_ch[channel].conf1.rx_en = 0;
|
RMT.conf_ch[channel].conf1.rx_en = 0;
|
||||||
RMT.conf_ch[channel].conf1.tx_conti_mode = 0;
|
RMT.conf_ch[channel].conf1.tx_conti_mode = 0;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
RMT.conf_ch[channel].conf1.ref_cnt_rst = 0;
|
RMT.conf_ch[channel].conf1.ref_cnt_rst = 0;
|
||||||
|
#else
|
||||||
|
RMT.conf_ch[channel].conf1.chk_rx_carrier_en = 0;
|
||||||
|
#endif
|
||||||
RMT.conf_ch[channel].conf1.rx_filter_en = 0;
|
RMT.conf_ch[channel].conf1.rx_filter_en = 0;
|
||||||
RMT.conf_ch[channel].conf1.rx_filter_thres = 0;
|
RMT.conf_ch[channel].conf1.rx_filter_thres = 0;
|
||||||
RMT.conf_ch[channel].conf1.idle_out_lv = 0; // signal level for idle
|
RMT.conf_ch[channel].conf1.idle_out_lv = 0; // signal level for idle
|
||||||
@ -543,7 +569,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
|
|||||||
|
|
||||||
// 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)ESP_INTR_FLAG_IRAM, _rmt_isr, NULL, &intr_handle);
|
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, _rmt_isr, NULL, &intr_handle);
|
||||||
}
|
}
|
||||||
RMT_MUTEX_UNLOCK(channel);
|
RMT_MUTEX_UNLOCK(channel);
|
||||||
|
|
||||||
@ -553,7 +579,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
|
|||||||
/**
|
/**
|
||||||
* Private methods definitions
|
* Private methods definitions
|
||||||
*/
|
*/
|
||||||
bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
|
bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size, bool continuous)
|
||||||
{
|
{
|
||||||
if (!rmt) {
|
if (!rmt) {
|
||||||
return false;
|
return false;
|
||||||
@ -571,6 +597,7 @@ bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
RMT_MUTEX_LOCK(channel);
|
RMT_MUTEX_LOCK(channel);
|
||||||
|
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;
|
||||||
RMT_MUTEX_UNLOCK(channel);
|
RMT_MUTEX_UNLOCK(channel);
|
||||||
@ -610,7 +637,7 @@ static void _initPin(int pin, int channel, bool tx_not_rx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void IRAM_ATTR _rmt_isr(void* arg)
|
static void ARDUINO_ISR_ATTR _rmt_isr(void* arg)
|
||||||
{
|
{
|
||||||
int intr_val = RMT.int_st.val;
|
int intr_val = RMT.int_st.val;
|
||||||
size_t ch;
|
size_t ch;
|
||||||
@ -665,7 +692,6 @@ static void IRAM_ATTR _rmt_isr(void* arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (intr_val & _INT_ERROR(ch)) {
|
if (intr_val & _INT_ERROR(ch)) {
|
||||||
digitalWrite(2, 1);
|
|
||||||
// clear the flag
|
// clear the flag
|
||||||
RMT.int_clr.val = _INT_ERROR(ch);
|
RMT.int_clr.val = _INT_ERROR(ch);
|
||||||
RMT.int_ena.val &= ~_INT_ERROR(ch);
|
RMT.int_ena.val &= ~_INT_ERROR(ch);
|
||||||
@ -701,7 +727,7 @@ static void IRAM_ATTR _rmt_isr(void* arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IRAM_ATTR _rmt_tx_mem_second(uint8_t ch)
|
static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch)
|
||||||
{
|
{
|
||||||
DEBUG_INTERRUPT_START(4)
|
DEBUG_INTERRUPT_START(4)
|
||||||
uint32_t* data = g_rmt_objects[ch].data_ptr;
|
uint32_t* data = g_rmt_objects[ch].data_ptr;
|
||||||
@ -753,7 +779,7 @@ static void IRAM_ATTR _rmt_tx_mem_second(uint8_t ch)
|
|||||||
DEBUG_INTERRUPT_END(4);
|
DEBUG_INTERRUPT_END(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IRAM_ATTR _rmt_tx_mem_first(uint8_t ch)
|
static void ARDUINO_ISR_ATTR _rmt_tx_mem_first(uint8_t ch)
|
||||||
{
|
{
|
||||||
DEBUG_INTERRUPT_START(2);
|
DEBUG_INTERRUPT_START(2);
|
||||||
uint32_t* data = g_rmt_objects[ch].data_ptr;
|
uint32_t* data = g_rmt_objects[ch].data_ptr;
|
||||||
@ -804,7 +830,7 @@ static void IRAM_ATTR _rmt_tx_mem_first(uint8_t ch)
|
|||||||
DEBUG_INTERRUPT_END(2);
|
DEBUG_INTERRUPT_END(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int IRAM_ATTR _rmt_get_mem_len(uint8_t channel)
|
static int ARDUINO_ISR_ATTR _rmt_get_mem_len(uint8_t channel)
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
@ -73,6 +73,12 @@ float rmtSetTick(rmt_obj_t* rmt, float tick);
|
|||||||
*/
|
*/
|
||||||
bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size);
|
bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loop data up to the reserved memsize continuously
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool rmtLoop(rmt_obj_t* rmt, rmt_data_t* data, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiates async receive, event flag indicates data received
|
* Initiates async receive, event flag indicates data received
|
||||||
*
|
*
|
||||||
|
@ -16,11 +16,23 @@
|
|||||||
#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 "rom/ets_sys.h"
|
|
||||||
#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 "esp_system.h"
|
||||||
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "esp32/rom/ets_sys.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
|
#include "rom/ets_sys.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_DISABLE_HAL_LOCKS
|
#if CONFIG_DISABLE_HAL_LOCKS
|
||||||
#define SD_MUTEX_LOCK()
|
#define SD_MUTEX_LOCK()
|
||||||
@ -69,6 +81,9 @@ uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq) //chan 0-7 freq 1220-31
|
|||||||
prescale = 0xFF;
|
prescale = 0xFF;
|
||||||
}
|
}
|
||||||
SD_MUTEX_LOCK();
|
SD_MUTEX_LOCK();
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32
|
||||||
|
SIGMADELTA.misc.function_clk_en = 1;
|
||||||
|
#endif
|
||||||
SIGMADELTA.channel[channel].prescale = prescale;
|
SIGMADELTA.channel[channel].prescale = prescale;
|
||||||
SIGMADELTA.cg.clk_en = 0;
|
SIGMADELTA.cg.clk_en = 0;
|
||||||
SIGMADELTA.cg.clk_en = 1;
|
SIGMADELTA.cg.clk_en = 1;
|
||||||
|
@ -17,10 +17,7 @@
|
|||||||
#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 "rom/ets_sys.h"
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_intr.h"
|
|
||||||
#include "rom/gpio.h"
|
|
||||||
#include "soc/spi_reg.h"
|
#include "soc/spi_reg.h"
|
||||||
#include "soc/spi_struct.h"
|
#include "soc/spi_struct.h"
|
||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
@ -28,17 +25,24 @@
|
|||||||
#include "soc/dport_reg.h"
|
#include "soc/dport_reg.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
|
|
||||||
#define SPI_CLK_IDX(p) ((p==0)?SPICLK_OUT_IDX:((p==1)?SPICLK_OUT_IDX:((p==2)?HSPICLK_OUT_IDX:((p==3)?VSPICLK_OUT_IDX:0))))
|
#include "esp_system.h"
|
||||||
#define SPI_MISO_IDX(p) ((p==0)?SPIQ_OUT_IDX:((p==1)?SPIQ_OUT_IDX:((p==2)?HSPIQ_OUT_IDX:((p==3)?VSPIQ_OUT_IDX:0))))
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
#define SPI_MOSI_IDX(p) ((p==0)?SPID_IN_IDX:((p==1)?SPID_IN_IDX:((p==2)?HSPID_IN_IDX:((p==3)?VSPID_IN_IDX:0))))
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
|
#include "esp32/rom/ets_sys.h"
|
||||||
#define SPI_SPI_SS_IDX(n) ((n==0)?SPICS0_OUT_IDX:((n==1)?SPICS1_OUT_IDX:((n==2)?SPICS2_OUT_IDX:SPICS0_OUT_IDX)))
|
#include "esp32/rom/gpio.h"
|
||||||
#define SPI_HSPI_SS_IDX(n) ((n==0)?HSPICS0_OUT_IDX:((n==1)?HSPICS1_OUT_IDX:((n==2)?HSPICS2_OUT_IDX:HSPICS0_OUT_IDX)))
|
#include "esp_intr_alloc.h"
|
||||||
#define SPI_VSPI_SS_IDX(n) ((n==0)?VSPICS0_OUT_IDX:((n==1)?VSPICS1_OUT_IDX:((n==2)?VSPICS2_OUT_IDX:VSPICS0_OUT_IDX)))
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
#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):((p==3)?SPI_VSPI_SS_IDX(n):0))))
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
|
#include "esp32s2/rom/gpio.h"
|
||||||
#define SPI_INUM(u) (2)
|
#include "esp_intr_alloc.h"
|
||||||
#define SPI_INTR_SOURCE(u) ((u==0)?ETS_SPI0_INTR_SOURCE:((u==1)?ETS_SPI1_INTR_SOURCE:((u==2)?ETS_SPI2_INTR_SOURCE:((p==3)?ETS_SPI3_INTR_SOURCE:0))))
|
#else
|
||||||
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
|
#endif
|
||||||
|
#else // ESP32 Before IDF 4.0
|
||||||
|
#include "rom/ets_sys.h"
|
||||||
|
#include "rom/gpio.h"
|
||||||
|
#include "esp_intr.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
struct spi_struct_t {
|
struct spi_struct_t {
|
||||||
spi_dev_t * dev;
|
spi_dev_t * dev;
|
||||||
@ -48,25 +52,69 @@ struct spi_struct_t {
|
|||||||
uint8_t num;
|
uint8_t num;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
// ESP32S2
|
||||||
|
#define SPI_COUNT (3)
|
||||||
|
|
||||||
|
#define SPI_CLK_IDX(p) ((p==0)?SPICLK_OUT_MUX_IDX:((p==1)?FSPICLK_OUT_MUX_IDX:((p==2)?SPI3_CLK_OUT_MUX_IDX:0)))
|
||||||
|
#define SPI_MISO_IDX(p) ((p==0)?SPIQ_OUT_IDX:((p==1)?FSPIQ_OUT_IDX:((p==2)?SPI3_Q_OUT_IDX:0)))
|
||||||
|
#define SPI_MOSI_IDX(p) ((p==0)?SPID_IN_IDX:((p==1)?FSPID_IN_IDX:((p==2)?SPI3_D_IN_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_FSPI_SS_IDX(n) ((n==0)?FSPICS0_OUT_IDX:((n==1)?FSPICS1_OUT_IDX:((n==2)?FSPICS2_OUT_IDX:VSPICS0_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_INTR_SOURCE(u) ((u==0)?ETS_SPI1_INTR_SOURCE:((u==1)?ETS_SPI2_INTR_SOURCE:((u==2)?ETS_SPI3_INTR_SOURCE:0)))
|
||||||
|
|
||||||
|
#else
|
||||||
|
// ESP32
|
||||||
|
#define SPI_COUNT (4)
|
||||||
|
|
||||||
|
#define SPI_CLK_IDX(p) ((p==0)?SPICLK_OUT_IDX:((p==1)?SPICLK_OUT_IDX:((p==2)?HSPICLK_OUT_IDX:((p==3)?VSPICLK_OUT_IDX:0))))
|
||||||
|
#define SPI_MISO_IDX(p) ((p==0)?SPIQ_OUT_IDX:((p==1)?SPIQ_OUT_IDX:((p==2)?HSPIQ_OUT_IDX:((p==3)?VSPIQ_OUT_IDX:0))))
|
||||||
|
#define SPI_MOSI_IDX(p) ((p==0)?SPID_IN_IDX:((p==1)?SPID_IN_IDX:((p==2)?HSPID_IN_IDX:((p==3)?VSPID_IN_IDX:0))))
|
||||||
|
|
||||||
|
#define SPI_SPI_SS_IDX(n) ((n==0)?SPICS0_OUT_IDX:((n==1)?SPICS1_OUT_IDX:((n==2)?SPICS2_OUT_IDX:SPICS0_OUT_IDX)))
|
||||||
|
#define SPI_HSPI_SS_IDX(n) ((n==0)?HSPICS0_OUT_IDX:((n==1)?HSPICS1_OUT_IDX:((n==2)?HSPICS2_OUT_IDX:HSPICS0_OUT_IDX)))
|
||||||
|
#define SPI_VSPI_SS_IDX(n) ((n==0)?VSPICS0_OUT_IDX:((n==1)?VSPICS1_OUT_IDX:((n==2)?VSPICS2_OUT_IDX:VSPICS0_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):((p==3)?SPI_VSPI_SS_IDX(n):0))))
|
||||||
|
|
||||||
|
#define SPI_INTR_SOURCE(u) ((u==0)?ETS_SPI0_INTR_SOURCE:((u==1)?ETS_SPI1_INTR_SOURCE:((u==2)?ETS_SPI2_INTR_SOURCE:((p==3)?ETS_SPI3_INTR_SOURCE:0))))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_DISABLE_HAL_LOCKS
|
#if CONFIG_DISABLE_HAL_LOCKS
|
||||||
#define SPI_MUTEX_LOCK()
|
#define SPI_MUTEX_LOCK()
|
||||||
#define SPI_MUTEX_UNLOCK()
|
#define SPI_MUTEX_UNLOCK()
|
||||||
|
|
||||||
static spi_t _spi_bus_array[4] = {
|
static spi_t _spi_bus_array[] = {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 0},
|
||||||
|
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 1},
|
||||||
|
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 2}
|
||||||
|
#else
|
||||||
{(volatile spi_dev_t *)(DR_REG_SPI0_BASE), 0},
|
{(volatile spi_dev_t *)(DR_REG_SPI0_BASE), 0},
|
||||||
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 1},
|
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 1},
|
||||||
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 2},
|
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 2},
|
||||||
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3}
|
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
#define SPI_MUTEX_LOCK() do {} while (xSemaphoreTake(spi->lock, portMAX_DELAY) != pdPASS)
|
#define SPI_MUTEX_LOCK() do {} while (xSemaphoreTake(spi->lock, portMAX_DELAY) != pdPASS)
|
||||||
#define SPI_MUTEX_UNLOCK() xSemaphoreGive(spi->lock)
|
#define SPI_MUTEX_UNLOCK() xSemaphoreGive(spi->lock)
|
||||||
|
|
||||||
static spi_t _spi_bus_array[4] = {
|
static spi_t _spi_bus_array[] = {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
{(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_SPI3_BASE), NULL, 2}
|
||||||
|
#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},
|
||||||
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2},
|
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2},
|
||||||
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3}
|
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -76,6 +124,14 @@ void spiAttachSCK(spi_t * spi, int8_t sck)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(sck < 0) {
|
if(sck < 0) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
if(spi->num == FSPI) {
|
||||||
|
sck = 36;
|
||||||
|
} else {
|
||||||
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
sck = 14;
|
sck = 14;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -83,6 +139,7 @@ void spiAttachSCK(spi_t * spi, int8_t sck)
|
|||||||
} else {
|
} else {
|
||||||
sck = 6;
|
sck = 6;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
pinMode(sck, OUTPUT);
|
pinMode(sck, OUTPUT);
|
||||||
pinMatrixOutAttach(sck, SPI_CLK_IDX(spi->num), false, false);
|
pinMatrixOutAttach(sck, SPI_CLK_IDX(spi->num), false, false);
|
||||||
@ -94,6 +151,14 @@ void spiAttachMISO(spi_t * spi, int8_t miso)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(miso < 0) {
|
if(miso < 0) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
if(spi->num == FSPI) {
|
||||||
|
miso = 37;
|
||||||
|
} else {
|
||||||
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
miso = 12;
|
miso = 12;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -101,6 +166,7 @@ void spiAttachMISO(spi_t * spi, int8_t miso)
|
|||||||
} else {
|
} else {
|
||||||
miso = 7;
|
miso = 7;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
pinMode(miso, INPUT);
|
pinMode(miso, INPUT);
|
||||||
@ -114,6 +180,14 @@ void spiAttachMOSI(spi_t * spi, int8_t mosi)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(mosi < 0) {
|
if(mosi < 0) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
if(spi->num == FSPI) {
|
||||||
|
mosi = 35;
|
||||||
|
} else {
|
||||||
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
mosi = 13;
|
mosi = 13;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -121,6 +195,7 @@ void spiAttachMOSI(spi_t * spi, int8_t mosi)
|
|||||||
} else {
|
} else {
|
||||||
mosi = 8;
|
mosi = 8;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
pinMode(mosi, OUTPUT);
|
pinMode(mosi, OUTPUT);
|
||||||
pinMatrixOutAttach(mosi, SPI_MOSI_IDX(spi->num), false, false);
|
pinMatrixOutAttach(mosi, SPI_MOSI_IDX(spi->num), false, false);
|
||||||
@ -132,6 +207,14 @@ void spiDetachSCK(spi_t * spi, int8_t sck)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(sck < 0) {
|
if(sck < 0) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
if(spi->num == FSPI) {
|
||||||
|
sck = 36;
|
||||||
|
} else {
|
||||||
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
sck = 14;
|
sck = 14;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -139,6 +222,7 @@ void spiDetachSCK(spi_t * spi, int8_t sck)
|
|||||||
} else {
|
} else {
|
||||||
sck = 6;
|
sck = 6;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
pinMatrixOutDetach(sck, false, false);
|
pinMatrixOutDetach(sck, false, false);
|
||||||
pinMode(sck, INPUT);
|
pinMode(sck, INPUT);
|
||||||
@ -150,6 +234,14 @@ void spiDetachMISO(spi_t * spi, int8_t miso)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(miso < 0) {
|
if(miso < 0) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
if(spi->num == FSPI) {
|
||||||
|
miso = 37;
|
||||||
|
} else {
|
||||||
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
miso = 12;
|
miso = 12;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -157,6 +249,7 @@ void spiDetachMISO(spi_t * spi, int8_t miso)
|
|||||||
} else {
|
} else {
|
||||||
miso = 7;
|
miso = 7;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
pinMatrixInDetach(SPI_MISO_IDX(spi->num), false, false);
|
pinMatrixInDetach(SPI_MISO_IDX(spi->num), false, false);
|
||||||
pinMode(miso, INPUT);
|
pinMode(miso, INPUT);
|
||||||
@ -168,6 +261,14 @@ void spiDetachMOSI(spi_t * spi, int8_t mosi)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(mosi < 0) {
|
if(mosi < 0) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
if(spi->num == FSPI) {
|
||||||
|
mosi = 35;
|
||||||
|
} else {
|
||||||
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
mosi = 13;
|
mosi = 13;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -175,6 +276,7 @@ void spiDetachMOSI(spi_t * spi, int8_t mosi)
|
|||||||
} else {
|
} else {
|
||||||
mosi = 8;
|
mosi = 8;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
pinMatrixOutDetach(mosi, false, false);
|
pinMatrixOutDetach(mosi, false, false);
|
||||||
pinMode(mosi, INPUT);
|
pinMode(mosi, INPUT);
|
||||||
@ -190,6 +292,14 @@ void spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss)
|
|||||||
}
|
}
|
||||||
if(ss < 0) {
|
if(ss < 0) {
|
||||||
cs_num = 0;
|
cs_num = 0;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
if(spi->num == FSPI) {
|
||||||
|
ss = 34;
|
||||||
|
} else {
|
||||||
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
ss = 15;
|
ss = 15;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -197,6 +307,7 @@ void spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss)
|
|||||||
} else {
|
} else {
|
||||||
ss = 11;
|
ss = 11;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
pinMode(ss, OUTPUT);
|
pinMode(ss, OUTPUT);
|
||||||
pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, cs_num), false, false);
|
pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, cs_num), false, false);
|
||||||
@ -209,6 +320,14 @@ void spiDetachSS(spi_t * spi, int8_t ss)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(ss < 0) {
|
if(ss < 0) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
if(spi->num == FSPI) {
|
||||||
|
ss = 34;
|
||||||
|
} else {
|
||||||
|
log_e("HSPI Does not have default pins on ESP32S2!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if(spi->num == HSPI) {
|
if(spi->num == HSPI) {
|
||||||
ss = 15;
|
ss = 15;
|
||||||
} else if(spi->num == VSPI) {
|
} else if(spi->num == VSPI) {
|
||||||
@ -216,6 +335,7 @@ void spiDetachSS(spi_t * spi, int8_t ss)
|
|||||||
} else {
|
} else {
|
||||||
ss = 11;
|
ss = 11;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
pinMatrixOutDetach(ss, false, false);
|
pinMatrixOutDetach(ss, false, false);
|
||||||
pinMode(ss, INPUT);
|
pinMode(ss, INPUT);
|
||||||
@ -227,7 +347,11 @@ void spiEnableSSPins(spi_t * spi, uint8_t cs_mask)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
spi->dev->misc.val &= ~(cs_mask & SPI_CS_MASK_ALL);
|
||||||
|
#else
|
||||||
spi->dev->pin.val &= ~(cs_mask & SPI_CS_MASK_ALL);
|
spi->dev->pin.val &= ~(cs_mask & SPI_CS_MASK_ALL);
|
||||||
|
#endif
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +361,11 @@ void spiDisableSSPins(spi_t * spi, uint8_t cs_mask)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
spi->dev->misc.val |= (cs_mask & SPI_CS_MASK_ALL);
|
||||||
|
#else
|
||||||
spi->dev->pin.val |= (cs_mask & SPI_CS_MASK_ALL);
|
spi->dev->pin.val |= (cs_mask & SPI_CS_MASK_ALL);
|
||||||
|
#endif
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,7 +397,11 @@ void spiSSSet(spi_t * spi)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
spi->dev->misc.cs_keep_active = 1;
|
||||||
|
#else
|
||||||
spi->dev->pin.cs_keep_active = 1;
|
spi->dev->pin.cs_keep_active = 1;
|
||||||
|
#endif
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +411,11 @@ void spiSSClear(spi_t * spi)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
spi->dev->misc.cs_keep_active = 0;
|
||||||
|
#else
|
||||||
spi->dev->pin.cs_keep_active = 0;
|
spi->dev->pin.cs_keep_active = 0;
|
||||||
|
#endif
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +442,11 @@ uint8_t spiGetDataMode(spi_t * spi)
|
|||||||
if(!spi) {
|
if(!spi) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
bool idleEdge = spi->dev->misc.ck_idle_edge;
|
||||||
|
#else
|
||||||
bool idleEdge = spi->dev->pin.ck_idle_edge;
|
bool idleEdge = spi->dev->pin.ck_idle_edge;
|
||||||
|
#endif
|
||||||
bool outEdge = spi->dev->user.ck_out_edge;
|
bool outEdge = spi->dev->user.ck_out_edge;
|
||||||
if(idleEdge) {
|
if(idleEdge) {
|
||||||
if(outEdge) {
|
if(outEdge) {
|
||||||
@ -328,20 +468,36 @@ 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
|
||||||
|
spi->dev->misc.ck_idle_edge = 0;
|
||||||
|
#else
|
||||||
spi->dev->pin.ck_idle_edge = 0;
|
spi->dev->pin.ck_idle_edge = 0;
|
||||||
|
#endif
|
||||||
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
|
||||||
|
spi->dev->misc.ck_idle_edge = 1;
|
||||||
|
#else
|
||||||
spi->dev->pin.ck_idle_edge = 1;
|
spi->dev->pin.ck_idle_edge = 1;
|
||||||
|
#endif
|
||||||
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
|
||||||
|
spi->dev->misc.ck_idle_edge = 1;
|
||||||
|
#else
|
||||||
spi->dev->pin.ck_idle_edge = 1;
|
spi->dev->pin.ck_idle_edge = 1;
|
||||||
|
#endif
|
||||||
spi->dev->user.ck_out_edge = 0;
|
spi->dev->user.ck_out_edge = 0;
|
||||||
break;
|
break;
|
||||||
case SPI_MODE0:
|
case SPI_MODE0:
|
||||||
default:
|
default:
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
spi->dev->misc.ck_idle_edge = 0;
|
||||||
|
#else
|
||||||
spi->dev->pin.ck_idle_edge = 0;
|
spi->dev->pin.ck_idle_edge = 0;
|
||||||
|
#endif
|
||||||
spi->dev->user.ck_out_edge = 0;
|
spi->dev->user.ck_out_edge = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -384,28 +540,39 @@ static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void spiStopBus(spi_t * spi)
|
static void spiInitBus(spi_t * spi)
|
||||||
{
|
{
|
||||||
if(!spi) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SPI_MUTEX_LOCK();
|
|
||||||
spi->dev->slave.trans_done = 0;
|
spi->dev->slave.trans_done = 0;
|
||||||
spi->dev->slave.slave_mode = 0;
|
spi->dev->slave.slave_mode = 0;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
spi->dev->misc.val = 0;
|
||||||
|
#else
|
||||||
spi->dev->pin.val = 0;
|
spi->dev->pin.val = 0;
|
||||||
|
#endif
|
||||||
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;
|
||||||
spi->dev->ctrl1.val = 0;
|
spi->dev->ctrl1.val = 0;
|
||||||
spi->dev->ctrl2.val = 0;
|
spi->dev->ctrl2.val = 0;
|
||||||
spi->dev->clock.val = 0;
|
spi->dev->clock.val = 0;
|
||||||
SPI_MUTEX_UNLOCK();
|
}
|
||||||
|
|
||||||
|
void spiStopBus(spi_t * spi)
|
||||||
|
{
|
||||||
|
if(!spi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
removeApbChangeCallback(spi, _on_apb_change);
|
removeApbChangeCallback(spi, _on_apb_change);
|
||||||
|
|
||||||
|
SPI_MUTEX_LOCK();
|
||||||
|
spiInitBus(spi);
|
||||||
|
SPI_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder)
|
spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder)
|
||||||
{
|
{
|
||||||
if(spi_num > 3){
|
if(spi_num >= SPI_COUNT){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,23 +587,32 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(spi_num == HSPI) {
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN);
|
if(spi_num == FSPI) {
|
||||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST);
|
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
|
||||||
} else if(spi_num == VSPI) {
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
|
||||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2);
|
} else if(spi_num == HSPI) {
|
||||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2);
|
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
|
||||||
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
|
||||||
} else {
|
} else {
|
||||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_1);
|
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_SPI_RST_1);
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
spiStopBus(spi);
|
if(spi_num == HSPI) {
|
||||||
spiSetDataMode(spi, dataMode);
|
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
|
||||||
spiSetBitOrder(spi, bitOrder);
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
|
||||||
spiSetClockDiv(spi, clockDiv);
|
} else if(spi_num == VSPI) {
|
||||||
|
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
|
||||||
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
|
spiInitBus(spi);
|
||||||
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;
|
||||||
@ -447,6 +623,10 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
|
|||||||
}
|
}
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
|
|
||||||
|
spiSetDataMode(spi, dataMode);
|
||||||
|
spiSetBitOrder(spi, bitOrder);
|
||||||
|
spiSetClockDiv(spi, clockDiv);
|
||||||
|
|
||||||
addApbChangeCallback(spi, _on_apb_change);
|
addApbChangeCallback(spi, _on_apb_change);
|
||||||
return spi;
|
return spi;
|
||||||
}
|
}
|
||||||
@ -459,7 +639,12 @@ void spiWaitReady(spi_t * spi)
|
|||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void spiWrite(spi_t * spi, uint32_t *data, uint8_t len)
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#define usr_mosi_dbitlen usr_mosi_bit_len
|
||||||
|
#define usr_miso_dbitlen usr_miso_bit_len
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void spiWrite(spi_t * spi, const uint32_t *data, uint8_t len)
|
||||||
{
|
{
|
||||||
if(!spi) {
|
if(!spi) {
|
||||||
return;
|
return;
|
||||||
@ -532,17 +717,7 @@ uint8_t spiTransferByte(spi_t * spi, uint8_t data)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t __spiTranslate24(uint32_t data)
|
static uint32_t __spiTranslate32(uint32_t data)
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint32_t l;
|
|
||||||
uint8_t b[4];
|
|
||||||
} out;
|
|
||||||
out.l = data;
|
|
||||||
return out.b[2] | (out.b[1] << 8) | (out.b[0] << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t __spiTranslate32(uint32_t data)
|
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
uint32_t l;
|
uint32_t l;
|
||||||
@ -630,7 +805,7 @@ uint32_t spiTransferLong(spi_t * spi, uint32_t data)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t bytes)
|
static void __spiTransferBytes(spi_t * spi, const uint8_t * data, uint8_t * out, uint32_t bytes)
|
||||||
{
|
{
|
||||||
if(!spi) {
|
if(!spi) {
|
||||||
return;
|
return;
|
||||||
@ -671,7 +846,7 @@ void __spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t byt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t size)
|
void spiTransferBytes(spi_t * spi, const uint8_t * data, uint8_t * out, uint32_t size)
|
||||||
{
|
{
|
||||||
if(!spi) {
|
if(!spi) {
|
||||||
return;
|
return;
|
||||||
@ -722,23 +897,39 @@ void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bi
|
|||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
spi->dev->clock.val = clockDiv;
|
spi->dev->clock.val = clockDiv;
|
||||||
switch (dataMode) {
|
switch (dataMode) {
|
||||||
case SPI_MODE1:
|
case SPI_MODE1:
|
||||||
spi->dev->pin.ck_idle_edge = 0;
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
spi->dev->user.ck_out_edge = 1;
|
spi->dev->misc.ck_idle_edge = 0;
|
||||||
break;
|
#else
|
||||||
case SPI_MODE2:
|
spi->dev->pin.ck_idle_edge = 0;
|
||||||
spi->dev->pin.ck_idle_edge = 1;
|
#endif
|
||||||
spi->dev->user.ck_out_edge = 1;
|
spi->dev->user.ck_out_edge = 1;
|
||||||
break;
|
break;
|
||||||
case SPI_MODE3:
|
case SPI_MODE2:
|
||||||
spi->dev->pin.ck_idle_edge = 1;
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
spi->dev->user.ck_out_edge = 0;
|
spi->dev->misc.ck_idle_edge = 1;
|
||||||
break;
|
#else
|
||||||
case SPI_MODE0:
|
spi->dev->pin.ck_idle_edge = 1;
|
||||||
default:
|
#endif
|
||||||
spi->dev->pin.ck_idle_edge = 0;
|
spi->dev->user.ck_out_edge = 1;
|
||||||
spi->dev->user.ck_out_edge = 0;
|
break;
|
||||||
break;
|
case SPI_MODE3:
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
spi->dev->misc.ck_idle_edge = 1;
|
||||||
|
#else
|
||||||
|
spi->dev->pin.ck_idle_edge = 1;
|
||||||
|
#endif
|
||||||
|
spi->dev->user.ck_out_edge = 0;
|
||||||
|
break;
|
||||||
|
case SPI_MODE0:
|
||||||
|
default:
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
spi->dev->misc.ck_idle_edge = 0;
|
||||||
|
#else
|
||||||
|
spi->dev->pin.ck_idle_edge = 0;
|
||||||
|
#endif
|
||||||
|
spi->dev->user.ck_out_edge = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (SPI_MSBFIRST == bitOrder) {
|
if (SPI_MSBFIRST == bitOrder) {
|
||||||
spi->dev->ctrl.wr_bit_order = 0;
|
spi->dev->ctrl.wr_bit_order = 0;
|
||||||
@ -765,7 +956,7 @@ void spiEndTransaction(spi_t * spi)
|
|||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR spiWriteByteNL(spi_t * spi, uint8_t data)
|
void ARDUINO_ISR_ATTR spiWriteByteNL(spi_t * spi, uint8_t data)
|
||||||
{
|
{
|
||||||
if(!spi) {
|
if(!spi) {
|
||||||
return;
|
return;
|
||||||
@ -791,7 +982,7 @@ uint8_t spiTransferByteNL(spi_t * spi, uint8_t data)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR spiWriteShortNL(spi_t * spi, uint16_t data)
|
void ARDUINO_ISR_ATTR spiWriteShortNL(spi_t * spi, uint16_t data)
|
||||||
{
|
{
|
||||||
if(!spi) {
|
if(!spi) {
|
||||||
return;
|
return;
|
||||||
@ -826,7 +1017,7 @@ uint16_t spiTransferShortNL(spi_t * spi, uint16_t data)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR spiWriteLongNL(spi_t * spi, uint32_t data)
|
void ARDUINO_ISR_ATTR spiWriteLongNL(spi_t * spi, uint32_t data)
|
||||||
{
|
{
|
||||||
if(!spi) {
|
if(!spi) {
|
||||||
return;
|
return;
|
||||||
@ -861,7 +1052,7 @@ uint32_t spiTransferLongNL(spi_t * spi, uint32_t data)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spiWriteNL(spi_t * spi, const void * data_in, size_t len){
|
void spiWriteNL(spi_t * spi, const void * data_in, uint32_t len){
|
||||||
size_t longs = len >> 2;
|
size_t longs = len >> 2;
|
||||||
if(len & 3){
|
if(len & 3){
|
||||||
longs++;
|
longs++;
|
||||||
@ -887,7 +1078,7 @@ void spiWriteNL(spi_t * spi, const void * data_in, size_t len){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void spiTransferBytesNL(spi_t * spi, const void * data_in, uint8_t * data_out, size_t len){
|
void spiTransferBytesNL(spi_t * spi, const void * data_in, uint8_t * data_out, uint32_t len){
|
||||||
if(!spi) {
|
if(!spi) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -974,7 +1165,7 @@ void spiTransferBitsNL(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR spiWritePixelsNL(spi_t * spi, const void * data_in, size_t len){
|
void ARDUINO_ISR_ATTR spiWritePixelsNL(spi_t * spi, const void * data_in, uint32_t len){
|
||||||
size_t longs = len >> 2;
|
size_t longs = len >> 2;
|
||||||
if(len & 3){
|
if(len & 3){
|
||||||
longs++;
|
longs++;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
@ -26,7 +27,9 @@ extern "C" {
|
|||||||
|
|
||||||
#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
|
||||||
#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
|
||||||
|
|
||||||
// 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
|
||||||
@ -96,7 +99,7 @@ void spiSetClockDiv(spi_t * spi, uint32_t clockDiv);
|
|||||||
void spiSetDataMode(spi_t * spi, uint8_t dataMode);
|
void spiSetDataMode(spi_t * spi, uint8_t dataMode);
|
||||||
void spiSetBitOrder(spi_t * spi, uint8_t bitOrder);
|
void spiSetBitOrder(spi_t * spi, uint8_t bitOrder);
|
||||||
|
|
||||||
void spiWrite(spi_t * spi, uint32_t *data, uint8_t len);
|
void spiWrite(spi_t * spi, const uint32_t *data, uint8_t len);
|
||||||
void spiWriteByte(spi_t * spi, uint8_t data);
|
void spiWriteByte(spi_t * spi, uint8_t data);
|
||||||
void spiWriteWord(spi_t * spi, uint16_t data);
|
void spiWriteWord(spi_t * spi, uint16_t data);
|
||||||
void spiWriteLong(spi_t * spi, uint32_t data);
|
void spiWriteLong(spi_t * spi, uint32_t data);
|
||||||
@ -105,7 +108,7 @@ void spiTransfer(spi_t * spi, uint32_t *out, uint8_t len);
|
|||||||
uint8_t spiTransferByte(spi_t * spi, uint8_t data);
|
uint8_t spiTransferByte(spi_t * spi, uint8_t data);
|
||||||
uint16_t spiTransferWord(spi_t * spi, uint16_t data);
|
uint16_t spiTransferWord(spi_t * spi, uint16_t data);
|
||||||
uint32_t spiTransferLong(spi_t * spi, uint32_t data);
|
uint32_t spiTransferLong(spi_t * spi, uint32_t data);
|
||||||
void spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t size);
|
void spiTransferBytes(spi_t * spi, const uint8_t * data, uint8_t * out, uint32_t size);
|
||||||
void spiTransferBits(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits);
|
void spiTransferBits(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -115,11 +118,11 @@ void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bi
|
|||||||
void spiSimpleTransaction(spi_t * spi);
|
void spiSimpleTransaction(spi_t * spi);
|
||||||
void spiEndTransaction(spi_t * spi);
|
void spiEndTransaction(spi_t * spi);
|
||||||
|
|
||||||
void spiWriteNL(spi_t * spi, const void * data, uint32_t len);
|
void spiWriteNL(spi_t * spi, const void * data_in, uint32_t len);
|
||||||
void spiWriteByteNL(spi_t * spi, uint8_t data);
|
void spiWriteByteNL(spi_t * spi, uint8_t data);
|
||||||
void spiWriteShortNL(spi_t * spi, uint16_t data);
|
void spiWriteShortNL(spi_t * spi, uint16_t data);
|
||||||
void spiWriteLongNL(spi_t * spi, uint32_t data);
|
void spiWriteLongNL(spi_t * spi, uint32_t data);
|
||||||
void spiWritePixelsNL(spi_t * spi, const void * data, uint32_t len);
|
void spiWritePixelsNL(spi_t * spi, const void * data_in, uint32_t len);
|
||||||
|
|
||||||
#define spiTransferNL(spi, data, len) spiTransferBytesNL(spi, data, data, len)
|
#define spiTransferNL(spi, data, len) spiTransferBytesNL(spi, data, data, len)
|
||||||
uint8_t spiTransferByteNL(spi_t * spi, uint8_t data);
|
uint8_t spiTransferByteNL(spi_t * spi, uint8_t data);
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
#include "lwip/apps/sntp.h"
|
#include "lwip/apps/sntp.h"
|
||||||
|
//#include "tcpip_adapter.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
|
||||||
static void setTimeZone(long offset, int daylight)
|
static void setTimeZone(long offset, int daylight)
|
||||||
{
|
{
|
||||||
@ -45,6 +47,8 @@ static void setTimeZone(long offset, int daylight)
|
|||||||
* */
|
* */
|
||||||
void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char* server2, const char* server3)
|
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()){
|
if(sntp_enabled()){
|
||||||
sntp_stop();
|
sntp_stop();
|
||||||
}
|
}
|
||||||
@ -62,6 +66,8 @@ void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1,
|
|||||||
* */
|
* */
|
||||||
void configTzTime(const char* tz, const char* server1, const char* server2, const char* server3)
|
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()){
|
if(sntp_enabled()){
|
||||||
sntp_stop();
|
sntp_stop();
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,27 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/xtensa_api.h"
|
#include "freertos/xtensa_api.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "rom/ets_sys.h"
|
|
||||||
#include "soc/timer_group_struct.h"
|
#include "soc/timer_group_struct.h"
|
||||||
#include "soc/dport_reg.h"
|
#include "soc/dport_reg.h"
|
||||||
#include "esp_attr.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"
|
||||||
|
#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"
|
#include "esp_intr.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define HWTIMER_LOCK() portENTER_CRITICAL(timer->lock)
|
#define HWTIMER_LOCK() portENTER_CRITICAL(timer->lock)
|
||||||
#define HWTIMER_UNLOCK() portEXIT_CRITICAL(timer->lock)
|
#define HWTIMER_UNLOCK() portEXIT_CRITICAL(timer->lock)
|
||||||
@ -67,11 +83,18 @@ static hw_timer_t hw_timer[4] = {
|
|||||||
typedef void (*voidFuncPtr)(void);
|
typedef void (*voidFuncPtr)(void);
|
||||||
static voidFuncPtr __timerInterruptHandlers[4] = {0,0,0,0};
|
static voidFuncPtr __timerInterruptHandlers[4] = {0,0,0,0};
|
||||||
|
|
||||||
void IRAM_ATTR __timerISR(void * arg){
|
void ARDUINO_ISR_ATTR __timerISR(void * arg){
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
uint32_t s0 = TIMERG0.int_st_timers.val;
|
uint32_t s0 = TIMERG0.int_st_timers.val;
|
||||||
uint32_t s1 = TIMERG1.int_st_timers.val;
|
uint32_t s1 = TIMERG1.int_st_timers.val;
|
||||||
TIMERG0.int_clr_timers.val = s0;
|
TIMERG0.int_clr_timers.val = s0;
|
||||||
TIMERG1.int_clr_timers.val = s1;
|
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 status = (s1 & 3) << 2 | (s0 & 3);
|
||||||
uint8_t i = 4;
|
uint8_t i = 4;
|
||||||
//restart the timers that should autoreload
|
//restart the timers that should autoreload
|
||||||
@ -165,6 +188,7 @@ void timerStop(hw_timer_t *timer){
|
|||||||
|
|
||||||
void timerRestart(hw_timer_t *timer){
|
void timerRestart(hw_timer_t *timer){
|
||||||
timer->dev->config.enable = 0;
|
timer->dev->config.enable = 0;
|
||||||
|
timer->dev->reload = 1;
|
||||||
timer->dev->config.enable = 1;
|
timer->dev->config.enable = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,15 +226,29 @@ hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){
|
|||||||
}
|
}
|
||||||
hw_timer_t * timer = &hw_timer[num];
|
hw_timer_t * timer = &hw_timer[num];
|
||||||
if(timer->group) {
|
if(timer->group) {
|
||||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_TIMERGROUP1_CLK_EN);
|
periph_module_enable(PERIPH_TIMG1_MODULE);
|
||||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP1_RST);
|
|
||||||
TIMERG1.int_ena.val &= ~BIT(timer->timer);
|
|
||||||
} else {
|
} else {
|
||||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_TIMERGROUP_CLK_EN);
|
periph_module_enable(PERIPH_TIMG0_MODULE);
|
||||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP_RST);
|
|
||||||
TIMERG0.int_ena.val &= ~BIT(timer->timer);
|
|
||||||
}
|
}
|
||||||
timer->dev->config.enable = 0;
|
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);
|
timerSetDivider(timer, divider);
|
||||||
timerSetCountUp(timer, countUp);
|
timerSetCountUp(timer, countUp);
|
||||||
timerSetAutoReload(timer, false);
|
timerSetAutoReload(timer, false);
|
||||||
@ -228,6 +266,9 @@ void timerEnd(hw_timer_t *timer){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
|
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
|
||||||
|
// EDGE DOES NOT WORK CURRENTLY
|
||||||
|
edge = false;
|
||||||
|
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
static intr_handle_t intr_handle = NULL;
|
static intr_handle_t intr_handle = NULL;
|
||||||
if(intr_handle){
|
if(intr_handle){
|
||||||
@ -239,8 +280,18 @@ void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
|
|||||||
timer->dev->config.alarm_en = 0;
|
timer->dev->config.alarm_en = 0;
|
||||||
if(timer->num & 2){
|
if(timer->num & 2){
|
||||||
TIMERG1.int_ena.val &= ~BIT(timer->timer);
|
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 {
|
} else {
|
||||||
TIMERG0.int_ena.val &= ~BIT(timer->timer);
|
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;
|
__timerInterruptHandlers[timer->num] = NULL;
|
||||||
} else {
|
} else {
|
||||||
@ -263,7 +314,7 @@ void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
|
|||||||
}
|
}
|
||||||
if(!initialized){
|
if(!initialized){
|
||||||
initialized = true;
|
initialized = true;
|
||||||
esp_intr_alloc(intr_source, (int)(ESP_INTR_FLAG_IRAM|ESP_INTR_FLAG_LOWMED|ESP_INTR_FLAG_EDGE), __timerISR, NULL, &intr_handle);
|
esp_intr_alloc(intr_source, (int)(ARDUINO_ISR_FLAG|ESP_INTR_FLAG_LOWMED), __timerISR, NULL, &intr_handle);
|
||||||
} else {
|
} else {
|
||||||
intr_matrix_set(esp_intr_get_cpu(intr_handle), intr_source, esp_intr_get_intno(intr_handle));
|
intr_matrix_set(esp_intr_get_cpu(intr_handle), intr_source, esp_intr_get_intno(intr_handle));
|
||||||
}
|
}
|
||||||
|
702
cores/esp32/esp32-hal-tinyusb.c
Normal file
702
cores/esp32/esp32-hal-tinyusb.c
Normal file
@ -0,0 +1,702 @@
|
|||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#if CONFIG_USB_ENABLED
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
#include "soc/soc.h"
|
||||||
|
#include "soc/efuse_reg.h"
|
||||||
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
#include "soc/usb_struct.h"
|
||||||
|
#include "soc/usb_reg.h"
|
||||||
|
#include "soc/usb_wrap_reg.h"
|
||||||
|
#include "soc/usb_wrap_struct.h"
|
||||||
|
#include "soc/periph_defs.h"
|
||||||
|
#include "soc/timer_group_struct.h"
|
||||||
|
#include "soc/system_reg.h"
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "driver/periph_ctrl.h"
|
||||||
|
|
||||||
|
#include "esp_efuse.h"
|
||||||
|
#include "esp_efuse_table.h"
|
||||||
|
|
||||||
|
#include "tinyusb.h"
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
|
||||||
|
#include "esp32-hal-tinyusb.h"
|
||||||
|
#include "esp32s2/rom/usb/usb_persist.h"
|
||||||
|
|
||||||
|
typedef char tusb_str_t[127];
|
||||||
|
|
||||||
|
static bool WEBUSB_ENABLED = false;
|
||||||
|
|
||||||
|
static tusb_str_t WEBUSB_URL = "";
|
||||||
|
static tusb_str_t USB_DEVICE_PRODUCT = "";
|
||||||
|
static tusb_str_t USB_DEVICE_MANUFACTURER = "";
|
||||||
|
static tusb_str_t USB_DEVICE_SERIAL = "";
|
||||||
|
|
||||||
|
static uint8_t USB_DEVICE_ATTRIBUTES = 0;
|
||||||
|
static uint16_t USB_DEVICE_POWER = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Device Descriptor
|
||||||
|
* */
|
||||||
|
static tusb_desc_device_t tinyusb_device_descriptor = {
|
||||||
|
.bLength = sizeof(tusb_desc_device_t),
|
||||||
|
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||||
|
.bcdUSB = 0,
|
||||||
|
.bDeviceClass = 0,
|
||||||
|
.bDeviceSubClass = 0,
|
||||||
|
.bDeviceProtocol = 0,
|
||||||
|
.bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE,
|
||||||
|
|
||||||
|
.idVendor = 0,
|
||||||
|
.idProduct = 0,
|
||||||
|
.bcdDevice = 0,
|
||||||
|
|
||||||
|
.iManufacturer = 0x01,
|
||||||
|
.iProduct = 0x02,
|
||||||
|
.iSerialNumber = 0x03,
|
||||||
|
|
||||||
|
.bNumConfigurations = 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* String Descriptors
|
||||||
|
* */
|
||||||
|
#define MAX_STRING_DESCRIPTORS 20
|
||||||
|
static uint32_t tinyusb_string_descriptor_len = 4;
|
||||||
|
static char * tinyusb_string_descriptor[MAX_STRING_DESCRIPTORS] = {
|
||||||
|
// array of pointer to string descriptors
|
||||||
|
"\x09\x04", // 0: is supported language is English (0x0409)
|
||||||
|
USB_DEVICE_MANUFACTURER,// 1: Manufacturer
|
||||||
|
USB_DEVICE_PRODUCT, // 2: Product
|
||||||
|
USB_DEVICE_SERIAL, // 3: Serials, should use chip ID
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Microsoft OS 2.0 registry property descriptor
|
||||||
|
Per MS requirements https://msdn.microsoft.com/en-us/library/windows/hardware/hh450799(v=vs.85).aspx
|
||||||
|
device should create DeviceInterfaceGUIDs. It can be done by driver and
|
||||||
|
in case of real PnP solution device should expose MS "Microsoft OS 2.0
|
||||||
|
registry property descriptor". Such descriptor can insert any record
|
||||||
|
into Windows registry per device/configuration/interface. In our case it
|
||||||
|
will insert "DeviceInterfaceGUIDs" multistring property.
|
||||||
|
|
||||||
|
GUID is freshly generated and should be OK to use.
|
||||||
|
|
||||||
|
https://developers.google.com/web/fundamentals/native-hardware/build-for-webusb/
|
||||||
|
(Section Microsoft OS compatibility descriptors)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MS_OS_20_DESC_LEN 0xB2
|
||||||
|
|
||||||
|
static uint8_t const tinyusb_ms_os_20_descriptor[] =
|
||||||
|
{
|
||||||
|
// Set header: length, type, windows version, total length
|
||||||
|
U16_TO_U8S_LE(0x000A), U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR), U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(MS_OS_20_DESC_LEN),
|
||||||
|
|
||||||
|
// Configuration subset header: length, type, configuration index, reserved, configuration total length
|
||||||
|
U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_CONFIGURATION), 0, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A),
|
||||||
|
|
||||||
|
// Function Subset header: length, type, first interface, reserved, subset length
|
||||||
|
U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), 0, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08),
|
||||||
|
|
||||||
|
// MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID
|
||||||
|
U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sub-compatible
|
||||||
|
|
||||||
|
// MS OS 2.0 Registry property descriptor: length, type
|
||||||
|
U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08-0x08-0x14), U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY),
|
||||||
|
U16_TO_U8S_LE(0x0007), U16_TO_U8S_LE(0x002A), // wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUIDs\0" in UTF-16
|
||||||
|
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00,
|
||||||
|
'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00,
|
||||||
|
U16_TO_U8S_LE(0x0050), // wPropertyDataLength
|
||||||
|
//bPropertyData: “{975F44D9-0D08-43FD-8B3E-127CA8AFFF9D}”.
|
||||||
|
'{', 0x00, '9', 0x00, '7', 0x00, '5', 0x00, 'F', 0x00, '4', 0x00, '4', 0x00, 'D', 0x00, '9', 0x00, '-', 0x00,
|
||||||
|
'0', 0x00, 'D', 0x00, '0', 0x00, '8', 0x00, '-', 0x00, '4', 0x00, '3', 0x00, 'F', 0x00, 'D', 0x00, '-', 0x00,
|
||||||
|
'8', 0x00, 'B', 0x00, '3', 0x00, 'E', 0x00, '-', 0x00, '1', 0x00, '2', 0x00, '7', 0x00, 'C', 0x00, 'A', 0x00,
|
||||||
|
'8', 0x00, 'A', 0x00, 'F', 0x00, 'F', 0x00, 'F', 0x00, '9', 0x00, 'D', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
TU_VERIFY_STATIC(sizeof(tinyusb_ms_os_20_descriptor) == MS_OS_20_DESC_LEN, "Incorrect size");
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BOS Descriptor (required for webUSB)
|
||||||
|
* */
|
||||||
|
#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_WEBUSB_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VENDOR_REQUEST_WEBUSB = 1,
|
||||||
|
VENDOR_REQUEST_MICROSOFT = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t const tinyusb_bos_descriptor[] = {
|
||||||
|
// total length, number of device caps
|
||||||
|
TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 2),
|
||||||
|
|
||||||
|
// Vendor Code, iLandingPage
|
||||||
|
TUD_BOS_WEBUSB_DESCRIPTOR(VENDOR_REQUEST_WEBUSB, 1),
|
||||||
|
|
||||||
|
// Microsoft OS 2.0 descriptor
|
||||||
|
TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, VENDOR_REQUEST_MICROSOFT)
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* URL Descriptor (required for webUSB)
|
||||||
|
* */
|
||||||
|
typedef struct TU_ATTR_PACKED {
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint8_t bScheme;
|
||||||
|
char url[127];
|
||||||
|
} tinyusb_desc_webusb_url_t;
|
||||||
|
|
||||||
|
static tinyusb_desc_webusb_url_t tinyusb_url_descriptor = {
|
||||||
|
.bLength = 3,
|
||||||
|
.bDescriptorType = 3, // WEBUSB URL type
|
||||||
|
.bScheme = 1, // URL Scheme Prefix: 0: "http://", 1: "https://", 255: ""
|
||||||
|
.url = ""
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configuration Descriptor
|
||||||
|
* */
|
||||||
|
|
||||||
|
static tinyusb_descriptor_cb_t tinyusb_loaded_interfaces_callbacks[USB_INTERFACE_MAX];
|
||||||
|
static uint32_t tinyusb_loaded_interfaces_mask = 0;
|
||||||
|
static uint8_t tinyusb_loaded_interfaces_num = 0;
|
||||||
|
static uint16_t tinyusb_config_descriptor_len = 0;
|
||||||
|
static uint8_t * tinyusb_config_descriptor = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Endpoint Usage Tracking
|
||||||
|
* */
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
uint32_t in:16;
|
||||||
|
uint32_t out:16;
|
||||||
|
};
|
||||||
|
uint32_t val;
|
||||||
|
} tinyusb_endpoints_usage_t;
|
||||||
|
|
||||||
|
static tinyusb_endpoints_usage_t tinyusb_endpoints;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TinyUSB Callbacks
|
||||||
|
* */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Invoked when received GET CONFIGURATION DESCRIPTOR.
|
||||||
|
*/
|
||||||
|
uint8_t const *tud_descriptor_configuration_cb(uint8_t index)
|
||||||
|
{
|
||||||
|
//log_d("%u", index);
|
||||||
|
return tinyusb_config_descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Invoked when received GET DEVICE DESCRIPTOR.
|
||||||
|
*/
|
||||||
|
uint8_t const *tud_descriptor_device_cb(void)
|
||||||
|
{
|
||||||
|
//log_d("");
|
||||||
|
return (uint8_t const *)&tinyusb_device_descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Invoked when received GET STRING DESCRIPTOR request.
|
||||||
|
*/
|
||||||
|
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
||||||
|
{
|
||||||
|
//log_d("%u (0x%x)", index, langid);
|
||||||
|
static uint16_t _desc_str[127];
|
||||||
|
uint8_t chr_count;
|
||||||
|
|
||||||
|
if (index == 0) {
|
||||||
|
memcpy(&_desc_str[1], tinyusb_string_descriptor[0], 2);
|
||||||
|
chr_count = 1;
|
||||||
|
} else {
|
||||||
|
// Convert ASCII string into UTF-16
|
||||||
|
if (index >= tinyusb_string_descriptor_len) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const char *str = tinyusb_string_descriptor[index];
|
||||||
|
// Cap at max char
|
||||||
|
chr_count = strlen(str);
|
||||||
|
if (chr_count > 126) {
|
||||||
|
chr_count = 126;
|
||||||
|
}
|
||||||
|
for (uint8_t i = 0; i < chr_count; i++) {
|
||||||
|
_desc_str[1 + i] = str[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// first byte is len, second byte is string type
|
||||||
|
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
|
||||||
|
|
||||||
|
return _desc_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Invoked when received GET BOS DESCRIPTOR request.
|
||||||
|
*/
|
||||||
|
uint8_t const * tud_descriptor_bos_cb(void)
|
||||||
|
{
|
||||||
|
//log_d("");
|
||||||
|
return tinyusb_bos_descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((weak)) bool tinyusb_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request){ return false; }
|
||||||
|
__attribute__ ((weak)) bool tinyusb_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request){ return true; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle WebUSB and Vendor requests.
|
||||||
|
*/
|
||||||
|
bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request)
|
||||||
|
{
|
||||||
|
if(WEBUSB_ENABLED && (request->bRequest == VENDOR_REQUEST_WEBUSB
|
||||||
|
|| (request->bRequest == VENDOR_REQUEST_MICROSOFT && request->wIndex == 7))){
|
||||||
|
if(request->bRequest == VENDOR_REQUEST_WEBUSB){
|
||||||
|
// match vendor request in BOS descriptor
|
||||||
|
// Get landing page url
|
||||||
|
tinyusb_url_descriptor.bLength = 3 + strlen(WEBUSB_URL);
|
||||||
|
snprintf(tinyusb_url_descriptor.url, 127, "%s", WEBUSB_URL);
|
||||||
|
return tud_control_xfer(rhport, request, (void*) &tinyusb_url_descriptor, tinyusb_url_descriptor.bLength);
|
||||||
|
}
|
||||||
|
// Get Microsoft OS 2.0 compatible descriptor
|
||||||
|
uint16_t total_len;
|
||||||
|
memcpy(&total_len, tinyusb_ms_os_20_descriptor + 8, 2);
|
||||||
|
return tud_control_xfer(rhport, request, (void*) tinyusb_ms_os_20_descriptor, total_len);
|
||||||
|
}
|
||||||
|
return tinyusb_vendor_control_request_cb(rhport, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request)
|
||||||
|
{
|
||||||
|
if(!WEBUSB_ENABLED || !(request->bRequest == VENDOR_REQUEST_WEBUSB
|
||||||
|
|| (request->bRequest == VENDOR_REQUEST_MICROSOFT && request->wIndex == 7))){
|
||||||
|
return tinyusb_vendor_control_complete_cb(rhport, request);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Required Callbacks
|
||||||
|
* */
|
||||||
|
#if CFG_TUD_HID
|
||||||
|
__attribute__ ((weak)) const uint8_t * tud_hid_descriptor_report_cb(void){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)) void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, const uint8_t * buffer, uint16_t bufsize){}
|
||||||
|
#endif
|
||||||
|
#if CFG_TUD_MSC
|
||||||
|
__attribute__ ((weak)) bool tud_msc_test_unit_ready_cb(uint8_t lun){return false;}
|
||||||
|
__attribute__ ((weak)) void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]){}
|
||||||
|
__attribute__ ((weak)) void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size){}
|
||||||
|
__attribute__ ((weak)) int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize){return -1;}
|
||||||
|
__attribute__ ((weak)) int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize){return -1;}
|
||||||
|
__attribute__ ((weak)) int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize){return -1;}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private API
|
||||||
|
* */
|
||||||
|
static bool usb_persist_enabled = false;
|
||||||
|
static restart_type_t usb_persist_mode = RESTART_NO_PERSIST;
|
||||||
|
|
||||||
|
static bool tinyusb_reserve_in_endpoint(uint8_t endpoint){
|
||||||
|
if(endpoint > 6 || (tinyusb_endpoints.in & BIT(endpoint)) != 0){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tinyusb_endpoints.in |= BIT(endpoint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tinyusb_reserve_out_endpoint(uint8_t endpoint){
|
||||||
|
if(endpoint > 6 || (tinyusb_endpoints.out & BIT(endpoint)) != 0){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tinyusb_endpoints.out |= BIT(endpoint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tinyusb_has_available_fifos(void){
|
||||||
|
uint8_t max_endpoints = 4, active_endpoints = 0;
|
||||||
|
if (tinyusb_loaded_interfaces_mask & BIT(USB_INTERFACE_CDC)) {
|
||||||
|
max_endpoints = 5; //CDC endpoint 0x85 is actually not linked to FIFO and not used
|
||||||
|
}
|
||||||
|
for(uint8_t i=1; i<7; i++){
|
||||||
|
if((tinyusb_endpoints.in & BIT(i)) != 0){
|
||||||
|
active_endpoints++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return active_endpoints < max_endpoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t tinyusb_load_descriptor(tinyusb_interface_t interface, uint8_t * dst, uint8_t * itf)
|
||||||
|
{
|
||||||
|
if(tinyusb_loaded_interfaces_callbacks[interface]){
|
||||||
|
return tinyusb_loaded_interfaces_callbacks[interface](dst, itf);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tinyusb_load_enabled_interfaces(){
|
||||||
|
tinyusb_config_descriptor_len += TUD_CONFIG_DESC_LEN;
|
||||||
|
tinyusb_config_descriptor = (uint8_t *)malloc(tinyusb_config_descriptor_len);
|
||||||
|
if (tinyusb_config_descriptor == NULL) {
|
||||||
|
log_e("Descriptor Malloc Failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t * dst = tinyusb_config_descriptor + TUD_CONFIG_DESC_LEN;
|
||||||
|
|
||||||
|
for(int i=0; i<USB_INTERFACE_MAX; i++){
|
||||||
|
if (tinyusb_loaded_interfaces_mask & (1U << i)) {
|
||||||
|
uint16_t len = tinyusb_load_descriptor((tinyusb_interface_t)i, dst, &tinyusb_loaded_interfaces_num);
|
||||||
|
if (!len) {
|
||||||
|
log_e("Descriptor Load Failed");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if(i == USB_INTERFACE_CDC){
|
||||||
|
if(!tinyusb_reserve_out_endpoint(3) ||!tinyusb_reserve_in_endpoint(4) || !tinyusb_reserve_in_endpoint(5)){
|
||||||
|
log_e("CDC Reserve Endpoints Failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB Device");
|
||||||
|
uint8_t descriptor[TUD_CONFIG_DESC_LEN] = {
|
||||||
|
//num configs, interface count, string index, total length, attribute, power in mA
|
||||||
|
TUD_CONFIG_DESCRIPTOR(1, tinyusb_loaded_interfaces_num, str_index, tinyusb_config_descriptor_len, USB_DEVICE_ATTRIBUTES, USB_DEVICE_POWER)
|
||||||
|
};
|
||||||
|
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))) {
|
||||||
|
usb_persist_enabled = true;
|
||||||
|
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);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char nibble_to_hex_char(uint8_t b)
|
||||||
|
{
|
||||||
|
if (b < 0xa) {
|
||||||
|
return '0' + b;
|
||||||
|
} else {
|
||||||
|
return 'a' + b - 0xa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_usb_serial_num(void)
|
||||||
|
{
|
||||||
|
/* Get the MAC address */
|
||||||
|
const uint32_t mac0 = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_0_REG, EFUSE_MAC_0);
|
||||||
|
const uint32_t mac1 = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_1_REG, EFUSE_MAC_1);
|
||||||
|
uint8_t mac_bytes[6];
|
||||||
|
memcpy(mac_bytes, &mac0, 4);
|
||||||
|
memcpy(mac_bytes + 4, &mac1, 2);
|
||||||
|
|
||||||
|
/* Convert to UTF16 string */
|
||||||
|
uint8_t* srl = (uint8_t*)USB_DEVICE_SERIAL;
|
||||||
|
for (int i = 0; i < 6; ++i) {
|
||||||
|
uint8_t b = mac_bytes[5 - i]; /* printing from the MSB */
|
||||||
|
if (i) {
|
||||||
|
*srl++ = ':';
|
||||||
|
}
|
||||||
|
*srl++ = nibble_to_hex_char(b >> 4);
|
||||||
|
*srl++ = nibble_to_hex_char(b & 0xf);
|
||||||
|
}
|
||||||
|
*srl++ = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tinyusb_apply_device_config(tinyusb_device_config_t *config){
|
||||||
|
if(config->product_name){
|
||||||
|
snprintf(USB_DEVICE_PRODUCT, 126, "%s", config->product_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(config->manufacturer_name){
|
||||||
|
snprintf(USB_DEVICE_MANUFACTURER, 126, "%s", config->manufacturer_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(config->serial_number && config->serial_number[0]){
|
||||||
|
snprintf(USB_DEVICE_SERIAL, 126, "%s", config->serial_number);
|
||||||
|
} else {
|
||||||
|
set_usb_serial_num();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(config->webusb_url){
|
||||||
|
snprintf(WEBUSB_URL, 126, "%s", config->webusb_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
WEBUSB_ENABLED = config->webusb_enabled;
|
||||||
|
USB_DEVICE_ATTRIBUTES = config->usb_attributes;
|
||||||
|
USB_DEVICE_POWER = config->usb_power_ma;
|
||||||
|
|
||||||
|
tinyusb_device_descriptor.bcdUSB = config->usb_version;
|
||||||
|
tinyusb_device_descriptor.idVendor = config->vid;
|
||||||
|
tinyusb_device_descriptor.idProduct = config->pid;
|
||||||
|
tinyusb_device_descriptor.bcdDevice = config->fw_version;
|
||||||
|
tinyusb_device_descriptor.bDeviceClass = config->usb_class;
|
||||||
|
tinyusb_device_descriptor.bDeviceSubClass = config->usb_subclass;
|
||||||
|
tinyusb_device_descriptor.bDeviceProtocol = config->usb_protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void IRAM_ATTR usb_persist_shutdown_handler(void)
|
||||||
|
{
|
||||||
|
if(usb_persist_mode != RESTART_NO_PERSIST){
|
||||||
|
if (usb_persist_enabled) {
|
||||||
|
REG_SET_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_IO_MUX_RESET_DISABLE);
|
||||||
|
REG_SET_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_USB_RESET_DISABLE);
|
||||||
|
}
|
||||||
|
if (usb_persist_mode == RESTART_BOOTLOADER) {
|
||||||
|
//USB CDC Download
|
||||||
|
if (usb_persist_enabled) {
|
||||||
|
USB_WRAP.date.val = USBDC_PERSIST_ENA;
|
||||||
|
}
|
||||||
|
REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
|
||||||
|
periph_module_disable(PERIPH_TIMG1_MODULE);
|
||||||
|
} else if (usb_persist_mode == RESTART_BOOTLOADER_DFU) {
|
||||||
|
//DFU Download
|
||||||
|
USB_WRAP.date.val = USBDC_BOOT_DFU;
|
||||||
|
REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
|
||||||
|
periph_module_disable(PERIPH_TIMG0_MODULE);
|
||||||
|
periph_module_disable(PERIPH_TIMG1_MODULE);
|
||||||
|
} else if (usb_persist_enabled) {
|
||||||
|
//USB Persist reboot
|
||||||
|
USB_WRAP.date.val = USBDC_PERSIST_ENA;
|
||||||
|
}
|
||||||
|
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// USB Device Driver task
|
||||||
|
// This top level thread processes all usb events and invokes callbacks
|
||||||
|
static void usb_device_task(void *param) {
|
||||||
|
(void)param;
|
||||||
|
while(1) tud_task(); // RTOS forever loop
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PUBLIC API
|
||||||
|
* */
|
||||||
|
|
||||||
|
esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb)
|
||||||
|
{
|
||||||
|
if((interface >= USB_INTERFACE_MAX) || (tinyusb_loaded_interfaces_mask & (1U << interface))){
|
||||||
|
log_e("Interface %u not enabled", interface);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
tinyusb_loaded_interfaces_mask |= (1U << interface);
|
||||||
|
tinyusb_config_descriptor_len += descriptor_len;
|
||||||
|
tinyusb_loaded_interfaces_callbacks[interface] = cb;
|
||||||
|
log_d("Interface %u enabled", interface);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
|
||||||
|
static bool initialized = false;
|
||||||
|
if(initialized){
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
tinyusb_endpoints.val = 0;
|
||||||
|
tinyusb_apply_device_config(config);
|
||||||
|
if (!tinyusb_load_enabled_interfaces()) {
|
||||||
|
initialized = false;
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool usb_did_persist = (USB_WRAP.date.val == USBDC_PERSIST_ENA);
|
||||||
|
|
||||||
|
if(usb_did_persist && usb_persist_enabled){
|
||||||
|
// 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_USB_RESET_DISABLE);
|
||||||
|
} else {
|
||||||
|
// Reset USB module
|
||||||
|
periph_module_reset(PERIPH_USB_MODULE);
|
||||||
|
periph_module_enable(PERIPH_USB_MODULE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usb_persist_enabled && esp_register_shutdown_handler(usb_persist_shutdown_handler) != ESP_OK) {
|
||||||
|
initialized = false;
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyusb_config_t tusb_cfg = {
|
||||||
|
.external_phy = false // In the most cases you need to use a `false` value
|
||||||
|
};
|
||||||
|
esp_err_t err = tinyusb_driver_install(&tusb_cfg);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
initialized = false;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
xTaskCreate(usb_device_task, "usbd", 4096, NULL, configMAX_PRIORITIES - 1, NULL);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_persist_restart(restart_type_t mode)
|
||||||
|
{
|
||||||
|
if (usb_persist_enabled && mode < RESTART_TYPE_MAX) {
|
||||||
|
usb_persist_mode = mode;
|
||||||
|
esp_restart();
|
||||||
|
} else {
|
||||||
|
log_e("Persistence is not enabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t tinyusb_add_string_descriptor(const char * str){
|
||||||
|
if(str == NULL || tinyusb_string_descriptor_len >= MAX_STRING_DESCRIPTORS){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint8_t index = tinyusb_string_descriptor_len;
|
||||||
|
tinyusb_string_descriptor[tinyusb_string_descriptor_len++] = (char*)str;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t tinyusb_get_free_duplex_endpoint(void){
|
||||||
|
if(!tinyusb_has_available_fifos()){
|
||||||
|
log_e("No available IN endpoints");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for(uint8_t i=1; i<7; i++){
|
||||||
|
if((tinyusb_endpoints.in & BIT(i)) == 0 && (tinyusb_endpoints.out & BIT(i)) == 0){
|
||||||
|
tinyusb_endpoints.in |= BIT(i);
|
||||||
|
tinyusb_endpoints.out |= BIT(i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log_e("No available duplex endpoints");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t tinyusb_get_free_in_endpoint(void){
|
||||||
|
if(!tinyusb_has_available_fifos()){
|
||||||
|
log_e("No available IN endpoints");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for(uint8_t i=1; i<7; i++){
|
||||||
|
if((tinyusb_endpoints.in & BIT(i)) == 0 && (tinyusb_endpoints.out & BIT(i)) != 0){
|
||||||
|
tinyusb_endpoints.in |= BIT(i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(uint8_t i=1; i<7; i++){
|
||||||
|
if((tinyusb_endpoints.in & BIT(i)) == 0){
|
||||||
|
tinyusb_endpoints.in |= BIT(i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t tinyusb_get_free_out_endpoint(void){
|
||||||
|
for(uint8_t i=1; i<7; i++){
|
||||||
|
if((tinyusb_endpoints.out & BIT(i)) == 0 && (tinyusb_endpoints.in & BIT(i)) != 0){
|
||||||
|
tinyusb_endpoints.out |= BIT(i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(uint8_t i=1; i<7; i++){
|
||||||
|
if((tinyusb_endpoints.out & BIT(i)) == 0){
|
||||||
|
tinyusb_endpoints.out |= BIT(i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void usb_dw_reg_dump(void)
|
||||||
|
{
|
||||||
|
#define USB_PRINT_REG(r) printf("USB0." #r " = 0x%x;\n", USB0.r)
|
||||||
|
#define USB_PRINT_IREG(i, r) printf("USB0.in_ep_reg[%u]." #r " = 0x%x;\n", i, USB0.in_ep_reg[i].r)
|
||||||
|
#define USB_PRINT_OREG(i, r) printf("USB0.out_ep_reg[%u]." #r " = 0x%x;\n", i, USB0.out_ep_reg[i].r)
|
||||||
|
uint8_t i;
|
||||||
|
USB_PRINT_REG(gotgctl);
|
||||||
|
USB_PRINT_REG(gotgint);
|
||||||
|
USB_PRINT_REG(gahbcfg);
|
||||||
|
USB_PRINT_REG(gusbcfg);
|
||||||
|
USB_PRINT_REG(grstctl);
|
||||||
|
USB_PRINT_REG(gintsts);
|
||||||
|
USB_PRINT_REG(gintmsk);
|
||||||
|
USB_PRINT_REG(grxstsr);
|
||||||
|
USB_PRINT_REG(grxstsp);
|
||||||
|
USB_PRINT_REG(grxfsiz);
|
||||||
|
USB_PRINT_REG(gnptxsts);
|
||||||
|
USB_PRINT_REG(gpvndctl);
|
||||||
|
USB_PRINT_REG(ggpio);
|
||||||
|
USB_PRINT_REG(guid);
|
||||||
|
USB_PRINT_REG(gsnpsid);
|
||||||
|
USB_PRINT_REG(ghwcfg1);
|
||||||
|
USB_PRINT_REG(ghwcfg2);
|
||||||
|
USB_PRINT_REG(ghwcfg3);
|
||||||
|
USB_PRINT_REG(ghwcfg4);
|
||||||
|
USB_PRINT_REG(glpmcfg);
|
||||||
|
USB_PRINT_REG(gpwrdn);
|
||||||
|
USB_PRINT_REG(gdfifocfg);
|
||||||
|
USB_PRINT_REG(gadpctl);
|
||||||
|
USB_PRINT_REG(hptxfsiz);
|
||||||
|
USB_PRINT_REG(hcfg);
|
||||||
|
USB_PRINT_REG(hfir);
|
||||||
|
USB_PRINT_REG(hfnum);
|
||||||
|
USB_PRINT_REG(hptxsts);
|
||||||
|
USB_PRINT_REG(haint);
|
||||||
|
USB_PRINT_REG(haintmsk);
|
||||||
|
USB_PRINT_REG(hflbaddr);
|
||||||
|
USB_PRINT_REG(hprt);
|
||||||
|
USB_PRINT_REG(dcfg);
|
||||||
|
USB_PRINT_REG(dctl);
|
||||||
|
USB_PRINT_REG(dsts);
|
||||||
|
USB_PRINT_REG(diepmsk);
|
||||||
|
USB_PRINT_REG(doepmsk);
|
||||||
|
USB_PRINT_REG(daint);
|
||||||
|
USB_PRINT_REG(daintmsk);
|
||||||
|
USB_PRINT_REG(dtknqr1);
|
||||||
|
USB_PRINT_REG(dtknqr2);
|
||||||
|
USB_PRINT_REG(dvbusdis);
|
||||||
|
USB_PRINT_REG(dvbuspulse);
|
||||||
|
USB_PRINT_REG(dtknqr3_dthrctl);
|
||||||
|
USB_PRINT_REG(dtknqr4_fifoemptymsk);
|
||||||
|
USB_PRINT_REG(deachint);
|
||||||
|
USB_PRINT_REG(deachintmsk);
|
||||||
|
USB_PRINT_REG(pcgctrl);
|
||||||
|
USB_PRINT_REG(pcgctrl1);
|
||||||
|
USB_PRINT_REG(gnptxfsiz);
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
printf("USB0.dieptxf[%u] = 0x%x;\n", i, USB0.dieptxf[i]);
|
||||||
|
}
|
||||||
|
// for (i = 0; i < 16; i++) {
|
||||||
|
// printf("USB0.diepeachintmsk[%u] = 0x%x;\n", i, USB0.diepeachintmsk[i]);
|
||||||
|
// }
|
||||||
|
// for (i = 0; i < 16; i++) {
|
||||||
|
// printf("USB0.doepeachintmsk[%u] = 0x%x;\n", i, USB0.doepeachintmsk[i]);
|
||||||
|
// }
|
||||||
|
for (i = 0; i < 7; i++) {
|
||||||
|
printf("// EP %u:\n", i);
|
||||||
|
USB_PRINT_IREG(i, diepctl);
|
||||||
|
USB_PRINT_IREG(i, diepint);
|
||||||
|
USB_PRINT_IREG(i, dieptsiz);
|
||||||
|
USB_PRINT_IREG(i, diepdma);
|
||||||
|
USB_PRINT_IREG(i, dtxfsts);
|
||||||
|
USB_PRINT_OREG(i, doepctl);
|
||||||
|
USB_PRINT_OREG(i, doepint);
|
||||||
|
USB_PRINT_OREG(i, doeptsiz);
|
||||||
|
USB_PRINT_OREG(i, doepdma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
#endif /* CONFIG_USB_ENABLED */
|
103
cores/esp32/esp32-hal-tinyusb.h
Normal file
103
cores/esp32/esp32-hal-tinyusb.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#if CONFIG_USB_ENABLED
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "tinyusb.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t vid;
|
||||||
|
uint16_t pid;
|
||||||
|
const char * product_name;
|
||||||
|
const char * manufacturer_name;
|
||||||
|
const char * serial_number;
|
||||||
|
uint16_t fw_version;
|
||||||
|
|
||||||
|
uint16_t usb_version;
|
||||||
|
uint8_t usb_class;
|
||||||
|
uint8_t usb_subclass;
|
||||||
|
uint8_t usb_protocol;
|
||||||
|
uint8_t usb_attributes;
|
||||||
|
uint16_t usb_power_ma;
|
||||||
|
|
||||||
|
bool webusb_enabled;
|
||||||
|
const char * webusb_url;
|
||||||
|
} tinyusb_device_config_t;
|
||||||
|
|
||||||
|
#define TINYUSB_CONFIG_DEFAULT() { \
|
||||||
|
.vid = USB_ESPRESSIF_VID, \
|
||||||
|
.pid = 0x0002, \
|
||||||
|
.product_name = CONFIG_USB_DESC_PRODUCT_STRING, \
|
||||||
|
.manufacturer_name = CONFIG_USB_DESC_MANUFACTURER_STRING, \
|
||||||
|
.serial_number = CONFIG_USB_DESC_SERIAL_STRING, \
|
||||||
|
.fw_version = CONFIG_USB_DESC_BCDDEVICE, \
|
||||||
|
.usb_version = 0x0200, \
|
||||||
|
.usb_class = TUSB_CLASS_MISC, \
|
||||||
|
.usb_subclass = MISC_SUBCLASS_COMMON, \
|
||||||
|
.usb_protocol = MISC_PROTOCOL_IAD, \
|
||||||
|
.usb_attributes = TUSB_DESC_CONFIG_ATT_SELF_POWERED, \
|
||||||
|
.usb_power_ma = 500, \
|
||||||
|
.webusb_enabled = false, \
|
||||||
|
.webusb_url = "espressif.github.io/arduino-esp32/webusb.html" \
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t tinyusb_init(tinyusb_device_config_t *config);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Persistence API
|
||||||
|
* */
|
||||||
|
typedef enum {
|
||||||
|
RESTART_NO_PERSIST,
|
||||||
|
RESTART_PERSIST,
|
||||||
|
RESTART_BOOTLOADER,
|
||||||
|
RESTART_BOOTLOADER_DFU,
|
||||||
|
RESTART_TYPE_MAX
|
||||||
|
} restart_type_t;
|
||||||
|
|
||||||
|
void usb_persist_restart(restart_type_t mode);
|
||||||
|
|
||||||
|
// The following definitions and functions are to be used only by the drivers
|
||||||
|
typedef enum {
|
||||||
|
USB_INTERFACE_CDC,
|
||||||
|
USB_INTERFACE_DFU,
|
||||||
|
USB_INTERFACE_HID,
|
||||||
|
USB_INTERFACE_VENDOR,
|
||||||
|
USB_INTERFACE_MSC,
|
||||||
|
USB_INTERFACE_MIDI,
|
||||||
|
USB_INTERFACE_CUSTOM,
|
||||||
|
USB_INTERFACE_MAX
|
||||||
|
} tinyusb_interface_t;
|
||||||
|
|
||||||
|
typedef uint16_t (*tinyusb_descriptor_cb_t)(uint8_t * dst, uint8_t * itf);
|
||||||
|
|
||||||
|
esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb);
|
||||||
|
uint8_t tinyusb_add_string_descriptor(const char * str);
|
||||||
|
uint8_t tinyusb_get_free_duplex_endpoint(void);
|
||||||
|
uint8_t tinyusb_get_free_in_endpoint(void);
|
||||||
|
uint8_t tinyusb_get_free_out_endpoint(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONFIG_USB_ENABLED */
|
||||||
|
#endif /* CONFIG_IDF_TARGET_ESP32S2 */
|
@ -15,12 +15,29 @@
|
|||||||
#include "esp32-hal-touch.h"
|
#include "esp32-hal-touch.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "rom/ets_sys.h"
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_intr.h"
|
|
||||||
#include "soc/rtc_io_reg.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 "soc/sens_reg.h"
|
||||||
|
#include "soc/sens_struct.h"
|
||||||
|
#include "driver/touch_sensor.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"
|
||||||
|
#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
|
||||||
|
|
||||||
static uint16_t __touchSleepCycles = 0x1000;
|
static uint16_t __touchSleepCycles = 0x1000;
|
||||||
static uint16_t __touchMeasureCycles = 0x1000;
|
static uint16_t __touchMeasureCycles = 0x1000;
|
||||||
@ -29,8 +46,9 @@ typedef void (*voidFuncPtr)(void);
|
|||||||
static voidFuncPtr __touchInterruptHandlers[10] = {0,};
|
static voidFuncPtr __touchInterruptHandlers[10] = {0,};
|
||||||
static intr_handle_t touch_intr_handle = NULL;
|
static intr_handle_t touch_intr_handle = NULL;
|
||||||
|
|
||||||
void IRAM_ATTR __touchISR(void * arg)
|
void ARDUINO_ISR_ATTR __touchISR(void * arg)
|
||||||
{
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
uint32_t pad_intr = READ_PERI_REG(SENS_SAR_TOUCH_CTRL2_REG) & 0x3ff;
|
uint32_t pad_intr = READ_PERI_REG(SENS_SAR_TOUCH_CTRL2_REG) & 0x3ff;
|
||||||
uint32_t rtc_intr = READ_PERI_REG(RTC_CNTL_INT_ST_REG);
|
uint32_t rtc_intr = READ_PERI_REG(RTC_CNTL_INT_ST_REG);
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
@ -47,16 +65,21 @@ void IRAM_ATTR __touchISR(void * arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void __touchSetCycles(uint16_t measure, uint16_t sleep)
|
void __touchSetCycles(uint16_t measure, uint16_t sleep)
|
||||||
{
|
{
|
||||||
__touchSleepCycles = sleep;
|
__touchSleepCycles = sleep;
|
||||||
__touchMeasureCycles = measure;
|
__touchMeasureCycles = measure;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
//Touch pad SleepCycle Time
|
//Touch pad SleepCycle Time
|
||||||
SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_SLEEP_CYCLES, __touchSleepCycles, SENS_TOUCH_SLEEP_CYCLES_S);
|
SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_SLEEP_CYCLES, __touchSleepCycles, SENS_TOUCH_SLEEP_CYCLES_S);
|
||||||
//Touch Pad Measure Time
|
//Touch Pad Measure Time
|
||||||
SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_MEAS_DELAY, __touchMeasureCycles, SENS_TOUCH_MEAS_DELAY_S);
|
SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_MEAS_DELAY, __touchMeasureCycles, SENS_TOUCH_MEAS_DELAY_S);
|
||||||
|
#else
|
||||||
|
touch_pad_set_meas_time(sleep, measure);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void __touchInit()
|
void __touchInit()
|
||||||
@ -66,15 +89,27 @@ void __touchInit()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS, 1, RTC_IO_TOUCH_XPD_BIAS_S);
|
SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS, 1, RTC_IO_TOUCH_XPD_BIAS_S);
|
||||||
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN_CLR);
|
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN_CLR);
|
||||||
//clear touch enable
|
//clear touch enable
|
||||||
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, 0x0);
|
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, 0x0);
|
||||||
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_TOUCH_SLP_TIMER_EN);
|
|
||||||
|
|
||||||
__touchSetCycles(__touchMeasureCycles, __touchSleepCycles);
|
__touchSetCycles(__touchMeasureCycles, __touchSleepCycles);
|
||||||
|
esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, __touchISR, NULL, &touch_intr_handle);
|
||||||
esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, __touchISR, NULL, &touch_intr_handle);
|
#else
|
||||||
|
touch_pad_init();
|
||||||
|
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V5);
|
||||||
|
touch_pad_set_idle_channel_connect(TOUCH_PAD_CONN_GND);
|
||||||
|
__touchSetCycles(__touchMeasureCycles, __touchSleepCycles);
|
||||||
|
touch_pad_denoise_t denoise = {
|
||||||
|
.grade = TOUCH_PAD_DENOISE_BIT4,
|
||||||
|
.cap_level = TOUCH_PAD_DENOISE_CAP_L4,
|
||||||
|
};
|
||||||
|
touch_pad_denoise_set_config(&denoise);
|
||||||
|
touch_pad_denoise_enable();
|
||||||
|
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
|
||||||
|
touch_pad_fsm_start();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t __touchRead(uint8_t pin)
|
uint16_t __touchRead(uint8_t pin)
|
||||||
@ -88,6 +123,7 @@ uint16_t __touchRead(uint8_t pin)
|
|||||||
|
|
||||||
__touchInit();
|
__touchInit();
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
uint32_t v0 = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
|
uint32_t v0 = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
|
||||||
//Disable Intr & enable touch pad
|
//Disable Intr & enable touch pad
|
||||||
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG,
|
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG,
|
||||||
@ -119,6 +155,25 @@ uint16_t __touchRead(uint8_t pin)
|
|||||||
//restore previous value
|
//restore previous value
|
||||||
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, v0);
|
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, v0);
|
||||||
return touch_value;
|
return touch_value;
|
||||||
|
#else
|
||||||
|
static uint32_t chan_mask = 0;
|
||||||
|
uint32_t value = 0;
|
||||||
|
if((chan_mask & (1 << pad)) == 0){
|
||||||
|
if(touch_pad_set_thresh((touch_pad_t)pad, TOUCH_PAD_THRESHOLD_MAX) != ESP_OK){
|
||||||
|
log_e("touch_pad_set_thresh failed");
|
||||||
|
} else if(touch_pad_config((touch_pad_t)pad) != ESP_OK){
|
||||||
|
log_e("touch_pad_config failed");
|
||||||
|
} else {
|
||||||
|
chan_mask |= (1 << pad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if((chan_mask & (1 << pad)) != 0) {
|
||||||
|
if(touch_pad_read_raw_data((touch_pad_t)pad, &value) != ESP_OK){
|
||||||
|
log_e("touch_pad_read_raw_data failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold)
|
void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold)
|
||||||
@ -134,6 +189,7 @@ void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t thresh
|
|||||||
|
|
||||||
__touchInterruptHandlers[pad] = userFunc;
|
__touchInterruptHandlers[pad] = userFunc;
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
//clear touch force ,select the Touch mode is Timer
|
//clear touch force ,select the Touch mode is Timer
|
||||||
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M);
|
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M);
|
||||||
|
|
||||||
@ -161,6 +217,9 @@ void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t thresh
|
|||||||
(1 << (pad + SENS_TOUCH_PAD_WORKEN_S)) | \
|
(1 << (pad + SENS_TOUCH_PAD_WORKEN_S)) | \
|
||||||
(1 << (pad + SENS_TOUCH_PAD_OUTEN2_S)) | \
|
(1 << (pad + SENS_TOUCH_PAD_OUTEN2_S)) | \
|
||||||
(1 << (pad + SENS_TOUCH_PAD_OUTEN1_S)));
|
(1 << (pad + SENS_TOUCH_PAD_OUTEN1_S)));
|
||||||
|
#else
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern uint16_t touchRead(uint8_t pin) __attribute__ ((weak, alias("__touchRead")));
|
extern uint16_t touchRead(uint8_t pin) __attribute__ ((weak, alias("__touchRead")));
|
||||||
|
@ -18,10 +18,7 @@
|
|||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/queue.h"
|
#include "freertos/queue.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "rom/ets_sys.h"
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_intr.h"
|
|
||||||
#include "rom/uart.h"
|
|
||||||
#include "soc/uart_reg.h"
|
#include "soc/uart_reg.h"
|
||||||
#include "soc/uart_struct.h"
|
#include "soc/uart_struct.h"
|
||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
@ -30,10 +27,37 @@
|
|||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "esp_intr_alloc.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 "esp32/rom/ets_sys.h"
|
||||||
|
#include "esp32/rom/uart.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/ets_sys.h"
|
||||||
|
#include "esp32s2/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_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 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_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_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_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)))
|
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:((u==2)?ETS_UART2_INTR_SOURCE:0)))
|
||||||
|
#endif
|
||||||
|
|
||||||
static int s_uart_debug_nr = 0;
|
static int s_uart_debug_nr = 0;
|
||||||
|
|
||||||
@ -51,31 +75,35 @@ struct uart_struct_t {
|
|||||||
#define UART_MUTEX_LOCK()
|
#define UART_MUTEX_LOCK()
|
||||||
#define UART_MUTEX_UNLOCK()
|
#define UART_MUTEX_UNLOCK()
|
||||||
|
|
||||||
static uart_t _uart_bus_array[3] = {
|
static uart_t _uart_bus_array[] = {
|
||||||
{(volatile uart_dev_t *)(DR_REG_UART_BASE), 0, NULL, NULL},
|
{&UART0, 0, NULL, NULL},
|
||||||
{(volatile uart_dev_t *)(DR_REG_UART1_BASE), 1, NULL, NULL},
|
{&UART1, 1, NULL, NULL},
|
||||||
{(volatile uart_dev_t *)(DR_REG_UART2_BASE), 2, NULL, NULL}
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
{&UART2, 2, NULL, NULL}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
#define UART_MUTEX_LOCK() do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS)
|
#define UART_MUTEX_LOCK() do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS)
|
||||||
#define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock)
|
#define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock)
|
||||||
|
|
||||||
static uart_t _uart_bus_array[3] = {
|
static uart_t _uart_bus_array[] = {
|
||||||
{(volatile uart_dev_t *)(DR_REG_UART_BASE), NULL, 0, NULL, NULL},
|
{&UART0, NULL, 0, NULL, NULL},
|
||||||
{(volatile uart_dev_t *)(DR_REG_UART1_BASE), NULL, 1, NULL, NULL},
|
{&UART1, NULL, 1, NULL, NULL},
|
||||||
{(volatile uart_dev_t *)(DR_REG_UART2_BASE), NULL, 2, NULL, NULL}
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
{&UART2, NULL, 2, NULL, NULL}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#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 uart_on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb);
|
||||||
|
|
||||||
static void IRAM_ATTR _uart_isr(void *arg)
|
static void ARDUINO_ISR_ATTR _uart_isr(void *arg)
|
||||||
{
|
{
|
||||||
uint8_t i, c;
|
uint8_t i, c;
|
||||||
BaseType_t xHigherPriorityTaskWoken;
|
BaseType_t xHigherPriorityTaskWoken;
|
||||||
uart_t* uart;
|
uart_t* uart;
|
||||||
|
|
||||||
for(i=0;i<3;i++){
|
for(i=0;i<UART_PORTS_NUM;i++){
|
||||||
uart = &_uart_bus_array[i];
|
uart = &_uart_bus_array[i];
|
||||||
if(uart->intr_handle == NULL){
|
if(uart->intr_handle == NULL){
|
||||||
continue;
|
continue;
|
||||||
@ -83,9 +111,15 @@ static void IRAM_ATTR _uart_isr(void *arg)
|
|||||||
uart->dev->int_clr.rxfifo_full = 1;
|
uart->dev->int_clr.rxfifo_full = 1;
|
||||||
uart->dev->int_clr.frm_err = 1;
|
uart->dev->int_clr.frm_err = 1;
|
||||||
uart->dev->int_clr.rxfifo_tout = 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)) {
|
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;
|
c = uart->dev->fifo.rw_byte;
|
||||||
if(uart->queue != NULL && !xQueueIsQueueFullFromISR(uart->queue)) {
|
#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);
|
xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,14 +134,18 @@ void uartEnableInterrupt(uart_t* uart)
|
|||||||
{
|
{
|
||||||
UART_MUTEX_LOCK();
|
UART_MUTEX_LOCK();
|
||||||
uart->dev->conf1.rxfifo_full_thrhd = 112;
|
uart->dev->conf1.rxfifo_full_thrhd = 112;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
uart->dev->conf1.rx_tout_thrhd = 2;
|
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->conf1.rx_tout_en = 1;
|
||||||
uart->dev->int_ena.rxfifo_full = 1;
|
uart->dev->int_ena.rxfifo_full = 1;
|
||||||
uart->dev->int_ena.frm_err = 1;
|
uart->dev->int_ena.frm_err = 1;
|
||||||
uart->dev->int_ena.rxfifo_tout = 1;
|
uart->dev->int_ena.rxfifo_tout = 1;
|
||||||
uart->dev->int_clr.val = 0xffffffff;
|
uart->dev->int_clr.val = 0xffffffff;
|
||||||
|
|
||||||
esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ESP_INTR_FLAG_IRAM, _uart_isr, NULL, &uart->intr_handle);
|
esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ARDUINO_ISR_FLAG, _uart_isr, NULL, &uart->intr_handle);
|
||||||
UART_MUTEX_UNLOCK();
|
UART_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +181,7 @@ void uartDetachTx(uart_t* uart)
|
|||||||
|
|
||||||
void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted)
|
void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted)
|
||||||
{
|
{
|
||||||
if(uart == NULL || rxPin > 39) {
|
if(uart == NULL || rxPin >= GPIO_PIN_COUNT) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pinMode(rxPin, INPUT);
|
pinMode(rxPin, INPUT);
|
||||||
@ -153,7 +191,7 @@ void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted)
|
|||||||
|
|
||||||
void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted)
|
void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted)
|
||||||
{
|
{
|
||||||
if(uart == NULL || txPin > 39) {
|
if(uart == NULL || txPin >= GPIO_PIN_COUNT) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pinMode(txPin, OUTPUT);
|
pinMode(txPin, OUTPUT);
|
||||||
@ -162,7 +200,7 @@ void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted)
|
|||||||
|
|
||||||
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted)
|
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted)
|
||||||
{
|
{
|
||||||
if(uart_nr > 2) {
|
if(uart_nr >= UART_PORTS_NUM) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,9 +228,11 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
|
|||||||
if(uart_nr == 1){
|
if(uart_nr == 1){
|
||||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN);
|
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);
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
} else if(uart_nr == 2){
|
} else if(uart_nr == 2){
|
||||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART2_CLK_EN);
|
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);
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART_CLK_EN);
|
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);
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST);
|
||||||
@ -208,6 +248,11 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
|
|||||||
uart->dev->conf0.stop_bit_num = ONE_STOP_BITS_CONF;
|
uart->dev->conf0.stop_bit_num = ONE_STOP_BITS_CONF;
|
||||||
uart->dev->rs485_conf.dl1_en = 1;
|
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();
|
UART_MUTEX_UNLOCK();
|
||||||
|
|
||||||
if(rxPin != -1) {
|
if(rxPin != -1) {
|
||||||
@ -217,7 +262,6 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
|
|||||||
if(txPin != -1) {
|
if(txPin != -1) {
|
||||||
uartAttachTx(uart, txPin, inverted);
|
uartAttachTx(uart, txPin, inverted);
|
||||||
}
|
}
|
||||||
|
|
||||||
addApbChangeCallback(uart, uart_on_apb_change);
|
addApbChangeCallback(uart, uart_on_apb_change);
|
||||||
return uart;
|
return uart;
|
||||||
}
|
}
|
||||||
@ -253,7 +297,7 @@ size_t uartResizeRxBuffer(uart_t * uart, size_t new_size) {
|
|||||||
vQueueDelete(uart->queue);
|
vQueueDelete(uart->queue);
|
||||||
uart->queue = xQueueCreate(new_size, sizeof(uint8_t));
|
uart->queue = xQueueCreate(new_size, sizeof(uint8_t));
|
||||||
if(uart->queue == NULL) {
|
if(uart->queue == NULL) {
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UART_MUTEX_UNLOCK();
|
UART_MUTEX_UNLOCK();
|
||||||
@ -266,7 +310,7 @@ uint32_t uartAvailable(uart_t* uart)
|
|||||||
if(uart == NULL || uart->queue == NULL) {
|
if(uart == NULL || uart->queue == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return uxQueueMessagesWaiting(uart->queue);
|
return (uxQueueMessagesWaiting(uart->queue) + uart->dev->status.rxfifo_cnt) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t uartAvailableForWrite(uart_t* uart)
|
uint32_t uartAvailableForWrite(uart_t* uart)
|
||||||
@ -277,12 +321,41 @@ uint32_t uartAvailableForWrite(uart_t* uart)
|
|||||||
return 0x7f - uart->dev->status.txfifo_cnt;
|
return 0x7f - uart->dev->status.txfifo_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t uartRead(uart_t* uart)
|
uint8_t uartRead(uart_t* uart)
|
||||||
{
|
{
|
||||||
if(uart == NULL || uart->queue == NULL) {
|
if(uart == NULL || uart->queue == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
|
if ((uxQueueMessagesWaiting(uart->queue) == 0) && (uart->dev->status.rxfifo_cnt > 0))
|
||||||
|
{
|
||||||
|
uartRxFifoToQueue(uart);
|
||||||
|
}
|
||||||
if(xQueueReceive(uart->queue, &c, 0)) {
|
if(xQueueReceive(uart->queue, &c, 0)) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@ -295,6 +368,10 @@ uint8_t uartPeek(uart_t* uart)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
|
if ((uxQueueMessagesWaiting(uart->queue) == 0) && (uart->dev->status.rxfifo_cnt > 0))
|
||||||
|
{
|
||||||
|
uartRxFifoToQueue(uart);
|
||||||
|
}
|
||||||
if(xQueuePeek(uart->queue, &c, 0)) {
|
if(xQueuePeek(uart->queue, &c, 0)) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@ -308,7 +385,11 @@ void uartWrite(uart_t* uart, uint8_t c)
|
|||||||
}
|
}
|
||||||
UART_MUTEX_LOCK();
|
UART_MUTEX_LOCK();
|
||||||
while(uart->dev->status.txfifo_cnt == 0x7F);
|
while(uart->dev->status.txfifo_cnt == 0x7F);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
uart->dev->fifo.rw_byte = c;
|
uart->dev->fifo.rw_byte = c;
|
||||||
|
#else
|
||||||
|
ESP_REG(UART_FIFO_AHB_REG(uart->num)) = c;
|
||||||
|
#endif
|
||||||
UART_MUTEX_UNLOCK();
|
UART_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,31 +399,53 @@ void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UART_MUTEX_LOCK();
|
UART_MUTEX_LOCK();
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32
|
||||||
|
uint32_t fifo_reg = UART_FIFO_AHB_REG(uart->num);
|
||||||
|
#endif
|
||||||
while(len) {
|
while(len) {
|
||||||
while(uart->dev->status.txfifo_cnt == 0x7F);
|
while(uart->dev->status.txfifo_cnt == 0x7F);
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
uart->dev->fifo.rw_byte = *data++;
|
uart->dev->fifo.rw_byte = *data++;
|
||||||
|
#else
|
||||||
|
ESP_REG(fifo_reg) = *data++;
|
||||||
|
#endif
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
UART_MUTEX_UNLOCK();
|
UART_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
void uartFlush(uart_t* uart)
|
void uartFlush(uart_t* uart)
|
||||||
|
{
|
||||||
|
uartFlushTxOnly(uart,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartFlushTxOnly(uart_t* uart, bool txOnly)
|
||||||
{
|
{
|
||||||
if(uart == NULL) {
|
if(uart == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UART_MUTEX_LOCK();
|
UART_MUTEX_LOCK();
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out);
|
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.
|
||||||
|
|
||||||
//Due to hardware issue, we can not use fifo_rst to reset uart fifo.
|
// we read the data out and make `fifo_len == 0 && rd_addr == wr_addr`.
|
||||||
//See description about UART_TXFIFO_RST and UART_RXFIFO_RST in <<esp32_technical_reference_manual>> v2.6 or later.
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
// we read the data out and make `fifo_len == 0 && rd_addr == wr_addr`.
|
xQueueReset(uart->queue);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
while(uart->dev->status.txfifo_cnt);
|
||||||
|
uart->dev->conf0.txfifo_rst = 1;
|
||||||
|
uart->dev->conf0.txfifo_rst = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
UART_MUTEX_UNLOCK();
|
UART_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,18 +471,31 @@ static void uart_on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old
|
|||||||
uart->dev->int_clr.val = 0xffffffff;
|
uart->dev->int_clr.val = 0xffffffff;
|
||||||
// read RX fifo
|
// read RX fifo
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
BaseType_t xHigherPriorityTaskWoken;
|
// 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)) {
|
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;
|
c = uart->dev->fifo.rw_byte;
|
||||||
if(uart->queue != NULL && !xQueueIsQueueFullFromISR(uart->queue)) {
|
#else
|
||||||
xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken);
|
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
|
// wait TX empty
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out);
|
while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out);
|
||||||
|
#else
|
||||||
|
while(uart->dev->status.txfifo_cnt);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
//todo:
|
//todo:
|
||||||
// set baudrate
|
// 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 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);
|
uint32_t baud_rate = ((old_apb<<4)/clk_div);
|
||||||
clk_div = ((new_apb<<4)/baud_rate);
|
clk_div = ((new_apb<<4)/baud_rate);
|
||||||
@ -399,27 +515,44 @@ uint32_t uartGetBaudRate(uart_t* uart)
|
|||||||
if(uart == NULL) {
|
if(uart == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F);
|
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);
|
return ((getApbFrequency()<<4)/clk_div);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IRAM_ATTR uart0_write_char(char c)
|
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);
|
while(((ESP_REG(0x01C+DR_REG_UART_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
|
||||||
ESP_REG(DR_REG_UART_BASE) = c;
|
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 IRAM_ATTR uart1_write_char(char c)
|
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);
|
while(((ESP_REG(0x01C+DR_REG_UART1_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
|
||||||
ESP_REG(DR_REG_UART1_BASE) = c;
|
ESP_REG(DR_REG_UART1_BASE) = c;
|
||||||
|
#else
|
||||||
|
while(UART1.status.txfifo_cnt == 0x7F);
|
||||||
|
WRITE_PERI_REG(UART_FIFO_AHB_REG(1), c);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IRAM_ATTR uart2_write_char(char c)
|
#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);
|
while(((ESP_REG(0x01C+DR_REG_UART2_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
|
||||||
ESP_REG(DR_REG_UART2_BASE) = c;
|
ESP_REG(DR_REG_UART2_BASE) = c;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void uart_install_putc()
|
void uart_install_putc()
|
||||||
{
|
{
|
||||||
@ -430,9 +563,11 @@ void uart_install_putc()
|
|||||||
case 1:
|
case 1:
|
||||||
ets_install_putc1((void (*)(char)) &uart1_write_char);
|
ets_install_putc1((void (*)(char)) &uart1_write_char);
|
||||||
break;
|
break;
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
case 2:
|
case 2:
|
||||||
ets_install_putc1((void (*)(char)) &uart2_write_char);
|
ets_install_putc1((void (*)(char)) &uart2_write_char);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
ets_install_putc1(NULL);
|
ets_install_putc1(NULL);
|
||||||
break;
|
break;
|
||||||
@ -441,7 +576,7 @@ void uart_install_putc()
|
|||||||
|
|
||||||
void uartSetDebug(uart_t* uart)
|
void uartSetDebug(uart_t* uart)
|
||||||
{
|
{
|
||||||
if(uart == NULL || uart->num > 2) {
|
if(uart == NULL || uart->num >= UART_PORTS_NUM) {
|
||||||
s_uart_debug_nr = -1;
|
s_uart_debug_nr = -1;
|
||||||
//ets_install_putc1(NULL);
|
//ets_install_putc1(NULL);
|
||||||
//return;
|
//return;
|
||||||
@ -460,9 +595,6 @@ int uartGetDebug()
|
|||||||
|
|
||||||
int log_printf(const char *format, ...)
|
int log_printf(const char *format, ...)
|
||||||
{
|
{
|
||||||
if(s_uart_debug_nr < 0){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static char loc_buf[64];
|
static char loc_buf[64];
|
||||||
char * temp = loc_buf;
|
char * temp = loc_buf;
|
||||||
int len;
|
int len;
|
||||||
@ -480,7 +612,7 @@ int log_printf(const char *format, ...)
|
|||||||
}
|
}
|
||||||
vsnprintf(temp, len+1, format, arg);
|
vsnprintf(temp, len+1, format, arg);
|
||||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||||
if(_uart_bus_array[s_uart_debug_nr].lock){
|
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);
|
xSemaphoreTake(_uart_bus_array[s_uart_debug_nr].lock, portMAX_DELAY);
|
||||||
ets_printf("%s", temp);
|
ets_printf("%s", temp);
|
||||||
xSemaphoreGive(_uart_bus_array[s_uart_debug_nr].lock);
|
xSemaphoreGive(_uart_bus_array[s_uart_debug_nr].lock);
|
||||||
@ -520,6 +652,14 @@ unsigned long uartBaudrateDetect(uart_t *uart, bool flg)
|
|||||||
* detected calling uartBadrateDetect(). The raw baudrate is computed using the UART_CLK_FREQ. The raw baudrate is
|
* detected calling uartBadrateDetect(). The raw baudrate is computed using the UART_CLK_FREQ. The raw baudrate is
|
||||||
* rounded to the closed real baudrate.
|
* rounded to the closed real baudrate.
|
||||||
*/
|
*/
|
||||||
|
void uartStartDetectBaudrate(uart_t *uart) {
|
||||||
|
if(!uart) return;
|
||||||
|
|
||||||
|
uart->dev->auto_baud.glitch_filt = 0x08;
|
||||||
|
uart->dev->auto_baud.en = 0;
|
||||||
|
uart->dev->auto_baud.en = 1;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long
|
unsigned long
|
||||||
uartDetectBaudrate(uart_t *uart)
|
uartDetectBaudrate(uart_t *uart)
|
||||||
{
|
{
|
||||||
@ -563,5 +703,9 @@ uartDetectBaudrate(uart_t *uart)
|
|||||||
* Returns the status of the RX state machine, if the value is non-zero the state machine is active.
|
* Returns the status of the RX state machine, if the value is non-zero the state machine is active.
|
||||||
*/
|
*/
|
||||||
bool uartRxActive(uart_t* uart) {
|
bool uartRxActive(uart_t* uart) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
return uart->dev->status.st_urx_out != 0;
|
return uart->dev->status.st_urx_out != 0;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ void uartWrite(uart_t* uart, uint8_t c);
|
|||||||
void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len);
|
void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len);
|
||||||
|
|
||||||
void uartFlush(uart_t* uart);
|
void uartFlush(uart_t* uart);
|
||||||
|
void uartFlushTxOnly(uart_t* uart, bool txOnly );
|
||||||
|
|
||||||
void uartSetBaudRate(uart_t* uart, uint32_t baud_rate);
|
void uartSetBaudRate(uart_t* uart, uint32_t baud_rate);
|
||||||
uint32_t uartGetBaudRate(uart_t* uart);
|
uint32_t uartGetBaudRate(uart_t* uart);
|
||||||
@ -72,6 +73,7 @@ size_t uartResizeRxBuffer(uart_t* uart, size_t new_size);
|
|||||||
void uartSetDebug(uart_t* uart);
|
void uartSetDebug(uart_t* uart);
|
||||||
int uartGetDebug();
|
int uartGetDebug();
|
||||||
|
|
||||||
|
void uartStartDetectBaudrate(uart_t *uart);
|
||||||
unsigned long uartDetectBaudrate(uart_t *uart);
|
unsigned long uartDetectBaudrate(uart_t *uart);
|
||||||
|
|
||||||
bool uartRxActive(uart_t* uart);
|
bool uartRxActive(uart_t* uart);
|
||||||
|
@ -20,10 +20,6 @@
|
|||||||
#ifndef HAL_ESP32_HAL_H_
|
#ifndef HAL_ESP32_HAL_H_
|
||||||
#define HAL_ESP32_HAL_H_
|
#define HAL_ESP32_HAL_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -34,9 +30,34 @@ extern "C" {
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef F_CPU
|
#ifndef F_CPU
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
#define F_CPU (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000U)
|
#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
|
||||||
|
#define ARDUINO_ISR_ATTR IRAM_ATTR
|
||||||
|
#define ARDUINO_ISR_FLAG ESP_INTR_FLAG_IRAM
|
||||||
|
#else
|
||||||
|
#define ARDUINO_ISR_ATTR
|
||||||
|
#define ARDUINO_ISR_FLAG (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARDUINO_RUNNING_CORE
|
||||||
|
#define ARDUINO_RUNNING_CORE CONFIG_ARDUINO_RUNNING_CORE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARDUINO_EVENT_RUNNING_CORE
|
||||||
|
#define ARDUINO_EVENT_RUNNING_CORE CONFIG_ARDUINO_EVENT_RUNNING_CORE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//forward declaration from freertos/portmacro.h
|
//forward declaration from freertos/portmacro.h
|
||||||
@ -64,12 +85,6 @@ void yield(void);
|
|||||||
#include "esp32-hal-psram.h"
|
#include "esp32-hal-psram.h"
|
||||||
#include "esp32-hal-cpu.h"
|
#include "esp32-hal-cpu.h"
|
||||||
|
|
||||||
#ifndef BOARD_HAS_PSRAM
|
|
||||||
#ifdef CONFIG_SPIRAM_SUPPORT
|
|
||||||
#undef CONFIG_SPIRAM_SUPPORT
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//returns chip temperature in Celsius
|
//returns chip temperature in Celsius
|
||||||
float temperatureRead();
|
float temperatureRead();
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#define _ESP8266_COMPAT_H_
|
#define _ESP8266_COMPAT_H_
|
||||||
|
|
||||||
#define ICACHE_FLASH_ATTR
|
#define ICACHE_FLASH_ATTR
|
||||||
#define ICACHE_RAM_ATTR IRAM_ATTR
|
#define ICACHE_RAM_ATTR ARDUINO_ISR_ATTR
|
||||||
|
|
||||||
|
|
||||||
#endif /* _ESP8266_COMPAT_H_ */
|
#endif /* _ESP8266_COMPAT_H_ */
|
@ -2,10 +2,23 @@
|
|||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
||||||
|
#include "USB.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
TaskHandle_t loopTaskHandle = NULL;
|
TaskHandle_t loopTaskHandle = NULL;
|
||||||
|
|
||||||
#if CONFIG_AUTOSTART_ARDUINO
|
#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;
|
bool loopTaskWDTEnabled;
|
||||||
|
|
||||||
@ -13,18 +26,25 @@ void loopTask(void *pvParameters)
|
|||||||
{
|
{
|
||||||
setup();
|
setup();
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
#if CONFIG_FREERTOS_UNICORE
|
||||||
|
yieldIfNecessary();
|
||||||
|
#endif
|
||||||
if(loopTaskWDTEnabled){
|
if(loopTaskWDTEnabled){
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
}
|
}
|
||||||
loop();
|
loop();
|
||||||
|
if (serialEventRun) serialEventRun();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void app_main()
|
extern "C" void app_main()
|
||||||
{
|
{
|
||||||
|
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
||||||
|
USB.begin();
|
||||||
|
#endif
|
||||||
loopTaskWDTEnabled = false;
|
loopTaskWDTEnabled = false;
|
||||||
initArduino();
|
initArduino();
|
||||||
xTaskCreateUniversal(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, CONFIG_ARDUINO_RUNNING_CORE);
|
xTaskCreateUniversal(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,7 +32,6 @@ typedef unsigned long prog_uint32_t;
|
|||||||
#define PROGMEM
|
#define PROGMEM
|
||||||
#define PGM_P const char *
|
#define PGM_P const char *
|
||||||
#define PGM_VOID_P const void *
|
#define PGM_VOID_P const void *
|
||||||
#define FPSTR(p) ((const char *)(p))
|
|
||||||
#define PSTR(s) (s)
|
#define PSTR(s) (s)
|
||||||
#define _SFR_BYTE(n) (n)
|
#define _SFR_BYTE(n) (n)
|
||||||
|
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
Installation instructions using Arduino IDE Boards Manager
|
## Installation instructions using Arduino IDE Boards Manager
|
||||||
==========================================================
|
### ==========================================================
|
||||||
|
|
||||||
Starting with 1.6.4, Arduino allows installation of third-party platform packages using Boards Manager. We have packages available for Windows, Mac OS, and Linux (32 and 64 bit).
|
- Stable release link: `https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json`
|
||||||
|
- Development release link: `https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json`
|
||||||
|
|
||||||
|
Starting with 1.6.4, Arduino allows installation of third-party platform packages using Boards Manager. We have packages available for Windows, Mac OS, and Linux (32, 64 bit and ARM).
|
||||||
|
|
||||||
- Install the current upstream Arduino IDE at the 1.8 level or later. The current version is at the [Arduino website](http://www.arduino.cc/en/main/software).
|
- Install the current upstream Arduino IDE at the 1.8 level or later. The current version is at the [Arduino website](http://www.arduino.cc/en/main/software).
|
||||||
- Start Arduino and open Preferences window.
|
- Start Arduino and open Preferences window.
|
||||||
- Enter ```https://dl.espressif.com/dl/package_esp32_index.json``` into *Additional Board Manager URLs* field. You can add multiple URLs, separating them with commas.
|
- Enter one of the release links above into *Additional Board Manager URLs* field. You can add multiple URLs, separating them with commas.
|
||||||
- Open Boards Manager from Tools > Board menu and install *esp32* platform (and don't forget to select your ESP32 board from Tools > Board menu after installation).
|
- Open Boards Manager from Tools > Board menu and install *esp32* platform (and don't forget to select your ESP32 board from Tools > Board menu after installation).
|
||||||
|
|
||||||
Stable release link: `https://dl.espressif.com/dl/package_esp32_index.json`
|
|
||||||
|
|
||||||
Development release link: `https://dl.espressif.com/dl/package_esp32_dev_index.json`
|
|
||||||
|
@ -23,5 +23,7 @@ Installation instructions for Mac OS
|
|||||||
|
|
||||||
- Try `python3` instead of `python` if you get the error: `IOError: [Errno socket error] [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:590)` when running `python get.py`
|
- Try `python3` instead of `python` if you get the error: `IOError: [Errno socket error] [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:590)` when running `python get.py`
|
||||||
|
|
||||||
|
- If you get the following error when running `python get.py` urllib.error.URLError: <urlopen error SSL: CERTIFICATE_VERIFY_FAILED, go to Macintosh HD > Applications > Python3.6 folder (or any other python version), and run the following scripts: Install Certificates.command and Update Shell Profile.command
|
||||||
|
|
||||||
- Restart Arduino IDE
|
- Restart Arduino IDE
|
||||||
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
To use as a component of ESP-IDF
|
To use as a component of ESP-IDF
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
|
## esp32-arduino-lib-builder
|
||||||
|
|
||||||
|
For a simplified method, see [lib-builder](lib_builder.md)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
- Download and install [esp-idf](https://github.com/espressif/esp-idf)
|
- Download and install [esp-idf](https://github.com/espressif/esp-idf)
|
||||||
|
14
docs/lib_builder.md
Normal file
14
docs/lib_builder.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
## Using esp32-arduino-lib-builder to compile custom libraries
|
||||||
|
|
||||||
|
Espressif has provided a [tool](https://github.com/espressif/esp32-arduino-lib-builder) to simplify building your own compiled libraries for use in Arduino IDE (or your favorite IDE).
|
||||||
|
To use it to generate custom libraries, follow these steps:
|
||||||
|
1. `git clone https://github.com/espressif/esp32-arduino-lib-builder`
|
||||||
|
2. `cd esp32-arduino-lib-builder`
|
||||||
|
3. `./tools/update-components.sh`
|
||||||
|
4. `./tools/install-esp-idf.sh` (if you already have an $IDF_PATH defined, it will use your local copy of the repository)
|
||||||
|
5. `make menuconfig` or directly edit sdkconfig.
|
||||||
|
6. `./build.sh`
|
||||||
|
|
||||||
|
The script automates the process of building [arduino as an ESP-IDF component](https://github.com/espressif/arduino-esp32/blob/master/docs/esp-idf_component.md).
|
||||||
|
Once it is complete, you can cherry pick the needed libraries from `out/tools/sdk/lib`, or run `tools/copy-to-arduino.sh` to copy the entire built system.
|
||||||
|
`tools/config.sh` contains a number of variables that control the process, particularly the $IDF_BRANCH variable. You can adjust this to try building against newer versions, but there are absolutely no guarantees that any components will work or even successfully compile against a newer IDF.
|
@ -1,11 +1,11 @@
|
|||||||
Installation instructions for using PlatformIO
|
Installation instructions for using PlatformIO
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
- [What is PlatformIO?](http://docs.platformio.org/en/latest/what-is-platformio.html?utm_source=github&utm_medium=arduino-esp32)
|
- [What is PlatformIO?](https://docs.platformio.org/en/latest/what-is-platformio.html?utm_source=github&utm_medium=arduino-esp32)
|
||||||
- [PlatformIO IDE](http://platformio.org/platformio-ide?utm_source=github&utm_medium=arduino-esp32)
|
- [PlatformIO IDE](https://platformio.org/platformio-ide?utm_source=github&utm_medium=arduino-esp32)
|
||||||
- [PlatformIO Core](http://docs.platformio.org/en/latest/core.html?utm_source=github&utm_medium=arduino-esp32) (command line tool)
|
- [PlatformIO Core](https://docs.platformio.org/en/latest/core.html?utm_source=github&utm_medium=arduino-esp32) (command line tool)
|
||||||
- [Advanced usage](http://docs.platformio.org/en/latest/platforms/espressif32.html?utm_source=github&utm_medium=arduino-esp32) -
|
- [Advanced usage](https://docs.platformio.org/en/latest/platforms/espressif32.html?utm_source=github&utm_medium=arduino-esp32) -
|
||||||
custom settings, uploading to SPIFFS, Over-the-Air (OTA), staging version
|
custom settings, uploading to SPIFFS, Over-the-Air (OTA), staging version
|
||||||
- [Integration with Cloud and Standalone IDEs](http://docs.platformio.org/en/latest/ide.html?utm_source=github&utm_medium=arduino-esp32) -
|
- [Integration with Cloud and Standalone IDEs](https://docs.platformio.org/en/latest/ide.html?utm_source=github&utm_medium=arduino-esp32) -
|
||||||
Cloud9, Codeanywhere, Eclipse Che (Codenvy), Atom, CLion, Eclipse, Emacs, NetBeans, Qt Creator, Sublime Text, VIM, Visual Studio, and VSCode
|
Cloud9, Codeanywhere, Eclipse Che (Codenvy), Atom, CLion, Eclipse, Emacs, NetBeans, Qt Creator, Sublime Text, VIM, Visual Studio, and VSCode
|
||||||
- [Project Examples](http://docs.platformio.org/en/latest/platforms/espressif32.html?utm_source=github&utm_medium=arduino-esp32#examples)
|
- [Project Examples](https://docs.platformio.org/en/latest/platforms/espressif32.html?utm_source=github&utm_medium=arduino-esp32#examples)
|
||||||
|
@ -127,9 +127,7 @@ void ArduinoOTAClass::begin() {
|
|||||||
}
|
}
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
_state = OTA_IDLE;
|
_state = OTA_IDLE;
|
||||||
#ifdef OTA_DEBUG
|
log_i("OTA server at: %s.local:%u", _hostname.c_str(), _port);
|
||||||
OTA_DEBUG.printf("OTA server at: %s.local:%u\n", _hostname.c_str(), _port);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ArduinoOTAClass::parseInt(){
|
int ArduinoOTAClass::parseInt(){
|
||||||
@ -173,6 +171,7 @@ void ArduinoOTAClass::_onRx(){
|
|||||||
_md5 = readStringUntil('\n');
|
_md5 = readStringUntil('\n');
|
||||||
_md5.trim();
|
_md5.trim();
|
||||||
if(_md5.length() != 32){
|
if(_md5.length() != 32){
|
||||||
|
log_e("bad md5 length");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,6 +197,7 @@ void ArduinoOTAClass::_onRx(){
|
|||||||
} else if (_state == OTA_WAITAUTH) {
|
} else if (_state == OTA_WAITAUTH) {
|
||||||
int cmd = parseInt();
|
int cmd = parseInt();
|
||||||
if (cmd != U_AUTH) {
|
if (cmd != U_AUTH) {
|
||||||
|
log_e("%d was expected. got %d instead", U_AUTH, cmd);
|
||||||
_state = OTA_IDLE;
|
_state = OTA_IDLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -205,6 +205,7 @@ void ArduinoOTAClass::_onRx(){
|
|||||||
String cnonce = readStringUntil(' ');
|
String cnonce = readStringUntil(' ');
|
||||||
String response = readStringUntil('\n');
|
String response = readStringUntil('\n');
|
||||||
if (cnonce.length() != 32 || response.length() != 32) {
|
if (cnonce.length() != 32 || response.length() != 32) {
|
||||||
|
log_e("auth param fail");
|
||||||
_state = OTA_IDLE;
|
_state = OTA_IDLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -225,6 +226,7 @@ void ArduinoOTAClass::_onRx(){
|
|||||||
} else {
|
} else {
|
||||||
_udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort());
|
_udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort());
|
||||||
_udp_ota.print("Authentication Failed");
|
_udp_ota.print("Authentication Failed");
|
||||||
|
log_w("Authentication Failed");
|
||||||
_udp_ota.endPacket();
|
_udp_ota.endPacket();
|
||||||
if (_error_callback) _error_callback(OTA_AUTH_ERROR);
|
if (_error_callback) _error_callback(OTA_AUTH_ERROR);
|
||||||
_state = OTA_IDLE;
|
_state = OTA_IDLE;
|
||||||
@ -234,9 +236,9 @@ void ArduinoOTAClass::_onRx(){
|
|||||||
|
|
||||||
void ArduinoOTAClass::_runUpdate() {
|
void ArduinoOTAClass::_runUpdate() {
|
||||||
if (!Update.begin(_size, _cmd)) {
|
if (!Update.begin(_size, _cmd)) {
|
||||||
#ifdef OTA_DEBUG
|
|
||||||
Update.printError(OTA_DEBUG);
|
log_e("Begin ERROR: %s", Update.errorString());
|
||||||
#endif
|
|
||||||
if (_error_callback) {
|
if (_error_callback) {
|
||||||
_error_callback(OTA_BEGIN_ERROR);
|
_error_callback(OTA_BEGIN_ERROR);
|
||||||
}
|
}
|
||||||
@ -272,21 +274,15 @@ void ArduinoOTAClass::_runUpdate() {
|
|||||||
}
|
}
|
||||||
if (!waited){
|
if (!waited){
|
||||||
if(written && tried++ < 3){
|
if(written && tried++ < 3){
|
||||||
#ifdef OTA_DEBUG
|
log_i("Try[%u]: %u", tried, written);
|
||||||
OTA_DEBUG.printf("Try[%u]: %u\n", tried, written);
|
|
||||||
#endif
|
|
||||||
if(!client.printf("%u", written)){
|
if(!client.printf("%u", written)){
|
||||||
#ifdef OTA_DEBUG
|
log_e("failed to respond");
|
||||||
OTA_DEBUG.printf("failed to respond\n");
|
|
||||||
#endif
|
|
||||||
_state = OTA_IDLE;
|
_state = OTA_IDLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#ifdef OTA_DEBUG
|
log_e("Receive Failed");
|
||||||
OTA_DEBUG.printf("Receive Failed\n");
|
|
||||||
#endif
|
|
||||||
if (_error_callback) {
|
if (_error_callback) {
|
||||||
_error_callback(OTA_RECEIVE_ERROR);
|
_error_callback(OTA_RECEIVE_ERROR);
|
||||||
}
|
}
|
||||||
@ -295,9 +291,7 @@ void ArduinoOTAClass::_runUpdate() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!available){
|
if(!available){
|
||||||
#ifdef OTA_DEBUG
|
log_e("No Data: %u", waited);
|
||||||
OTA_DEBUG.printf("No Data: %u\n", waited);
|
|
||||||
#endif
|
|
||||||
_state = OTA_IDLE;
|
_state = OTA_IDLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -317,18 +311,14 @@ void ArduinoOTAClass::_runUpdate() {
|
|||||||
log_w("didn't write enough! %u != %u", written, r);
|
log_w("didn't write enough! %u != %u", written, r);
|
||||||
}
|
}
|
||||||
if(!client.printf("%u", written)){
|
if(!client.printf("%u", written)){
|
||||||
#ifdef OTA_DEBUG
|
log_w("failed to respond");
|
||||||
OTA_DEBUG.printf("failed to respond\n");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
total += written;
|
total += written;
|
||||||
if(_progress_callback) {
|
if(_progress_callback) {
|
||||||
_progress_callback(total, _size);
|
_progress_callback(total, _size);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#ifdef OTA_DEBUG
|
log_e("Write ERROR: %s", Update.errorString());
|
||||||
Update.printError(OTA_DEBUG);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,10 +341,7 @@ void ArduinoOTAClass::_runUpdate() {
|
|||||||
Update.printError(client);
|
Update.printError(client);
|
||||||
client.stop();
|
client.stop();
|
||||||
delay(10);
|
delay(10);
|
||||||
#ifdef OTA_DEBUG
|
log_e("Update ERROR: %s", Update.errorString());
|
||||||
OTA_DEBUG.print("Update ERROR: ");
|
|
||||||
Update.printError(OTA_DEBUG);
|
|
||||||
#endif
|
|
||||||
_state = OTA_IDLE;
|
_state = OTA_IDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -366,9 +353,7 @@ void ArduinoOTAClass::end() {
|
|||||||
MDNS.end();
|
MDNS.end();
|
||||||
}
|
}
|
||||||
_state = OTA_IDLE;
|
_state = OTA_IDLE;
|
||||||
#ifdef OTA_DEBUG
|
log_i("OTA server stopped.");
|
||||||
OTA_DEBUG.println("OTA server stopped.");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArduinoOTAClass::handle() {
|
void ArduinoOTAClass::handle() {
|
||||||
@ -395,4 +380,4 @@ void ArduinoOTAClass::setTimeout(int timeoutInMillis) {
|
|||||||
|
|
||||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_ARDUINOOTA)
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_ARDUINOOTA)
|
||||||
ArduinoOTAClass ArduinoOTA;
|
ArduinoOTAClass ArduinoOTA;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"name":"AsyncUDP",
|
|
||||||
"description":"Asynchronous UDP Library for ESP32",
|
|
||||||
"keywords":"async,udp,server,client,multicast,broadcast",
|
|
||||||
"authors":
|
|
||||||
{
|
|
||||||
"name": "Hristo Gochkov",
|
|
||||||
"maintainer": true
|
|
||||||
},
|
|
||||||
"repository":
|
|
||||||
{
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/me-no-dev/ESPAsyncUDP.git"
|
|
||||||
},
|
|
||||||
"frameworks": "arduino",
|
|
||||||
"platforms":"espressif"
|
|
||||||
}
|
|
@ -682,8 +682,9 @@ void AsyncUDP::_recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t po
|
|||||||
if(_handler) {
|
if(_handler) {
|
||||||
AsyncUDPPacket packet(this, this_pb, addr, port, netif);
|
AsyncUDPPacket packet(this, this_pb, addr, port, netif);
|
||||||
_handler(packet);
|
_handler(packet);
|
||||||
|
} else {
|
||||||
|
pbuf_free(this_pb);
|
||||||
}
|
}
|
||||||
pbuf_free(this_pb);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include <tcpip_adapter.h>
|
#include "esp_netif.h"
|
||||||
#include "freertos/queue.h"
|
#include "freertos/queue.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
}
|
}
|
||||||
|
Submodule libraries/AzureIoT deleted from 67dfa4f31e
0
libraries/BLE/examples/BLE_client/.skip.esp32s2
Normal file
0
libraries/BLE/examples/BLE_client/.skip.esp32s2
Normal file
@ -87,6 +87,7 @@ bool connectToServer() {
|
|||||||
pRemoteCharacteristic->registerForNotify(notifyCallback);
|
pRemoteCharacteristic->registerForNotify(notifyCallback);
|
||||||
|
|
||||||
connected = true;
|
connected = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Scan for BLE servers and find the first one that advertises the service we are looking for.
|
* Scan for BLE servers and find the first one that advertises the service we are looking for.
|
||||||
@ -153,7 +154,7 @@ void loop() {
|
|||||||
// Set the characteristic's value to be the array of bytes that is actually a string.
|
// Set the characteristic's value to be the array of bytes that is actually a string.
|
||||||
pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
|
pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
|
||||||
}else if(doScan){
|
}else if(doScan){
|
||||||
BLEDevice::getScan()->start(0); // this is just eample to start scan after disconnect, most likely there is better way to do it in arduino
|
BLEDevice::getScan()->start(0); // this is just example to start scan after disconnect, most likely there is better way to do it in arduino
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(1000); // Delay a second between loops.
|
delay(1000); // Delay a second between loops.
|
||||||
|
0
libraries/BLE/examples/BLE_iBeacon/.skip.esp32s2
Normal file
0
libraries/BLE/examples/BLE_iBeacon/.skip.esp32s2
Normal file
@ -65,6 +65,7 @@ void setBeacon() {
|
|||||||
|
|
||||||
pAdvertising->setAdvertisementData(oAdvertisementData);
|
pAdvertising->setAdvertisementData(oAdvertisementData);
|
||||||
pAdvertising->setScanResponseData(oScanResponseData);
|
pAdvertising->setScanResponseData(oScanResponseData);
|
||||||
|
pAdvertising->setAdvertisementType(ADV_TYPE_NONCONN_IND);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
0
libraries/BLE/examples/BLE_notify/.skip.esp32s2
Normal file
0
libraries/BLE/examples/BLE_notify/.skip.esp32s2
Normal file
0
libraries/BLE/examples/BLE_scan/.skip.esp32s2
Normal file
0
libraries/BLE/examples/BLE_scan/.skip.esp32s2
Normal file
0
libraries/BLE/examples/BLE_server/.skip.esp32s2
Normal file
0
libraries/BLE/examples/BLE_server/.skip.esp32s2
Normal file
0
libraries/BLE/examples/BLE_uart/.skip.esp32s2
Normal file
0
libraries/BLE/examples/BLE_uart/.skip.esp32s2
Normal file
0
libraries/BLE/examples/BLE_write/.skip.esp32s2
Normal file
0
libraries/BLE/examples/BLE_write/.skip.esp32s2
Normal file
@ -13,6 +13,7 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
#include "esp32-hal-log.h"
|
#include "esp32-hal-log.h"
|
||||||
#endif
|
#endif
|
||||||
@ -83,13 +84,11 @@ esp_bd_addr_t *BLEAddress::getNative() {
|
|||||||
* @return The string representation of the address.
|
* @return The string representation of the address.
|
||||||
*/
|
*/
|
||||||
std::string BLEAddress::toString() {
|
std::string BLEAddress::toString() {
|
||||||
std::stringstream stream;
|
auto size = 18;
|
||||||
stream << std::setfill('0') << std::setw(2) << std::hex << (int) ((uint8_t*) (m_address))[0] << ':';
|
char *res = (char*)malloc(size);
|
||||||
stream << std::setfill('0') << std::setw(2) << std::hex << (int) ((uint8_t*) (m_address))[1] << ':';
|
snprintf(res, size, "%02x:%02x:%02x:%02x:%02x:%02x", m_address[0], m_address[1], m_address[2], m_address[3], m_address[4], m_address[5]);
|
||||||
stream << std::setfill('0') << std::setw(2) << std::hex << (int) ((uint8_t*) (m_address))[2] << ':';
|
std::string ret(res);
|
||||||
stream << std::setfill('0') << std::setw(2) << std::hex << (int) ((uint8_t*) (m_address))[3] << ':';
|
free(res);
|
||||||
stream << std::setfill('0') << std::setw(2) << std::hex << (int) ((uint8_t*) (m_address))[4] << ':';
|
return ret;
|
||||||
stream << std::setfill('0') << std::setw(2) << std::hex << (int) ((uint8_t*) (m_address))[5];
|
|
||||||
return stream.str();
|
|
||||||
} // toString
|
} // toString
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,7 +25,8 @@ BLEAdvertisedDevice::BLEAdvertisedDevice() {
|
|||||||
m_manufacturerData = "";
|
m_manufacturerData = "";
|
||||||
m_name = "";
|
m_name = "";
|
||||||
m_rssi = -9999;
|
m_rssi = -9999;
|
||||||
m_serviceData = "";
|
m_serviceData = {};
|
||||||
|
m_serviceDataUUIDs = {};
|
||||||
m_txPower = 0;
|
m_txPower = 0;
|
||||||
m_pScan = nullptr;
|
m_pScan = nullptr;
|
||||||
|
|
||||||
@ -101,33 +102,66 @@ BLEScan* BLEAdvertisedDevice::getScan() {
|
|||||||
return m_pScan;
|
return m_pScan;
|
||||||
} // getScan
|
} // getScan
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of service data.
|
||||||
|
* @return Number of service data discovered.
|
||||||
|
*/
|
||||||
|
int BLEAdvertisedDevice::getServiceDataCount() {
|
||||||
|
if (m_haveServiceData)
|
||||||
|
return m_serviceData.size();
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} //getServiceDataCount
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the service data.
|
* @brief Get the service data.
|
||||||
* @return The ServiceData of the advertised device.
|
* @return The ServiceData of the advertised device.
|
||||||
*/
|
*/
|
||||||
std::string BLEAdvertisedDevice::getServiceData() {
|
std::string BLEAdvertisedDevice::getServiceData() {
|
||||||
return m_serviceData;
|
return m_serviceData[0];
|
||||||
} //getServiceData
|
} //getServiceData
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the service data.
|
||||||
|
* @return The ServiceData of the advertised device.
|
||||||
|
*/
|
||||||
|
std::string BLEAdvertisedDevice::getServiceData(int i) {
|
||||||
|
return m_serviceData[i];
|
||||||
|
} //getServiceData
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the service data UUID.
|
* @brief Get the service data UUID.
|
||||||
* @return The service data UUID.
|
* @return The service data UUID.
|
||||||
*/
|
*/
|
||||||
BLEUUID BLEAdvertisedDevice::getServiceDataUUID() {
|
BLEUUID BLEAdvertisedDevice::getServiceDataUUID() {
|
||||||
return m_serviceDataUUID;
|
return m_serviceDataUUIDs[0];
|
||||||
} // getServiceDataUUID
|
} // getServiceDataUUID
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the service data UUID.
|
||||||
|
* @return The service data UUID.
|
||||||
|
*/
|
||||||
|
BLEUUID BLEAdvertisedDevice::getServiceDataUUID(int i) {
|
||||||
|
return m_serviceDataUUIDs[i];
|
||||||
|
} // getServiceDataUUID
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the Service UUID.
|
* @brief Get the Service UUID.
|
||||||
* @return The Service UUID of the advertised device.
|
* @return The Service UUID of the advertised device.
|
||||||
*/
|
*/
|
||||||
BLEUUID BLEAdvertisedDevice::getServiceUUID() { //TODO Remove it eventually, is no longer useful
|
BLEUUID BLEAdvertisedDevice::getServiceUUID() {
|
||||||
return m_serviceUUIDs[0];
|
return m_serviceUUIDs[0];
|
||||||
} // getServiceUUID
|
} // getServiceUUID
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the Service UUID.
|
||||||
|
* @return The Service UUID of the advertised device.
|
||||||
|
*/
|
||||||
|
BLEUUID BLEAdvertisedDevice::getServiceUUID(int i) {
|
||||||
|
return m_serviceUUIDs[i];
|
||||||
|
} // getServiceUUID
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check advertised serviced for existence required UUID
|
* @brief Check advertised serviced for existence required UUID
|
||||||
* @return Return true if service is advertised
|
* @return Return true if service is advertised
|
||||||
@ -454,7 +488,7 @@ void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) {
|
|||||||
*/
|
*/
|
||||||
void BLEAdvertisedDevice::setServiceData(std::string serviceData) {
|
void BLEAdvertisedDevice::setServiceData(std::string serviceData) {
|
||||||
m_haveServiceData = true; // Set the flag that indicates we have service data.
|
m_haveServiceData = true; // Set the flag that indicates we have service data.
|
||||||
m_serviceData = serviceData; // Save the service data that we received.
|
m_serviceData.push_back(serviceData); // Save the service data that we received.
|
||||||
} //setServiceData
|
} //setServiceData
|
||||||
|
|
||||||
|
|
||||||
@ -464,7 +498,8 @@ void BLEAdvertisedDevice::setServiceData(std::string serviceData) {
|
|||||||
*/
|
*/
|
||||||
void BLEAdvertisedDevice::setServiceDataUUID(BLEUUID uuid) {
|
void BLEAdvertisedDevice::setServiceDataUUID(BLEUUID uuid) {
|
||||||
m_haveServiceData = true; // Set the flag that indicates we have service data.
|
m_haveServiceData = true; // Set the flag that indicates we have service data.
|
||||||
m_serviceDataUUID = uuid;
|
m_serviceDataUUIDs.push_back(uuid);
|
||||||
|
log_d("- addServiceDataUUID(): serviceDataUUID: %s", uuid.toString().c_str());
|
||||||
} // setServiceDataUUID
|
} // setServiceDataUUID
|
||||||
|
|
||||||
|
|
||||||
@ -484,23 +519,31 @@ void BLEAdvertisedDevice::setTXPower(int8_t txPower) {
|
|||||||
* @return A string representation of this device.
|
* @return A string representation of this device.
|
||||||
*/
|
*/
|
||||||
std::string BLEAdvertisedDevice::toString() {
|
std::string BLEAdvertisedDevice::toString() {
|
||||||
std::stringstream ss;
|
std::string res = "Name: " + getName() + ", Address: " + getAddress().toString();
|
||||||
ss << "Name: " << getName() << ", Address: " << getAddress().toString();
|
|
||||||
if (haveAppearance()) {
|
if (haveAppearance()) {
|
||||||
ss << ", appearance: " << getAppearance();
|
char val[6];
|
||||||
|
snprintf(val, sizeof(val), "%d", getAppearance());
|
||||||
|
res += ", appearance: ";
|
||||||
|
res += val;
|
||||||
}
|
}
|
||||||
if (haveManufacturerData()) {
|
if (haveManufacturerData()) {
|
||||||
char *pHex = BLEUtils::buildHexData(nullptr, (uint8_t*)getManufacturerData().data(), getManufacturerData().length());
|
char *pHex = BLEUtils::buildHexData(nullptr, (uint8_t*)getManufacturerData().data(), getManufacturerData().length());
|
||||||
ss << ", manufacturer data: " << pHex;
|
res += ", manufacturer data: ";
|
||||||
|
res += pHex;
|
||||||
free(pHex);
|
free(pHex);
|
||||||
}
|
}
|
||||||
if (haveServiceUUID()) {
|
if (haveServiceUUID()) {
|
||||||
ss << ", serviceUUID: " << getServiceUUID().toString();
|
for (int i=0; i < m_serviceUUIDs.size(); i++) {
|
||||||
|
res += ", serviceUUID: " + getServiceUUID(i).toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (haveTXPower()) {
|
if (haveTXPower()) {
|
||||||
ss << ", txPower: " << (int)getTXPower();
|
char val[6];
|
||||||
|
snprintf(val, sizeof(val), "%d", getTXPower());
|
||||||
|
res += ", txPower: ";
|
||||||
|
res += val;
|
||||||
}
|
}
|
||||||
return ss.str();
|
return res;
|
||||||
} // toString
|
} // toString
|
||||||
|
|
||||||
uint8_t* BLEAdvertisedDevice::getPayload() {
|
uint8_t* BLEAdvertisedDevice::getPayload() {
|
||||||
|
@ -36,8 +36,12 @@ public:
|
|||||||
int getRSSI();
|
int getRSSI();
|
||||||
BLEScan* getScan();
|
BLEScan* getScan();
|
||||||
std::string getServiceData();
|
std::string getServiceData();
|
||||||
|
std::string getServiceData(int i);
|
||||||
BLEUUID getServiceDataUUID();
|
BLEUUID getServiceDataUUID();
|
||||||
|
BLEUUID getServiceDataUUID(int i);
|
||||||
BLEUUID getServiceUUID();
|
BLEUUID getServiceUUID();
|
||||||
|
BLEUUID getServiceUUID(int i);
|
||||||
|
int getServiceDataCount();
|
||||||
int8_t getTXPower();
|
int8_t getTXPower();
|
||||||
uint8_t* getPayload();
|
uint8_t* getPayload();
|
||||||
size_t getPayloadLength();
|
size_t getPayloadLength();
|
||||||
@ -93,8 +97,8 @@ private:
|
|||||||
int m_rssi;
|
int m_rssi;
|
||||||
std::vector<BLEUUID> m_serviceUUIDs;
|
std::vector<BLEUUID> m_serviceUUIDs;
|
||||||
int8_t m_txPower;
|
int8_t m_txPower;
|
||||||
std::string m_serviceData;
|
std::vector<std::string> m_serviceData;
|
||||||
BLEUUID m_serviceDataUUID;
|
std::vector<BLEUUID> m_serviceDataUUIDs;
|
||||||
uint8_t* m_payload;
|
uint8_t* m_payload;
|
||||||
size_t m_payloadLength = 0;
|
size_t m_payloadLength = 0;
|
||||||
esp_ble_addr_type_t m_addressType;
|
esp_ble_addr_type_t m_addressType;
|
||||||
|
@ -85,6 +85,10 @@ void BLEAdvertising::setAppearance(uint16_t appearance) {
|
|||||||
m_advData.appearance = appearance;
|
m_advData.appearance = appearance;
|
||||||
} // setAppearance
|
} // setAppearance
|
||||||
|
|
||||||
|
void BLEAdvertising::setAdvertisementType(esp_ble_adv_type_t adv_type){
|
||||||
|
m_advParams.adv_type = adv_type;
|
||||||
|
} // setAdvertisementType
|
||||||
|
|
||||||
void BLEAdvertising::setMinInterval(uint16_t mininterval) {
|
void BLEAdvertising::setMinInterval(uint16_t mininterval) {
|
||||||
m_advParams.adv_int_min = mininterval;
|
m_advParams.adv_int_min = mininterval;
|
||||||
} // setMinInterval
|
} // setMinInterval
|
||||||
@ -253,6 +257,27 @@ void BLEAdvertising::stop() {
|
|||||||
log_v("<< stop");
|
log_v("<< stop");
|
||||||
} // stop
|
} // stop
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set BLE address.
|
||||||
|
* @param [in] Bluetooth address.
|
||||||
|
* @param [in] Bluetooth address type.
|
||||||
|
* Set BLE address.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void BLEAdvertising::setDeviceAddress(esp_bd_addr_t addr, esp_ble_addr_type_t type)
|
||||||
|
{
|
||||||
|
log_v(">> setPrivateAddress");
|
||||||
|
|
||||||
|
m_advParams.own_addr_type = type;
|
||||||
|
esp_err_t errRc = esp_ble_gap_set_rand_addr((uint8_t*)addr);
|
||||||
|
if (errRc != ESP_OK)
|
||||||
|
{
|
||||||
|
log_e("esp_ble_gap_set_rand_addr: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log_v("<< setPrivateAddress");
|
||||||
|
} // setPrivateAddress
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add data to the payload to be advertised.
|
* @brief Add data to the payload to be advertised.
|
||||||
* @param [in] data The data to be added to the payload.
|
* @param [in] data The data to be added to the payload.
|
||||||
@ -484,7 +509,7 @@ void BLEAdvertising::handleGAPEvent(
|
|||||||
}
|
}
|
||||||
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: {
|
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: {
|
||||||
log_i("STOP advertising");
|
log_i("STOP advertising");
|
||||||
start();
|
//start();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include <esp_gap_ble_api.h>
|
#include <esp_gap_ble_api.h>
|
||||||
#include "BLEUUID.h"
|
#include "BLEUUID.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "FreeRTOS.h"
|
#include "RTOS.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Advertisement data set by the programmer to be published by the %BLE server.
|
* @brief Advertisement data set by the programmer to be published by the %BLE server.
|
||||||
@ -52,12 +52,14 @@ public:
|
|||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
void setAppearance(uint16_t appearance);
|
void setAppearance(uint16_t appearance);
|
||||||
|
void setAdvertisementType(esp_ble_adv_type_t adv_type);
|
||||||
void setMaxInterval(uint16_t maxinterval);
|
void setMaxInterval(uint16_t maxinterval);
|
||||||
void setMinInterval(uint16_t mininterval);
|
void setMinInterval(uint16_t mininterval);
|
||||||
void setAdvertisementData(BLEAdvertisementData& advertisementData);
|
void setAdvertisementData(BLEAdvertisementData& advertisementData);
|
||||||
void setScanFilter(bool scanRequertWhitelistOnly, bool connectWhitelistOnly);
|
void setScanFilter(bool scanRequertWhitelistOnly, bool connectWhitelistOnly);
|
||||||
void setScanResponseData(BLEAdvertisementData& advertisementData);
|
void setScanResponseData(BLEAdvertisementData& advertisementData);
|
||||||
void setPrivateAddress(esp_ble_addr_type_t type = BLE_ADDR_TYPE_RANDOM);
|
void setPrivateAddress(esp_ble_addr_type_t type = BLE_ADDR_TYPE_RANDOM);
|
||||||
|
void setDeviceAddress(esp_bd_addr_t addr, esp_ble_addr_type_t type = BLE_ADDR_TYPE_RANDOM);
|
||||||
|
|
||||||
void handleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param);
|
void handleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param);
|
||||||
void setMinPreferred(uint16_t);
|
void setMinPreferred(uint16_t);
|
||||||
@ -75,4 +77,4 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* COMPONENTS_CPP_UTILS_BLEADVERTISING_H_ */
|
#endif /* COMPONENTS_CPP_UTILS_BLEADVERTISING_H_ */
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#define NULL_HANDLE (0xffff)
|
#define NULL_HANDLE (0xffff)
|
||||||
|
|
||||||
|
static BLECharacteristicCallbacks defaultCallback; //null-object-pattern
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct a characteristic
|
* @brief Construct a characteristic
|
||||||
@ -40,7 +41,7 @@ BLECharacteristic::BLECharacteristic(BLEUUID uuid, uint32_t properties) {
|
|||||||
m_bleUUID = uuid;
|
m_bleUUID = uuid;
|
||||||
m_handle = NULL_HANDLE;
|
m_handle = NULL_HANDLE;
|
||||||
m_properties = (esp_gatt_char_prop_t)0;
|
m_properties = (esp_gatt_char_prop_t)0;
|
||||||
m_pCallbacks = nullptr;
|
m_pCallbacks = &defaultCallback;
|
||||||
|
|
||||||
setBroadcastProperty((properties & PROPERTY_BROADCAST) != 0);
|
setBroadcastProperty((properties & PROPERTY_BROADCAST) != 0);
|
||||||
setReadProperty((properties & PROPERTY_READ) != 0);
|
setReadProperty((properties & PROPERTY_READ) != 0);
|
||||||
@ -220,9 +221,7 @@ void BLECharacteristic::handleGATTServerEvent(
|
|||||||
case ESP_GATTS_EXEC_WRITE_EVT: {
|
case ESP_GATTS_EXEC_WRITE_EVT: {
|
||||||
if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) {
|
if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) {
|
||||||
m_value.commit();
|
m_value.commit();
|
||||||
if (m_pCallbacks != nullptr) {
|
m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
|
||||||
m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
m_value.cancel();
|
m_value.cancel();
|
||||||
}
|
}
|
||||||
@ -307,7 +306,7 @@ void BLECharacteristic::handleGATTServerEvent(
|
|||||||
}
|
}
|
||||||
} // Response needed
|
} // Response needed
|
||||||
|
|
||||||
if (m_pCallbacks != nullptr && param->write.is_prep != true) {
|
if (param->write.is_prep != true) {
|
||||||
m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
|
m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
|
||||||
}
|
}
|
||||||
} // Match on handles.
|
} // Match on handles.
|
||||||
@ -378,6 +377,10 @@ void BLECharacteristic::handleGATTServerEvent(
|
|||||||
}
|
}
|
||||||
} else { // read.is_long == false
|
} else { // read.is_long == false
|
||||||
|
|
||||||
|
// If is.long is false then this is the first (or only) request to read data, so invoke the callback
|
||||||
|
// Invoke the read callback.
|
||||||
|
m_pCallbacks->onRead(this);
|
||||||
|
|
||||||
std::string value = m_value.getValue();
|
std::string value = m_value.getValue();
|
||||||
|
|
||||||
if (value.length() + 1 > maxOffset) {
|
if (value.length() + 1 > maxOffset) {
|
||||||
@ -392,10 +395,6 @@ void BLECharacteristic::handleGATTServerEvent(
|
|||||||
rsp.attr_value.offset = 0;
|
rsp.attr_value.offset = 0;
|
||||||
memcpy(rsp.attr_value.value, value.data(), rsp.attr_value.len);
|
memcpy(rsp.attr_value.value, value.data(), rsp.attr_value.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pCallbacks != nullptr) { // If is.long is false then this is the first (or only) request to read data, so invoke the callback
|
|
||||||
m_pCallbacks->onRead(this); // Invoke the read callback.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
rsp.attr_value.handle = param->read.handle;
|
rsp.attr_value.handle = param->read.handle;
|
||||||
rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE;
|
rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE;
|
||||||
@ -480,10 +479,13 @@ void BLECharacteristic::notify(bool is_notification) {
|
|||||||
assert(getService() != nullptr);
|
assert(getService() != nullptr);
|
||||||
assert(getService()->getServer() != nullptr);
|
assert(getService()->getServer() != nullptr);
|
||||||
|
|
||||||
|
m_pCallbacks->onNotify(this); // Invoke the notify callback.
|
||||||
|
|
||||||
GeneralUtils::hexDump((uint8_t*)m_value.getValue().data(), m_value.getValue().length());
|
GeneralUtils::hexDump((uint8_t*)m_value.getValue().data(), m_value.getValue().length());
|
||||||
|
|
||||||
if (getService()->getServer()->getConnectedCount() == 0) {
|
if (getService()->getServer()->getConnectedCount() == 0) {
|
||||||
log_v("<< notify: No connected clients.");
|
log_v("<< notify: No connected clients.");
|
||||||
|
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::ERROR_NO_CLIENT, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,12 +496,14 @@ void BLECharacteristic::notify(bool is_notification) {
|
|||||||
if(is_notification) {
|
if(is_notification) {
|
||||||
if (p2902 != nullptr && !p2902->getNotifications()) {
|
if (p2902 != nullptr && !p2902->getNotifications()) {
|
||||||
log_v("<< notifications disabled; ignoring");
|
log_v("<< notifications disabled; ignoring");
|
||||||
|
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::ERROR_NOTIFY_DISABLED, 0); // Invoke the notify callback.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if (p2902 != nullptr && !p2902->getIndications()) {
|
if (p2902 != nullptr && !p2902->getIndications()) {
|
||||||
log_v("<< indications disabled; ignoring");
|
log_v("<< indications disabled; ignoring");
|
||||||
|
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::ERROR_INDICATE_DISABLED, 0); // Invoke the notify callback.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -510,7 +514,7 @@ void BLECharacteristic::notify(bool is_notification) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t length = m_value.getValue().length();
|
size_t length = m_value.getValue().length();
|
||||||
if(!is_notification)
|
if(!is_notification) // is indication
|
||||||
m_semaphoreConfEvt.take("indicate");
|
m_semaphoreConfEvt.take("indicate");
|
||||||
esp_err_t errRc = ::esp_ble_gatts_send_indicate(
|
esp_err_t errRc = ::esp_ble_gatts_send_indicate(
|
||||||
getService()->getServer()->getGattsIf(),
|
getService()->getServer()->getGattsIf(),
|
||||||
@ -519,10 +523,23 @@ void BLECharacteristic::notify(bool is_notification) {
|
|||||||
if (errRc != ESP_OK) {
|
if (errRc != ESP_OK) {
|
||||||
log_e("<< esp_ble_gatts_send_ %s: rc=%d %s",is_notification?"notify":"indicate", errRc, GeneralUtils::errorToString(errRc));
|
log_e("<< esp_ble_gatts_send_ %s: rc=%d %s",is_notification?"notify":"indicate", errRc, GeneralUtils::errorToString(errRc));
|
||||||
m_semaphoreConfEvt.give();
|
m_semaphoreConfEvt.give();
|
||||||
|
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::ERROR_GATT, errRc); // Invoke the notify callback.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!is_notification)
|
if(!is_notification){ // is indication
|
||||||
m_semaphoreConfEvt.wait("indicate");
|
if(!m_semaphoreConfEvt.timedWait("indicate", indicationTimeout)){
|
||||||
|
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT, 0); // Invoke the notify callback.
|
||||||
|
} else {
|
||||||
|
auto code = (esp_gatt_status_t) m_semaphoreConfEvt.value();
|
||||||
|
if(code == ESP_GATT_OK) {
|
||||||
|
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::SUCCESS_INDICATE, code); // Invoke the notify callback.
|
||||||
|
} else {
|
||||||
|
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE, code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::SUCCESS_NOTIFY, 0); // Invoke the notify callback.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log_v("<< notify");
|
log_v("<< notify");
|
||||||
} // Notify
|
} // Notify
|
||||||
@ -551,7 +568,11 @@ void BLECharacteristic::setBroadcastProperty(bool value) {
|
|||||||
*/
|
*/
|
||||||
void BLECharacteristic::setCallbacks(BLECharacteristicCallbacks* pCallbacks) {
|
void BLECharacteristic::setCallbacks(BLECharacteristicCallbacks* pCallbacks) {
|
||||||
log_v(">> setCallbacks: 0x%x", (uint32_t)pCallbacks);
|
log_v(">> setCallbacks: 0x%x", (uint32_t)pCallbacks);
|
||||||
m_pCallbacks = pCallbacks;
|
if (pCallbacks != nullptr){
|
||||||
|
m_pCallbacks = pCallbacks;
|
||||||
|
} else {
|
||||||
|
m_pCallbacks = &defaultCallback;
|
||||||
|
}
|
||||||
log_v("<< setCallbacks");
|
log_v("<< setCallbacks");
|
||||||
} // setCallbacks
|
} // setCallbacks
|
||||||
|
|
||||||
@ -628,7 +649,9 @@ void BLECharacteristic::setValue(uint8_t* data, size_t length) {
|
|||||||
log_e("Size %d too large, must be no bigger than %d", length, ESP_GATT_MAX_ATTR_LEN);
|
log_e("Size %d too large, must be no bigger than %d", length, ESP_GATT_MAX_ATTR_LEN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
m_semaphoreSetValue.take();
|
||||||
m_value.setValue(data, length);
|
m_value.setValue(data, length);
|
||||||
|
m_semaphoreSetValue.give();
|
||||||
log_v("<< setValue");
|
log_v("<< setValue");
|
||||||
} // setValue
|
} // setValue
|
||||||
|
|
||||||
@ -670,15 +693,13 @@ void BLECharacteristic::setValue(int& data32) {
|
|||||||
} // setValue
|
} // setValue
|
||||||
|
|
||||||
void BLECharacteristic::setValue(float& data32) {
|
void BLECharacteristic::setValue(float& data32) {
|
||||||
uint8_t temp[4];
|
float temp = data32;
|
||||||
*((float*)temp) = data32;
|
setValue((uint8_t*)&temp, 4);
|
||||||
setValue(temp, 4);
|
|
||||||
} // setValue
|
} // setValue
|
||||||
|
|
||||||
void BLECharacteristic::setValue(double& data64) {
|
void BLECharacteristic::setValue(double& data64) {
|
||||||
uint8_t temp[8];
|
double temp = data64;
|
||||||
*((double*)temp) = data64;
|
setValue((uint8_t*)&temp, 8);
|
||||||
setValue(temp, 8);
|
|
||||||
} // setValue
|
} // setValue
|
||||||
|
|
||||||
|
|
||||||
@ -715,17 +736,18 @@ void BLECharacteristic::setWriteProperty(bool value) {
|
|||||||
* @return A string representation of the characteristic.
|
* @return A string representation of the characteristic.
|
||||||
*/
|
*/
|
||||||
std::string BLECharacteristic::toString() {
|
std::string BLECharacteristic::toString() {
|
||||||
std::stringstream stringstream;
|
std::string res = "UUID: " + m_bleUUID.toString() + ", handle : 0x";
|
||||||
stringstream << std::hex << std::setfill('0');
|
char hex[5];
|
||||||
stringstream << "UUID: " << m_bleUUID.toString() + ", handle: 0x" << std::setw(2) << m_handle;
|
snprintf(hex, sizeof(hex), "%04x", m_handle);
|
||||||
stringstream << " " <<
|
res += hex;
|
||||||
((m_properties & ESP_GATT_CHAR_PROP_BIT_READ) ? "Read " : "") <<
|
res += " ";
|
||||||
((m_properties & ESP_GATT_CHAR_PROP_BIT_WRITE) ? "Write " : "") <<
|
if (m_properties & ESP_GATT_CHAR_PROP_BIT_READ) res += "Read ";
|
||||||
((m_properties & ESP_GATT_CHAR_PROP_BIT_WRITE_NR) ? "WriteNoResponse " : "") <<
|
if (m_properties & ESP_GATT_CHAR_PROP_BIT_WRITE) res += "Write ";
|
||||||
((m_properties & ESP_GATT_CHAR_PROP_BIT_BROADCAST) ? "Broadcast " : "") <<
|
if (m_properties & ESP_GATT_CHAR_PROP_BIT_WRITE_NR) res += "WriteNoResponse ";
|
||||||
((m_properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY) ? "Notify " : "") <<
|
if (m_properties & ESP_GATT_CHAR_PROP_BIT_BROADCAST) res += "Broadcast ";
|
||||||
((m_properties & ESP_GATT_CHAR_PROP_BIT_INDICATE) ? "Indicate " : "");
|
if (m_properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY) res += "Notify ";
|
||||||
return stringstream.str();
|
if (m_properties & ESP_GATT_CHAR_PROP_BIT_INDICATE) res += "Indicate ";
|
||||||
|
return res;
|
||||||
} // toString
|
} // toString
|
||||||
|
|
||||||
|
|
||||||
@ -751,4 +773,27 @@ void BLECharacteristicCallbacks::onWrite(BLECharacteristic* pCharacteristic) {
|
|||||||
log_d("BLECharacteristicCallbacks", "<< onWrite");
|
log_d("BLECharacteristicCallbacks", "<< onWrite");
|
||||||
} // onWrite
|
} // onWrite
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function to support a Notify request.
|
||||||
|
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
||||||
|
*/
|
||||||
|
void BLECharacteristicCallbacks::onNotify(BLECharacteristic* pCharacteristic) {
|
||||||
|
log_d("BLECharacteristicCallbacks", ">> onNotify: default");
|
||||||
|
log_d("BLECharacteristicCallbacks", "<< onNotify");
|
||||||
|
} // onNotify
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function to support a Notify/Indicate Status report.
|
||||||
|
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
||||||
|
* @param [in] s Status of the notification/indication
|
||||||
|
* @param [in] code Additional code of underlying errors
|
||||||
|
*/
|
||||||
|
void BLECharacteristicCallbacks::onStatus(BLECharacteristic* pCharacteristic, Status s, uint32_t code) {
|
||||||
|
log_d("BLECharacteristicCallbacks", ">> onStatus: default");
|
||||||
|
log_d("BLECharacteristicCallbacks", "<< onStatus");
|
||||||
|
} // onStatus
|
||||||
|
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include <esp_gap_ble_api.h>
|
#include <esp_gap_ble_api.h>
|
||||||
#include "BLEDescriptor.h"
|
#include "BLEDescriptor.h"
|
||||||
#include "BLEValue.h"
|
#include "BLEValue.h"
|
||||||
#include "FreeRTOS.h"
|
#include "RTOS.h"
|
||||||
|
|
||||||
class BLEService;
|
class BLEService;
|
||||||
class BLEDescriptor;
|
class BLEDescriptor;
|
||||||
@ -90,6 +90,8 @@ public:
|
|||||||
static const uint32_t PROPERTY_INDICATE = 1<<4;
|
static const uint32_t PROPERTY_INDICATE = 1<<4;
|
||||||
static const uint32_t PROPERTY_WRITE_NR = 1<<5;
|
static const uint32_t PROPERTY_WRITE_NR = 1<<5;
|
||||||
|
|
||||||
|
static const uint32_t indicationTimeout = 1000;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
friend class BLEServer;
|
friend class BLEServer;
|
||||||
@ -117,6 +119,7 @@ private:
|
|||||||
void setHandle(uint16_t handle);
|
void setHandle(uint16_t handle);
|
||||||
FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt");
|
FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt");
|
||||||
FreeRTOS::Semaphore m_semaphoreConfEvt = FreeRTOS::Semaphore("ConfEvt");
|
FreeRTOS::Semaphore m_semaphoreConfEvt = FreeRTOS::Semaphore("ConfEvt");
|
||||||
|
FreeRTOS::Semaphore m_semaphoreSetValue = FreeRTOS::Semaphore("SetValue");
|
||||||
}; // BLECharacteristic
|
}; // BLECharacteristic
|
||||||
|
|
||||||
|
|
||||||
@ -129,9 +132,22 @@ private:
|
|||||||
*/
|
*/
|
||||||
class BLECharacteristicCallbacks {
|
class BLECharacteristicCallbacks {
|
||||||
public:
|
public:
|
||||||
|
typedef enum {
|
||||||
|
SUCCESS_INDICATE,
|
||||||
|
SUCCESS_NOTIFY,
|
||||||
|
ERROR_INDICATE_DISABLED,
|
||||||
|
ERROR_NOTIFY_DISABLED,
|
||||||
|
ERROR_GATT,
|
||||||
|
ERROR_NO_CLIENT,
|
||||||
|
ERROR_INDICATE_TIMEOUT,
|
||||||
|
ERROR_INDICATE_FAILURE
|
||||||
|
}Status;
|
||||||
|
|
||||||
virtual ~BLECharacteristicCallbacks();
|
virtual ~BLECharacteristicCallbacks();
|
||||||
virtual void onRead(BLECharacteristic* pCharacteristic);
|
virtual void onRead(BLECharacteristic* pCharacteristic);
|
||||||
virtual void onWrite(BLECharacteristic* pCharacteristic);
|
virtual void onWrite(BLECharacteristic* pCharacteristic);
|
||||||
|
virtual void onNotify(BLECharacteristic* pCharacteristic);
|
||||||
|
virtual void onStatus(BLECharacteristic* pCharacteristic, Status s, uint32_t code);
|
||||||
};
|
};
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* COMPONENTS_CPP_UTILS_BLECHARACTERISTIC_H_ */
|
#endif /* COMPONENTS_CPP_UTILS_BLECHARACTERISTIC_H_ */
|
||||||
|
@ -116,17 +116,18 @@ void BLECharacteristicMap::setByUUID(BLECharacteristic* pCharacteristic, BLEUUID
|
|||||||
* @return A string representation of the characteristic map.
|
* @return A string representation of the characteristic map.
|
||||||
*/
|
*/
|
||||||
std::string BLECharacteristicMap::toString() {
|
std::string BLECharacteristicMap::toString() {
|
||||||
std::stringstream stringStream;
|
std::string res;
|
||||||
stringStream << std::hex << std::setfill('0');
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
char hex[5];
|
||||||
for (auto &myPair: m_uuidMap) {
|
for (auto &myPair: m_uuidMap) {
|
||||||
if (count > 0) {
|
if (count > 0) {res += "\n";}
|
||||||
stringStream << "\n";
|
snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle());
|
||||||
}
|
|
||||||
count++;
|
count++;
|
||||||
stringStream << "handle: 0x" << std::setw(2) << myPair.first->getHandle() << ", uuid: " + myPair.first->getUUID().toString();
|
res += "handle: 0x";
|
||||||
|
res += hex;
|
||||||
|
res += ", uuid: " + myPair.first->getUUID().toString();
|
||||||
}
|
}
|
||||||
return stringStream.str();
|
return res;
|
||||||
} // toString
|
} // toString
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,10 +184,11 @@ void BLEClient::gattClientEventHandler(
|
|||||||
if (m_pClientCallbacks != nullptr) {
|
if (m_pClientCallbacks != nullptr) {
|
||||||
m_pClientCallbacks->onDisconnect(this);
|
m_pClientCallbacks->onDisconnect(this);
|
||||||
}
|
}
|
||||||
BLEDevice::removePeerDevice(m_appId, true);
|
|
||||||
esp_ble_gattc_app_unregister(m_gattc_if);
|
esp_ble_gattc_app_unregister(m_gattc_if);
|
||||||
|
m_semaphoreOpenEvt.give(ESP_GATT_IF_NONE);
|
||||||
m_semaphoreRssiCmplEvt.give();
|
m_semaphoreRssiCmplEvt.give();
|
||||||
m_semaphoreSearchCmplEvt.give(1);
|
m_semaphoreSearchCmplEvt.give(1);
|
||||||
|
BLEDevice::removePeerDevice(m_appId, true);
|
||||||
break;
|
break;
|
||||||
} // ESP_GATTC_DISCONNECT_EVT
|
} // ESP_GATTC_DISCONNECT_EVT
|
||||||
|
|
||||||
@ -515,14 +516,13 @@ uint16_t BLEClient::getMTU() {
|
|||||||
* @return A string representation of this client.
|
* @return A string representation of this client.
|
||||||
*/
|
*/
|
||||||
std::string BLEClient::toString() {
|
std::string BLEClient::toString() {
|
||||||
std::ostringstream ss;
|
std::string res = "peer address: " + m_peerAddress.toString();
|
||||||
ss << "peer address: " << m_peerAddress.toString();
|
res += "\nServices:\n";
|
||||||
ss << "\nServices:\n";
|
|
||||||
for (auto &myPair : m_servicesMap) {
|
for (auto &myPair : m_servicesMap) {
|
||||||
ss << myPair.second->toString() << "\n";
|
res += myPair.second->toString() + "\n";
|
||||||
// myPair.second is the value
|
// myPair.second is the value
|
||||||
}
|
}
|
||||||
return ss.str();
|
return res;
|
||||||
} // toString
|
} // toString
|
||||||
|
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user